bug 610198 - Replacing JS_GetStringBytes usage with JS_EncodeString. r=gal
☠☠ backed out by 3ab57a9fb7b8 ☠ ☠
authorIgor Bukanov <igor@mir2.org>
Tue, 02 Nov 2010 15:36:25 +0100
changeset 57785 8e119f847f97ba1e29da8192ca5fc93248e6c960
parent 57784 3d63107fc7881db6a31745d283b4e74643ceb719
child 57786 3ab57a9fb7b817b70d579082599ad1c08c6438ed
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersgal
bugs610198
milestone2.0b8pre
bug 610198 - Replacing JS_GetStringBytes usage with JS_EncodeString. r=gal
caps/src/nsSecurityManagerFactory.cpp
dom/base/nsJSEnvironment.cpp
extensions/jssh/nsJSSh.cpp
ipc/testshell/XPCShellEnvironment.cpp
js/src/ctypes/CTypes.cpp
js/src/jsapi-tests/tests.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsatom.cpp
js/src/jsatom.h
js/src/jsdate.cpp
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsopcode.cpp
js/src/jsparse.cpp
js/src/jsprobes.cpp
js/src/jsprobes.h
js/src/jspropertycache.cpp
js/src/jsproxy.cpp
js/src/jsregexp.cpp
js/src/jsstr.cpp
js/src/jsstr.h
js/src/jstracer.cpp
js/src/jsutil.h
js/src/jsxml.cpp
js/src/methodjit/StubCalls-inl.h
js/src/shell/js.cpp
js/src/shell/jsworkers.cpp
js/src/xpconnect/loader/mozJSComponentLoader.cpp
js/src/xpconnect/loader/mozJSSubScriptLoader.cpp
js/src/xpconnect/shell/xpcshell.cpp
js/src/xpconnect/src/qsgen.py
js/src/xpconnect/src/xpccomponents.cpp
js/src/xpconnect/src/xpcconvert.cpp
js/src/xpconnect/src/xpcdebug.cpp
js/src/xpconnect/src/xpcquickstubs.cpp
js/src/xpconnect/src/xpcquickstubs.h
js/src/xpconnect/src/xpcthrower.cpp
js/src/xpconnect/src/xpcwrappednativejsops.cpp
js/src/xpconnect/tests/TestXPC.cpp
js/src/xpconnect/wrappers/WrapperFactory.cpp
security/manager/ssl/src/nsCrypto.cpp
storage/src/mozStorageStatementRow.cpp
xpinstall/src/nsJSInstallTriggerGlobal.cpp
--- a/caps/src/nsSecurityManagerFactory.cpp
+++ b/caps/src/nsSecurityManagerFactory.cpp
@@ -63,33 +63,37 @@ nsSecurityNameSet::nsSecurityNameSet()
 }
 
 nsSecurityNameSet::~nsSecurityNameSet()
 {
 }
 
 NS_IMPL_ISUPPORTS1(nsSecurityNameSet, nsIScriptExternalNameSet)
 
-static char *
+static JSString *
 getStringArgument(JSContext *cx, JSObject *obj, PRUint16 argNum, uintN argc, jsval *argv)
 {
     if (argc <= argNum || !JSVAL_IS_STRING(argv[argNum])) {
         JS_ReportError(cx, "String argument expected");
         return nsnull;
     }
 
     /*
      * We don't want to use JS_ValueToString because we want to be able
      * to have an object to represent a target in subsequent versions.
      */
-    JSString *str = JSVAL_TO_STRING(argv[argNum]);
-    if (!str)
-        return nsnull;
+    return JSVAL_TO_STRING(argv[argNum]);
+}
 
-    return JS_GetStringBytes(str);
+static bool
+getBytesArgument(JSContext *cx, JSObject *obj, PRUint16 argNum, uintN argc, jsval *argv,
+                 JSAutoByteString *bytes)
+{
+    JSString *str = getStringArgument(cx, obj, argNum, argc, argv);
+    return str && bytes->encode(cx, str);
 }
 
 static void
 getUTF8StringArgument(JSContext *cx, JSObject *obj, PRUint16 argNum,
                       uintN argc, jsval *argv, nsCString& aRetval)
 {
     if (argc <= argNum || !JSVAL_IS_STRING(argv[argNum])) {
         JS_ReportError(cx, "String argument expected");
@@ -114,135 +118,140 @@ getUTF8StringArgument(JSContext *cx, JSO
 static JSBool
 netscape_security_isPrivilegeEnabled(JSContext *cx, uintN argc, jsval *vp)
 {
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     JSBool result = JS_FALSE;
-    char *cap = getStringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp));
-    if (cap) {
+    if (JSString *str = getStringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp))) {
+        JSAutoByteString cap(cx, str);
+        if (!cap)
+            return JS_FALSE;
+
         nsresult rv;
         nsCOMPtr<nsIScriptSecurityManager> securityManager = 
                  do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
         if (NS_SUCCEEDED(rv)) {
             //            NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
 
-            rv = securityManager->IsCapabilityEnabled(cap, &result);
+            rv = securityManager->IsCapabilityEnabled(cap.ptr(), &result);
             if (NS_FAILED(rv)) 
                 result = JS_FALSE;
         }
     }
     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(result));
     return JS_TRUE;
 }
 
 
 static JSBool
 netscape_security_enablePrivilege(JSContext *cx, uintN argc, jsval *vp)
 {
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
-    char *cap = getStringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp));
-    if (!cap)
+    JSAutoByteString cap;
+    if (!getBytesArgument(cx, obj, 0, argc, JS_ARGV(cx, vp), &cap))
         return JS_FALSE;
 
     nsresult rv;
     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
     if (NS_FAILED(rv)) 
         return JS_FALSE;
 
     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
 
-    rv = securityManager->EnableCapability(cap);
+    rv = securityManager->EnableCapability(cap.ptr());
     if (NS_FAILED(rv))
         return JS_FALSE;
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
 netscape_security_disablePrivilege(JSContext *cx, uintN argc, jsval *vp)
 {
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
-    char *cap = getStringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp));
-    if (!cap)
+    JSAutoByteString cap;
+    if (!getBytesArgument(cx, obj, 0, argc, JS_ARGV(cx, vp), &cap))
         return JS_FALSE;
 
     nsresult rv;
     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
     if (NS_FAILED(rv)) 
         return JS_FALSE;
 
     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
 
-    rv = securityManager->DisableCapability(cap);
+    rv = securityManager->DisableCapability(cap.ptr());
     if (NS_FAILED(rv))
         return JS_FALSE;
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
 netscape_security_revertPrivilege(JSContext *cx, uintN argc, jsval *vp)
 {
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
-    char *cap = getStringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp));
-    if (!cap)
+    JSAutoByteString cap;
+    if (!getBytesArgument(cx, obj, 0, argc, JS_ARGV(cx, vp), &cap))
         return JS_FALSE;
 
     nsresult rv;
     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
     if (NS_FAILED(rv)) 
         return JS_FALSE;
 
     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
 
-    rv = securityManager->RevertCapability(cap);
+    rv = securityManager->RevertCapability(cap.ptr());
     if (NS_FAILED(rv))
         return JS_FALSE;
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
 netscape_security_setCanEnablePrivilege(JSContext *cx, uintN argc, jsval *vp)
 {
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     if (argc < 2) return JS_FALSE;
     nsCAutoString principalFingerprint;
     getUTF8StringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp), principalFingerprint);
-    char *cap = getStringArgument(cx, obj, 1, argc, JS_ARGV(cx, vp));
+    JSAutoByteString cap;
+    getBytesArgument(cx, obj, 1, argc, JS_ARGV(cx, vp), &cap);
     if (principalFingerprint.IsEmpty() || !cap)
         return JS_FALSE;
 
     nsresult rv;
     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
     if (NS_FAILED(rv)) 
         return JS_FALSE;
 
     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
 
-    rv = securityManager->SetCanEnableCapability(principalFingerprint, cap, 
+    rv = securityManager->SetCanEnableCapability(principalFingerprint,
+                                                 cap.ptr(), 
                                                  nsIPrincipal::ENABLE_GRANTED);
     if (NS_FAILED(rv))
         return JS_FALSE;
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -3142,17 +3142,19 @@ TraceMallocOpenLogFile(JSContext *cx, ui
         return JS_FALSE;
 
     if (argc == 0) {
         fd = -1;
     } else {
         str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
         if (!str)
             return JS_FALSE;
-        filename = JS_GetStringBytes(str);
+        JSAutoByteString filename(cx, str);
+        if (!filename)
+            return JS_FALSE;
         fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
         if (fd < 0) {
             JS_ReportError(cx, "can't open %s: %s", filename, strerror(errno));
             return JS_FALSE;
         }
     }
     JS_SET_RVAL(cx, vp, INT_TO_JSVAL(fd));
     return JS_TRUE;
@@ -3196,46 +3198,44 @@ TraceMallocCloseLogFD(JSContext *cx, uin
         return JS_FALSE;
     NS_TraceMallocCloseLogFD((int) fd);
     return JS_TRUE;
 }
 
 static JSBool
 TraceMallocLogTimestamp(JSContext *cx, uintN argc, jsval *vp)
 {
-    JSString *str;
-    const char *caption;
-
     if (!CheckUniversalXPConnectForTraceMalloc(cx))
         return JS_FALSE;
 
-    str = JS_ValueToString(cx, argc ? JS_ARGV(cx, vp)[0] : JSVAL_VOID);
+    JSString *str = JS_ValueToString(cx, argc ? JS_ARGV(cx, vp)[0] : JSVAL_VOID);
     if (!str)
         return JS_FALSE;
-    caption = JS_GetStringBytes(str);
+    JSAutoByteString caption(cx, str);
+    if (!caption)
+        return JS_FALSE;
     NS_TraceMallocLogTimestamp(caption);
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
 TraceMallocDumpAllocations(JSContext *cx, uintN argc, jsval *vp)
 {
-    JSString *str;
-    const char *pathname;
-
     if (!CheckUniversalXPConnectForTraceMalloc(cx))
         return JS_FALSE;
 
-    str = JS_ValueToString(cx, argc ? JS_ARGV(cx, vp)[0] : JSVAL_VOID);
+    JSString *str = JS_ValueToString(cx, argc ? JS_ARGV(cx, vp)[0] : JSVAL_VOID);
     if (!str)
         return JS_FALSE;
-    pathname = JS_GetStringBytes(str);
+    JSAutoByteString pathname(cx, str);
+    if (!pathname)
+        return JS_FALSE;
     if (NS_TraceMallocDumpAllocations(pathname) < 0) {
-        JS_ReportError(cx, "can't dump to %s: %s", pathname, strerror(errno));
+        JS_ReportError(cx, "can't dump to %s: %s", pathname.ptr(), strerror(errno));
         return JS_FALSE;
     }
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSFunctionSpec TraceMallocFunctions[] = {
     {"TraceMallocDisable",         TraceMallocDisable,         0, 0},
--- a/extensions/jssh/nsJSSh.cpp
+++ b/extensions/jssh/nsJSSh.cpp
@@ -146,28 +146,30 @@ Print(JSContext *cx, JSObject *obj, uint
 //     nsCOMPtr<nsIThread> thread;
 //     nsIThread::GetCurrent(getter_AddRefs(thread));
 //     printf("printing on thread %p, shell %p, output %p, cx=%p, obj=%p\n", thread.get(), shell, shell->mOutput, cx, obj);
 #endif
 
     for (unsigned int i=0; i<argc; ++i) {
      JSString *str = JS_ValueToString(cx, argv[i]);
      if (!str) return JS_FALSE;
+     JSAutoByteString bytes(cx, str);
+     if (!bytes) return JS_FALSE;
      if (shell->mOutput) {
        if (shell->mEmitHeader) {
          char buf[80];
          sprintf(buf, "[%d]", JS_GetStringLength(str));
          shell->mOutput->Write(buf, strlen(buf), &bytesWritten);
        }
-       shell->mOutput->Write(JS_GetStringBytes(str), JS_GetStringLength(str), &bytesWritten);
+       shell->mOutput->Write(bytes.ptr(), strlen(bytes), &bytesWritten);
      }
      else
-       printf("%s", JS_GetStringBytes(str)); // use cout if no output stream given.
+       printf("%s", bytes.ptr()); // use cout if no output stream given.
 #ifdef DEBUG
-//        printf("%s", JS_GetStringBytes(str));
+//        printf("%s", bytes.ptr());
 #endif
    }
   return JS_TRUE;
 }
 
 static JSBool
 Quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
@@ -191,17 +193,18 @@ Load(JSContext *cx, JSObject *obj, uintN
   JSAutoRequest ar(cx);
 
   if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
 
   for (unsigned int i=0; i<argc; ++i) {
     JSString *str = JS_ValueToString(cx, argv[i]);
     if (!str) return JS_FALSE;
     //argv[i] = STRING_TO_JSVAL(str);
-    const char *url = JS_GetStringBytes(str);
+    JSAutoByteString url(cx, str);
+    if (!url) return JS_FALSE;
     if (!shell->LoadURL(url, rval))
       return JS_FALSE;
   }
   return JS_TRUE;
 }
 
 static JSBool
 FlushEventQueue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -249,17 +249,20 @@ Print(JSContext *cx,
     uintN i, n;
     JSString *str;
 
     jsval *argv = JS_ARGV(cx, vp);
     for (i = n = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
             return JS_FALSE;
-        fprintf(stdout, "%s%s", i ? " " : "", JS_GetStringBytes(str));
+        JSAutoByteString bytes(cx, str);
+        if (!bytes)
+            return JS_FALSE;
+        fprintf(stdout, "%s%s", i ? " " : "", bytes.ptr());
         fflush(stdout);
     }
     n++;
     if (n)
         fputc('\n', stdout);
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
@@ -299,39 +302,40 @@ Dump(JSContext *cx,
 
 static JSBool
 Load(JSContext *cx,
      uintN argc,
      jsval *vp)
 {
     uintN i;
     JSString *str;
-    const char *filename;
     JSScript *script;
     JSBool ok;
     jsval result;
     FILE *file;
 
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     jsval *argv = JS_ARGV(cx, vp);
     for (i = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
             return JS_FALSE;
         argv[i] = STRING_TO_JSVAL(str);
-        filename = JS_GetStringBytes(str);
-        file = fopen(filename, "r");
+        JSAutoByteString filename(cx, str);
+        if (!filename)
+            return JS_FALSE;
+        file = fopen(filename.ptr(), "r");
         if (!file) {
-            JS_ReportError(cx, "cannot open file '%s' for reading", filename);
+            JS_ReportError(cx, "cannot open file '%s' for reading", filename.ptr());
             return JS_FALSE;
         }
-        script = JS_CompileFileHandleForPrincipals(cx, obj, filename, file,
+        script = JS_CompileFileHandleForPrincipals(cx, obj, filename.ptr(), file,
                                                    Environment(cx)->GetPrincipal());
         fclose(file);
         if (!script)
             return JS_FALSE;
 
         ok = !Environment(cx)->ShouldCompileOnly()
              ? JS_ExecuteScript(cx, obj, script, &result)
              : JS_TRUE;
@@ -425,17 +429,17 @@ GC(JSContext *cx,
 
 #ifdef DEBUG
 
 static JSBool
 DumpHeap(JSContext *cx,
          uintN argc,
          jsval *vp)
 {
-    char *fileName = NULL;
+    JSAutoByteString fileName;
     void* startThing = NULL;
     uint32 startTraceKind = 0;
     void *thingToFind = NULL;
     size_t maxDepth = (size_t)-1;
     void *thingToIgnore = NULL;
     FILE *dumpFile;
     JSBool ok;
 
@@ -445,17 +449,18 @@ DumpHeap(JSContext *cx,
     vp = argv + 0;
     if (argc > 0 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
         JSString *str;
 
         str = JS_ValueToString(cx, *vp);
         if (!str)
             return JS_FALSE;
         *vp = STRING_TO_JSVAL(str);
-        fileName = JS_GetStringBytes(str);
+        if (!fileName.encode(cx, str))
+            return JS_FALSE;
     }
 
     vp = argv + 1;
     if (argc > 1 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
         if (!JSVAL_IS_TRACEABLE(*vp))
             goto not_traceable_arg;
         startThing = JSVAL_TO_TRACEABLE(*vp);
         startTraceKind = JSVAL_TRACE_KIND(*vp);
@@ -482,20 +487,20 @@ DumpHeap(JSContext *cx,
         if (!JSVAL_IS_TRACEABLE(*vp))
             goto not_traceable_arg;
         thingToIgnore = JSVAL_TO_TRACEABLE(*vp);
     }
 
     if (!fileName) {
         dumpFile = stdout;
     } else {
-        dumpFile = fopen(fileName, "w");
+        dumpFile = fopen(fileName.ptr(), "w");
         if (!dumpFile) {
             fprintf(stderr, "dumpHeap: can't open %s: %s\n",
-                    fileName, strerror(errno));
+                    fileName.ptr(), strerror(errno));
             return JS_FALSE;
         }
     }
 
     ok = JS_DumpHeap(cx, dumpFile, startThing, startTraceKind, thingToFind,
                      maxDepth, thingToIgnore);
     if (dumpFile != stdout)
         fclose(dumpFile);
@@ -666,20 +671,23 @@ ProcessFile(JSContext *cx,
             JSErrorReporter older;
 
             if (!env->ShouldCompileOnly()) {
                 ok = JS_ExecuteScript(cx, obj, script, &result);
                 if (ok && result != JSVAL_VOID) {
                     /* Suppress error reports from JS_ValueToString(). */
                     older = JS_SetErrorReporter(cx, NULL);
                     str = JS_ValueToString(cx, result);
+                    JSAutoByteString bytes;
+                    if (str)
+                        bytes.encode(cx, str);
                     JS_SetErrorReporter(cx, older);
 
-                    if (str)
-                        fprintf(stdout, "%s\n", JS_GetStringBytes(str));
+                    if (!!bytes)
+                        fprintf(stdout, "%s\n", bytes.ptr());
                     else
                         ok = JS_FALSE;
                 }
             }
             JS_DestroyScript(cx, script);
         }
     } while (!hitEOF && !env->IsQuitting());
 
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -508,28 +508,27 @@ GetErrorMessage(void* userRef, const cha
     return &ErrorFormatString[errorNumber];
   return NULL;
 }
 
 JSBool
 TypeError(JSContext* cx, const char* expected, jsval actual)
 {
   JSString* str = JS_ValueToSource(cx, actual);
-  js::AutoStringRooter root(cx, str);
-
+  JSAutoByteString bytes;
+  
   const char* src;
   if (str) {
-    src = JS_GetStringBytesZ(cx, str);
+    src = bytes.encode(cx, str);
     if (!src)
       return false;
   } else {
     JS_ClearPendingException(cx);
     src = "<<error converting value to string>>";
   }
-
   JS_ReportErrorNumber(cx, GetErrorMessage, NULL,
                        CTYPESMSG_TYPE_ERROR, expected, src);
   return false;
 }
 
 static JSObject*
 InitCTypeClass(JSContext* cx, JSObject* parent)
 {
@@ -4326,21 +4325,21 @@ StructType::LookupField(JSContext* cx, J
 {
   JS_ASSERT(CType::IsCType(cx, obj));
   JS_ASSERT(CType::GetTypeCode(cx, obj) == TYPE_struct);
 
   FieldInfoHash::Ptr ptr = GetFieldInfo(cx, obj)->lookup(name);
   if (ptr)
     return &ptr->value;
 
-  const char* bytes = JS_GetStringBytesZ(cx, name);
+  JSAutoByteString bytes(cx, name);
   if (!bytes)
     return NULL;
 
-  JS_ReportError(cx, "%s does not name a field", bytes);
+  JS_ReportError(cx, "%s does not name a field", bytes.ptr());
   return NULL;
 }
 
 JSObject*
 StructType::BuildFieldsArray(JSContext* cx, JSObject* obj)
 {
   JS_ASSERT(CType::IsCType(cx, obj));
   JS_ASSERT(CType::GetTypeCode(cx, obj) == TYPE_struct);
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -169,18 +169,21 @@ class JSAPITest
 
     bool evaluate(const char *bytes, const char *filename, int lineno, jsval *vp) {
         return JS_EvaluateScript(cx, global, bytes, strlen(bytes), filename, lineno, vp) ||
                fail(bytes, filename, lineno);
     }
 
     JSAPITestString toSource(jsval v) {
         JSString *str = JS_ValueToSource(cx, v);
-        if (str)
-            return JSAPITestString(JS_GetStringBytes(str));
+        if (str) {
+            JSAutoByteString bytes(cx, str);
+            if (!!bytes)
+                return JSAPITestString(bytes.ptr());
+        }
         JS_ClearPendingException(cx);
         return JSAPITestString("<<error converting value to string>>");
     }
 
 #define CHECK_SAME(actual, expected) \
     do { \
         if (!checkSame(actual, expected, #actual, #expected, __FILE__, __LINE__)) \
             return false; \
@@ -202,18 +205,21 @@ class JSAPITest
     } while (false)
 
     bool fail(JSAPITestString msg = JSAPITestString(), const char *filename = "-", int lineno = 0) {
         if (JS_IsExceptionPending(cx)) {
             jsvalRoot v(cx);
             JS_GetPendingException(cx, v.addr());
             JS_ClearPendingException(cx);
             JSString *s = JS_ValueToString(cx, v);
-            if (s)
-                msg += JS_GetStringBytes(s);
+            if (s) {
+                JSAutoByteString bytes(cx, s);
+                if (!!bytes)
+                    msg += bytes.ptr();
+            }
         }
         fprintf(stderr, "%s:%d:%.*s\n", filename, lineno, (int) msg.length(), msg.begin());
         msgs += msg;
         return false;
     }
 
     JSAPITestString messages() const { return msgs; }
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -248,20 +248,21 @@ JS_ConvertArgumentsVA(JSContext *cx, uin
             continue;
         }
         if (sp == argv + argc) {
             if (required) {
                 fun = js_ValueToFunction(cx, Valueify(&argv[-2]), 0);
                 if (fun) {
                     char numBuf[12];
                     JS_snprintf(numBuf, sizeof numBuf, "%u", argc);
-                    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                         JSMSG_MORE_ARGS_NEEDED,
-                                         JS_GetFunctionName(fun), numBuf,
-                                         (argc == 1) ? "" : "s");
+                    JSAutoByteString funNameBytes;
+                    if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
+                        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
+                                             name, numBuf, (argc == 1) ? "" : "s");
+                    }
                 }
                 return JS_FALSE;
             }
             break;
         }
         switch (c) {
           case 'b':
             *va_arg(ap, JSBool *) = js_ValueToBoolean(Valueify(*sp));
@@ -5003,18 +5004,21 @@ JS_New(JSContext *cx, JSObject *ctor, ui
     if (ok) {
         if (args.rval().isObject()) {
             obj = &args.rval().toObject();
         } else {
             /*
              * Although constructors may return primitives (via proxies), this
              * API is asking for an object, so we report an error.
              */
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_NEW_RESULT,
-                                 js_ValueToPrintableString(cx, args.rval()));
+            JSAutoByteString bytes;
+            if (js_ValueToPrintable(cx, args.rval(), &bytes)) {
+                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_NEW_RESULT,
+                                     bytes.ptr());
+            }
         }
     }
 
     LAST_FRAME_CHECKS(cx, ok);
     return obj;
 }
 
 JS_PUBLIC_API(JSOperationCallback)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2913,16 +2913,66 @@ JS_DecodeBytes(JSContext *cx, const char
 
 /*
  * A variation on JS_EncodeCharacters where a null terminated string is
  * returned that you are expected to call JS_free on when done.
  */
 JS_PUBLIC_API(char *)
 JS_EncodeString(JSContext *cx, JSString *str);
 
+#ifdef __cplusplus
+
+class JSAutoByteString {
+  public:
+    JSAutoByteString(JSContext *cx, JSString *str JS_GUARD_OBJECT_NOTIFIER_PARAM)
+      : mBytes(JS_EncodeString(cx, str)) {
+        JS_ASSERT(cx);
+        JS_GUARD_OBJECT_NOTIFIER_INIT;
+    }
+
+    JSAutoByteString(JS_GUARD_OBJECT_NOTIFIER_PARAM0)
+      : mBytes(NULL) {
+        JS_GUARD_OBJECT_NOTIFIER_INIT;
+    }
+
+    ~JSAutoByteString() {
+        js_free(mBytes);
+    }
+
+    char *encode(JSContext *cx, JSString *str) {
+        JS_ASSERT(!mBytes);
+        JS_ASSERT(cx);
+        mBytes = JS_EncodeString(cx, str);
+        return mBytes;
+    }
+
+    void clear() {
+        js_free(mBytes);
+        mBytes = NULL;
+    }
+
+    char *ptr() const {
+        return mBytes;
+    }
+
+    bool operator!() const {
+        return !mBytes;
+    }
+
+  private:
+    char        *mBytes;
+    JS_DECL_USE_GUARD_OBJECT_NOTIFIER
+
+    /* Copy and assignment are not supported. */
+    JSAutoByteString(const JSAutoByteString &another);
+    JSAutoByteString &operator=(const JSAutoByteString &another);
+};
+
+#endif
+
 /************************************************************************/
 /*
  * JSON functions
  */
 typedef JSBool (* JSONWriteCallback)(const jschar *buf, uint32 len, void *data);
 
 /*
  * JSON.stringify as specified by ES3.1 (draft)
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -85,19 +85,19 @@ JS_STATIC_ASSERT(ATOM_OFFSET_LIMIT % siz
  * index 1 and type name starts from the index 1+2 atoms in JSAtomState.
  */
 JS_STATIC_ASSERT(1 * sizeof(JSAtom *) ==
                  offsetof(JSAtomState, booleanAtoms) - ATOM_OFFSET_START);
 JS_STATIC_ASSERT((1 + 2) * sizeof(JSAtom *) ==
                  offsetof(JSAtomState, typeAtoms) - ATOM_OFFSET_START);
 
 const char *
-js_AtomToPrintableString(JSContext *cx, JSAtom *atom)
+js_AtomToPrintableString(JSContext *cx, JSAtom *atom, JSAutoByteString *bytes)
 {
-    return js_ValueToPrintableString(cx, StringValue(ATOM_TO_STRING(atom)));
+    return js_ValueToPrintable(cx, StringValue(ATOM_TO_STRING(atom)), bytes);
 }
 
 #define JS_PROTO(name,code,init) const char js_##name##_str[] = #name;
 #include "jsproto.tbl"
 #undef JS_PROTO
 
 /*
  * String constants for common atoms defined in JSAtomState starting from
--- a/js/src/jsatom.h
+++ b/js/src/jsatom.h
@@ -128,21 +128,20 @@ IdToJsval(jsid id)
 # define ATOM_HASH(atom)          (((JSHashNumber)(jsuword)(atom) >> 3) ^     \
                                    (JSHashNumber)((jsuword)(atom) >> 32))
 #else
 # error "Unsupported configuration"
 #endif
 
 /*
  * Return a printable, lossless char[] representation of a string-type atom.
- * The lifetime of the result extends at least until the next GC activation,
- * longer if cx's string newborn root is not overwritten.
+ * The lifetime of the result matches the lifetime of bytes.
  */
 extern const char *
-js_AtomToPrintableString(JSContext *cx, JSAtom *atom);
+js_AtomToPrintableString(JSContext *cx, JSAtom *atom, JSAutoByteString *bytes);
 
 struct JSAtomListElement {
     JSHashEntry         entry;
 };
 
 #define ALE_ATOM(ale)   ((JSAtom *) (ale)->entry.key)
 #define ALE_INDEX(ale)  (jsatomid(uintptr_t((ale)->entry.value)))
 #define ALE_VALUE(ale)  ((jsboxedword) (ale)->entry.value)
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -2294,31 +2294,28 @@ static JSBool
 date_toLocaleTimeString(JSContext *cx, uintN argc, Value *vp)
 {
     return date_toLocaleHelper(cx, "%X", vp);
 }
 
 static JSBool
 date_toLocaleFormat(JSContext *cx, uintN argc, Value *vp)
 {
-    JSString *fmt;
-    const char *fmtbytes;
-
     if (argc == 0)
         return date_toLocaleString(cx, argc, vp);
 
-    fmt = js_ValueToString(cx, vp[2]);
+    JSString *fmt = js_ValueToString(cx, vp[2]);
     if (!fmt)
         return JS_FALSE;
     vp[2].setString(fmt);
-    fmtbytes = js_GetStringBytes(cx, fmt);
+    JSAutoByteString fmtbytes(cx, fmt);
     if (!fmtbytes)
         return JS_FALSE;
 
-    return date_toLocaleHelper(cx, fmtbytes, vp);
+    return date_toLocaleHelper(cx, fmtbytes.ptr(), vp);
 }
 
 static JSBool
 date_toTimeString(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble utctime;
 
     if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &utctime))
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -693,22 +693,16 @@ StackTraceToString(JSContext *cx, JSExnP
 /* XXXbe Consolidate the ugly truth that we don't treat filename as UTF-8
          with these two functions. */
 static JSString *
 FilenameToString(JSContext *cx, const char *filename)
 {
     return JS_NewStringCopyZ(cx, filename);
 }
 
-static const char *
-StringToFilename(JSContext *cx, JSString *str)
-{
-    return js_GetStringBytes(cx, str);
-}
-
 static JSBool
 Exception(JSContext *cx, uintN argc, Value *vp)
 {
     JSString *message, *filename;
     JSStackFrame *fp;
 
     /*
      * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when
@@ -1242,54 +1236,52 @@ js_ReportUncaughtException(JSContext *cx
         roots[0] = exn;
     }
 
     JS_ClearPendingException(cx);
     reportp = js_ErrorFromException(cx, exn);
 
     /* XXX L10N angels cry once again (see also jsemit.c, /L10N gaffes/) */
     str = js_ValueToString(cx, Valueify(exn));
+    JSAutoByteString bytesStorage;
     if (!str) {
         bytes = "unknown (can't convert to string)";
     } else {
         roots[1] = STRING_TO_JSVAL(str);
-        bytes = js_GetStringBytes(cx, str);
-        if (!bytes)
+        if (!bytesStorage.encode(cx, str))
             return false;
+        bytes = bytesStorage.ptr();
     }
 
+    JSAutoByteString filename;
     if (!reportp && exnObject && exnObject->getClass() == &js_ErrorClass) {
-        const char *filename;
-
         if (!JS_GetProperty(cx, exnObject, js_message_str, &roots[2]))
             return false;
         if (JSVAL_IS_STRING(roots[2])) {
-            bytes = js_GetStringBytes(cx, JSVAL_TO_STRING(roots[2]));
-            if (!bytes)
+            bytesStorage.clear();
+            if (!bytesStorage.encode(cx, str))
                 return false;
+            bytes = bytesStorage.ptr();
         }
 
         if (!JS_GetProperty(cx, exnObject, js_fileName_str, &roots[3]))
             return false;
         str = js_ValueToString(cx, Valueify(roots[3]));
-        if (!str)
-            return false;
-        filename = StringToFilename(cx, str);
-        if (!filename)
+        if (!str || !filename.encode(cx, str))
             return false;
 
         if (!JS_GetProperty(cx, exnObject, js_lineNumber_str, &roots[4]))
             return false;
         uint32_t lineno;
-        if (!ValueToECMAUint32 (cx, Valueify(roots[4]), &lineno))
+        if (!ValueToECMAUint32(cx, Valueify(roots[4]), &lineno))
             return false;
 
         reportp = &report;
         PodZero(&report);
-        report.filename = filename;
+        report.filename = filename.ptr();
         report.lineno = (uintN) lineno;
         if (JSVAL_IS_STRING(roots[2])) {
             report.ucmessage = js_GetStringChars(cx, JSVAL_TO_STRING(roots[2]));
             if (!report.ucmessage)
                 return false;
         }
     }
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1801,25 +1801,27 @@ js_XDRFunctionObject(JSXDRState *xdr, JS
     uintN nargs, nvars, nupvars, n;
     uint32 localsword;          /* word for argument and variable counts */
     uint32 flagsword;           /* word for fun->u.i.nupvars and fun->flags */
 
     cx = xdr->cx;
     if (xdr->mode == JSXDR_ENCODE) {
         fun = GET_FUNCTION_PRIVATE(cx, *objp);
         if (!FUN_INTERPRETED(fun)) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                 JSMSG_NOT_SCRIPTED_FUNCTION,
-                                 JS_GetFunctionName(fun));
+            JSAutoByteString funNameBytes;
+            if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
+                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_SCRIPTED_FUNCTION,
+                                     name);
+            }
             return false;
         }
         if (fun->u.i.wrapper) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                 JSMSG_XDR_CLOSURE_WRAPPER,
-                                 JS_GetFunctionName(fun));
+            JSAutoByteString funNameBytes;
+            if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes))
+                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_XDR_CLOSURE_WRAPPER, name);
             return false;
         }
         JS_ASSERT((fun->u.i.wrapper & ~1U) == 0);
         firstword = (fun->u.i.skipmin << 2) | (fun->u.i.wrapper << 1) | !!fun->atom;
         nargs = fun->nargs;
         nvars = fun->u.i.nvars;
         nupvars = fun->u.i.nupvars;
         localsword = (nargs << 16) | nvars;
@@ -2183,23 +2185,22 @@ js_fun_call(JSContext *cx, uintN argc, V
     JSObject *obj = ComputeThisFromVp(cx, vp);
     if (!obj)
         return JS_FALSE;
     Value fval = vp[1];
 
     if (!js_IsCallable(fval)) {
         JSString *str = js_ValueToString(cx, fval);
         if (str) {
-            const char *bytes = js_GetStringBytes(cx, str);
-
-            if (bytes) {
+            JSAutoByteString bytes(cx, str);
+            if (!!bytes) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                      JSMSG_INCOMPATIBLE_PROTO,
                                      js_Function_str, js_call_str,
-                                     bytes);
+                                     bytes.ptr());
             }
         }
         return JS_FALSE;
     }
 
     Value *argv = vp + 2;
     Value thisv;
     if (argc == 0) {
@@ -2233,21 +2234,22 @@ js_fun_apply(JSContext *cx, uintN argc, 
     JSObject *obj = ComputeThisFromVp(cx, vp);
     if (!obj)
         return false;
 
     /* Step 1. */
     Value fval = vp[1];
     if (!js_IsCallable(fval)) {
         if (JSString *str = js_ValueToString(cx, fval)) {
-            if (const char *bytes = js_GetStringBytes(cx, str)) {
+            JSAutoByteString bytes(cx, str);
+            if (!!bytes) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                      JSMSG_INCOMPATIBLE_PROTO,
                                      js_Function_str, js_apply_str,
-                                     bytes);
+                                     bytes.ptr());
             }
         }
         return false;
     }
 
     /* Step 2. */
     if (argc < 2 || vp[3].isNullOrUndefined())
         return js_fun_call(cx, (argc > 0) ? 1 : 0, vp);
@@ -2409,20 +2411,21 @@ fun_bind(JSContext *cx, uintN argc, Valu
     /* Step 1. */
     JSObject *target = ComputeThisFromVp(cx, vp);
     if (!target)
         return false;
 
     /* Step 2. */
     if (!target->isCallable()) {
         if (JSString *str = js_ValueToString(cx, vp[1])) {
-            if (const char *bytes = js_GetStringBytes(cx, str)) {
+            JSAutoByteString bytes(cx, str);
+            if (!!bytes) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                      JSMSG_INCOMPATIBLE_PROTO,
-                                     js_Function_str, "bind", bytes);
+                                     js_Function_str, "bind", bytes.ptr());
             }
         }
         return false;
     }
 
     /* Step 3. */
     Value *args = NULL;
     uintN argslen = 0;
@@ -2631,22 +2634,24 @@ Function(JSContext *cx, uintN argc, Valu
                  * Get the atom corresponding to the name from the token
                  * stream; we're assured at this point that it's a valid
                  * identifier.
                  */
                 JSAtom *atom = ts.currentToken().t_atom;
 
                 /* Check for a duplicate parameter name. */
                 if (fun->lookupLocal(cx, atom, NULL) != JSLOCAL_NONE) {
-                    const char *name;
-
-                    name = js_AtomToPrintableString(cx, atom);
-                    if (!name && ReportCompileErrorNumber(cx, &ts, NULL,
-                                                          JSREPORT_WARNING | JSREPORT_STRICT,
-                                                          JSMSG_DUPLICATE_FORMAL, name)) {
+                    JSAutoByteString name;
+                    if (!js_AtomToPrintableString(cx, atom, &name)) {
+                        state = BAD;
+                        goto after_args;
+                    }
+                    if (!ReportCompileErrorNumber(cx, &ts, NULL,
+                                                  JSREPORT_WARNING | JSREPORT_STRICT,
+                                                  JSMSG_DUPLICATE_FORMAL, name.ptr())) {
                         goto after_args;
                     }
                 }
                 if (!fun->addLocal(cx, atom, JSLOCAL_ARG))
                     goto after_args;
 
                 /*
                  * Get the next token.  Stop on end of stream.  Otherwise
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -484,16 +484,24 @@ IsConstructing_PossiblyWithGivenThisObje
     }
 #endif
     bool isCtor = vp[1].isMagic();
     if (isCtor)
         *ctorThis = vp[1].getMagicObjectOrNullPayload();
     return isCtor;
 }
 
+inline const char *
+GetFunctionNameBytes(JSContext *cx, JSFunction *fun, JSAutoByteString *bytes)
+{
+    if (fun->atom)
+        return bytes->encode(cx, ATOM_TO_STRING(fun->atom));
+    return js_anonymous_str;
+}
+
 } /* namespace js */
 
 extern JSString *
 fun_toStringHelper(JSContext *cx, JSObject *obj, uintN indent);
 
 extern JSFunction *
 js_NewFunction(JSContext *cx, JSObject *funobj, js::Native native, uintN nargs,
                uintN flags, JSObject *parent, JSAtom *atom);
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -494,20 +494,21 @@ ReportIncompatibleMethod(JSContext *cx, 
                            ? "number"
                            : thisv.isBoolean()
                            ? "boolean"
                            : thisv.isNull()
                            ? js_null_str
                            : thisv.isUndefined()
                            ? js_undefined_str
                            : "value";
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                             JSMSG_INCOMPATIBLE_PROTO,
-                             clasp->name, JS_GetFunctionName(fun),
-                             name);
+        JSAutoByteString funNameBytes;
+        if (const char *funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
+                                 clasp->name, funName, name);
+        }
     }
 }
 
 bool
 ComputeThisFromArgv(JSContext *cx, Value *argv)
 {
     /*
      * Check for SynthesizeFrame poisoning and fast constructors which
@@ -1108,17 +1109,18 @@ CheckRedeclaration(JSContext *cx, JSObje
            ? js_getter_str
            : (oldAttrs & attrs & JSPROP_SETTER)
            ? js_setter_str
            : (oldAttrs & JSPROP_READONLY)
            ? js_const_str
            : isFunction
            ? js_function_str
            : js_var_str;
-    name = js_ValueToPrintableString(cx, IdToValue(id));
+    JSAutoByteString bytes;
+    name = js_ValueToPrintable(cx, IdToValue(id), &bytes);
     if (!name)
         return JS_FALSE;
     return !!JS_ReportErrorFlagsAndNumber(cx, report,
                                           js_GetErrorMessage, NULL,
                                           JSMSG_REDECLARED_VAR,
                                           type, name);
 }
 
@@ -1213,22 +1215,22 @@ TypeOfValue(JSContext *cx, const Value &
 
 bool
 InstanceOfSlow(JSContext *cx, JSObject *obj, Class *clasp, Value *argv)
 {
     JS_ASSERT(!obj || obj->getClass() != clasp);
     if (argv) {
         JSFunction *fun = js_ValueToFunction(cx, &argv[-2], 0);
         if (fun) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                 JSMSG_INCOMPATIBLE_PROTO,
-                                 clasp->name, JS_GetFunctionName(fun),
-                                 obj
-                                 ? obj->getClass()->name
-                                 : js_null_str);
+            JSAutoByteString funNameBytes;
+            if (const char *funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
+                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
+                                     clasp->name, funName,
+                                     obj ? obj->getClass()->name : js_null_str);
+            }
         }
     }
     return false;
 }
 
 JS_REQUIRES_STACK bool
 InvokeConstructor(JSContext *cx, const CallArgs &argsRef)
 {
@@ -1264,20 +1266,22 @@ InvokeConstructor(JSContext *cx, const C
     }
 
     if (!Invoke(cx, args, JSINVOKE_CONSTRUCT))
         return false;
 
     if (args.rval().isPrimitive()) {
         if (clasp != &js_FunctionClass) {
             /* native [[Construct]] returning primitive is error */
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                 JSMSG_BAD_NEW_RESULT,
-                                 js_ValueToPrintableString(cx, args.rval()));
-            return false;
+            JSAutoByteString bytes;
+            if (js_ValueToPrintable(cx, args.rval(), &bytes)) {
+                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+                                     JSMSG_BAD_NEW_RESULT, bytes.ptr());
+                return false;
+            }
         }
 
         /* The interpreter fixes rval for us. */
         JS_ASSERT(!fun->isInterpreted());
 
         args.rval() = args.thisv();
     }
 
@@ -6964,23 +6968,21 @@ END_CASE(JSOP_ARRAYPUSH)
 #endif
 
     JS_ASSERT_IF(!regs.fp->isGeneratorFrame(), !js_IsActiveWithOrBlock(cx, &regs.fp->scopeChain(), 0));
 
     return interpReturnOK;
 
   atom_not_defined:
     {
-        const char *printable;
-
-        printable = js_AtomToPrintableString(cx, atomNotDefined);
-        if (printable)
-            js_ReportIsNotDefined(cx, printable);
-        goto error;
-    }
+        JSAutoByteString printable;
+        if (js_AtomToPrintableString(cx, atomNotDefined, &printable))
+            js_ReportIsNotDefined(cx, printable.ptr());
+    }
+    goto error;
 
     /*
      * This path is used when it's guaranteed the method can be finished
      * inside the JIT.
      */
 #if defined(JS_TRACER) && defined(JS_METHODJIT)
   leave_on_safe_point:
 #endif
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -412,19 +412,21 @@ GetCustomIterator(JSContext *cx, JSObjec
     Value arg = BooleanValue((flags & JSITER_FOREACH) == 0);
     if (!ExternalInvoke(cx, obj, *vp, 1, &arg, vp))
         return false;
     if (vp->isPrimitive()) {
         /*
          * We are always coming from js_ValueToIterator, and we are no longer on
          * trace, so the object we are iterating over is on top of the stack (-1).
          */
+        JSAutoByteString bytes;
+        if (!js_AtomToPrintableString(cx, atom, &bytes))
+            return false;
         js_ReportValueError2(cx, JSMSG_BAD_TRAP_RETURN_VALUE,
-                             -1, ObjectValue(*obj), NULL,
-                             js_AtomToPrintableString(cx, atom));
+                             -1, ObjectValue(*obj), NULL, bytes.ptr());
         return false;
     }
     return true;
 }
 
 template <typename T>
 static inline bool
 Compare(T *a, T *b, size_t c)
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -726,17 +726,20 @@ num_toLocaleString(JSContext *cx, uintN 
 
     /*
      * Create the string, move back to bytes to make string twiddling
      * a bit easier and so we can insert platform charset seperators.
      */
     if (!num_toString(cx, 0, vp))
         return JS_FALSE;
     JS_ASSERT(vp->isString());
-    num = js_GetStringBytes(cx, vp->toString());
+    JSAutoByteString numBytes(cx, vp->toString());
+    if (!numBytes)
+        return JS_FALSE;
+    num = numBytes.ptr();
     if (!num)
         return JS_FALSE;
 
     /*
      * Find the first non-integer value, whether it be a letter as in
      * 'Infinity', a decimal point, or an 'e' from exponential notation.
      */
     nint = num;
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -908,28 +908,27 @@ js_CheckContentSecurityPolicy(JSContext 
  * the JS API, which does not require principals), and false otherwise.
  */
 JSBool
 js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj,
                          JSPrincipals *principals, JSAtom *caller)
 {
     JSSecurityCallbacks *callbacks;
     JSPrincipals *scopePrincipals;
-    const char *callerstr;
 
     callbacks = JS_GetSecurityCallbacks(cx);
     if (callbacks && callbacks->findObjectPrincipals) {
         scopePrincipals = callbacks->findObjectPrincipals(cx, scopeobj);
         if (!principals || !scopePrincipals ||
             !principals->subsume(principals, scopePrincipals)) {
-            callerstr = js_AtomToPrintableString(cx, caller);
-            if (!callerstr)
+            JSAutoByteString callerstr;
+            if (!js_AtomToPrintableString(cx, caller, &callerstr))
                 return JS_FALSE;
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                 JSMSG_BAD_INDIRECT_CALL, callerstr);
+                                 JSMSG_BAD_INDIRECT_CALL, callerstr.ptr());
             return JS_FALSE;
         }
     }
     return JS_TRUE;
 }
 
 static bool
 CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj)
@@ -1944,18 +1943,20 @@ PropDesc::initialize(JSContext* cx, jsid
 
 static JSBool
 Reject(JSContext *cx, uintN errorNumber, bool throwError, jsid id, bool *rval)
 {
     if (throwError) {
         jsid idstr;
         if (!js_ValueToStringId(cx, IdToValue(id), &idstr))
            return JS_FALSE;
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, errorNumber,
-                             JS_GetStringBytes(JSID_TO_STRING(idstr)));
+        JSAutoByteString bytes(cx, JSID_TO_STRING(idstr));
+        if (!bytes)
+            return JS_FALSE;
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, errorNumber, bytes.ptr());
         return JS_FALSE;
     }
 
     *rval = false;
     return JS_TRUE;
 }
 
 static JSBool
@@ -5138,23 +5139,23 @@ js_CheckUndeclaredVarAssignment(JSContex
         return true;
 
     /* If neither cx nor the code is strict, then no check is needed. */
     if (!(fp->isScriptFrame() && fp->script()->strictModeCode) &&
         !JS_HAS_STRICT_OPTION(cx)) {
         return true;
     }
 
-    const char *bytes = js_GetStringBytes(cx, propname);
-    return bytes &&
+    JSAutoByteString bytes(cx, propname);
+    return !!bytes &&
            JS_ReportErrorFlagsAndNumber(cx,
                                         (JSREPORT_WARNING | JSREPORT_STRICT
                                          | JSREPORT_STRICT_MODE_ERROR),
                                         js_GetErrorMessage, NULL,
-                                        JSMSG_UNDECLARED_VAR, bytes);
+                                        JSMSG_UNDECLARED_VAR, bytes.ptr());
 }
 
 bool
 JSObject::reportReadOnly(JSContext* cx, jsid id, uintN report)
 {
     return js_ReportValueErrorFlags(cx, report, JSMSG_READ_ONLY,
                                     JSDVG_IGNORE_STACK, IdToValue(id), NULL,
                                     NULL, NULL);
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -284,81 +284,80 @@ js_DumpPC(JSContext *cx)
 }
 
 JSBool
 js_DumpScript(JSContext *cx, JSScript *script)
 {
     return js_Disassemble(cx, script, true, stdout);
 }
 
-const char *
-ToDisassemblySource(JSContext *cx, jsval v)
+static bool
+ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes)
 {
     if (!JSVAL_IS_PRIMITIVE(v)) {
         JSObject *obj = JSVAL_TO_OBJECT(v);
         Class *clasp = obj->getClass();
 
         if (clasp == &js_BlockClass) {
             char *source = JS_sprintf_append(NULL, "depth %d {", OBJ_BLOCK_DEPTH(cx, obj));
 
             Shape::Range r = obj->lastProperty()->all();
             while (!r.empty()) {
                 const Shape &shape = r.front();
-                const char *bytes = js_AtomToPrintableString(cx, JSID_TO_ATOM(shape.id));
-                if (!bytes)
+                JSAutoByteString bytes;
+                if (!js_AtomToPrintableString(cx, JSID_TO_ATOM(shape.id), &bytes))
                     return NULL;
 
                 r.popFront();
                 source = JS_sprintf_append(source, "%s: %d%s",
-                                           bytes, shape.shortid,
+                                           bytes.ptr(), shape.shortid,
                                            !r.empty() ? ", " : "");
             }
 
             source = JS_sprintf_append(source, "}");
             if (!source)
                 return NULL;
 
             JSString *str = JS_NewString(cx, source, strlen(source));
             if (!str)
                 return NULL;
-            return js_GetStringBytes(cx, str);
+            return bytes->encode(cx, str);
         }
 
         if (clasp == &js_FunctionClass) {
             JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
             JSString *str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT);
             if (!str)
                 return NULL;
-            return js_GetStringBytes(cx, str);
+            return bytes->encode(cx, str);
         }
 
         if (clasp == &js_RegExpClass) {
             AutoValueRooter tvr(cx);
             if (!js_regexp_toString(cx, obj, tvr.addr()))
                 return NULL;
-            return js_GetStringBytes(cx, JSVAL_TO_STRING(Jsvalify(tvr.value())));
+            return bytes->encode(cx, JSVAL_TO_STRING(Jsvalify(tvr.value())));
         }
     }
 
-    return js_ValueToPrintableSource(cx, Valueify(v));
+    return !!js_ValueToPrintable(cx, Valueify(v), bytes, true);
 }
 
 JS_FRIEND_API(uintN)
 js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc,
                 uintN loc, JSBool lines, FILE *fp)
 {
     JSOp op;
     const JSCodeSpec *cs;
     ptrdiff_t len, off, jmplen;
     uint32 type;
     JSAtom *atom;
     uintN index;
     JSObject *obj;
     jsval v;
-    const char *bytes;
     jsint i;
 
     op = (JSOp)*pc;
     if (op >= JSOP_LIMIT) {
         char numBuf1[12], numBuf2[12];
         JS_snprintf(numBuf1, sizeof numBuf1, "%d", op);
         JS_snprintf(numBuf2, sizeof numBuf2, "%d", JSOP_LIMIT);
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
@@ -399,29 +398,33 @@ js_Disassemble1(JSContext *cx, JSScript 
             }
         } else {
             if (type == JOF_OBJECT)
                 obj = script->getObject(index);
             else
                 obj = script->getRegExp(index);
             v = OBJECT_TO_JSVAL(obj);
         }
-        bytes = ToDisassemblySource(cx, v);
-        if (!bytes)
-            return 0;
-        fprintf(fp, " %s", bytes);
+        {
+            JSAutoByteString bytes;
+            if (!ToDisassemblySource(cx, v, &bytes))
+                return 0;
+            fprintf(fp, " %s", bytes.ptr());
+        }
         break;
 
       case JOF_GLOBAL:
         atom = script->getGlobalAtom(GET_SLOTNO(pc));
         v = ATOM_TO_JSVAL(atom);
-        bytes = ToDisassemblySource(cx, v);
-        if (!bytes)
-            return 0;
-        fprintf(fp, " %s", bytes);
+        {
+            JSAutoByteString bytes;
+            if (!ToDisassemblySource(cx, v, &bytes))
+                return 0;
+            fprintf(fp, " %s", bytes.ptr());
+        }
         break;
 
       case JOF_UINT16PAIR:
         i = (jsint)GET_UINT16(pc);
         fprintf(fp, " %d", i);
         pc += UINT16_LEN;
         /* FALL THROUGH */
 
@@ -469,50 +472,52 @@ js_Disassemble1(JSContext *cx, JSScript 
         pc2 += UINT16_LEN;
         fprintf(fp, " offset %d npairs %u", (intN) off, (uintN) npairs);
         while (npairs) {
             uint16 constIndex = GET_INDEX(pc2);
             pc2 += INDEX_LEN;
             off = GetJumpOffset(pc, pc2);
             pc2 += jmplen;
 
-            bytes = ToDisassemblySource(cx, Jsvalify(script->getConst(constIndex)));
-            if (!bytes)
+            JSAutoByteString bytes;
+            if (!ToDisassemblySource(cx, Jsvalify(script->getConst(constIndex)), &bytes))
                 return 0;
-            fprintf(fp, "\n\t%s: %d", bytes, (intN) off);
+            fprintf(fp, "\n\t%s: %d", bytes.ptr(), (intN) off);
             npairs--;
         }
         len = 1 + pc2 - pc;
         break;
       }
 
       case JOF_QARG:
         fprintf(fp, " %u", GET_ARGNO(pc));
         break;
 
       case JOF_LOCAL:
         fprintf(fp, " %u", GET_SLOTNO(pc));
         break;
 
       case JOF_SLOTATOM:
-      case JOF_SLOTOBJECT:
+      case JOF_SLOTOBJECT: {
         fprintf(fp, " %u", GET_SLOTNO(pc));
         index = js_GetIndexFromBytecode(cx, script, pc, SLOTNO_LEN);
         if (type == JOF_SLOTATOM) {
             JS_GET_SCRIPT_ATOM(script, pc, index, atom);
             v = ATOM_TO_JSVAL(atom);
         } else {
             obj = script->getObject(index);
             v = OBJECT_TO_JSVAL(obj);
         }
-        bytes = ToDisassemblySource(cx, v);
-        if (!bytes)
+
+        JSAutoByteString bytes;
+        if (!ToDisassemblySource(cx, v, &bytes))
             return 0;
-        fprintf(fp, " %s", bytes);
+        fprintf(fp, " %s", bytes.ptr());
         break;
+      }
 
       case JOF_UINT24:
         JS_ASSERT(op == JSOP_UINT24 || op == JSOP_NEWARRAY);
         i = (jsint)GET_UINT24(pc);
         goto print_int;
 
       case JOF_UINT8:
         i = pc[1];
@@ -1456,20 +1461,23 @@ DecompileDestructuringLHS(SprintStack *s
         } else if (op == JSOP_SETGLOBAL) {
             atom = jp->script->getGlobalAtom(GET_SLOTNO(pc));
         } else if (IsVarSlot(jp, pc, &i)) {
             atom = GetArgOrVarAtom(jp, i);
             LOCAL_ASSERT(atom);
         } else {
             lval = GetLocal(ss, i);
         }
-        if (atom)
-            lval = js_AtomToPrintableString(cx, atom);
-        LOCAL_ASSERT(lval);
-        todo = SprintCString(&ss->sprinter, lval);
+        {
+            JSAutoByteString bytes;
+            if (atom)
+                lval = js_AtomToPrintableString(cx, atom, &bytes);
+            LOCAL_ASSERT(lval);
+            todo = SprintCString(&ss->sprinter, lval);
+        }
         if (op != JSOP_SETLOCALPOP) {
             pc += oplen;
             if (pc == endpc)
                 return pc;
             LOAD_OP_DATA(pc);
             if (op == JSOP_POPN)
                 return pc;
             LOCAL_ASSERT(op == JSOP_POP);
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -1227,26 +1227,26 @@ HasFinalReturn(JSParseNode *pn)
         return ENDS_IN_OTHER;
     }
 }
 
 static JSBool
 ReportBadReturn(JSContext *cx, JSTreeContext *tc, uintN flags, uintN errnum,
                 uintN anonerrnum)
 {
-    const char *name;
+    JSAutoByteString name;
 
     JS_ASSERT(tc->inFunction());
     if (tc->fun->atom) {
-        name = js_AtomToPrintableString(cx, tc->fun->atom);
+        if (!js_AtomToPrintableString(cx, tc->fun->atom, &name))
+            return false;
     } else {
         errnum = anonerrnum;
-        name = NULL;
-    }
-    return ReportCompileErrorNumber(cx, TS(tc->parser), NULL, flags, errnum, name);
+    }
+    return ReportCompileErrorNumber(cx, TS(tc->parser), NULL, flags, errnum, name.ptr());
 }
 
 static JSBool
 CheckFinalReturn(JSContext *cx, JSTreeContext *tc, JSParseNode *pn)
 {
     JS_ASSERT(tc->inFunction());
     return HasFinalReturn(pn) == ENDS_IN_RETURN ||
            ReportBadReturn(cx, tc, JSREPORT_WARNING | JSREPORT_STRICT,
@@ -1259,20 +1259,20 @@ CheckFinalReturn(JSContext *cx, JSTreeCo
  */
 bool
 CheckStrictAssignment(JSContext *cx, JSTreeContext *tc, JSParseNode *lhs)
 {
     if (tc->needStrictChecks() && lhs->pn_type == TOK_NAME) {
         JSAtom *atom = lhs->pn_atom;
         JSAtomState *atomState = &cx->runtime->atomState;
         if (atom == atomState->evalAtom || atom == atomState->argumentsAtom) {
-            const char *name = js_AtomToPrintableString(cx, atom);
-            if (!name ||
+            JSAutoByteString name;
+            if (!js_AtomToPrintableString(cx, atom, &name) ||
                 !ReportStrictModeError(cx, TS(tc->parser), tc, lhs, JSMSG_DEPRECATED_ASSIGN,
-                                       name)) {
+                                       name.ptr())) {
                 return false;
             }
         }
     }
     return true;
 }
 
 /*
@@ -1284,20 +1284,20 @@ CheckStrictAssignment(JSContext *cx, JST
 bool
 CheckStrictBinding(JSContext *cx, JSTreeContext *tc, JSAtom *atom, JSParseNode *pn)
 {
     if (!tc->needStrictChecks())
         return true;
 
     JSAtomState *atomState = &cx->runtime->atomState;
     if (atom == atomState->evalAtom || atom == atomState->argumentsAtom) {
-        const char *name = js_AtomToPrintableString(cx, atom);
-        if (!name)
+        JSAutoByteString name;
+        if (!js_AtomToPrintableString(cx, atom, &name))
             return false;
-        return ReportStrictModeError(cx, TS(tc->parser), tc, pn, JSMSG_BAD_BINDING, name);
+        return ReportStrictModeError(cx, TS(tc->parser), tc, pn, JSMSG_BAD_BINDING, name.ptr());
     }
     return true;
 }
 
 /*
  * In strict mode code, all formal parameter names must be distinct. If fun's
  * formals are legit given fun's strictness level, return true. Otherwise,
  * report an error and return false. Use pn for error position reporting,
@@ -1324,33 +1324,34 @@ CheckStrictFormals(JSContext *cx, JSTree
         /*
          * We have found a duplicate parameter name. If we can find the
          * JSDefinition for the argument, that will have a more accurate source
          * location.
          */
         JSDefinition *dn = ALE_DEFN(tc->decls.lookup(atom));
         if (dn->pn_op == JSOP_GETARG)
             pn = dn;
-        const char *name = js_AtomToPrintableString(cx, atom);
-        if (!name ||
-            !ReportStrictModeError(cx, TS(tc->parser), tc, pn, JSMSG_DUPLICATE_FORMAL, name)) {
+        JSAutoByteString name;
+        if (!js_AtomToPrintableString(cx, atom, &name) ||
+            !ReportStrictModeError(cx, TS(tc->parser), tc, pn, JSMSG_DUPLICATE_FORMAL,
+                                   name.ptr())) {
             return false;
         }
     }
 
     if (tc->flags & (TCF_FUN_PARAM_ARGUMENTS | TCF_FUN_PARAM_EVAL)) {
         JSAtomState *atoms = &cx->runtime->atomState;
         atom = (tc->flags & TCF_FUN_PARAM_ARGUMENTS) ? atoms->argumentsAtom : atoms->evalAtom;
 
         /* The definition's source position will be more precise. */
         JSDefinition *dn = ALE_DEFN(tc->decls.lookup(atom));
         JS_ASSERT(dn->pn_atom == atom);
-        const char *name = js_AtomToPrintableString(cx, atom);
-        if (!name ||
-            !ReportStrictModeError(cx, TS(tc->parser), tc, dn, JSMSG_BAD_BINDING, name)) {
+        JSAutoByteString name;
+        if (!js_AtomToPrintableString(cx, atom, &name) ||
+            !ReportStrictModeError(cx, TS(tc->parser), tc, dn, JSMSG_BAD_BINDING, name.ptr())) {
             return false;
         }
     }
 
     return true;
 }
 
 JSParseNode *
@@ -2883,25 +2884,25 @@ Parser::functionDef(JSAtom *funAtom, Fun
         if (JSAtomListElement *ale = tc->decls.lookup(funAtom)) {
             JSDefinition *dn = ALE_DEFN(ale);
             JSDefinition::Kind dn_kind = dn->kind();
 
             JS_ASSERT(!dn->pn_used);
             JS_ASSERT(dn->pn_defn);
 
             if (JS_HAS_STRICT_OPTION(context) || dn_kind == JSDefinition::CONST) {
-                const char *name = js_AtomToPrintableString(context, funAtom);
-                if (!name ||
+                JSAutoByteString name;
+                if (!js_AtomToPrintableString(context, funAtom, &name) ||
                     !reportErrorNumber(NULL,
                                        (dn_kind != JSDefinition::CONST)
                                        ? JSREPORT_WARNING | JSREPORT_STRICT
                                        : JSREPORT_ERROR,
                                        JSMSG_REDECLARED_VAR,
                                        JSDefinition::kindString(dn_kind),
-                                       name)) {
+                                       name.ptr())) {
                     return NULL;
                 }
             }
 
             if (topLevel) {
                 ALE_SET_DEFN(ale, pn);
                 pn->pn_defn = true;
                 pn->dn_uses = dn;               /* dn->dn_uses is now pn_link */
@@ -3372,24 +3373,24 @@ BindLet(JSContext *cx, BindData *data, J
 
     pn = data->pn;
     if (!CheckStrictBinding(cx, tc, atom, pn))
         return false;
 
     blockObj = tc->blockChain();
     ale = tc->decls.lookup(atom);
     if (ale && ALE_DEFN(ale)->pn_blockid == tc->blockid()) {
-        const char *name = js_AtomToPrintableString(cx, atom);
-        if (name) {
+        JSAutoByteString name;
+        if (js_AtomToPrintableString(cx, atom, &name)) {
             ReportCompileErrorNumber(cx, TS(tc->parser), pn,
                                      JSREPORT_ERROR, JSMSG_REDECLARED_VAR,
                                      (ale && ALE_DEFN(ale)->isConst())
                                      ? js_const_str
                                      : js_variable_str,
-                                     name);
+                                     name.ptr());
         }
         return false;
     }
 
     n = OBJ_BLOCK_COUNT(cx, blockObj);
     if (n == JS_BIT(16)) {
         ReportCompileErrorNumber(cx, TS(tc->parser), pn,
                                  JSREPORT_ERROR, data->let.overflow);
@@ -3614,52 +3615,51 @@ BindVarOrConst(JSContext *cx, BindData *
     }
 
     JSAtomListElement *ale = tc->decls.lookup(atom);
     JSOp op = data->op;
 
     if (stmt || ale) {
         JSDefinition *dn = ale ? ALE_DEFN(ale) : NULL;
         JSDefinition::Kind dn_kind = dn ? dn->kind() : JSDefinition::VAR;
-        const char *name;
 
         if (dn_kind == JSDefinition::ARG) {
-            name = js_AtomToPrintableString(cx, atom);
-            if (!name)
+            JSAutoByteString name;
+            if (!js_AtomToPrintableString(cx, atom, &name))
                 return JS_FALSE;
 
             if (op == JSOP_DEFCONST) {
                 ReportCompileErrorNumber(cx, TS(tc->parser), pn,
                                          JSREPORT_ERROR, JSMSG_REDECLARED_PARAM,
-                                         name);
+                                         name.ptr());
                 return JS_FALSE;
             }
             if (!ReportCompileErrorNumber(cx, TS(tc->parser), pn,
                                           JSREPORT_WARNING | JSREPORT_STRICT,
-                                          JSMSG_VAR_HIDES_ARG, name)) {
+                                          JSMSG_VAR_HIDES_ARG, name.ptr())) {
                 return JS_FALSE;
             }
         } else {
             bool error = (op == JSOP_DEFCONST ||
                           dn_kind == JSDefinition::CONST ||
                           (dn_kind == JSDefinition::LET &&
                            (stmt->type != STMT_CATCH || OuterLet(tc, stmt, atom))));
 
             if (JS_HAS_STRICT_OPTION(cx)
                 ? op != JSOP_DEFVAR || dn_kind != JSDefinition::VAR
                 : error) {
-                name = js_AtomToPrintableString(cx, atom);
-                if (!name ||
+                JSAutoByteString name;
+                if (!js_AtomToPrintableString(cx, atom, &name) ||
                     !ReportCompileErrorNumber(cx, TS(tc->parser), pn,
                                               !error
                                               ? JSREPORT_WARNING | JSREPORT_STRICT
                                               : JSREPORT_ERROR,
                                               JSMSG_REDECLARED_VAR,
                                               JSDefinition::kindString(dn_kind),
-                                              name)) {
+                                              name.ptr())) {
                     return JS_FALSE;
                 }
             }
         }
     }
 
     if (!ale) {
         if (!Define(pn, atom, tc))
@@ -8423,20 +8423,20 @@ Parser::primaryExpr(TokenKind tt, JSBool
                 } else {
                     JS_NOT_REACHED("bad opcode in object initializer");
                     attributesMask = 0;
                 }
 
                 JSAtomListElement *ale = seen.lookup(atom);
                 if (ale) {
                     if (ALE_INDEX(ale) & attributesMask) {
-                        const char *name = js_AtomToPrintableString(context, atom);
-                        if (!name ||
+                        JSAutoByteString name;
+                        if (!js_AtomToPrintableString(context, atom, &name) ||
                             !ReportStrictModeError(context, &tokenStream, tc, NULL,
-                                                   JSMSG_DUPLICATE_PROPERTY, name)) {
+                                                   JSMSG_DUPLICATE_PROPERTY, name.ptr())) {
                             return NULL;
                         }
                     }
                     ALE_SET_INDEX(ale, attributesMask | ALE_INDEX(ale));
                 } else {
                     ale = seen.add(tc->parser, atom);
                     if (!ale)
                         return NULL;
--- a/js/src/jsprobes.cpp
+++ b/js/src/jsprobes.cpp
@@ -119,33 +119,32 @@ jsprobes_jsvaltovoid(JSContext *cx, cons
         //return (void *)argval.toDouble();
     }
 
     return argval.toGCThing();
 }
 #endif
 
 const char *
-Probes::FunctionName(JSContext *cx, const JSFunction *fun)
+Probes::FunctionName(JSContext *cx, const JSFunction *fun, JSAutoByteString *bytes)
 {
     if (!fun)
         return nullName;
 
     JSAtom *atom = fun->atom;
     if (!atom) {
         /*
          * TODO: maybe do more work here to figure out the name of the property
          * or variable that held the anonymous function that we're calling, if anyone
          * cares; an easy workaround is to just give your anonymous functions names.
          */
         return nullName;
     }
 
-    char *name = (char *)js_GetStringBytes(cx, ATOM_TO_STRING(atom));
-    return name ? name : nullName;
+    return bytes->encode(cx, ATOM_TO_STRING(atom)) ? bytes->ptr() : nullName;
 }
 
 #ifdef INCLUDE_MOZILLA_DTRACE
 /*
  * These functions call the DTrace macros for the JavaScript USDT probes.
  * Originally this code was inlined in the JavaScript code; however since
  * a number of operations are called, these have been placed into functions
  * to reduce any negative compiler optimization effect that the addition of
--- a/js/src/jsprobes.h
+++ b/js/src/jsprobes.h
@@ -45,17 +45,17 @@
 namespace js {
 
 class Probes {
     static const char nullName[];
 
     static const char *FunctionClassname(const JSFunction *fun);
     static const char *ScriptFilename(JSScript *script);
     static int FunctionLineNumber(JSContext *cx, const JSFunction *fun);
-    static const char *FunctionName(JSContext *cx, const JSFunction *fun);
+    static const char *FunctionName(JSContext *cx, const JSFunction *fun, JSAutoByteString *bytes);
 
     static void enterJSFunImpl(JSContext *cx, JSFunction *fun, JSScript *script);
     static void handleFunctionReturn(JSContext *cx, JSFunction *fun, JSScript *script);
     static void finalizeObjectImpl(JSObject *obj);
   public:
     static bool callTrackingActive(JSContext *);
 
     static void enterJSFun(JSContext *, JSFunction *, JSScript *, int counter = 1);
--- a/js/src/jspropertycache.cpp
+++ b/js/src/jspropertycache.cpp
@@ -174,22 +174,24 @@ PropertyCache::fill(JSContext *cx, JSObj
                      * obj with a new shape and set the JSObject::BRANDED flag.
                      * Once this flag is set, any property assignment that
                      * changes the value from or to a different function object
                      * will result in shape being regenerated.
                      */
                     if (!pobj->branded()) {
                         PCMETER(brandfills++);
 #ifdef DEBUG_notme
-                        fprintf(stderr,
-                                "branding %p (%s) for funobj %p (%s), shape %lu\n",
-                                pobj, pobj->getClass()->name,
-                                JSVAL_TO_OBJECT(v),
-                                JS_GetFunctionName(GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(v))),
-                                obj->shape());
+                        JSFunction *fun = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(v));
+                        JSAutoByteString funNameBytes;
+                        if (const char *funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
+                            fprintf(stderr,
+                                    "branding %p (%s) for funobj %p (%s), shape %lu\n",
+                                    pobj, pobj->getClass()->name, JSVAL_TO_OBJECT(v), funName,
+                                    obj->shape());
+                        }
 #endif
                         if (!pobj->brand(cx))
                             return JS_NO_PROP_CACHE_FILL;
                     }
                     vword.setFunObj(*funobj);
                     break;
                 }
             }
@@ -335,20 +337,21 @@ PropertyCache::fullTest(JSContext *cx, j
     vcap = entry->vcap;
 
     if (entry->kpc != pc) {
         PCMETER(kpcmisses++);
 
         JSAtom *atom = GetAtomFromBytecode(cx, pc, op, cs);
 #ifdef DEBUG_notme
         JSScript *script = cx->fp()->getScript();
+        JSAutoByteString printable;
         fprintf(stderr,
                 "id miss for %s from %s:%u"
                 " (pc %u, kpc %u, kshape %u, shape %u)\n",
-                js_AtomToPrintableString(cx, atom),
+                js_AtomToPrintableString(cx, atom, &printable),
                 script->filename,
                 js_PCToLineNumber(cx, script, pc),
                 pc - script->code,
                 entry->kpc - script->code,
                 entry->kshape,
                 obj->shape());
                 js_Disassemble1(cx, script, pc,
                                 pc - script->code,
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -305,18 +305,19 @@ GetTrap(JSContext *cx, JSObject *handler
 
 static bool
 GetFundamentalTrap(JSContext *cx, JSObject *handler, JSAtom *atom, Value *fvalp)
 {
     if (!GetTrap(cx, handler, atom, fvalp))
         return false;
 
     if (!js_IsCallable(*fvalp)) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_FUNCTION,
-                             js_AtomToPrintableString(cx, atom));
+        JSAutoByteString bytes;
+        if (js_AtomToPrintableString(cx, atom, &bytes))
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_FUNCTION, bytes.ptr());
         return false;
     }
 
     return true;
 }
 
 static bool
 GetDerivedTrap(JSContext *cx, JSObject *handler, JSAtom *atom, Value *fvalp)
@@ -467,19 +468,21 @@ JSScriptedProxyHandler::JSScriptedProxyH
 JSScriptedProxyHandler::~JSScriptedProxyHandler()
 {
 }
 
 static bool
 ReturnedValueMustNotBePrimitive(JSContext *cx, JSObject *proxy, JSAtom *atom, const Value &v)
 {
     if (v.isPrimitive()) {
-        js_ReportValueError2(cx, JSMSG_BAD_TRAP_RETURN_VALUE,
-                             JSDVG_SEARCH_STACK, ObjectOrNullValue(proxy), NULL,
-                             js_AtomToPrintableString(cx, atom));
+        JSAutoByteString bytes;
+        if (js_AtomToPrintableString(cx, atom, &bytes)) {
+            js_ReportValueError2(cx, JSMSG_BAD_TRAP_RETURN_VALUE,
+                                 JSDVG_SEARCH_STACK, ObjectOrNullValue(proxy), NULL, bytes.ptr());
+        }
         return false;
     }
     return true;
 }
 
 static JSObject *
 GetProxyHandlerObject(JSContext *cx, JSObject *proxy)
 {
--- a/js/src/jsregexp.cpp
+++ b/js/src/jsregexp.cpp
@@ -780,19 +780,20 @@ regexp_exec_sub(JSContext *cx, JSObject 
             ok = JS_FALSE;
             goto out;
         }
         argv[0] = StringValue(str);
     } else {
         /* Need to grab input from statics. */
         str = res->getInput();
         if (!str) {
-            const char *sourceBytes = js_GetStringBytes(cx, re->getSource());
-            if (sourceBytes) {
-                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_INPUT, sourceBytes,
+            JSAutoByteString sourceBytes(cx, re->getSource());
+            if (!!sourceBytes) {
+                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_INPUT,
+                                     sourceBytes.ptr(),
                                      re->global() ? "g" : "",
                                      re->ignoreCase() ? "i" : "",
                                      re->multiline() ? "m" : "",
                                      re->sticky() ? "y" : "");
             }
             ok = false;
             goto out;
         }
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -3712,28 +3712,28 @@ js_NewStringCopyZ(JSContext *cx, const j
 }
 
 JSString *
 js_NewStringCopyZ(JSContext *cx, const char *s)
 {
     return js_NewStringCopyN(cx, s, strlen(s));
 }
 
-JS_FRIEND_API(const char *)
-js_ValueToPrintable(JSContext *cx, const Value &v, JSValueToStringFun v2sfun)
+const char *
+js_ValueToPrintable(JSContext *cx, const Value &v, JSAutoByteString *bytes, bool asSource)
 {
     JSString *str;
 
-    str = v2sfun(cx, v);
+    str = (asSource ? js_ValueToSource : js_ValueToString)(cx, v);
     if (!str)
         return NULL;
     str = js_QuoteString(cx, str, 0);
     if (!str)
         return NULL;
-    return js_GetStringBytes(cx, str);
+    return bytes->encode(cx, str);
 }
 
 JSString *
 js_ValueToString(JSContext *cx, const Value &arg)
 {
     Value v = arg;
     if (v.isObject() && !DefaultValue(cx, &v.toObject(), JSTYPE_STRING, &v))
         return NULL;
--- a/js/src/jsstr.h
+++ b/js/src/jsstr.h
@@ -939,26 +939,19 @@ extern JSString *
 js_NewStringCopyZ(JSContext *cx, const jschar *s);
 
 extern JSString *
 js_NewStringCopyZ(JSContext *cx, const char *s);
 
 /*
  * Convert a value to a printable C string.
  */
-typedef JSString *(*JSValueToStringFun)(JSContext *cx, const js::Value &v);
-
-extern JS_FRIEND_API(const char *)
-js_ValueToPrintable(JSContext *cx, const js::Value &, JSValueToStringFun v2sfun);
-
-#define js_ValueToPrintableString(cx,v) \
-    js_ValueToPrintable(cx, v, js_ValueToString)
-
-#define js_ValueToPrintableSource(cx,v) \
-    js_ValueToPrintable(cx, v, js_ValueToSource)
+extern const char *
+js_ValueToPrintable(JSContext *cx, const js::Value &,
+                    JSAutoByteString *bytes, bool asSource = false);
 
 /*
  * Convert a value to a string, returning null after reporting an error,
  * otherwise returning a new string reference.
  */
 extern JSString *
 js_ValueToString(JSContext *cx, const js::Value &v);
 
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -3436,34 +3436,39 @@ TraceRecorder::importImpl(Address addr, 
     tracker.set(p, ins);
 
 #ifdef DEBUG
     char name[64];
     JS_ASSERT(strlen(prefix) < 11);
     void* mark = NULL;
     jsuword* localNames = NULL;
     const char* funName = NULL;
+    JSAutoByteString funNameBytes;
     if (*prefix == 'a' || *prefix == 'v') {
         mark = JS_ARENA_MARK(&cx->tempPool);
         if (fp->fun()->hasLocalNames())
             localNames = fp->fun()->getLocalNameArray(cx, &cx->tempPool);
         funName = fp->fun()->atom
-                ? js_AtomToPrintableString(cx, fp->fun()->atom)
+                  ? js_AtomToPrintableString(cx, fp->fun()->atom, &funNameBytes)
                 : "<anonymous>";
     }
     if (!strcmp(prefix, "argv")) {
         if (index < fp->numFormalArgs()) {
             JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(localNames[index]);
-            JS_snprintf(name, sizeof name, "$%s.%s", funName, js_AtomToPrintableString(cx, atom));
+            JSAutoByteString atomBytes;
+            JS_snprintf(name, sizeof name, "$%s.%s", funName,
+                        js_AtomToPrintableString(cx, atom, &atomBytes));
         } else {
             JS_snprintf(name, sizeof name, "$%s.<arg%d>", funName, index);
         }
     } else if (!strcmp(prefix, "vars")) {
         JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(localNames[fp->numFormalArgs() + index]);
-        JS_snprintf(name, sizeof name, "$%s.%s", funName, js_AtomToPrintableString(cx, atom));
+        JSAutoByteString atomBytes;
+        JS_snprintf(name, sizeof name, "$%s.%s", funName,
+                    js_AtomToPrintableString(cx, atom, &atomBytes));
     } else {
         JS_snprintf(name, sizeof name, "$%s%d", prefix, index);
     }
 
     if (mark)
         JS_ARENA_RELEASE(&cx->tempPool, mark);
     w.name(ins, name);
 
@@ -10087,18 +10092,19 @@ TraceRecorder::putActivationObjects()
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_EnterFrame()
 {
     JSStackFrame* const fp = cx->fp();
 
     if (++callDepth >= MAX_CALLDEPTH)
         RETURN_STOP_A("exceeded maximum call depth");
 
+    debug_only_stmt(JSAutoByteString funBytes);
     debug_only_printf(LC_TMTracer, "EnterFrame %s, callDepth=%d\n",
-                      js_AtomToPrintableString(cx, cx->fp()->fun()->atom),
+                      js_AtomToPrintableString(cx, cx->fp()->fun()->atom, &funBytes),
                       callDepth);
     debug_only_stmt(
         if (LogController.lcbits & LC_TMRecorder) {
             js_Disassemble(cx, cx->fp()->script(), JS_TRUE, stdout);
             debug_only_print0(LC_TMTracer, "----\n");
         }
     )
     LIns* void_ins = w.immiUndefined();
@@ -10289,19 +10295,20 @@ TraceRecorder::record_JSOP_RETURN()
     /* If we inlined this function call, make the return value available to the caller code. */
     Value& rval = stackval(-1);
     JSStackFrame *fp = cx->fp();
     if (fp->isConstructing() && rval.isPrimitive()) {
         rval_ins = get(&fp->thisValue());
     } else {
         rval_ins = get(&rval);
     }
+    debug_only_stmt(JSAutoByteString funBytes);
     debug_only_printf(LC_TMTracer,
                       "returning from %s\n",
-                      js_AtomToPrintableString(cx, fp->fun()->atom));
+                      js_AtomToPrintableString(cx, fp->fun()->atom, &funBytes));
     clearCurrentFrameSlotsFromTracker(nativeFrameTracker);
 
     return ARECORD_CONTINUE;
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_JSOP_GOTO()
 {
@@ -11343,17 +11350,26 @@ TraceRecorder::callNative(uintN argc, JS
 
     CallInfo* ci = new (traceAlloc()) CallInfo();
     ci->_address = uintptr_t(fun->u.n.native);
     ci->_isPure = 0;
     ci->_storeAccSet = ACCSET_STORE_ANY;
     ci->_abi = ABI_CDECL;
     ci->_typesig = typesig;
 #ifdef DEBUG
-    ci->_name = JS_GetFunctionName(fun);
+    ci->_name = js_anonymous_str;
+    if (fun->atom) {
+        JSAutoByteString bytes(cx, ATOM_TO_STRING(fun->atom));
+        if (!!bytes) {
+            size_t n = strlen(bytes.ptr()) + 1;
+            char *buffer = new (traceAlloc()) char[n];
+            memcpy(buffer, bytes.ptr(), n);
+            ci->_name = buffer;
+        }
+    }
  #endif
 
     // Generate a JSSpecializedNative structure on the fly.
     generatedSpecializedNative.builtin = ci;
     generatedSpecializedNative.flags = FAIL_STATUS | ((mode == JSOP_NEW)
                                                         ? JSTN_CONSTRUCTOR
                                                         : JSTN_UNBOX_AFTER);
     generatedSpecializedNative.prefix = NULL;
--- a/js/src/jsutil.h
+++ b/js/src/jsutil.h
@@ -295,23 +295,26 @@ public:
             setStatementDone(&mStatementDone);
     }
 };
 
 #define JS_DECL_USE_GUARD_OBJECT_NOTIFIER \
     JSGuardObjectNotificationReceiver _mCheckNotUsedAsTemporary;
 #define JS_GUARD_OBJECT_NOTIFIER_PARAM \
     , const JSGuardObjectNotifier& _notifier = JSGuardObjectNotifier()
+#define JS_GUARD_OBJECT_NOTIFIER_PARAM0 \
+    const JSGuardObjectNotifier& _notifier = JSGuardObjectNotifier()
 #define JS_GUARD_OBJECT_NOTIFIER_INIT \
     JS_BEGIN_MACRO _mCheckNotUsedAsTemporary.Init(_notifier); JS_END_MACRO
 
 #else /* defined(DEBUG) */
 
 #define JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 #define JS_GUARD_OBJECT_NOTIFIER_PARAM
+#define JS_GUARD_OBJECT_NOTIFIER_PARAM0
 #define JS_GUARD_OBJECT_NOTIFIER_INIT JS_BEGIN_MACRO JS_END_MACRO
 
 #endif /* !defined(DEBUG) */
 
 namespace js {
 
 template <class T>
 JS_ALWAYS_INLINE static void
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -684,19 +684,21 @@ NamespaceHelper(JSContext *cx, JSObject 
         prefixval = argv[0];
         if (uri->empty()) {
             if (!JSVAL_IS_VOID(prefixval)) {
                 prefix = js_ValueToString(cx, Valueify(prefixval));
                 if (!prefix)
                     return JS_FALSE;
                 if (!prefix->empty()) {
                     Value v = StringValue(prefix);
-                    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                         JSMSG_BAD_XML_NAMESPACE,
-                                         js_ValueToPrintableString(cx, v));
+                    JSAutoByteString bytes;
+                    if (js_ValueToPrintable(cx, v, &bytes)) {
+                        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+                                             JSMSG_BAD_XML_NAMESPACE, bytes.ptr());
+                    }
                     return JS_FALSE;
                 }
             }
         } else if (JSVAL_IS_VOID(prefixval) || !js_IsXMLName(cx, prefixval)) {
             obj->setNamePrefix(JSVAL_VOID);
         } else {
             prefix = js_ValueToString(cx, Valueify(prefixval));
             if (!prefix)
@@ -1226,19 +1228,21 @@ ParseNodeToQName(Parser *parser, JSParse
                     uri = GetURI(ns);
                     break;
                 }
             }
         }
 
         if (!uri) {
             Value v = StringValue(prefix);
-            ReportCompileErrorNumber(parser->context, &parser->tokenStream, pn,
-                                     JSREPORT_ERROR, JSMSG_BAD_XML_NAMESPACE,
-                                     js_ValueToPrintableString(parser->context, v));
+            JSAutoByteString bytes;
+            if (js_ValueToPrintable(parser->context, v, &bytes)) {
+                ReportCompileErrorNumber(parser->context, &parser->tokenStream, pn,
+                                         JSREPORT_ERROR, JSMSG_BAD_XML_NAMESPACE, bytes.ptr());
+            }
             return NULL;
         }
 
         localName = js_NewStringCopyN(parser->context, colon + 1, length - (offset + 1));
         if (!localName)
             return NULL;
     } else {
         if (isAttributeName) {
@@ -1445,19 +1449,22 @@ ParseNodeToXML(Parser *parser, JSParseNo
 
             if (pn2->pn_type != TOK_XMLNAME || pn2->pn_arity != PN_NULLARY)
                 goto syntax;
 
             /* Enforce "Well-formedness constraint: Unique Att Spec". */
             for (pn3 = head; pn3 != pn2; pn3 = pn3->pn_next->pn_next) {
                 if (pn3->pn_atom == pn2->pn_atom) {
                     Value v = StringValue(ATOM_TO_STRING(pn2->pn_atom));
-                    ReportCompileErrorNumber(cx, &parser->tokenStream, pn2,
-                                             JSREPORT_ERROR, JSMSG_DUPLICATE_XML_ATTR,
-                                             js_ValueToPrintableString(cx, v));
+                    JSAutoByteString bytes;
+                    if (js_ValueToPrintable(cx, v, &bytes)) { 
+                        ReportCompileErrorNumber(cx, &parser->tokenStream, pn2,
+                                                 JSREPORT_ERROR, JSMSG_DUPLICATE_XML_ATTR,
+                                                 bytes.ptr());
+                    }
                     goto fail;
                 }
             }
 
             str = ATOM_TO_STRING(pn2->pn_atom);
             pn2 = pn2->pn_next;
             JS_ASSERT(pn2);
             if (pn2->pn_type != TOK_XMLATTR)
@@ -1539,19 +1546,22 @@ ParseNodeToXML(Parser *parser, JSParseNo
              * this time checking local name and namespace URI.
              */
             for (j = 0; j < i; j++) {
                 attrj = XMLARRAY_MEMBER(&xml->xml_attrs, j, JSXML);
                 attrjqn = attrj->name;
                 if (js_EqualStrings(GetURI(attrjqn), GetURI(qn)) &&
                     js_EqualStrings(GetLocalName(attrjqn), GetLocalName(qn))) {
                     Value v = StringValue(ATOM_TO_STRING(pn2->pn_atom));
-                    ReportCompileErrorNumber(cx, &parser->tokenStream, pn2,
-                                             JSREPORT_ERROR, JSMSG_DUPLICATE_XML_ATTR,
-                                             js_ValueToPrintableString(cx, v));
+                    JSAutoByteString bytes;
+                    if (js_ValueToPrintable(cx, v, &bytes)) {
+                        ReportCompileErrorNumber(cx, &parser->tokenStream, pn2,
+                                                 JSREPORT_ERROR, JSMSG_DUPLICATE_XML_ATTR,
+                                                 bytes.ptr());
+                    }
                     goto fail;
                 }
             }
 
             pn2 = pn2->pn_next;
             JS_ASSERT(pn2);
             JS_ASSERT(pn2->pn_type == TOK_XMLATTR);
 
@@ -1579,19 +1589,21 @@ ParseNodeToXML(Parser *parser, JSParseNo
         qn = NULL;
         if (pn->pn_type == TOK_XMLCOMMENT) {
             if (flags & XSF_IGNORE_COMMENTS)
                 goto skip_child;
             xml_class = JSXML_CLASS_COMMENT;
         } else if (pn->pn_type == TOK_XMLPI) {
             if (IS_XML(str)) {
                 Value v = StringValue(str);
-                ReportCompileErrorNumber(cx, &parser->tokenStream, pn,
-                                         JSREPORT_ERROR, JSMSG_RESERVED_ID,
-                                         js_ValueToPrintableString(cx, v));
+                JSAutoByteString bytes;
+                if (js_ValueToPrintable(cx, v, &bytes)) { 
+                    ReportCompileErrorNumber(cx, &parser->tokenStream, pn,
+                                             JSREPORT_ERROR, JSMSG_RESERVED_ID, bytes.ptr());
+                }
                 goto fail;
             }
 
             if (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS)
                 goto skip_child;
 
             qn = ParseNodeToQName(parser, pn, inScopeNSes, JS_FALSE);
             if (!qn)
@@ -2163,22 +2175,22 @@ GetNamespace(JSContext *cx, JSObject *qn
     JSObject *match, *ns;
     uint32 i, n;
     jsval argv[2];
 
     uri = GetURI(qn);
     prefix = GetPrefix(qn);
     JS_ASSERT(uri);
     if (!uri) {
-        Value v = StringValue(prefix);
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                             JSMSG_BAD_XML_NAMESPACE,
-                             prefix
-                             ? js_ValueToPrintableString(cx, v)
-                             : js_undefined_str);
+        JSAutoByteString bytes;
+        const char *s = !prefix ?
+                        js_undefined_str
+                        : js_ValueToPrintable(cx, StringValue(prefix), &bytes);
+        if (s)
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_XML_NAMESPACE, s);
         return NULL;
     }
 
     /* Look for a matching namespace in inScopeNSes, if provided. */
     match = NULL;
     if (inScopeNSes) {
         for (i = 0, n = inScopeNSes->length; i < n; i++) {
             ns = XMLARRAY_MEMBER(inScopeNSes, i, JSObject);
@@ -2904,19 +2916,19 @@ construct:
         return NULL;
 
 out:
     if (!IsFunctionQName(cx, obj, funidp))
         return NULL;
     return obj;
 
 bad:
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                         JSMSG_BAD_XML_NAME,
-                         js_ValueToPrintableString(cx, StringValue(name)));
+    JSAutoByteString bytes;
+    if (js_ValueToPrintable(cx, StringValue(name), &bytes))
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_XML_NAME, bytes.ptr());
     return NULL;
 }
 
 /* ECMA-357 9.1.1.13 XML [[AddInScopeNamespace]]. */
 static JSBool
 AddInScopeNamespace(JSContext *cx, JSXML *xml, JSObject *ns)
 {
     JSString *prefix, *prefix2;
@@ -4459,19 +4471,21 @@ PutProperty(JSContext *cx, JSObject *obj
         }
     }
 
 out:
     js_LeaveLocalRootScope(cx);
     return ok;
 
 type_error:
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                         JSMSG_BAD_XMLLIST_PUT,
-                         js_ValueToPrintableString(cx, IdToValue(id)));
+    {
+        JSAutoByteString bytes;
+        if (js_ValueToPrintable(cx, IdToValue(id), &bytes))
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_XMLLIST_PUT, bytes.ptr());
+    }
 bad:
     ok = JS_FALSE;
     goto out;
 }
 
 /* ECMA-357 9.1.1.10 XML [[ResolveValue]], 9.2.1.10 XMLList [[ResolveValue]]. */
 static JSBool
 ResolveValue(JSContext *cx, JSXML *list, JSXML **result)
@@ -5161,19 +5175,21 @@ StartNonListXMLMethod(JSContext *cx, jsv
                 return NULL;
             vp[1] = OBJECT_TO_JSVAL(*objp);
             return xml;
         }
     }
 
     fun = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(*vp));
     JS_snprintf(numBuf, sizeof numBuf, "%u", xml->xml_kids.length);
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                         JSMSG_NON_LIST_XML_METHOD,
-                         JS_GetFunctionName(fun), numBuf);
+    JSAutoByteString funNameBytes;
+    if (const char *funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NON_LIST_XML_METHOD,
+                             funName, numBuf);
+    }
     return NULL;
 }
 
 /* Beware: these two are not bracketed by JS_BEGIN/END_MACRO. */
 #define XML_METHOD_PROLOG                                                     \
     JSObject *obj = JS_THIS_OBJECT(cx, vp);                                   \
     JSXML *xml = (JSXML *)GetInstancePrivate(cx, obj, &js_XMLClass, Valueify(vp+2)); \
     if (!xml)                                                                 \
@@ -7370,17 +7386,16 @@ js_FindXMLProperty(JSContext *cx, const 
     JSObject *nameobj;
     jsval v;
     JSObject *qn;
     jsid funid;
     JSObject *obj, *target, *proto, *pobj;
     JSXML *xml;
     JSBool found;
     JSProperty *prop;
-    const char *printable;
 
     JS_ASSERT(nameval.isObject());
     nameobj = &nameval.toObject();
     if (nameobj->getClass() == &js_AnyNameClass) {
         v = ATOM_TO_JSVAL(cx->runtime->atomState.starAtom);
         nameobj = js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 1,
                                      Valueify(&v));
         if (!nameobj)
@@ -7424,21 +7439,20 @@ js_FindXMLProperty(JSContext *cx, const 
             if (prop) {
                 *idp = funid;
                 *objp = target;
                 return JS_TRUE;
             }
         }
     } while ((obj = obj->getParent()) != NULL);
 
-    printable = js_ValueToPrintableString(cx, ObjectValue(*nameobj));
-    if (printable) {
-        JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
-                                     js_GetErrorMessage, NULL,
-                                     JSMSG_UNDEFINED_XML_NAME, printable);
+    JSAutoByteString printable;
+    if (js_ValueToPrintable(cx, ObjectValue(*nameobj), &printable)) {
+        JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
+                                     JSMSG_UNDEFINED_XML_NAME, printable.ptr());
     }
     return JS_FALSE;
 }
 
 static JSBool
 GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
     JS_ASSERT(obj->isXML());
--- a/js/src/methodjit/StubCalls-inl.h
+++ b/js/src/methodjit/StubCalls-inl.h
@@ -60,19 +60,19 @@ ValueToObject(JSContext *cx, Value *vp)
     if (vp->isObject())
         return &vp->toObject();
     return js_ValueToNonNullObject(cx, *vp);
 }
 
 static inline void
 ReportAtomNotDefined(JSContext *cx, JSAtom *atom)
 {
-    const char *printable = js_AtomToPrintableString(cx, atom);
-    if (printable)
-        js_ReportIsNotDefined(cx, printable);
+    JSAutoByteString printable;
+    if (js_AtomToPrintableString(cx, atom, &printable))
+        js_ReportIsNotDefined(cx, printable.ptr());
 }
 
 #define NATIVE_SET(cx,obj,shape,entry,vp)                                     \
     JS_BEGIN_MACRO                                                            \
         if (shape->hasDefaultSetter() &&                                      \
             (shape)->slot != SHAPE_INVALID_SLOT &&                            \
             !(obj)->brandedOrHasMethodBarrier()) {                            \
             /* Fast path for, e.g., plain Object instance properties. */      \
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sw=4 et tw=99:
  *
  * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
@@ -235,38 +235,40 @@ ReportException(JSContext *cx)
 {
     if (JS_IsExceptionPending(cx)) {
         if (!JS_ReportPendingException(cx))
             JS_ClearPendingException(cx);
     }
 }
 
 class ToString {
-public:
+  public:
     ToString(JSContext *aCx, jsval v, JSBool aThrow = JS_FALSE)
-    : cx(aCx)
-    , mThrow(aThrow)
+      : cx(aCx), mThrow(aThrow)
     {
         mStr = JS_ValueToString(cx, v);
         if (!aThrow && !mStr)
             ReportException(cx);
         JS_AddNamedStringRoot(cx, &mStr, "Value ToString helper");
     }
     ~ToString() {
         JS_RemoveStringRoot(cx, &mStr);
     }
     JSBool threw() { return !mStr; }
     jsval getJSVal() { return STRING_TO_JSVAL(mStr); }
     const char *getBytes() {
-        return mStr ? JS_GetStringBytes(mStr) : "(error converting value)";
+        if (mStr && (mBytes.ptr() || mBytes.encode(cx, mStr)))
+            return mBytes.ptr();
+        return "(error converting value)";
     }
-private:
+  private:
     JSContext *cx;
     JSString *mStr;
     JSBool mThrow;
+    JSAutoByteString mBytes;
 };
 
 class IdToString : public ToString {
 public:
     IdToString(JSContext *cx, jsid id, JSBool aThrow = JS_FALSE)
     : ToString(cx, IdToJsval(id), aThrow)
     { }
 };
@@ -543,20 +545,23 @@ Process(JSContext *cx, JSObject *obj, ch
         if (!compileOnly)
             JS_SetOptions(cx, oldopts);
 
         if (script) {
             if (!compileOnly) {
                 ok = JS_ExecuteScript(cx, obj, script, &result);
                 if (ok && !JSVAL_IS_VOID(result)) {
                     str = JS_ValueToSource(cx, result);
-                    if (str)
-                        fprintf(gOutFile, "%s\n", JS_GetStringBytes(str));
-                    else
-                        ok = JS_FALSE;
+                    ok = !!str;
+                    if (ok) {
+                        JSAutoByteString bytes(cx, str);
+                        ok = !!bytes;
+                        if (ok)
+                            fprintf(gOutFile, "%s\n", bytes.ptr());
+                    }
                 }
             }
             JS_DestroyScript(cx, script);
         }
         *buffer = '\0';
     } while (!hitEOF && !gQuitting);
 
     free(buffer);
@@ -967,31 +972,30 @@ RevertVersion(JSContext *cx, uintN argc,
     return JS_TRUE;
 }
 
 static JSBool
 Options(JSContext *cx, uintN argc, jsval *vp)
 {
     uint32 optset, flag;
     JSString *str;
-    const char *opt;
     char *names;
     JSBool found;
 
     optset = 0;
     jsval *argv = JS_ARGV(cx, vp);
     for (uintN i = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
             return JS_FALSE;
         argv[i] = STRING_TO_JSVAL(str);
-        opt = JS_GetStringBytes(str);
+        JSAutoByteString opt(cx, str);
         if (!opt)
             return JS_FALSE;
-        flag = MapContextOptionNameToFlag(cx,  opt);
+        flag = MapContextOptionNameToFlag(cx, opt.ptr());
         if (!flag)
             return JS_FALSE;
         optset |= flag;
     }
     optset = JS_ToggleOptions(cx, optset);
 
     names = NULL;
     found = JS_FALSE;
@@ -1019,36 +1023,37 @@ Options(JSContext *cx, uintN argc, jsval
     return JS_TRUE;
 }
 
 static JSBool
 Load(JSContext *cx, uintN argc, jsval *vp)
 {
     uintN i;
     JSString *str;
-    const char *filename;
     JSScript *script;
     JSBool ok;
     uint32 oldopts;
 
     JSObject *thisobj = JS_THIS_OBJECT(cx, vp);
     if (!thisobj)
         return JS_FALSE;
 
     jsval *argv = JS_ARGV(cx, vp);
     for (i = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
             return JS_FALSE;
         argv[i] = STRING_TO_JSVAL(str);
-        filename = JS_GetStringBytes(str);
+        JSAutoByteString filename(cx, str);
+        if (!filename)
+            return JS_FALSE;
         errno = 0;
         oldopts = JS_GetOptions(cx);
         JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
-        script = JS_CompileFile(cx, thisobj, filename);
+        script = JS_CompileFile(cx, thisobj, filename.ptr());
         JS_SetOptions(cx, oldopts);
         if (!script) {
             ok = JS_FALSE;
         } else {
             ok = !compileOnly
                  ? JS_ExecuteScript(cx, thisobj, script, NULL)
                  : JS_TRUE;
             JS_DestroyScript(cx, script);
@@ -1213,22 +1218,23 @@ Quit(JSContext *cx, uintN argc, jsval *v
 #ifdef JS_THREADSAFE
     if (gWorkerThreadPool)
         js::workers::terminateAll(JS_GetRuntime(cx), gWorkerThreadPool);
 #endif
     return JS_FALSE;
 }
 
 static const char *
-ToSource(JSContext *cx, jsval *vp)
+ToSource(JSContext *cx, jsval *vp, JSAutoByteString *bytes)
 {
     JSString *str = JS_ValueToSource(cx, *vp);
     if (str) {
         *vp = STRING_TO_JSVAL(str);
-        return JS_GetStringBytes(str);
+        if (bytes->encode(cx, str))
+            return bytes->ptr();
     }
     JS_ClearPendingException(cx);
     return "<<error converting value to string>>";
 }
 
 static JSBool
 AssertEq(JSContext *cx, uintN argc, jsval *vp)
 {
@@ -1240,24 +1246,28 @@ AssertEq(JSContext *cx, uintN argc, jsva
                              ? JSSMSG_INVALID_ARGS
                              : JSSMSG_TOO_MANY_ARGS,
                              "assertEq");
         return JS_FALSE;
     }
 
     jsval *argv = JS_ARGV(cx, vp);
     if (!JS_SameValue(cx, argv[0], argv[1])) {
-        const char *actual = ToSource(cx, &argv[0]);
-        const char *expected = ToSource(cx, &argv[1]);
+        JSAutoByteString bytes0, bytes1;
+        const char *actual = ToSource(cx, &argv[0], &bytes0);
+        const char *expected = ToSource(cx, &argv[1], &bytes1);
         if (argc == 2) {
             JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_ASSERT_EQ_FAILED,
                                  actual, expected);
         } else {
+            JSAutoByteString bytes2(cx, JSVAL_TO_STRING(argv[2]));
+            if (!bytes2)
+                return JS_FALSE;
             JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_ASSERT_EQ_FAILED_MSG,
-                                 actual, expected, JS_GetStringBytes(JSVAL_TO_STRING(argv[2])));
+                                 actual, expected, bytes2.ptr());
         }
         return JS_FALSE;
     }
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
@@ -1488,17 +1498,19 @@ CountHeap(JSContext *cx, uintN argc, jsv
         if (!str)
             return JS_FALSE;
         for (i = 0; ;) {
             if (JS_MatchStringAndAscii(str, traceKindNames[i].name)) {
                 traceKind = traceKindNames[i].kind;
                 break;
             }
             if (++i == JS_ARRAY_LENGTH(traceKindNames)) {
-                JS_ReportError(cx, "trace kind name '%s' is unknown", JS_GetStringBytes(str));
+                JSAutoByteString bytes(cx, str);
+                if (!!bytes)
+                    JS_ReportError(cx, "trace kind name '%s' is unknown", bytes.ptr());
                 return JS_FALSE;
             }
         }
     }
 
     JS_TRACER_INIT(&countTracer.base, cx, CountHeapNotify);
     if (!JS_DHashTableInit(&countTracer.visited, JS_DHashGetStubOps(),
                            NULL, sizeof(JSDHashEntryStub),
@@ -1899,31 +1911,24 @@ SrcNotes(JSContext *cx, JSScript *script
             index = js_GetSrcNoteOffset(sn, 0);
             JS_GET_SCRIPT_ATOM(script, NULL, index, atom);
             str = ATOM_TO_STRING(atom);
             fprintf(gOutFile, " atom %u (", index);
             JS_FileEscapedString(gOutFile, str, 0);
             putc(')', gOutFile);
             break;
           case SRC_FUNCDEF: {
-            const char *bytes;
-            JSObject *obj;
-            JSFunction *fun;
-
             index = js_GetSrcNoteOffset(sn, 0);
-            obj = script->getObject(index);
-            fun = (JSFunction *) JS_GetPrivate(cx, obj);
+            JSObject *obj = script->getObject(index);
+            JSFunction *fun = (JSFunction *) JS_GetPrivate(cx, obj);
             str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT);
-            if (str) {
-              bytes = JS_GetStringBytes(str);
-            } else {
-              ReportException(cx);
-              bytes = "N/A";
-            }
-            fprintf(gOutFile, " function %u (%s)", index, bytes);
+            JSAutoByteString bytes;
+            if (!str || !bytes.encode(cx, str))
+                ReportException(cx);
+            fprintf(gOutFile, " function %u (%s)", index, !!bytes ? bytes.ptr() : "N/A");
             break;
           }
           case SRC_SWITCH:
             fprintf(gOutFile, " length %u", (uintN) js_GetSrcNoteOffset(sn, 0));
             caseOff = (uintN) js_GetSrcNoteOffset(sn, 1);
             if (caseOff)
                 fprintf(gOutFile, " first case offset %u", caseOff);
             UpdateSwitchTableBounds(cx, script, offset,
@@ -2026,19 +2031,21 @@ DisassembleValue(JSContext *cx, jsval v,
                         return false;
 
                     JSUpvarArray *uva = fun->u.i.script->upvars();
                     uintN upvar_base = fun->countArgsAndVars();
 
                     for (uint32 i = 0, n = uva->length; i < n; i++) {
                         JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(localNames[upvar_base + i]);
                         UpvarCookie cookie = uva->vector[i];
-
-                        printf("  %s: {skip:%u, slot:%u},\n",
-                               js_AtomToPrintableString(cx, atom), cookie.level(), cookie.slot());
+                        JSAutoByteString printable;
+                        if (js_AtomToPrintableString(cx, atom, &printable)) {
+                            printf("  %s: {skip:%u, slot:%u},\n",
+                                   printable.ptr(), cookie.level(), cookie.slot());
+                        }
                     }
 
                     JS_ARENA_RELEASE(&cx->tempPool, mark);
                     putchar('}');
                 }
             }
             putchar('\n');
         }
@@ -2086,55 +2093,52 @@ Disassemble(JSContext *cx, uintN argc, j
     }
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return true;
 }
 
 static JSBool
 DisassFile(JSContext *cx, uintN argc, jsval *vp)
 {
-    JSString *str;
-    const char *filename;
-    JSScript *script;
-    JSBool ok;
-    uint32 oldopts;
     jsval *argv = JS_ARGV(cx, vp);
 
     if (!argc) {
         JS_SET_RVAL(cx, vp, JSVAL_VOID);
         return JS_TRUE;
     }
 
     JSObject *thisobj = JS_THIS_OBJECT(cx, vp);
     if (!thisobj)
         return JS_FALSE;
 
-    str = JS_ValueToString(cx, argv[0]);
+    JSString *str = JS_ValueToString(cx, argv[0]);
     if (!str)
         return JS_FALSE;
-
-    filename = JS_GetStringBytes(str);
-    oldopts = JS_GetOptions(cx);
+    JSAutoByteString filename(cx, str);
+    if (!filename)
+        return JS_FALSE;
+
+    uint32 oldopts = JS_GetOptions(cx);
     JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
-    script = JS_CompileFile(cx, thisobj, filename);
+    JSScript *script = JS_CompileFile(cx, thisobj, filename.ptr());
     JS_SetOptions(cx, oldopts);
     if (!script)
         return JS_FALSE;
 
     if (script->isEmpty()) {
         JS_SET_RVAL(cx, vp, JSVAL_VOID);
         return JS_TRUE;
     }
 
     JSObject *obj = JS_NewScriptObject(cx, script);
     if (!obj)
         return JS_FALSE;
 
     argv[0] = OBJECT_TO_JSVAL(obj); /* I like to root it, root it. */
-    ok = Disassemble(cx, 1, vp); /* gross, but works! */
+    JSBool ok = Disassemble(cx, 1, vp); /* gross, but works! */
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return ok;
 }
 
 static JSBool
 DisassWithSrc(JSContext *cx, uintN argc, jsval *vp)
 {
 #define LINE_BUF_LEN 512
@@ -2241,21 +2245,23 @@ Tracing(JSContext *cx, uintN argc, jsval
       case JSTYPE_NUMBER:
       case JSTYPE_BOOLEAN: {
         JSBool bval;
         JS_ValueToBoolean(cx, argv[0], &bval);
         file = bval ? stderr : NULL;
         break;
       }
       case JSTYPE_STRING: {
-        char *name = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
-        file = fopen(name, "w");
+        JSAutoByteString name(cx, JSVAL_TO_STRING(argv[0]));
+        if (!name)
+            return JS_FALSE;
+        file = fopen(name.ptr(), "w");
         if (!file) {
             JS_ReportError(cx, "tracing: couldn't open output file %s: %s", 
-                           name, strerror(errno));
+                           name.ptr(), strerror(errno));
             return JS_FALSE;
         }
         break;
       }
       default:
           goto bad_argument;
     }
     if (cx->logfp && cx->logfp != stderr)
@@ -2264,18 +2270,20 @@ Tracing(JSContext *cx, uintN argc, jsval
     cx->logPrevPc = NULL;
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 
  bad_argument:
     JSString *str = JS_ValueToString(cx, argv[0]);
     if (!str)
         return JS_FALSE;
-    JS_ReportError(cx, "tracing: illegal argument %s",
-                   JS_GetStringBytes(str));
+    JSAutoByteString bytes(cx, str);
+    if (!bytes)
+        return JS_FALSE;
+    JS_ReportError(cx, "tracing: illegal argument %s", bytes.ptr());
     return JS_FALSE;
 }
 
 static void
 DumpScope(JSContext *cx, JSObject *obj, FILE *fp)
 {
     uintN i = 0;
     for (JSScopeProperty *sprop = NULL; JS_PropertyIterator(obj, &sprop);) {
@@ -2331,38 +2339,40 @@ DumpStats(JSContext *cx, uintN argc, jsv
     }
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
 DumpHeap(JSContext *cx, uintN argc, jsval *vp)
 {
-    char *fileName;
     jsval v;
     void* startThing;
     uint32 startTraceKind;
     const char *badTraceArg;
     void *thingToFind;
     size_t maxDepth;
     void *thingToIgnore;
     FILE *dumpFile;
     JSBool ok;
 
-    fileName = NULL;
+    const char *fileName = NULL;
+    JSAutoByteString fileNameBytes;
     if (argc > 0) {
         v = JS_ARGV(cx, vp)[0];
         if (!JSVAL_IS_NULL(v)) {
             JSString *str;
 
             str = JS_ValueToString(cx, v);
             if (!str)
                 return JS_FALSE;
             JS_ARGV(cx, vp)[0] = STRING_TO_JSVAL(str);
-            fileName = JS_GetStringBytes(str);
+            if (!fileNameBytes.encode(cx, str))
+                return JS_FALSE;
+            fileName = fileNameBytes.ptr();
         }
     }
 
     startThing = NULL;
     startTraceKind = 0;
     if (argc > 1) {
         v = JS_ARGV(cx, vp)[1];
         if (JSVAL_IS_TRACEABLE(v)) {
@@ -2526,51 +2536,49 @@ ZZ_formatter(JSContext *cx, const char *
 static JSBool
 ConvertArgs(JSContext *cx, uintN argc, jsval *vp)
 {
     JSBool b = JS_FALSE;
     jschar c = 0;
     int32 i = 0, j = 0;
     uint32 u = 0;
     jsdouble d = 0, I = 0, re = 0, im = 0;
-    char *s = NULL;
     JSString *str = NULL;
     jschar *w = NULL;
     JSObject *obj2 = NULL;
     JSFunction *fun = NULL;
     jsval v = JSVAL_VOID;
     JSBool ok;
 
     if (!JS_AddArgumentFormatter(cx, "ZZ", ZZ_formatter))
         return JS_FALSE;
-    ok = JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "b/ciujdIsSWofvZZ*",
-                             &b, &c, &i, &u, &j, &d, &I, &s, &str, &w, &obj2,
+    ok = JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "b/ciujdISWofvZZ*",
+                             &b, &c, &i, &u, &j, &d, &I, &str, &w, &obj2,
                              &fun, &v, &re, &im);
     JS_RemoveArgumentFormatter(cx, "ZZ");
     if (!ok)
         return JS_FALSE;
     fprintf(gOutFile,
             "b %u, c %x (%c), i %ld, u %lu, j %ld\n",
             b, c, (char)c, i, u, j);
     ToString obj2string(cx, obj2);
     ToString valueString(cx, v);
+    JSAutoByteString strBytes;
+    if (str)
+        strBytes.encode(cx, str);
     JSString *tmpstr = JS_DecompileFunction(cx, fun, 4);
-    const char *func;
-    if (tmpstr) {
-        func = JS_GetStringBytes(tmpstr);
-    } else {
+    JSAutoByteString func;
+    if (!tmpstr || !func.encode(cx, tmpstr));
         ReportException(cx);
-        func = "error decompiling fun";
-    }
     fprintf(gOutFile,
-            "d %g, I %g, s %s, S %s, W %s, obj %s, fun %s\n"
+            "d %g, I %g, S %s, W %s, obj %s, fun %s\n"
             "v %s, re %g, im %g\n",
-            d, I, s, str ? JS_GetStringBytes(str) : "", EscapeWideString(w),
+            d, I, !!strBytes ? strBytes.ptr() : "", EscapeWideString(w),
             obj2string.getBytes(),
-            fun ? func : "",
+            fun ? (!!func ? func.ptr() : "error decompiling fun") : "",
             valueString.getBytes(), re, im);
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 #endif
 
 static JSBool
 BuildDate(JSContext *cx, uintN argc, jsval *vp)
@@ -4049,37 +4057,38 @@ Parse(JSContext *cx, uintN argc, jsval *
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
 Snarf(JSContext *cx, uintN argc, jsval *vp)
 {
     JSString *str;
-    const char *filename;
     const char *pathname;
     JSStackFrame *fp;
     JSBool ok;
     size_t cc, len;
     char *buf;
     FILE *file;
 
     if (!argc)
         return JS_FALSE;
 
     str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
     if (!str)
         return JS_FALSE;
-    filename = JS_GetStringBytes(str);
+    JSAutoByteString filename(cx, str);
+    if (!filename)
+        return JS_FALSE;
 
     /* Get the currently executing script's name. */
     fp = JS_GetScriptedCaller(cx, NULL);
     JS_ASSERT(fp && fp->script()->filename);
 #ifdef XP_UNIX
-    pathname = MakeAbsolutePathname(cx, fp->script()->filename, filename);
+    pathname = MakeAbsolutePathname(cx, fp->script()->filename, filename.ptr());
     if (!pathname)
         return JS_FALSE;
 #else
     pathname = filename;
 #endif
 
     ok = JS_FALSE;
     len = 0;
@@ -4590,36 +4599,46 @@ static JSPropertySpec its_props[] = {
     {"customRdOnly",    ITS_CUSTOMRDONLY, JSPROP_ENUMERATE | JSPROP_READONLY,
                         its_getter,     its_setter},
     {NULL,0,0,NULL,NULL}
 };
 
 static JSBool
 its_bindMethod(JSContext *cx, uintN argc, jsval *vp)
 {
-    char *name;
+    JSString *name;
     JSObject *method;
 
     JSObject *thisobj = JS_THIS_OBJECT(cx, vp);
 
-    if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "so", &name, &method))
+    if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "So", &name, &method))
         return JS_FALSE;
 
     *vp = OBJECT_TO_JSVAL(method);
 
     if (JS_TypeOfValue(cx, *vp) != JSTYPE_FUNCTION) {
-        JSString *valstr = JS_ValueToString(cx, *vp);
-        if (valstr) {
-            JS_ReportError(cx, "can't bind method %s to non-callable object %s",
-                           name, JS_GetStringBytes(valstr));
+        JSAutoByteString nameBytes(cx, name);
+        if (!!nameBytes) {
+            JSString *valstr = JS_ValueToString(cx, *vp);
+            if (valstr) {
+                JSAutoByteString valBytes(cx, valstr);
+                if (!!valBytes) {
+                    JS_ReportError(cx, "can't bind method %s to non-callable object %s",
+                                   nameBytes.ptr(), valBytes.ptr());
+                }
+            }
         }
         return JS_FALSE;
     }
 
-    if (!JS_DefineProperty(cx, thisobj, name, *vp, NULL, NULL, JSPROP_ENUMERATE))
+    jsid id;
+    if (!JS_ValueToId(cx, STRING_TO_JSVAL(name), &id))
+        return JS_FALSE;
+    
+    if (!JS_DefinePropertyById(cx, thisobj, id, *vp, NULL, NULL, JSPROP_ENUMERATE))
         return JS_FALSE;
 
     return JS_SetParent(cx, method, thisobj);
 }
 
 static JSFunctionSpec its_methods[] = {
     {"bindMethod",      its_bindMethod, 2,0},
     {NULL,NULL,0,0}
@@ -4916,58 +4935,70 @@ my_ErrorReporter(JSContext *cx, const ch
 #if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
 static JSBool
 Exec(JSContext *cx, uintN argc, jsval *vp)
 {
     JSFunction *fun;
     const char *name, **nargv;
     uintN i, nargc;
     JSString *str;
+    bool ok;
     pid_t pid;
     int status;
 
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
 
     fun = JS_ValueToFunction(cx, vp[0]);
     if (!fun)
         return JS_FALSE;
     if (!fun->atom)
         return JS_TRUE;
-    name = JS_GetStringBytes(ATOM_TO_STRING(fun->atom));
+
     nargc = 1 + argc;
-    nargv = JS_malloc(cx, (nargc + 1) * sizeof(char *));
+
+    /* nargc + 1 accounts for the terminating NULL. */ 
+    nargv = new (char *)[nargc + 1];
     if (!nargv)
         return JS_FALSE;
+    memset(nargv, 0, sizeof(nargv[0]) * (nargc + 1));
     nargv[0] = name;
     jsval *argv = JS_ARGV(cx, vp);
-    for (i = 1; i < nargc; i++) {
-        str = JS_ValueToString(cx, argv[i-1]);
+    for (i = 0; i < nargc; i++) {
+        str = (i == 0) ? ATOM_TO_STRING(fun->atom) : JS_ValueToString(cx, argv[i-1]);
         if (!str) {
-            JS_free(cx, nargv);
-            return JS_FALSE;
+            ok = false;
+            goto done;
         }
-        nargv[i] = JS_GetStringBytes(str);
+        nargv[i] = JS_EncodeString(cx, str);
+        if (!nargv[i]) {
+            ok = false;
+            goto done;
+        }
     }
-    nargv[nargc] = 0;
     pid = fork();
     switch (pid) {
       case -1:
         perror("js");
         break;
       case 0:
         (void) execvp(name, (char **)nargv);
         perror("js");
         exit(127);
       default:
         while (waitpid(pid, &status, 0) < 0 && errno == EINTR)
             continue;
         break;
     }
-    JS_free(cx, nargv);
-    return JS_TRUE;
+    ok = true;
+
+  done:
+    for (i = 0; i < nargc; i++)
+        JS_free(cx, nargv[i]);
+    delete[] nargv;
+    return ok;
 }
 #endif
 
 static JSBool
 global_enumerate(JSContext *cx, JSObject *obj)
 {
 #ifdef LAZY_STANDARD_CLASSES
     return JS_EnumerateStandardClasses(cx, obj);
@@ -5005,21 +5036,23 @@ global_resolve(JSContext *cx, JSObject *
         if (!JSVAL_IS_STRING(id))
             return JS_TRUE;
         path = getenv("PATH");
         if (!path)
             return JS_TRUE;
         path = JS_strdup(cx, path);
         if (!path)
             return JS_FALSE;
-        name = JS_GetStringBytes(JSVAL_TO_STRING(id));
+        JSAutoByteString name(cx, JSVAL_TO_STRING(id));
+        if (!name)
+            return JS_FALSE;
         ok = JS_TRUE;
         for (comp = strtok(path, ":"); comp; comp = strtok(NULL, ":")) {
             if (*comp != '\0') {
-                full = JS_smprintf("%s/%s", comp, name);
+                full = JS_smprintf("%s/%s", comp, name.ptr());
                 if (!full) {
                     JS_ReportOutOfMemory(cx);
                     ok = JS_FALSE;
                     break;
                 }
             } else {
                 full = (char *)name;
             }
--- a/js/src/shell/jsworkers.cpp
+++ b/js/src/shell/jsworkers.cpp
@@ -393,21 +393,21 @@ class MainQueue : public EventQueue, pub
             JS_RELEASE_LOCK(lock);
             Event::Result result;
             {
                 JSAutoRequest req(cx);
                 result = event->process(cx);
                 if (result == Event::forwardToParent) {
                     // FIXME - pointlessly truncates the string to 8 bits
                     jsval data;
-                    const char *s;
+                    JSAutoByteString bytes;
                     if (event->deserializeData(cx, &data) &&
                         JSVAL_IS_STRING(data) &&
-                        (s = JS_GetStringBytesZ(cx, JSVAL_TO_STRING(data)))) {
-                        JS_ReportError(cx, "%s", s);
+                        bytes.encode(cx, JSVAL_TO_STRING(data))) {
+                        JS_ReportError(cx, "%s", bytes.ptr());
                     } else {
                         JS_ReportOutOfMemory(cx);
                     }
                     result = Event::fail;
                 }
                 if (result == Event::fail && continueOnError) {
                     if (JS_IsExceptionPending(cx) && !JS_ReportPendingException(cx))
                         JS_ClearPendingException(cx);
@@ -885,21 +885,21 @@ class InitEvent : public Event
         return createEvent<InitEvent>(cx, worker, worker, STRING_TO_JSVAL(scriptName));
     }
 
     Result process(JSContext *cx) {
         jsval s;
         if (!deserializeData(cx, &s))
             return fail;
         JS_ASSERT(JSVAL_IS_STRING(s));
-        const char *filename = JS_GetStringBytesZ(cx, JSVAL_TO_STRING(s));
+        JSAutoByteString filename(cx, JSVAL_TO_STRING(s));
         if (!filename)
             return fail;
 
-        JSScript *script = JS_CompileFile(cx, child->getGlobal(), filename);
+        JSScript *script = JS_CompileFile(cx, child->getGlobal(), filename.ptr());
         if (!script)
             return fail;
 
         AutoValueRooter rval(cx);
         JSBool ok = JS_ExecuteScript(cx, child->getGlobal(), script, Jsvalify(rval.addr()));
         JS_DestroyScript(cx, script);
         return Result(ok);
     }
--- a/js/src/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/src/xpconnect/loader/mozJSComponentLoader.cpp
@@ -221,18 +221,21 @@ Atob(JSContext *cx, uintN argc, jsval *v
     JSString *str;
     if (!argc)
         return JS_TRUE;
 
     str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
     if (!str)
         return JS_FALSE;
 
+    JSAutoByteString base64Bytes(cx, str);
+    if (!base64Bytes)
+        return JS_FALSE;
+    const char *base64Str = base64Bytes.ptr();
     size_t base64StrLength = JS_GetStringLength(str);
-    char *base64Str = JS_GetStringBytes(str);
 
     PRUint32 bin_dataLength = (PRUint32)base64StrLength;
     if (base64StrLength >= 1 && base64Str[base64StrLength - 1] == '=') {
         if (base64StrLength >= 2 && base64Str[base64StrLength - 2] == '=')
             bin_dataLength -= 2;
         else
             --bin_dataLength;
     }
@@ -257,17 +260,20 @@ Btoa(JSContext *cx, uintN argc, jsval *v
     JSString *str;
     if (!argc)
         return JS_TRUE;
 
     str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
     if (!str)
         return JS_FALSE;
 
-    char *bin_data = JS_GetStringBytes(str);
+    JSAutoByteString bin_dataBytes(cx, str);
+    if (!bin_dataBytes)
+        return JS_FALSE;
+    const char *bin_data = bin_dataBytes.ptr();
     size_t bin_dataLength = JS_GetStringLength(str);
 
     char *base64 = PL_Base64Encode(bin_data, bin_dataLength, nsnull);
     if (!base64)
         return JS_FALSE;
 
     PRUint32 base64Length = ((bin_dataLength + 2) / 3) * 4;
     str = JS_NewStringCopyN(cx, base64, base64Length);
@@ -1528,35 +1534,43 @@ mozJSComponentLoader::ImportInto(const n
             if (!JS_GetElement(mContext, symbolsObj, i, &val) ||
                 !JSVAL_IS_STRING(val) ||
                 !JS_ValueToId(mContext, val, &symbolId)) {
                 return ReportOnCaller(cxhelper, ERROR_ARRAY_ELEMENT,
                                       PromiseFlatCString(aLocation).get(), i);
             }
 
             if (!JS_GetPropertyById(mContext, mod->global, symbolId, &val)) {
+                JSAutoByteString bytes(mContext, JSID_TO_STRING(symbolId));
+                if (!bytes)
+                    return NS_ERROR_FAILURE;
                 return ReportOnCaller(cxhelper, ERROR_GETTING_SYMBOL,
                                       PromiseFlatCString(aLocation).get(),
-                                      JS_GetStringBytes(JSID_TO_STRING(symbolId)));
+                                      bytes.ptr());
             }
 
             JSAutoEnterCompartment target_ac;
 
             if (!target_ac.enter(mContext, targetObj) ||
                 !JS_WrapValue(mContext, &val) ||
                 !JS_SetPropertyById(mContext, targetObj, symbolId, &val)) {
+                JSAutoByteString bytes(mContext, JSID_TO_STRING(symbolId));
+                if (!bytes)
+                    return NS_ERROR_FAILURE;
                 return ReportOnCaller(cxhelper, ERROR_SETTING_SYMBOL,
                                       PromiseFlatCString(aLocation).get(),
-                                      JS_GetStringBytes(JSID_TO_STRING(symbolId)));
+                                      bytes.ptr());
             }
 #ifdef DEBUG
             if (i == 0) {
                 logBuffer.AssignLiteral("Installing symbols [ ");
             }
-            logBuffer.Append(JS_GetStringBytes(JSID_TO_STRING(symbolId)));
+            JSAutoByteString bytes(mContext, JSID_TO_STRING(symbolId));
+            if (!!bytes)
+                logBuffer.Append(bytes.ptr());
             logBuffer.AppendLiteral(" ");
             if (i == symbolCount - 1) {
                 LOG(("%s] from %s\n", PromiseFlatCString(logBuffer).get(),
                                       PromiseFlatCString(aLocation).get()));
             }
 #endif
         }
     }
--- a/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -156,26 +156,32 @@ mozJSSubScriptLoader::LoadSubScript (con
 
         rv = secman->GetSystemPrincipal(getter_AddRefs(mSystemPrincipal));
         if (NS_FAILED(rv) || !mSystemPrincipal)
             return rv;
     }
 
     JSAutoRequest ar(cx);
 
-    char     *url;
+    JSString *url;
     JSObject *target_obj = nsnull;
     jschar   *charset = nsnull;
-    ok = JS_ConvertArguments (cx, argc, argv, "s / o W", &url, &target_obj, &charset);
+    ok = JS_ConvertArguments (cx, argc, argv, "S / o W", &url, &target_obj, &charset);
     if (!ok)
     {
         /* let the exception raised by JS_ConvertArguments show through */
         return NS_OK;
     }
 
+    JSAutoByteString urlbytes(cx, url);
+    if (!urlbytes)
+    {
+        return NS_OK;
+    }
+
     if (!target_obj)
     {
         /* if the user didn't provide an object to eval onto, find the global
          * object by walking the parent chain of the calling object */
 
 #ifdef DEBUG_rginda
         JSObject *got_glob = JS_GetGlobalObject (cx);
         fprintf (stderr, "JS_GetGlobalObject says glob is %p.\n", got_glob);
@@ -272,17 +278,17 @@ mozJSSubScriptLoader::LoadSubScript (con
     if (!serv)
     {
         errmsg = JS_NewStringCopyZ (cx, LOAD_ERROR_NOSERVICE);
         goto return_exception;
     }
 
     // Make sure to explicitly create the URI, since we'll need the
     // canonicalized spec.
-    rv = NS_NewURI(getter_AddRefs(uri), url, nsnull, serv);
+    rv = NS_NewURI(getter_AddRefs(uri), urlbytes.ptr(), nsnull, serv);
     if (NS_FAILED(rv)) {
         errmsg = JS_NewStringCopyZ (cx, LOAD_ERROR_NOURI);
         goto return_exception;
     }
 
     rv = uri->GetSpec(uriStr);
     if (NS_FAILED(rv)) {
         errmsg = JS_NewStringCopyZ (cx, LOAD_ERROR_NOSPEC);
--- a/js/src/xpconnect/shell/xpcshell.cpp
+++ b/js/src/xpconnect/shell/xpcshell.cpp
@@ -383,17 +383,18 @@ ReadLine(JSContext *cx, uintN argc, jsva
         str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
         if (!str)
             return JS_FALSE;
     } else {
         str = JSVAL_TO_STRING(JS_GetEmptyStringValue(cx));
     }
 
     /* Get a line from the infile */
-    if (!GetLine(cx, buf, gInFile, JS_GetStringBytes(str)))
+    JSAutoByteString strBytes(cx, str);
+    if (!strBytes || !GetLine(cx, buf, gInFile, strBytes.ptr()))
         return JS_FALSE;
 
     /* Strip newline character added by GetLine() */
     unsigned int buflen = strlen(buf);
     if (buflen == 0) {
         if (feof(gInFile)) {
             JS_SET_RVAL(cx, vp, JSVAL_NULL);
             return JS_TRUE;
@@ -417,17 +418,20 @@ Print(JSContext *cx, uintN argc, jsval *
     uintN i, n;
     JSString *str;
 
     jsval *argv = JS_ARGV(cx, vp);
     for (i = n = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
             return JS_FALSE;
-        fprintf(gOutFile, "%s%s", i ? " " : "", JS_GetStringBytes(str));
+        JSAutoByteString strBytes(cx, str);
+        if (!strBytes)
+            return JS_FALSE;
+        fprintf(gOutFile, "%s%s", i ? " " : "", strBytes.ptr());
         fflush(gOutFile);
     }
     n++;
     if (n)
         fputc('\n', gOutFile);
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
@@ -450,40 +454,42 @@ Dump(JSContext *cx, uintN argc, jsval *v
     return JS_TRUE;
 }
 
 static JSBool
 Load(JSContext *cx, uintN argc, jsval *vp)
 {
     uintN i;
     JSString *str;
-    const char *filename;
     JSScript *script;
     JSBool ok;
     jsval result;
     FILE *file;
 
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     jsval *argv = JS_ARGV(cx, vp);
     for (i = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
             return JS_FALSE;
         argv[i] = STRING_TO_JSVAL(str);
-        filename = JS_GetStringBytes(str);
-        file = fopen(filename, "r");
+        JSAutoByteString filename(cx, str);
+        if (!filename)
+            return JS_FALSE;
+        file = fopen(filename.ptr(), "r");
         if (!file) {
-            JS_ReportError(cx, "cannot open file '%s' for reading", filename);
+            JS_ReportError(cx, "cannot open file '%s' for reading",
+                           filename.ptr());
             return JS_FALSE;
         }
-        script = JS_CompileFileHandleForPrincipals(cx, obj, filename, file,
-                                                   gJSPrincipals);
+        script = JS_CompileFileHandleForPrincipals(cx, obj, filename.ptr(),
+                                                   file, gJSPrincipals);
         fclose(file);
         if (!script)
             return JS_FALSE;
 
         ok = !compileOnly
              ? JS_ExecuteScript(cx, obj, script, &result)
              : JS_TRUE;
         JS_DestroyScript(cx, script);
@@ -578,37 +584,38 @@ GCZeal(JSContext *cx, uintN argc, jsval 
 }
 #endif
 
 #ifdef DEBUG
 
 static JSBool
 DumpHeap(JSContext *cx, uintN argc, jsval *vp)
 {
-    char *fileName = NULL;
     void* startThing = NULL;
     uint32 startTraceKind = 0;
     void *thingToFind = NULL;
     size_t maxDepth = (size_t)-1;
     void *thingToIgnore = NULL;
     FILE *dumpFile;
     JSBool ok;
 
     jsval *argv = JS_ARGV(cx, vp);
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
 
     vp = argv + 0;
+    JSAutoByteString fileName;
     if (argc > 0 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
         JSString *str;
 
         str = JS_ValueToString(cx, *vp);
         if (!str)
             return JS_FALSE;
         *vp = STRING_TO_JSVAL(str);
-        fileName = JS_GetStringBytes(str);
+        if (!fileName.encode(cx, str))
+            return JS_FALSE;
     }
 
     vp = argv + 1;
     if (argc > 1 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
         if (!JSVAL_IS_TRACEABLE(*vp))
             goto not_traceable_arg;
         startThing = JSVAL_TO_TRACEABLE(*vp);
         startTraceKind = JSVAL_TRACE_KIND(*vp);
@@ -635,20 +642,20 @@ DumpHeap(JSContext *cx, uintN argc, jsva
         if (!JSVAL_IS_TRACEABLE(*vp))
             goto not_traceable_arg;
         thingToIgnore = JSVAL_TO_TRACEABLE(*vp);
     }
 
     if (!fileName) {
         dumpFile = gOutFile;
     } else {
-        dumpFile = fopen(fileName, "w");
+        dumpFile = fopen(fileName.ptr(), "w");
         if (!dumpFile) {
             fprintf(gErrFile, "dumpHeap: can't open %s: %s\n",
-                    fileName, strerror(errno));
+                    fileName.ptr(), strerror(errno));
             return JS_FALSE;
         }
     }
 
     ok = JS_DumpHeap(cx, dumpFile, startThing, startTraceKind, thingToFind,
                      maxDepth, thingToIgnore);
     if (dumpFile != gOutFile)
         fclose(dumpFile);
@@ -771,31 +778,30 @@ MapContextOptionNameToFlag(JSContext* cx
     return 0;
 }
 
 static JSBool
 Options(JSContext *cx, uintN argc, jsval *vp)
 {
     uint32 optset, flag;
     JSString *str;
-    const char *opt;
     char *names;
     JSBool found;
 
     optset = 0;
     jsval *argv = JS_ARGV(cx, vp);
     for (uintN i = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
             return JS_FALSE;
         argv[i] = STRING_TO_JSVAL(str);
-        opt = JS_GetStringBytes(str);
+        JSAutoByteString opt(cx, str);
         if (!opt)
             return JS_FALSE;
-        flag = MapContextOptionNameToFlag(cx,  opt);
+        flag = MapContextOptionNameToFlag(cx,  opt.ptr());
         if (!flag)
             return JS_FALSE;
         optset |= flag;
     }
     optset = JS_ToggleOptions(cx, optset);
 
     names = NULL;
     found = JS_FALSE;
@@ -885,33 +891,36 @@ JSClass global_class = {
 };
 
 static JSBool
 env_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
 /* XXX porting may be easy, but these don't seem to supply setenv by default */
 #if !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS
     JSString *idstr, *valstr;
-    const char *name, *value;
     int rv;
 
     jsval idval;
     if (!JS_IdToValue(cx, id, &idval))
         return JS_FALSE;
     
     idstr = JS_ValueToString(cx, idval);
     valstr = JS_ValueToString(cx, *vp);
     if (!idstr || !valstr)
         return JS_FALSE;
-    name = JS_GetStringBytes(idstr);
-    value = JS_GetStringBytes(valstr);
+    JSAutoByteString name(cx, idstr);
+    if (!name)
+        return JS_FALSE;
+    JSAutoByteString value(cx, valstr);
+    if (!value)
+        return JS_FALSE;
 #if defined XP_WIN || defined HPUX || defined OSF1 || defined IRIX \
     || defined SCO
     {
-        char *waste = JS_smprintf("%s=%s", name, value);
+        char *waste = JS_smprintf("%s=%s", name.ptr(), value.ptr());
         if (!waste) {
             JS_ReportOutOfMemory(cx);
             return JS_FALSE;
         }
         rv = putenv(waste);
 #ifdef XP_WIN
         /*
          * HPUX9 at least still has the bad old non-copying putenv.
@@ -919,20 +928,20 @@ env_setProperty(JSContext *cx, JSObject 
          * Per mail from <s.shanmuganathan@digital.com>, OSF1 also has a putenv
          * that will crash if you pass it an auto char array (so it must place
          * its argument directly in the char *environ[] array).
          */
         free(waste);
 #endif
     }
 #else
-    rv = setenv(name, value, 1);
+    rv = setenv(name.ptr(), value.ptr(), 1);
 #endif
     if (rv < 0) {
-        JS_ReportError(cx, "can't set envariable %s to %s", name, value);
+        JS_ReportError(cx, "can't set envariable %s to %s", name.ptr(), value.ptr());
         return JS_FALSE;
     }
     *vp = STRING_TO_JSVAL(valstr);
 #endif /* !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS */
     return JS_TRUE;
 }
 
 static JSBool
@@ -967,36 +976,37 @@ env_enumerate(JSContext *cx, JSObject *o
     return JS_TRUE;
 }
 
 static JSBool
 env_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
             JSObject **objp)
 {
     JSString *idstr, *valstr;
-    const char *name, *value;
 
     if (flags & JSRESOLVE_ASSIGNING)
         return JS_TRUE;
 
     jsval idval;
     if (!JS_IdToValue(cx, id, &idval))
         return JS_FALSE;
 
     idstr = JS_ValueToString(cx, idval);
     if (!idstr)
         return JS_FALSE;
-    name = JS_GetStringBytes(idstr);
-    value = getenv(name);
+    JSAutoByteString name(cx, idstr);
+    if (!name)
+        return JS_FALSE;
+    const char *value = getenv(name.ptr());
     if (value) {
         valstr = JS_NewStringCopyZ(cx, value);
         if (!valstr)
             return JS_FALSE;
-        if (!JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr),
-                               NULL, NULL, JSPROP_ENUMERATE)) {
+        if (!JS_DefinePropertyById(cx, obj, id, STRING_TO_JSVAL(valstr),
+                                   NULL, NULL, JSPROP_ENUMERATE)) {
             return JS_FALSE;
         }
         *objp = obj;
     }
     return JS_TRUE;
 }
 
 static JSClass env_class = {
@@ -1117,19 +1127,19 @@ ProcessFile(JSContext *cx, JSObject *obj
 
             if (!compileOnly) {
                 ok = JS_ExecuteScript(cx, obj, script, &result);
                 if (ok && result != JSVAL_VOID) {
                     /* Suppress error reports from JS_ValueToString(). */
                     older = JS_SetErrorReporter(cx, NULL);
                     str = JS_ValueToString(cx, result);
                     JS_SetErrorReporter(cx, older);
-
-                    if (str)
-                        fprintf(gOutFile, "%s\n", JS_GetStringBytes(str));
+                    JSAutoByteString bytes;
+                    if (str && bytes.encode(cx, str))
+                        fprintf(gOutFile, "%s\n", bytes.ptr());
                     else
                         ok = JS_FALSE;
                 }
             }
             JS_DestroyScript(cx, script);
         }
         DoEndRequest(cx);
     } while (!hitEOF && !gQuitting);
--- a/js/src/xpconnect/src/qsgen.py
+++ b/js/src/xpconnect/src/qsgen.py
@@ -476,19 +476,20 @@ argumentUnboxingTemplates = {
     '[domstring]':
         "    xpc_qsDOMString ${name}(cx, ${argVal}, ${argPtr},\n"
         "                            xpc_qsDOMString::e${nullBehavior},\n"
         "                            xpc_qsDOMString::e${undefinedBehavior});\n"
         "    if (!${name}.IsValid())\n"
         "        return JS_FALSE;\n",
 
     'string':
-        "    char *${name};\n"
-        "    if (!xpc_qsJsvalToCharStr(cx, ${argVal}, ${argPtr}, &${name}))\n"
-        "        return JS_FALSE;\n",
+        "    JSAutoByteString ${name}_bytes;\n"
+        "    if (!xpc_qsJsvalToCharStr(cx, ${argVal}, &${name}_bytes))\n"
+        "        return JS_FALSE;\n"
+        "    char *${name} = ${name}_bytes.ptr();\n",
 
     'wstring':
         "    PRUnichar *${name};\n"
         "    if (!xpc_qsJsvalToWcharStr(cx, ${argVal}, ${argPtr}, &${name}))\n"
         "        return JS_FALSE;\n",
 
     '[cstring]':
         "    xpc_qsACString ${name}(cx, ${argVal}, ${argPtr});\n"
--- a/js/src/xpconnect/src/xpccomponents.cpp
+++ b/js/src/xpconnect/src/xpccomponents.cpp
@@ -332,25 +332,24 @@ nsXPCComponents_Interfaces::NewEnumerate
 
 /* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, in PRUint32 flags, out JSObjectPtr objp); */
 NS_IMETHODIMP
 nsXPCComponents_Interfaces::NewResolve(nsIXPConnectWrappedNative *wrapper,
                                        JSContext * cx, JSObject * obj,
                                        jsid id, PRUint32 flags,
                                        JSObject * *objp, PRBool *_retval)
 {
-    const char* name = nsnull;
-
+    JSAutoByteString name;
     if(mManager &&
        JSID_IS_STRING(id) &&
-       nsnull != (name = JS_GetStringBytes(JSID_TO_STRING(id))) &&
-       name[0] != '{') // we only allow interfaces by name here
+       name.encode(cx, JSID_TO_STRING(id)) &&
+       name.ptr()[0] != '{') // we only allow interfaces by name here
     {
         nsCOMPtr<nsIInterfaceInfo> info;
-        mManager->GetInfoForName(name, getter_AddRefs(info));
+        mManager->GetInfoForName(name.ptr(), getter_AddRefs(info));
         if(!info)
             return NS_OK;
 
         nsCOMPtr<nsIJSIID> nsid =
             dont_AddRef(static_cast<nsIJSIID*>(nsJSIID::NewID(info)));
 
         if(nsid)
         {
@@ -969,24 +968,24 @@ nsXPCComponents_Classes::NewEnumerate(ns
 /* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, in PRUint32 flags, out JSObjectPtr objp); */
 NS_IMETHODIMP
 nsXPCComponents_Classes::NewResolve(nsIXPConnectWrappedNative *wrapper,
                                     JSContext * cx, JSObject * obj,
                                     jsid id, PRUint32 flags,
                                     JSObject * *objp, PRBool *_retval)
 
 {
-    const char* name = nsnull;
+    JSAutoByteString name;
 
     if(JSID_IS_STRING(id) &&
-       nsnull != (name = JS_GetStringBytes(JSID_TO_STRING(id))) &&
-       name[0] != '{') // we only allow contractids here
+       name.encode(cx, JSID_TO_STRING(id)) &&
+       name.ptr()[0] != '{') // we only allow contractids here
     {
         nsCOMPtr<nsIJSCID> nsid =
-            dont_AddRef(static_cast<nsIJSCID*>(nsJSCID::NewID(name)));
+            dont_AddRef(static_cast<nsIJSCID*>(nsJSCID::NewID(name.ptr())));
         if(nsid)
         {
             nsCOMPtr<nsIXPConnect> xpc;
             wrapper->GetXPConnect(getter_AddRefs(xpc));
             if(xpc)
             {
                 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
                 if(NS_SUCCEEDED(xpc->WrapNative(cx, obj,
@@ -1237,25 +1236,25 @@ IsRegisteredCLSID(const char* str)
 
 /* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, in PRUint32 flags, out JSObjectPtr objp); */
 NS_IMETHODIMP
 nsXPCComponents_ClassesByID::NewResolve(nsIXPConnectWrappedNative *wrapper,
                                         JSContext * cx, JSObject * obj,
                                         jsid id, PRUint32 flags,
                                         JSObject * *objp, PRBool *_retval)
 {
-    const char* name = nsnull;
+    JSAutoByteString name;
 
     if(JSID_IS_STRING(id) &&
-       nsnull != (name = JS_GetStringBytes(JSID_TO_STRING(id))) &&
-       name[0] == '{' &&
-       IsRegisteredCLSID(name)) // we only allow canonical CLSIDs here
+       name.encode(cx, JSID_TO_STRING(id)) &&
+       name.ptr()[0] == '{' &&
+       IsRegisteredCLSID(name.ptr())) // we only allow canonical CLSIDs here
     {
         nsCOMPtr<nsIJSCID> nsid =
-            dont_AddRef(static_cast<nsIJSCID*>(nsJSCID::NewID(name)));
+            dont_AddRef(static_cast<nsIJSCID*>(nsJSCID::NewID(name.ptr())));
         if(nsid)
         {
             nsCOMPtr<nsIXPConnect> xpc;
             wrapper->GetXPConnect(getter_AddRefs(xpc));
             if(xpc)
             {
                 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
                 if(NS_SUCCEEDED(xpc->WrapNative(cx, obj,
@@ -1472,27 +1471,26 @@ nsXPCComponents_Results::NewEnumerate(ns
 
 /* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, in PRUint32 flags, out JSObjectPtr objp); */
 NS_IMETHODIMP
 nsXPCComponents_Results::NewResolve(nsIXPConnectWrappedNative *wrapper,
                                     JSContext * cx, JSObject * obj,
                                     jsid id, PRUint32 flags,
                                     JSObject * *objp, PRBool *_retval)
 {
-    const char* name = nsnull;
-
-    if(JSID_IS_STRING(id) &&
-       nsnull != (name = JS_GetStringBytes(JSID_TO_STRING(id))))
+    JSAutoByteString name;
+
+    if(JSID_IS_STRING(id) && name.encode(cx, JSID_TO_STRING(id)))
     {
         const char* rv_name;
         void* iter = nsnull;
         nsresult rv;
         while(nsXPCException::IterateNSResults(&rv, &rv_name, nsnull, &iter))
         {
-            if(!strcmp(name, rv_name))
+            if(!strcmp(name.ptr(), rv_name))
             {
                 jsval val;
 
                 *objp = obj;
                 if(!JS_NewNumberValue(cx, (jsdouble)rv, &val) ||
                    !JS_DefinePropertyById(cx, obj, id, val,
                                           nsnull, nsnull,
                                           JSPROP_ENUMERATE |
@@ -1699,22 +1697,22 @@ nsXPCComponents_ID::CallOrConstruct(nsIX
         // the security manager vetoed. It should have set an exception.
         *_retval = JS_FALSE;
         return NS_OK;
     }
 
     // convert the first argument into a string and see if it looks like an id
 
     JSString* jsstr;
-    const char* str;
+    JSAutoByteString bytes;
     nsID id;
 
     if(!(jsstr = JS_ValueToString(cx, argv[0])) ||
-       !(str = JS_GetStringBytes(jsstr)) ||
-       ! id.Parse(str))
+       !bytes.encode(cx, jsstr) ||
+       !id.Parse(bytes.ptr()))
     {
         return ThrowAndFail(NS_ERROR_XPC_BAD_ID_STRING, cx, _retval);
     }
 
     // make the new object and return it.
 
     JSObject* newobj = xpc_NewIDObject(cx, obj, id);
 
@@ -1922,16 +1920,17 @@ nsXPCComponents_Exception::CallOrConstru
     {
         // the security manager vetoed. It should have set an exception.
         *_retval = JS_FALSE;
         return NS_OK;
     }
 
     // initialization params for the exception object we will create
     const char*             eMsg = "exception";
+    JSAutoByteString        eMsgBytes;
     nsresult                eResult = NS_ERROR_FAILURE;
     nsCOMPtr<nsIStackFrame> eStack;
     nsCOMPtr<nsISupports>   eData;
 
     // all params are optional - grab any passed in
     switch(argc)
     {
         default:    // more than 4 - ignore extra
@@ -1966,17 +1965,17 @@ nsXPCComponents_Exception::CallOrConstru
             // fall through...
         case 2:     // argv[1] is nsresult for eResult
             if(!JS_ValueToECMAInt32(cx, argv[1], (int32*) &eResult))
                 return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
             // ...fall through...
         case 1:     // argv[0] is string for eMsg
             {
                 JSString* str = JS_ValueToString(cx, argv[0]);
-                if(!str || !(eMsg = JS_GetStringBytes(str)))
+                if(!str || !(eMsg = eMsgBytes.encode(cx, str)))
                     return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
             }
             // ...fall through...
         case 0: // this case required so that 'default' does not include zero.
             ;   // -- do nothing --
     }
 
     nsCOMPtr<nsIException> e;
@@ -2496,22 +2495,23 @@ nsXPCComponents_Constructor::CallOrConst
         *_retval = JS_FALSE;
         return NS_OK;
     }
 
     // initialization params for the Constructor object we will create
     nsCOMPtr<nsIJSCID> cClassID;
     nsCOMPtr<nsIJSIID> cInterfaceID;
     const char*        cInitializer = nsnull;
-
+    JSAutoByteString  cInitializerBytes;
+    
     if(argc >= 3)
     {
         // argv[2] is an initializer function or property name
         JSString* str = JS_ValueToString(cx, argv[2]);
-        if(!str || !(cInitializer = JS_GetStringBytes(str)))
+        if(!str || !(cInitializer = cInitializerBytes.encode(cx, str)))
             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
     }
 
     if(argc >= 2)
     {
         // argv[1] is an iid name string
         // XXXjband support passing "Components.interfaces.foo"?
 
@@ -3527,41 +3527,48 @@ nsXPCComponents_Utils::EvalInSandbox(con
         return NS_ERROR_XPC_NOT_ENOUGH_ARGS;
 
     jsval *argv;
     rv = cc->GetArgvPtr(&argv);
     if (NS_FAILED(rv))
         return rv;
 
     JSObject *sandbox;
-    char *jsVersionStr = NULL;
-    char *filenameStr = NULL;
+    JSString *jsVersionStr = NULL;
+    JSString *filenameStr = NULL;
     PRInt32 lineNo = 0;
 
-    JSBool ok = JS_ConvertArguments(cx, argc, argv, "*o/ssi",
+    JSBool ok = JS_ConvertArguments(cx, argc, argv, "*o/SSi",
                                     &sandbox, &jsVersionStr,
                                     &filenameStr, &lineNo);
 
     if (!ok || !sandbox)
         return NS_ERROR_INVALID_ARG;
 
     JSVersion jsVersion = JSVERSION_DEFAULT;
 
     // Optional third argument: JS version, as a string.
     if (jsVersionStr) {
-        jsVersion = JS_StringToVersion(jsVersionStr);
+        JSAutoByteString bytes(cx, jsVersionStr);
+        if (!bytes)
+            return NS_ERROR_INVALID_ARG;
+        jsVersion = JS_StringToVersion(bytes.ptr());
         if (jsVersion == JSVERSION_UNKNOWN)
             return NS_ERROR_INVALID_ARG;
     }
 
+    JSAutoByteString filenameBytes;
     nsXPIDLCString filename;
+    
 
     // Optional fourth and fifth arguments: filename and line number.
     if (filenameStr) {
-        filename = filenameStr;
+        if (!filenameBytes.encode(cx, filenameStr))
+            return NS_ERROR_INVALID_ARG;
+        filename = filenameBytes.ptr();
     } else {
         // Get the current source info from xpc.
         nsCOMPtr<nsIStackFrame> frame;
         xpc->GetCurrentJSStack(getter_AddRefs(frame));
         if (frame) {
             frame->GetFilename(getter_Copies(filename));
             frame->GetLineNumber(&lineNo);
         }
--- a/js/src/xpconnect/src/xpcconvert.cpp
+++ b/js/src/xpconnect/src/xpcconvert.cpp
@@ -1648,21 +1648,21 @@ XPCConvert::JSValToXPCException(XPCCallC
         {
             // It is a JSObject, but not a wrapped native...
 
             // If it is an engine Error with an error report then let's
             // extract the report and build an xpcexception from that
             const JSErrorReport* report;
             if(nsnull != (report = JS_ErrorFromException(cx, s)))
             {
-                const char* message = nsnull;
+                JSAutoByteString message;
                 JSString* str;
                 if(nsnull != (str = JS_ValueToString(cx, s)))
-                    message = JS_GetStringBytes(str);
-                return JSErrorToXPCException(ccx, message, ifaceName,
+                    message.encode(cx, str);
+                return JSErrorToXPCException(ccx, message.ptr(), ifaceName,
                                              methodName, report, exceptn);
             }
 
 
             uintN ignored;
             JSBool found;
 
             // heuristic to see if it might be usable as an xpcexception
@@ -1691,20 +1691,23 @@ XPCConvert::JSValToXPCException(XPCCallC
             // particular info and our 'result' should reflect that.
 
             // otherwise we'll just try to convert it to a string
 
             JSString* str = JS_ValueToString(cx, s);
             if(!str)
                 return NS_ERROR_FAILURE;
 
+            JSAutoByteString strBytes(cx, str);
+            if (!strBytes)
+                return NS_ERROR_FAILURE;
+
             return ConstructException(NS_ERROR_XPC_JS_THREW_JS_OBJECT,
-                                      JS_GetStringBytes(str),
-                                      ifaceName, methodName, nsnull,
-                                      exceptn, cx, &s);
+                                      strBytes.ptr(), ifaceName, methodName,
+                                      nsnull, exceptn, cx, &s);
         }
     }
 
     if(JSVAL_IS_VOID(s) || JSVAL_IS_NULL(s))
     {
         return ConstructException(NS_ERROR_XPC_JS_THREW_NULL,
                                   nsnull, ifaceName, methodName, nsnull,
                                   exceptn, cx, &s);
@@ -1762,20 +1765,25 @@ XPCConvert::JSValToXPCException(XPCCallC
         }
     }
 
     // otherwise we'll just try to convert it to a string
     // Note: e.g., JSBools get converted to JSStrings by this code.
 
     JSString* str = JS_ValueToString(cx, s);
     if(str)
-        return ConstructException(NS_ERROR_XPC_JS_THREW_STRING,
-                                  JS_GetStringBytes(str),
-                                  ifaceName, methodName, nsnull,
-                                  exceptn, cx, &s);
+    {
+        JSAutoByteString strBytes(cx, str);
+        if(!!strBytes)
+        {
+            return ConstructException(NS_ERROR_XPC_JS_THREW_STRING,
+                                      strBytes.ptr(), ifaceName, methodName,
+                                      nsnull, exceptn, cx, &s);
+        }
+    }
     return NS_ERROR_FAILURE;
 }
 
 /********************************/
 
 // static
 nsresult
 XPCConvert::JSErrorToXPCException(XPCCallContext& ccx,
--- a/js/src/xpconnect/src/xpcdebug.cpp
+++ b/js/src/xpconnect/src/xpcdebug.cpp
@@ -40,23 +40,24 @@
 
 #include "xpcprivate.h"
 
 #ifdef TAB
 #undef TAB
 #endif
 #define TAB "    "
 
-static const char* JSVAL2String(JSContext* cx, jsval val, JSBool* isString)
+static const char* JSVAL2String(JSContext* cx, jsval val, JSBool* isString,
+                                JSAutoByteString *bytes)
 {
     JSAutoRequest ar(cx);
     const char* value = nsnull;
     JSString* value_str = JS_ValueToString(cx, val);
     if(value_str)
-        value = JS_GetStringBytes(value_str);
+        value = bytes->encode(cx, value_str);
     if(value)
     {
         const char* found = strstr(value, "function ");
         if(found && (value == found || value+1 == found || value+2 == found))
             value = "[function]";
     }
 
     if(isString)
@@ -74,18 +75,16 @@ static char* FormatJSFrame(JSContext* cx
     jsval thisVal;
     JSObject* callObj = nsnull;
     const char* funname = nsnull;
     const char* filename = nsnull;
     PRInt32 lineno = 0;
     JSFunction* fun = nsnull;
     uint32 namedArgCount = 0;
     jsval val;
-    const char* name;
-    const char* value;
     JSBool isString;
 
     // get the info for this stack frame
 
     JSScript* script = JS_GetFrameScript(cx, fp);
     jsbytecode* pc = JS_GetFramePC(cx, fp);
 
     JSAutoRequest ar(cx);
@@ -134,21 +133,23 @@ static char* FormatJSFrame(JSContext* cx
 
     if(showArgs && callObj)
     {
         for(uint32 i = 0; i < callProps.length; i++)
         {
             JSPropertyDesc* desc = &callProps.array[i];
             if(desc->flags & JSPD_ARGUMENT)
             {
-                name = JSVAL2String(cx, desc->id, &isString);
+                JSAutoByteString nameBytes;
+                const char* name = JSVAL2String(cx, desc->id, &isString, &nameBytes);
                 if(!isString)
                     name = nsnull;
-                value = JSVAL2String(cx, desc->value, &isString);
-
+                JSAutoByteString valueBytes;
+                const char* value = JSVAL2String(cx, desc->value, &isString, &valueBytes);
+                
                 buf = JS_sprintf_append(buf, "%s%s%s%s%s%s",
                                         namedArgCount ? ", " : "",
                                         name ? name :"",
                                         name ? " = " : "",
                                         isString ? "\"" : "",
                                         value ? value : "?unknown?",
                                         isString ? "\"" : "");
                 if(!buf) goto out;
@@ -169,17 +170,18 @@ static char* FormatJSFrame(JSContext* cx
             {
                 for(uint32 k = namedArgCount; k < argCount; k++)
                 {
                     char number[8];
                     JS_snprintf(number, 8, "%d", (int) k);
 
                     if(JS_GetProperty(cx, argsObj, number, &val))
                     {
-                        value = JSVAL2String(cx, val, &isString);
+                        JSAutoByteString valueBytes;
+                        const char *value = JSVAL2String(cx, val, &isString, &valueBytes);
                         buf = JS_sprintf_append(buf, "%s%s%s%s",
                                         k ? ", " : "",
                                         isString ? "\"" : "",
                                         value ? value : "?unknown?",
                                         isString ? "\"" : "");
                         if(!buf) goto out;
                     }
                 }
@@ -199,18 +201,20 @@ static char* FormatJSFrame(JSContext* cx
 
     if(showLocals && callProps.array)
     {
         for(uint32 i = 0; i < callProps.length; i++)
         {
             JSPropertyDesc* desc = &callProps.array[i];
             if(desc->flags & JSPD_VARIABLE)
             {
-                name = JSVAL2String(cx, desc->id, nsnull);
-                value = JSVAL2String(cx, desc->value, &isString);
+                JSAutoByteString nameBytes;
+                JSAutoByteString valueBytes;
+                const char *name = JSVAL2String(cx, desc->id, nsnull, &nameBytes);
+                const char *value = JSVAL2String(cx, desc->value, &isString, &valueBytes);
 
                 if(name && value)
                 {
                     buf = JS_sprintf_append(buf, TAB "%s = %s%s%s\n",
                                             name,
                                             isString ? "\"" : "",
                                             value,
                                             isString ? "\"" : "");
@@ -222,22 +226,22 @@ static char* FormatJSFrame(JSContext* cx
 
     // print the value of 'this'
 
     if(showLocals)
     {
         if(gotThisVal)
         {
             JSString* thisValStr;
-            char* thisValChars;
+            JSAutoByteString thisValBytes;
 
             if(nsnull != (thisValStr = JS_ValueToString(cx, thisVal)) &&
-               nsnull != (thisValChars = JS_GetStringBytes(thisValStr)))
+               thisValBytes.encode(cx, thisValStr))
             {
-                buf = JS_sprintf_append(buf, TAB "this = %s\n", thisValChars);
+                buf = JS_sprintf_append(buf, TAB "this = %s\n", thisValBytes.ptr());
                 if(!buf) goto out;
             }
         }
         else
             buf = JS_sprintf_append(buf, TAB "<failed to get 'this' value>\n");
     }
 
     // print the properties of 'this', if it is an object
@@ -245,19 +249,20 @@ static char* FormatJSFrame(JSContext* cx
     if(showThisProps && thisProps.array)
     {
 
         for(uint32 i = 0; i < thisProps.length; i++)
         {
             JSPropertyDesc* desc = &thisProps.array[i];
             if(desc->flags & JSPD_ENUMERATE)
             {
-
-                name = JSVAL2String(cx, desc->id, nsnull);
-                value = JSVAL2String(cx, desc->value, &isString);
+                JSAutoByteString nameBytes;
+                JSAutoByteString valueBytes;
+                const char *name = JSVAL2String(cx, desc->id, nsnull, &nameBytes);
+                const char *value = JSVAL2String(cx, desc->value, &isString, &valueBytes);
                 if(name && value)
                 {
                     buf = JS_sprintf_append(buf, TAB "this.%s = %s%s%s\n",
                                             name,
                                             isString ? "\"" : "",
                                             value,
                                             isString ? "\"" : "");
                     if(!buf) goto out;
@@ -363,22 +368,22 @@ xpc_DumpEvalInJSStackFrame(JSContext* cx
 
     JSAutoRequest ar(cx);
 
     JSExceptionState* exceptionState = JS_SaveExceptionState(cx);
     JSErrorReporter older = JS_SetErrorReporter(cx, xpcDumpEvalErrorReporter);
 
     jsval rval;
     JSString* str;
-    const char* chars;
+    JSAutoByteString bytes;
     if(JS_EvaluateInStackFrame(cx, fp, text, strlen(text), "eval", 1, &rval) &&
        nsnull != (str = JS_ValueToString(cx, rval)) &&
-       nsnull != (chars = JS_GetStringBytes(str)))
+       bytes.encode(cx, str))
     {
-        printf("%s\n", chars);
+        printf("%s\n", bytes.ptr());
     }
     else
         puts("eval failed!");
     JS_SetErrorReporter(cx, older);
     JS_RestoreExceptionState(cx, exceptionState);
     return JS_TRUE;
 }
 
--- a/js/src/xpconnect/src/xpcquickstubs.cpp
+++ b/js/src/xpconnect/src/xpcquickstubs.cpp
@@ -556,19 +556,20 @@ ThrowCallFailed(JSContext *cx, nsresult 
 
     if(!nsXPCException::NameAndFormatForNSResult(
             NS_ERROR_XPC_NATIVE_RETURNED_FAILURE, nsnull, &format) ||
         !format)
     {
         format = "";
     }
 
+    JSAutoByteString memberNameBytes;
     if (!memberName) {
         memberName = JSID_IS_STRING(memberId)
-                     ? JS_GetStringBytes(JSID_TO_STRING(memberId))
+                     ? memberNameBytes.encode(cx, JSID_TO_STRING(memberId))
                      : "unknown";
     }
     if(nsXPCException::NameAndFormatForNSResult(rv, &name, nsnull)
         && name)
     {
         sz = JS_smprintf("%s 0x%x (%s) [%s.%s]",
                          format, rv, name, ifaceName, memberName);
     }
@@ -628,19 +629,20 @@ ThrowBadArg(JSContext *cx, nsresult rv, 
 
     // From XPCThrower::ThrowBadParam.
     char* sz;
     const char* format;
 
     if(!nsXPCException::NameAndFormatForNSResult(rv, nsnull, &format))
         format = "";
 
+    JSAutoByteString memberNameBytes;
     if (!memberName) {
         memberName = JSID_IS_STRING(memberId)
-                     ? JS_GetStringBytes(JSID_TO_STRING(memberId))
+                     ? memberNameBytes.encode(cx, JSID_TO_STRING(memberId))
                      : "unknown";
     }
     sz = JS_smprintf("%s arg %u [%s.%s]",
                      format, (unsigned int) paramnum, ifaceName, memberName);
 
     XPCThrower::BuildAndThrowException(cx, rv, sz);
 
     if(sz)
@@ -765,19 +767,24 @@ xpc_qsACString::xpc_qsACString(JSContext
         if(!s)
         {
             mValid = JS_FALSE;
             return;
         }
         *pval = STRING_TO_JSVAL(s);  // Root the new string.
     }
 
-    const char *bytes = JS_GetStringBytes(s);
-    size_t len = s->length();
-    new(mBuf) implementation_type(bytes, len);
+    JSAutoByteString bytes(cx, s);
+    if(!bytes)
+    {
+        mValid = JS_FALSE;
+        return;
+    }
+
+    new(mBuf) implementation_type(bytes.ptr(), strlen(bytes.ptr()));
     mValid = JS_TRUE;
 }
 
 static nsresult
 getNative(nsISupports *idobj,
           QITableEntry* entries,
           JSObject *obj,
           const nsIID &iid,
@@ -1005,38 +1012,35 @@ xpc_qsUnwrapArgImpl(JSContext *cx,
     {
         *ppArgRef = static_cast<nsISupports*>(*ppArg);
         *vp = OBJECT_TO_JSVAL(wrappedJS->GetJSObject());
     }
     return rv;
 }
 
 JSBool
-xpc_qsJsvalToCharStr(JSContext *cx, jsval v, jsval *pval, char **pstr)
+xpc_qsJsvalToCharStr(JSContext *cx, jsval v, JSAutoByteString *bytes)
 {
     JSString *str;
 
+    JS_ASSERT(!bytes->ptr());
     if(JSVAL_IS_STRING(v))
     {
         str = JSVAL_TO_STRING(v);
     }
     else if(JSVAL_IS_VOID(v) || JSVAL_IS_NULL(v))
     {
-        *pstr = NULL;
-        return JS_TRUE;
+        return true;
     }
     else
     {
         if(!(str = JS_ValueToString(cx, v)))
-            return JS_FALSE;
-        *pval = STRING_TO_JSVAL(str);  // Root the new string.
+            return false;
     }
-
-    *pstr = JS_GetStringBytes(str);
-    return JS_TRUE;
+    return !!bytes->encode(cx, str);
 }
 
 JSBool
 xpc_qsJsvalToWcharStr(JSContext *cx, jsval v, jsval *pval, PRUnichar **pstr)
 {
     JSString *str;
 
     if(JSVAL_IS_STRING(v))
--- a/js/src/xpconnect/src/xpcquickstubs.h
+++ b/js/src/xpconnect/src/xpcquickstubs.h
@@ -407,26 +407,25 @@ struct xpc_qsArgValArray
     js::AutoArrayRooter tvr;
     jsval array[N];
 };
 
 /**
  * Convert a jsval to char*, returning JS_TRUE on success.
  *
  * @param cx
- *      A context.
- * @param pval
- *     In/out. *pval is the jsval to convert; the function may write to *pval,
- *     using it as a GC root (like xpc_qsDOMString's constructor).
- * @param pstr
- *     Out. On success *pstr receives the converted string or NULL if *pval is
- *     null or undefined. Unicode data is garbled as with JS_GetStringBytes.
+ *     A context.
+ * @param v
+ *     A value to convert.
+ * @param bytes
+ *     Out. On success it receives the converted string unless v is null or
+ *     undefinedin which case bytes->ptr() remains null.
  */
 JSBool
-xpc_qsJsvalToCharStr(JSContext *cx, jsval v, jsval *pval, char **pstr);
+xpc_qsJsvalToCharStr(JSContext *cx, jsval v, JSAutoByteString *bytes);
 
 JSBool
 xpc_qsJsvalToWcharStr(JSContext *cx, jsval v, jsval *pval, PRUnichar **pstr);
 
 
 /** Convert an nsString to jsval, returning JS_TRUE on success.
  *  Note, the ownership of the string buffer may be moved from str to rval.
  *  If that happens, str will point to an empty string after this call.
--- a/js/src/xpconnect/src/xpcthrower.cpp
+++ b/js/src/xpconnect/src/xpcthrower.cpp
@@ -194,21 +194,23 @@ XPCThrower::Verbosify(XPCCallContext& cc
                 id = member->GetName();
             }
         }
         else
 #endif
         {
             id = ccx.GetMember()->GetName();
         }
-        const char *name = JSID_IS_VOID(id) ? "Unknown" : JS_GetStringBytes(JSID_TO_STRING(id));
-        sz = JS_smprintf("%s [%s.%s]",
-                         *psz,
-                         iface->GetNameString(),
-                         name);
+        JSAutoByteString bytes;
+        const char *name = JSID_IS_VOID(id) ? "Unknown" : bytes.encode(ccx, JSID_TO_STRING(id));
+        if(!name)
+        {
+            name = "";
+        }
+        sz = JS_smprintf("%s [%s.%s]", *psz, iface->GetNameString(), name);
     }
 
     if(sz)
     {
         if(own)
             JS_smprintf_free(*psz);
         *psz = sz;
     }
--- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp
@@ -345,23 +345,24 @@ DefinePropertyIfFound(XPCCallContext& cc
         }
         // This *might* be a tearoff name that is not yet part of our
         // set. Let's lookup the name and see if it is the name of an
         // interface. Then we'll see if the object actually *does* this
         // interface and add a tearoff as necessary.
 
         if(wrapperToReflectInterfaceNames)
         {
+            JSAutoByteString name;
             AutoMarkingNativeInterfacePtr iface2(ccx);
             XPCWrappedNativeTearOff* to;
             JSObject* jso;
 
             if(JSID_IS_STRING(id) &&
-               nsnull != (name = JS_GetStringBytes(JSID_TO_STRING(id))) &&
-               (iface2 = XPCNativeInterface::GetNewOrUsed(ccx, name), iface2) &&
+               name.encode(ccx, JSID_TO_STRING(id)) &&
+               (iface2 = XPCNativeInterface::GetNewOrUsed(ccx, name.ptr()), iface2) &&
                nsnull != (to = wrapperToReflectInterfaceNames->
                                     FindTearOff(ccx, iface2, JS_TRUE)) &&
                nsnull != (jso = to->GetJSObject()))
 
             {
                 AutoResolveName arn(ccx, id);
                 if(resolved)
                     *resolved = JS_TRUE;
--- a/js/src/xpconnect/tests/TestXPC.cpp
+++ b/js/src/xpconnect/tests/TestXPC.cpp
@@ -76,48 +76,52 @@ Print(JSContext *cx, uintN argc, jsval *
 {
     uintN i, n;
     JSString *str;
 
     jsval *argv = JS_ARGV(cx, vp);
     for (i = n = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
-            return JS_FALSE;
-        fprintf(gOutFile, "%s%s", i ? " " : "", JS_GetStringBytes(str));
+            return false;
+        JSAutoByteString bytes(cx, str);
+        if (!bytes)
+            return false;
+        fprintf(gOutFile, "%s%s", i ? " " : "", bytes.ptr());
     }
     n++;
     if (n)
         fputc('\n', gOutFile);
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return JS_TRUE;
+    return true;
 }
 
 static JSBool
 Load(JSContext *cx, uintN argc, jsval *vp)
 {
     uintN i;
     JSString *str;
-    const char *filename;
     JSScript *script;
     JSBool ok;
     jsval result;
 
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     jsval *argv = JS_ARGV(cx, vp);
     for (i = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
             return JS_FALSE;
         argv[i] = STRING_TO_JSVAL(str);
-        filename = JS_GetStringBytes(str);
-        script = JS_CompileFile(cx, obj, filename);
+        JSAutoByteString filename(cx, str);
+        if (!filename)
+            return false;
+        script = JS_CompileFile(cx, obj, filename.ptr());
         if (!script)
             ok = JS_FALSE;
         else {
             ok = JS_ExecuteScript(cx, obj, script, &result);
             JS_DestroyScript(cx, script);
         }
         if (!ok)
             return JS_FALSE;
--- a/js/src/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/src/xpconnect/wrappers/WrapperFactory.cpp
@@ -174,17 +174,17 @@ WrapperFactory::PrepareForWrapping(JSCon
             // newly-created WN will not have any useful functions or
             // properties on it. We detect that here and use the old WN's
             // set on the new wrapper.
 
 #ifdef DEBUG
             {
                 XPCNativeInterface *iface = newwn->GetSet()->GetInterfaceAt(0);
                 JSString *name = JSID_TO_STRING(iface->GetName());
-                NS_ASSERTION(!strcmp("nsISupports", JS_GetStringBytes(name)), "weird interface");
+                NS_ASSERTION(JS_MatchStringAndAscii(name, "nsISupports"), "weird interface");
             }
 #endif
 
             newwn->SetSet(wn->GetSet());
         }
 
     }
 
--- a/security/manager/ssl/src/nsCrypto.cpp
+++ b/security/manager/ssl/src/nsCrypto.cpp
@@ -865,65 +865,64 @@ cryptojs_generateOneKeyPair(JSContext *c
 static nsresult
 cryptojs_ReadArgsAndGenerateKey(JSContext *cx,
                                 jsval *argv,
                                 nsKeyPairInfo *keyGenType,
                                 nsIInterfaceRequestor *uiCxt,
                                 PK11SlotInfo **slot, PRBool willEscrow)
 {
   JSString  *jsString;
-  char    *params, *keyGenAlg; //Never free these strings cause
-                               //they are owned by the JS layer.
+  JSAutoByteString params, keyGenAlg;
   int    keySize;
   nsresult  rv;
 
   if (!JSVAL_IS_INT(argv[0])) {
     JS_ReportError(cx, "%s%s\n", JS_ERROR,
                    "passed in non-integer for key size");
     return NS_ERROR_FAILURE;
   }
   keySize = JSVAL_TO_INT(argv[0]);
-  if (JSVAL_IS_NULL(argv[1])) {
-    params = nsnull;
-  } else {
+  if (!JSVAL_IS_NULL(argv[1])) {
     jsString = JS_ValueToString(cx,argv[1]);
     NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
     argv[1] = STRING_TO_JSVAL(jsString);
-    params   = JS_GetStringBytes(jsString);
+    params.encode(cx, jsString);
+    NS_ENSURE_TRUE(!!params, NS_ERROR_OUT_OF_MEMORY);
   }
 
   if (JSVAL_IS_NULL(argv[2])) {
     JS_ReportError(cx,"%s%s\n", JS_ERROR,
              "key generation type not specified");
     return NS_ERROR_FAILURE;
   }
   jsString = JS_ValueToString(cx, argv[2]);
   NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
   argv[2] = STRING_TO_JSVAL(jsString);
-  keyGenAlg = JS_GetStringBytes(jsString);
-  keyGenType->keyGenType = cryptojs_interpret_key_gen_type(keyGenAlg);
+  keyGenAlg.encode(cx, jsString);
+  NS_ENSURE_TRUE(!!keyGenAlg, NS_ERROR_OUT_OF_MEMORY);
+  keyGenType->keyGenType = cryptojs_interpret_key_gen_type(keyGenAlg.ptr());
   if (keyGenType->keyGenType == invalidKeyGen) {
     JS_ReportError(cx, "%s%s%s", JS_ERROR,
                    "invalid key generation argument:",
-                   keyGenAlg);
+                   keyGenAlg.ptr());
     goto loser;
   }
   if (*slot == nsnull) {
     *slot = nsGetSlotForKeyGen(keyGenType->keyGenType, uiCxt);
     if (*slot == nsnull)
       goto loser;
   }
 
-  rv = cryptojs_generateOneKeyPair(cx,keyGenType,keySize,params,uiCxt,*slot,
-                                   willEscrow);
+  rv = cryptojs_generateOneKeyPair(cx,keyGenType,keySize,params.ptr(),uiCxt,
+                                   *slot,willEscrow);
 
   if (rv != NS_OK) {
     JS_ReportError(cx,"%s%s%s", JS_ERROR,
                    "could not generate the key for algorithm ",
-                   keyGenAlg);
+                   keyGenAlg.ptr());
     goto loser;
   }
   return NS_OK;
 loser:
   return NS_ERROR_FAILURE;
 }
 
 //Utility funciton to free up the memory used by nsKeyPairInfo
@@ -1844,75 +1843,72 @@ nsCrypto::GenerateCRMFRequest(nsIDOMCRMF
   if (JSVAL_IS_NULL(argv[0])) {
     JS_ReportError(cx, "%s%s\n", JS_ERROR, "no DN specified");
     return NS_ERROR_FAILURE;
   }
   
   JSString *jsString = JS_ValueToString(cx,argv[0]);
   NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
   argv[0] = STRING_TO_JSVAL(jsString);
-  
-  char * reqDN = JS_GetStringBytes(jsString);
-  char *regToken;
-  if (JSVAL_IS_NULL(argv[1])) {
-    regToken           = nsnull;
-  } else {
+  JSAutoByteString reqDN(cx,jsString);
+  NS_ENSURE_TRUE(!!reqDN, NS_ERROR_OUT_OF_MEMORY);
+
+  JSAutoByteString regToken;
+  if (!JSVAL_IS_NULL(argv[1])) {
     jsString = JS_ValueToString(cx, argv[1]);
     NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
     argv[1] = STRING_TO_JSVAL(jsString);
-
-    regToken = JS_GetStringBytes(jsString);
+    regToken.encode(cx, jsString);
+    NS_ENSURE_TRUE(!!regToken, NS_ERROR_OUT_OF_MEMORY);
   }
-  char *authenticator;
-  if (JSVAL_IS_NULL(argv[2])) {
-    authenticator           = nsnull;
-  } else {
+  JSAutoByteString authenticator;
+  if (!JSVAL_IS_NULL(argv[2])) {
     jsString      = JS_ValueToString(cx, argv[2]);
     NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
     argv[2] = STRING_TO_JSVAL(jsString);
-
-    authenticator = JS_GetStringBytes(jsString);
+    authenticator.encode(cx, jsString);
+    NS_ENSURE_TRUE(!!authenticator, NS_ERROR_OUT_OF_MEMORY);
   }
-  char *eaCert;
-  if (JSVAL_IS_NULL(argv[3])) {
-    eaCert           = nsnull;
-  } else {
+  JSAutoByteString eaCert;
+  if (!JSVAL_IS_NULL(argv[3])) {
     jsString     = JS_ValueToString(cx, argv[3]);
     NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
     argv[3] = STRING_TO_JSVAL(jsString);
-
-    eaCert       = JS_GetStringBytes(jsString);
+    eaCert.encode(cx, jsString);
+    NS_ENSURE_TRUE(!!eaCert, NS_ERROR_OUT_OF_MEMORY);
   }
   if (JSVAL_IS_NULL(argv[4])) {
     JS_ReportError(cx, "%s%s\n", JS_ERROR, "no completion "
                    "function specified");
     return NS_ERROR_FAILURE;
   }
   jsString = JS_ValueToString(cx, argv[4]);
   NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
   argv[4] = STRING_TO_JSVAL(jsString);
+  JSAutoByteString jsCallback(cx, jsString);
+  NS_ENSURE_TRUE(!!jsCallback, NS_ERROR_OUT_OF_MEMORY);
 
   nrv = xpc->WrapNative(cx, ::JS_GetGlobalObject(cx),
                         static_cast<nsIDOMCrypto *>(this),
                         NS_GET_IID(nsIDOMCrypto), getter_AddRefs(holder));
   NS_ENSURE_SUCCESS(nrv, nrv);
 
   nrv = holder->GetJSObject(&script_obj);
   NS_ENSURE_SUCCESS(nrv, nrv);
 
   //Put up some UI warning that someone is trying to 
   //escrow the private key.
   //Don't addref this copy.  That way ths reference goes away
   //at the same the nsIX09Cert ref goes away.
   nsNSSCertificate *escrowCert = nsnull;
   nsCOMPtr<nsIX509Cert> nssCert;
   PRBool willEscrow = PR_FALSE;
-  if (eaCert) {
+  if (!!eaCert) {
     SECItem certDer = {siBuffer, nsnull, 0};
-    SECStatus srv = ATOB_ConvertAsciiToItem(&certDer, eaCert);
+    SECStatus srv = ATOB_ConvertAsciiToItem(&certDer, eaCert.ptr());
     if (srv != SECSuccess) {
       return NS_ERROR_FAILURE;
     }
     CERTCertificate *cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
                                                     &certDer, nsnull, PR_FALSE,
                                                     PR_TRUE);
     if (!cert)
       return NS_ERROR_FAILURE;
@@ -1967,19 +1963,20 @@ nsCrypto::GenerateCRMFRequest(nsIDOMCRMF
       return nrv;
     }
   }
   // By this time we'd better have a slot for the key gen.
   NS_ASSERTION(slot, "There was no slot selected for key generation");
   if (slot) 
     PK11_FreeSlot(slot);
 
-  char *encodedRequest = nsCreateReqFromKeyPairs(keyids, numRequests,
-                                                 reqDN, regToken, 
-                                                 authenticator,escrowCert);
+  char *encodedRequest = nsCreateReqFromKeyPairs(keyids,numRequests,
+                                                 reqDN.ptr(),regToken.ptr(),
+                                                 authenticator.ptr(),
+                                                 escrowCert);
 #ifdef DEBUG_javi
   printf ("Created the folloing CRMF request:\n%s\n", encodedRequest);
 #endif
   if (!encodedRequest) {
     nsFreeKeyPairInfo(keyids, numRequests);
     return NS_ERROR_FAILURE;
   }                                                    
   nsCRMFObject *newObject = new nsCRMFObject();
@@ -2018,18 +2015,17 @@ nsCrypto::GenerateCRMFRequest(nsIDOMCRMF
   nsCryptoRunArgs *args = new nsCryptoRunArgs();
   if (!args)
     return NS_ERROR_OUT_OF_MEMORY;
 
   args->m_cx         = cx;
   args->m_kungFuDeathGrip = GetISupportsFromContext(cx);
   args->m_scope      = JS_GetParent(cx, script_obj);
 
-  char *jsCallback = JS_GetStringBytes(jsString);
-  args->m_jsCallback.Adopt(jsCallback ? nsCRT::strdup(jsCallback) : 0);
+  args->m_jsCallback.Adopt(!!jsCallback ? nsCRT::strdup(jsCallback.ptr()) : 0);
   args->m_principals = principals;
   
   nsCryptoRunnable *cryptoRunnable = new nsCryptoRunnable(args);
   if (!cryptoRunnable)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsresult rv = NS_DispatchToMainThread(cryptoRunnable);
   if (NS_FAILED(rv))
@@ -2545,42 +2541,45 @@ nsCrypto::SignText(const nsAString& aStr
   PRBool bestOnly = PR_TRUE;
   PRBool validOnly = PR_TRUE;
   CERTCertList* certList =
     CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(), certUsageEmailSigner,
                               bestOnly, validOnly, uiContext);
 
   PRUint32 numCAs = argc - 2;
   if (numCAs > 0) {
-    nsAutoArrayPtr<char*> caNames(new char*[numCAs]);
-    if (!caNames) {
+    jsval *argv = nsnull;
+    ncc->GetArgvPtr(&argv);
+
+    nsAutoArrayPtr<JSAutoByteString> caNameBytes(new JSAutoByteString[numCAs]);
+    if (!caNameBytes) {
       aResult.Append(internalError);
-
       return NS_OK;
     }
 
-    jsval *argv = nsnull;
-    ncc->GetArgvPtr(&argv);
-
     JSAutoRequest ar(cx);
 
     PRUint32 i;
     for (i = 2; i < argc; ++i) {
       JSString *caName = JS_ValueToString(cx, argv[i]);
       NS_ENSURE_TRUE(caName, NS_ERROR_OUT_OF_MEMORY);
       argv[i] = STRING_TO_JSVAL(caName);
-
-      if (!caName) {
-        aResult.Append(internalError);
-
-        return NS_OK;
-      }
-      caNames[i - 2] = JS_GetStringBytes(caName);
+      caNameBytes[i - 2].encode(cx, caName);
+      NS_ENSURE_TRUE(!!caNameBytes[i - 2], NS_ERROR_OUT_OF_MEMORY);
     }
 
+    nsAutoArrayPtr<char*> caNames(new char*[numCAs]);
+    if (!caNames) {
+      aResult.Append(internalError);
+      return NS_OK;
+    }
+
+    for (i = 0; i < numCAs; ++i)
+      caNames[i] = caNameBytes[i].ptr();
+
     if (certList &&
         CERT_FilterCertListByCANames(certList, numCAs, caNames,
                                      certUsageEmailSigner) != SECSuccess) {
       aResult.Append(internalError);
 
       return NS_OK;
     }
   }
--- a/storage/src/mozStorageStatementRow.cpp
+++ b/storage/src/mozStorageStatementRow.cpp
@@ -80,17 +80,19 @@ StatementRow::GetProperty(nsIXPConnectWr
                           JSObject *aScopeObj,
                           jsid aId,
                           jsval *_vp,
                           PRBool *_retval)
 {
   NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
 
   if (JSID_IS_STRING(aId)) {
-    nsDependentCString jsid(::JS_GetStringBytes(JSID_TO_STRING(aId)));
+    ::JSAutoByteString idBytes(aCtx, JSID_TO_STRING(aId));
+    NS_ENSURE_TRUE(!!idBytes, NS_ERROR_OUT_OF_MEMORY);
+    nsDependentCString jsid(idBytes.ptr());
 
     PRUint32 idx;
     nsresult rv = mStatement->GetColumnIndex(jsid, &idx);
     NS_ENSURE_SUCCESS(rv, rv);
     PRInt32 type;
     rv = mStatement->GetTypeOfIndex(idx, &type);
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -157,32 +159,31 @@ StatementRow::NewResolve(nsIXPConnectWra
                          JSObject **_objp,
                          PRBool *_retval)
 {
   NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
   // We do not throw at any point after this because we want to allow the
   // prototype chain to be checked for the property.
 
   if (JSID_IS_STRING(aId)) {
-    JSString *str = JSID_TO_STRING(aId);
-    nsDependentCString name(::JS_GetStringBytes(str));
+    ::JSAutoByteString idBytes(aCtx, JSID_TO_STRING(aId));
+    NS_ENSURE_TRUE(!!idBytes, NS_ERROR_OUT_OF_MEMORY);
+    nsDependentCString name(idBytes.ptr());
 
     PRUint32 idx;
     nsresult rv = mStatement->GetColumnIndex(name, &idx);
     if (NS_FAILED(rv)) {
       // It's highly likely that the name doesn't exist, so let the JS engine
       // check the prototype chain and throw if that doesn't have the property
       // either.
       *_objp = NULL;
       return NS_OK;
     }
 
-    *_retval = ::JS_DefineUCProperty(aCtx, aScopeObj, ::JS_GetStringChars(str),
-                                     ::JS_GetStringLength(str),
-                                     JSVAL_VOID,
+    *_retval = ::JS_DefinePropertyById(aCtx, aScopeObj, aId, JSVAL_VOID,
                                      nsnull, nsnull, 0);
     *_objp = aScopeObj;
     return NS_OK;
   }
 
   return NS_OK;
 }
 
--- a/xpinstall/src/nsJSInstallTriggerGlobal.cpp
+++ b/xpinstall/src/nsJSInstallTriggerGlobal.cpp
@@ -289,32 +289,31 @@ InstallTriggerGlobalInstall(JSContext *c
     trigger->SetPrincipal(principal);
 
     JSIdArray *ida = JS_Enumerate( cx, JSVAL_TO_OBJECT(argv[0]) );
     if ( ida )
     {
       jsval v;
       const PRUnichar *name, *URL;
       const PRUnichar *iconURL = nsnull;
-      const char *hash;
 
       for (int i = 0; i < ida->length && !abortLoad; i++ )
       {
         JS_IdToValue( cx, ida->vector[i], &v );
         JSString * str = JS_ValueToString( cx, v );
         if (!str)
         {
           abortLoad = PR_TRUE;
           break;
         }
 
         name = reinterpret_cast<const PRUnichar*>(JS_GetStringChars( str ));
 
         URL = iconURL = nsnull;
-        hash = nsnull;
+        JSAutoByteString hash;
         JS_GetUCProperty( cx, JSVAL_TO_OBJECT(argv[0]), reinterpret_cast<const jschar*>(name), nsCRT::strlen(name), &v );
         if ( JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) )
         {
           jsval v2;
           if (JS_GetProperty( cx, JSVAL_TO_OBJECT(v), "URL", &v2 ) && !JSVAL_IS_VOID(v2)) {
             JSString *str = JS_ValueToString(cx, v2);
             if (!str) {
               abortLoad = PR_TRUE;
@@ -329,21 +328,20 @@ InstallTriggerGlobalInstall(JSContext *c
               abortLoad = PR_TRUE;
               break;
             }
             iconURL = reinterpret_cast<const PRUnichar*>(JS_GetStringChars(str));
           }
 
           if (JS_GetProperty( cx, JSVAL_TO_OBJECT(v), "Hash", &v2) && !JSVAL_IS_VOID(v2)) {
             JSString *str = JS_ValueToString(cx, v2);
-            if (!str) {
+            if (!str || !hash.encode(cx, str)) {
               abortLoad = PR_TRUE;
               break;
             }
-            hash = reinterpret_cast<const char*>(JS_GetStringBytes(str));
           }
         }
         else
         {
           JSString *str = JS_ValueToString(cx, v);
           if (!str) {
             abortLoad = PR_TRUE;
             break;