Bug 1485066 - Part 2: Use UniqueChars as return-type in functions previously using JSAutoByteString out-param. r=Waldo
☠☠ backed out by 3d23c2f43b8a ☠ ☠
authorAndré Bargull <andre.bargull@gmail.com>
Wed, 05 Sep 2018 01:25:09 -0700
changeset 434758 c22fc17c9d87281c0c074ccb2c2f21fb9a3bf4dd
parent 434757 d35bb63dbc1d7c5892ee32c1f20aaab17ceaf9f5
child 434759 4f89260d5e30f7b77ddd05e15414be8036b1937e
push id107490
push usercsabou@mozilla.com
push dateWed, 05 Sep 2018 12:25:08 +0000
treeherdermozilla-inbound@e40f67f15bf1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1485066
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1485066 - Part 2: Use UniqueChars as return-type in functions previously using JSAutoByteString out-param. r=Waldo
js/src/builtin/TestingFunctions.cpp
js/src/ctypes/CTypes.cpp
js/src/jsfriendapi.cpp
js/src/shell/js.cpp
js/src/vm/BytecodeUtil.cpp
js/src/vm/EnvironmentObject.cpp
js/src/vm/Interpreter.cpp
js/src/vm/JSContext.cpp
js/src/vm/SelfHosting.cpp
js/src/vm/StringType.cpp
js/src/vm/StringType.h
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2192,18 +2192,17 @@ DumpHeap(JSContext* cx, unsigned argc, V
     if (args.length() > i) {
         Value v = args[i];
         if (v.isString()) {
             if (!fuzzingSafe) {
                 RootedString str(cx, v.toString());
                 UniqueChars fileNameBytes = JS_EncodeString(cx, str);
                 if (!fileNameBytes)
                     return false;
-                const char* fileName = fileNameBytes.get();
-                dumpFile = fopen(fileName, "w");
+                dumpFile = fopen(fileNameBytes.get(), "w");
                 if (!dumpFile) {
                     fileNameBytes = JS_EncodeStringToUTF8(cx, str);
                     if (!fileNameBytes)
                         return false;
                     JS_ReportErrorUTF8(cx, "can't open %s", fileNameBytes.get());
                     return false;
                 }
             }
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -977,21 +977,20 @@ static const JSErrorFormatString ErrorFo
 static const JSErrorFormatString*
 GetErrorMessage(void* userRef, const unsigned errorNumber)
 {
   if (0 < errorNumber && errorNumber < CTYPESERR_LIMIT)
     return &ErrorFormatString[errorNumber];
   return nullptr;
 }
 
-static const char*
-EncodeLatin1(JSContext* cx, AutoString& str, JS::UniqueChars& bytes)
-{
-  bytes = JS_EncodeString(cx, NewUCString(cx, str.finish()));
-  return bytes.get();
+static JS::UniqueChars
+EncodeLatin1(JSContext* cx, AutoString& str)
+{
+  return JS_EncodeString(cx, NewUCString(cx, str.finish()));
 }
 
 static const char*
 CTypesToSourceForError(JSContext* cx, HandleValue val, JS::UniqueChars& bytes)
 {
   if (val.isObject()) {
       RootedObject obj(cx, &val.toObject());
       if (CType::IsCType(obj) || CData::IsCDataMaybeUnwrap(&obj)) {
@@ -1193,122 +1192,114 @@ ConvError(JSContext* cx, const char* exp
     switch (CType::GetTypeCode(arrObj)) {
     case TYPE_array: {
       MOZ_ASSERT(!funObj);
 
       char indexStr[16];
       SprintfLiteral(indexStr, "%u", arrIndex);
 
       AutoString arrSource;
-      JS::UniqueChars arrBytes;
       BuildTypeSource(cx, arrObj, true, arrSource);
       if (!arrSource)
           return false;
-      const char* arrStr = EncodeLatin1(cx, arrSource, arrBytes);
+      JS::UniqueChars arrStr = EncodeLatin1(cx, arrSource);
       if (!arrStr)
         return false;
 
       JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                                  CTYPESMSG_CONV_ERROR_ARRAY,
-                                 valStr, indexStr, arrStr);
+                                 valStr, indexStr, arrStr.get());
       break;
     }
     case TYPE_struct: {
       JSFlatString* name = GetFieldName(arrObj, arrIndex);
       MOZ_ASSERT(name);
-      JS::UniqueChars nameBytes = JS_EncodeString(cx, name);
-      const char* nameStr = nameBytes.get();
+      JS::UniqueChars nameStr = JS_EncodeString(cx, name);
       if (!nameStr)
         return false;
 
       AutoString structSource;
-      JS::UniqueChars structBytes;
       BuildTypeSource(cx, arrObj, true, structSource);
       if (!structSource)
           return false;
-      const char* structStr = EncodeLatin1(cx, structSource, structBytes);
+      JS::UniqueChars structStr = EncodeLatin1(cx, structSource);
       if (!structStr)
         return false;
 
-      JS::UniqueChars posBytes;
-      const char* posStr;
+      JS::UniqueChars posStr;
       if (funObj) {
         AutoString posSource;
         BuildConversionPosition(cx, convType, funObj, argIndex, posSource);
         if (!posSource)
             return false;
-        posStr = EncodeLatin1(cx, posSource, posBytes);
+        posStr = EncodeLatin1(cx, posSource);
         if (!posStr)
           return false;
-      } else {
-        posStr = "";
       }
 
       JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                                  CTYPESMSG_CONV_ERROR_STRUCT,
-                                 valStr, nameStr, expectedStr, structStr, posStr);
+                                 valStr, nameStr.get(), expectedStr, structStr.get(),
+                                 (posStr ? posStr.get() : ""));
       break;
     }
     default:
       MOZ_CRASH("invalid arrObj value");
     }
     return false;
   }
 
   switch (convType) {
   case ConversionType::Argument: {
     MOZ_ASSERT(funObj);
 
     char indexStr[16];
     SprintfLiteral(indexStr, "%u", argIndex + 1);
 
     AutoString funSource;
-    JS::UniqueChars funBytes;
     BuildFunctionTypeSource(cx, funObj, funSource);
     if (!funSource)
         return false;
-    const char* funStr = EncodeLatin1(cx, funSource, funBytes);
+    JS::UniqueChars funStr = EncodeLatin1(cx, funSource);
     if (!funStr)
       return false;
 
     JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                                CTYPESMSG_CONV_ERROR_ARG,
-                               valStr, indexStr, funStr);
+                               valStr, indexStr, funStr.get());
     break;
   }
   case ConversionType::Finalizer: {
     MOZ_ASSERT(funObj);
 
     AutoString funSource;
-    JS::UniqueChars funBytes;
     BuildFunctionTypeSource(cx, funObj, funSource);
     if (!funSource)
         return false;
-    const char* funStr = EncodeLatin1(cx, funSource, funBytes);
+    JS::UniqueChars funStr = EncodeLatin1(cx, funSource);
     if (!funStr)
       return false;
 
     JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                               CTYPESMSG_CONV_ERROR_FIN, valStr, funStr);
+                               CTYPESMSG_CONV_ERROR_FIN, valStr, funStr.get());
     break;
   }
   case ConversionType::Return: {
     MOZ_ASSERT(funObj);
 
     AutoString funSource;
-    JS::UniqueChars funBytes;
     BuildFunctionTypeSource(cx, funObj, funSource);
     if (!funSource)
         return false;
-    const char* funStr = EncodeLatin1(cx, funSource, funBytes);
+    JS::UniqueChars funStr = EncodeLatin1(cx, funSource);
     if (!funStr)
       return false;
 
     JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                               CTYPESMSG_CONV_ERROR_RET, valStr, funStr);
+                               CTYPESMSG_CONV_ERROR_RET, valStr, funStr.get());
     break;
   }
   case ConversionType::Setter:
   case ConversionType::Construct:
     MOZ_ASSERT(!funObj);
 
     JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                                CTYPESMSG_CONV_ERROR_SET, valStr, expectedStr);
@@ -1322,25 +1313,24 @@ static bool
 ConvError(JSContext* cx, HandleObject expectedType, HandleValue actual,
           ConversionType convType,
           HandleObject funObj = nullptr, unsigned argIndex = 0,
           HandleObject arrObj = nullptr, unsigned arrIndex = 0)
 {
   MOZ_ASSERT(CType::IsCType(expectedType));
 
   AutoString expectedSource;
-  JS::UniqueChars expectedBytes;
   BuildTypeSource(cx, expectedType, true, expectedSource);
   if (!expectedSource)
       return false;
-  const char* expectedStr = EncodeLatin1(cx, expectedSource, expectedBytes);
+  JS::UniqueChars expectedStr = EncodeLatin1(cx, expectedSource);
   if (!expectedStr)
     return false;
 
-  return ConvError(cx, expectedStr, actual, convType, funObj, argIndex,
+  return ConvError(cx, expectedStr.get(), actual, convType, funObj, argIndex,
                    arrObj, arrIndex);
 }
 
 static bool
 ArgumentConvError(JSContext* cx, HandleValue actual, const char* funStr,
                   unsigned argIndex)
 {
   JS::UniqueChars valBytes;
@@ -1378,27 +1368,26 @@ ArrayLengthMismatch(JSContext* cx, unsig
     return false;
 
   char expectedLengthStr[16];
   SprintfLiteral(expectedLengthStr, "%u", expectedLength);
   char actualLengthStr[16];
   SprintfLiteral(actualLengthStr, "%u", actualLength);
 
   AutoString arrSource;
-  JS::UniqueChars arrBytes;
   BuildTypeSource(cx, arrObj, true, arrSource);
   if (!arrSource)
       return false;
-  const char* arrStr = EncodeLatin1(cx, arrSource, arrBytes);
+  JS::UniqueChars arrStr = EncodeLatin1(cx, arrSource);
   if (!arrStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_ARRAY_MISMATCH,
-                             valStr, arrStr, expectedLengthStr, actualLengthStr);
+                             valStr, arrStr.get(), expectedLengthStr, actualLengthStr);
   return false;
 }
 
 static bool
 ArrayLengthOverflow(JSContext* cx, unsigned expectedLength, HandleObject arrObj,
                     unsigned actualLength, HandleValue actual,
                     ConversionType convType)
 {
@@ -1410,27 +1399,26 @@ ArrayLengthOverflow(JSContext* cx, unsig
     return false;
 
   char expectedLengthStr[16];
   SprintfLiteral(expectedLengthStr, "%u", expectedLength);
   char actualLengthStr[16];
   SprintfLiteral(actualLengthStr, "%u", actualLength);
 
   AutoString arrSource;
-  JS::UniqueChars arrBytes;
   BuildTypeSource(cx, arrObj, true, arrSource);
   if (!arrSource)
       return false;
-  const char* arrStr = EncodeLatin1(cx, arrSource, arrBytes);
+  JS::UniqueChars arrStr = EncodeLatin1(cx, arrSource);
   if (!arrStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_ARRAY_OVERFLOW,
-                             valStr, arrStr, expectedLengthStr, actualLengthStr);
+                             valStr, arrStr.get(), expectedLengthStr, actualLengthStr);
   return false;
 }
 
 static bool
 ArgumentRangeMismatch(JSContext* cx, const char* func, const char* range)
 {
   JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                             CTYPESMSG_ARG_RANGE_MISMATCH, func, range);
@@ -1452,54 +1440,50 @@ CannotConstructError(JSContext* cx, cons
   JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                             CTYPESMSG_CANNOT_CONSTRUCT, type);
   return false;
 }
 
 static bool
 DuplicateFieldError(JSContext* cx, Handle<JSFlatString*> name)
 {
-  JS::UniqueChars nameBytes = JS_EncodeString(cx, name);
-  const char* nameStr = nameBytes.get();
+  JS::UniqueChars nameStr = JS_EncodeString(cx, name);
   if (!nameStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                             CTYPESMSG_DUPLICATE_FIELD, nameStr);
+                             CTYPESMSG_DUPLICATE_FIELD, nameStr.get());
   return false;
 }
 
 static bool
 EmptyFinalizerCallError(JSContext* cx, const char* funName)
 {
   JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                             CTYPESMSG_EMPTY_FIN_CALL, funName);
   return false;
 }
 
 static bool
 EmptyFinalizerError(JSContext* cx, ConversionType convType,
                     HandleObject funObj = nullptr, unsigned argIndex = 0)
 {
-  JS::UniqueChars posBytes;
-  const char* posStr;
+  JS::UniqueChars posStr;
   if (funObj) {
     AutoString posSource;
     BuildConversionPosition(cx, convType, funObj, argIndex, posSource);
     if (!posSource)
         return false;
-    posStr = EncodeLatin1(cx, posSource, posBytes);
+    posStr = EncodeLatin1(cx, posSource);
     if (!posStr)
       return false;
-  } else {
-    posStr = "";
   }
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                             CTYPESMSG_EMPTY_FIN, posStr);
+                             CTYPESMSG_EMPTY_FIN, (posStr ? posStr.get() : ""));
   return false;
 }
 
 static bool
 FieldCountMismatch(JSContext* cx,
                    unsigned expectedCount, HandleObject structObj,
                    unsigned actualCount, HandleValue actual,
                    ConversionType convType,
@@ -1508,47 +1492,43 @@ FieldCountMismatch(JSContext* cx,
   MOZ_ASSERT(structObj && CType::IsCType(structObj));
 
   JS::UniqueChars valBytes;
   const char* valStr = CTypesToSourceForError(cx, actual, valBytes);
   if (!valStr)
     return false;
 
   AutoString structSource;
-  JS::UniqueChars structBytes;
   BuildTypeSource(cx, structObj, true, structSource);
   if (!structSource)
       return false;
-  const char* structStr = EncodeLatin1(cx, structSource, structBytes);
+  JS::UniqueChars structStr = EncodeLatin1(cx, structSource);
   if (!structStr)
     return false;
 
   char expectedCountStr[16];
   SprintfLiteral(expectedCountStr, "%u", expectedCount);
   char actualCountStr[16];
   SprintfLiteral(actualCountStr, "%u", actualCount);
 
-  JS::UniqueChars posBytes;
-  const char* posStr;
+  JS::UniqueChars posStr;
   if (funObj) {
     AutoString posSource;
     BuildConversionPosition(cx, convType, funObj, argIndex, posSource);
     if (!posSource)
         return false;
-    posStr = EncodeLatin1(cx, posSource, posBytes);
+    posStr = EncodeLatin1(cx, posSource);
     if (!posStr)
       return false;
-  } else {
-    posStr = "";
   }
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_FIELD_MISMATCH,
-                             valStr, structStr, expectedCountStr, actualCountStr,
-                             posStr);
+                             valStr, structStr.get(), expectedCountStr, actualCountStr,
+                             (posStr ? posStr.get() : ""));
   return false;
 }
 
 static bool
 FieldDescriptorCountError(JSContext* cx, HandleValue typeVal, size_t length)
 {
   JS::UniqueChars valBytes;
   const char* valStr = CTypesToSourceForError(cx, typeVal, valBytes);
@@ -1582,23 +1562,22 @@ FieldDescriptorSizeError(JSContext* cx, 
 {
   RootedValue typeVal(cx, ObjectValue(*typeObj));
   JS::UniqueChars typeBytes;
   const char* typeStr = CTypesToSourceForError(cx, typeVal, typeBytes);
   if (!typeStr)
     return false;
 
   RootedString idStr(cx, IdToString(cx, id));
-  JS::UniqueChars idBytes = JS_EncodeString(cx, idStr);
-  const char* propStr = idBytes.get();
+  JS::UniqueChars propStr = JS_EncodeString(cx, idStr);
   if (!propStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                             CTYPESMSG_FIELD_DESC_SIZE, typeStr, propStr);
+                             CTYPESMSG_FIELD_DESC_SIZE, typeStr, propStr.get());
   return false;
 }
 
 static bool
 FieldDescriptorNameTypeError(JSContext* cx, HandleValue typeVal)
 {
   JS::UniqueChars valBytes;
   const char* valStr = CTypesToSourceForError(cx, typeVal, valBytes);
@@ -1614,100 +1593,96 @@ static bool
 FieldDescriptorTypeError(JSContext* cx, HandleValue poroVal, HandleId id)
 {
   JS::UniqueChars typeBytes;
   const char* typeStr = CTypesToSourceForError(cx, poroVal, typeBytes);
   if (!typeStr)
     return false;
 
   RootedString idStr(cx, IdToString(cx, id));
-  JS::UniqueChars idBytes = JS_EncodeString(cx, idStr);
-  const char* propStr = idBytes.get();
+  JS::UniqueChars propStr = JS_EncodeString(cx, idStr);
   if (!propStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                             CTYPESMSG_FIELD_DESC_TYPE, typeStr, propStr);
+                             CTYPESMSG_FIELD_DESC_TYPE, typeStr, propStr.get());
   return false;
 }
 
 static bool
 FieldMissingError(JSContext* cx, JSObject* typeObj, JSFlatString* name_)
 {
   JS::UniqueChars typeBytes;
   RootedString name(cx, name_);
   RootedValue typeVal(cx, ObjectValue(*typeObj));
   const char* typeStr = CTypesToSourceForError(cx, typeVal, typeBytes);
   if (!typeStr)
     return false;
 
-  JS::UniqueChars nameBytes = JS_EncodeString(cx, name);
-  const char* nameStr = nameBytes.get();
+  JS::UniqueChars nameStr = JS_EncodeString(cx, name);
   if (!nameStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                             CTYPESMSG_FIELD_MISSING, typeStr, nameStr);
+                             CTYPESMSG_FIELD_MISSING, typeStr, nameStr.get());
   return false;
 }
 
 static bool
 FinalizerSizeError(JSContext* cx, HandleObject funObj, HandleValue actual)
 {
   MOZ_ASSERT(CType::IsCType(funObj));
 
   JS::UniqueChars valBytes;
   const char* valStr = CTypesToSourceForError(cx, actual, valBytes);
   if (!valStr)
     return false;
 
   AutoString funSource;
-  JS::UniqueChars funBytes;
   BuildFunctionTypeSource(cx, funObj, funSource);
   if (!funSource)
       return false;
-  const char* funStr = EncodeLatin1(cx, funSource, funBytes);
+  JS::UniqueChars funStr = EncodeLatin1(cx, funSource);
   if (!funStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                             CTYPESMSG_FIN_SIZE_ERROR, funStr, valStr);
+                             CTYPESMSG_FIN_SIZE_ERROR, funStr.get(), valStr);
   return false;
 }
 
 static bool
 FunctionArgumentLengthMismatch(JSContext* cx,
                                unsigned expectedCount, unsigned actualCount,
                                HandleObject funObj, HandleObject typeObj,
                                bool isVariadic)
 {
   AutoString funSource;
-  JS::UniqueChars funBytes;
   Value slot = JS_GetReservedSlot(funObj, SLOT_REFERENT);
   if (!slot.isUndefined() && Library::IsLibrary(&slot.toObject())) {
     BuildFunctionTypeSource(cx, funObj, funSource);
   } else {
     BuildFunctionTypeSource(cx, typeObj, funSource);
   }
   if (!funSource)
       return false;
-  const char* funStr = EncodeLatin1(cx, funSource, funBytes);
+  JS::UniqueChars funStr = EncodeLatin1(cx, funSource);
   if (!funStr)
     return false;
 
   char expectedCountStr[16];
   SprintfLiteral(expectedCountStr, "%u", expectedCount);
   char actualCountStr[16];
   SprintfLiteral(actualCountStr, "%u", actualCount);
 
   const char* variadicStr = isVariadic ? " or more": "";
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_ARG_COUNT_MISMATCH,
-                             funStr, expectedCountStr, variadicStr,
+                             funStr.get(), expectedCountStr, variadicStr,
                              actualCountStr);
   return false;
 }
 
 static bool
 FunctionArgumentTypeError(JSContext* cx,
                           uint32_t index, HandleValue typeVal, const char* reason)
 {
@@ -1835,26 +1810,25 @@ InvalidIndexRangeError(JSContext* cx, si
 }
 
 static bool
 NonPrimitiveError(JSContext* cx, HandleObject typeObj)
 {
   MOZ_ASSERT(CType::IsCType(typeObj));
 
   AutoString typeSource;
-  JS::UniqueChars typeBytes;
   BuildTypeSource(cx, typeObj, true, typeSource);
   if (!typeSource)
       return false;
-  const char* typeStr = EncodeLatin1(cx, typeSource, typeBytes);
+  JS::UniqueChars typeStr = EncodeLatin1(cx, typeSource);
   if (!typeStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                             CTYPESMSG_NON_PRIMITIVE, typeStr);
+                             CTYPESMSG_NON_PRIMITIVE, typeStr.get());
   return false;
 }
 
 static bool
 NonStringBaseError(JSContext* cx, HandleValue thisVal)
 {
   JS::UniqueChars valBytes;
   const char* valStr = CTypesToSourceForError(cx, thisVal, valBytes);
@@ -1891,32 +1865,30 @@ PropNameNonStringError(JSContext* cx, Ha
     return false;
 
   JS::UniqueChars idBytes;
   RootedValue idVal(cx, IdToValue(id));
   const char* propStr = CTypesToSourceForError(cx, idVal, idBytes);
   if (!propStr)
     return false;
 
-  JS::UniqueChars posBytes;
-  const char* posStr;
+  JS::UniqueChars posStr;
   if (funObj) {
     AutoString posSource;
     BuildConversionPosition(cx, convType, funObj, argIndex, posSource);
     if (!posSource)
         return false;
-    posStr = EncodeLatin1(cx, posSource, posBytes);
+    posStr = EncodeLatin1(cx, posSource);
     if (!posStr)
       return false;
-  } else {
-    posStr = "";
   }
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                             CTYPESMSG_PROP_NONSTRING, propStr, valStr, posStr);
+                             CTYPESMSG_PROP_NONSTRING, propStr, valStr,
+                             (posStr ? posStr.get() : ""));
   return false;
 }
 
 static bool
 SizeOverflow(JSContext* cx, const char* name, const char* limit)
 {
   JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                             CTYPESMSG_SIZE_OVERFLOW, name, limit);
@@ -1948,60 +1920,57 @@ TypeOverflow(JSContext* cx, const char* 
                              CTYPESMSG_TYPE_OVERFLOW, valStr, expected);
   return false;
 }
 
 static bool
 UndefinedSizeCastError(JSContext* cx, HandleObject targetTypeObj)
 {
   AutoString targetTypeSource;
-  JS::UniqueChars targetTypeBytes;
   BuildTypeSource(cx, targetTypeObj, true, targetTypeSource);
   if (!targetTypeSource)
       return false;
-  const char* targetTypeStr = EncodeLatin1(cx, targetTypeSource, targetTypeBytes);
+  JS::UniqueChars targetTypeStr = EncodeLatin1(cx, targetTypeSource);
   if (!targetTypeStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                             CTYPESMSG_UNDEFINED_SIZE_CAST, targetTypeStr);
+                             CTYPESMSG_UNDEFINED_SIZE_CAST, targetTypeStr.get());
   return false;
 }
 
 static bool
 SizeMismatchCastError(JSContext* cx,
                       HandleObject sourceTypeObj, HandleObject targetTypeObj,
                       size_t sourceSize, size_t targetSize)
 {
   AutoString sourceTypeSource;
-  JS::UniqueChars sourceTypeBytes;
   BuildTypeSource(cx, sourceTypeObj, true, sourceTypeSource);
   if (!sourceTypeSource)
       return false;
-  const char* sourceTypeStr = EncodeLatin1(cx, sourceTypeSource, sourceTypeBytes);
+  JS::UniqueChars sourceTypeStr = EncodeLatin1(cx, sourceTypeSource);
   if (!sourceTypeStr)
     return false;
 
   AutoString targetTypeSource;
-  JS::UniqueChars targetTypeBytes;
   BuildTypeSource(cx, targetTypeObj, true, targetTypeSource);
   if (!targetTypeSource)
       return false;
-  const char* targetTypeStr = EncodeLatin1(cx, targetTypeSource, targetTypeBytes);
+  JS::UniqueChars targetTypeStr = EncodeLatin1(cx, targetTypeSource);
   if (!targetTypeStr)
     return false;
 
   char sourceSizeStr[16];
   char targetSizeStr[16];
   SprintfLiteral(sourceSizeStr, "%zu", sourceSize);
   SprintfLiteral(targetSizeStr, "%zu", targetSize);
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_SIZE_MISMATCH_CAST,
-                             targetTypeStr, sourceTypeStr,
+                             targetTypeStr.get(), sourceTypeStr.get(),
                              targetSizeStr, sourceSizeStr);
   return false;
 }
 
 static bool
 UndefinedSizePointerError(JSContext* cx, const char* action, HandleObject obj)
 {
   JS::UniqueChars valBytes;
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -828,19 +828,19 @@ FormatValue(JSContext* cx, const Value& 
         str = ToString<CanGC>(cx, v);
     } else {
         str = ToString<CanGC>(cx, v);
     }
 
     if (!str)
         return nullptr;
     bytes = JS_EncodeString(cx, str);
+    if (!bytes)
+        return nullptr;
     const char* buf = bytes.get();
-    if (!buf)
-        return nullptr;
     const char* found = strstr(buf, "function ");
     if (found && (found - buf <= 2))
         return "[function]";
     return buf;
 }
 
 // Wrapper for JS_sprintf_append() that reports allocation failure to the
 // context.
@@ -889,20 +889,19 @@ FormatFrame(JSContext* cx, const FrameIt
         if (!GetFunctionThis(cx, iter.abstractFramePtr(), &thisVal))
             return nullptr;
     }
 
     // print the frame number and function name
     JS::UniqueChars buf(std::move(inBuf));
     if (funname) {
         UniqueChars funbytes = JS_EncodeString(cx, funname);
-        char* str = funbytes.get();
-        if (!str)
+        if (!funbytes)
             return nullptr;
-        buf = sprintf_append(cx, std::move(buf), "%d %s(", num, str);
+        buf = sprintf_append(cx, std::move(buf), "%d %s(", num, funbytes.get());
     } else if (fun) {
         buf = sprintf_append(cx, std::move(buf), "%d anonymous(", num);
     } else {
         buf = sprintf_append(cx, std::move(buf), "%d <TOP LEVEL>", num);
     }
     if (!buf)
         return nullptr;
 
@@ -991,20 +990,19 @@ FormatFrame(JSContext* cx, const FrameIt
             RootedString thisValStr(cx, ToString<CanGC>(cx, thisVal));
             if (!thisValStr) {
                 if (cx->isThrowingOutOfMemory())
                     return nullptr;
                 cx->clearPendingException();
             }
             if (thisValStr) {
                 thisValBytes = JS_EncodeString(cx, thisValStr);
-                const char* str = thisValBytes.get();
-                if (!str)
+                if (!thisValBytes)
                     return nullptr;
-                buf = sprintf_append(cx, std::move(buf), "    this = %s\n", str);
+                buf = sprintf_append(cx, std::move(buf), "    this = %s\n", thisValBytes.get());
             } else {
                 buf = sprintf_append(cx, std::move(buf), "    <failed to get 'this' value>\n");
             }
             if (!buf)
                 return nullptr;
         }
     }
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1609,20 +1609,19 @@ ParseCompileOptions(JSContext* cx, Compi
         return false;
     if (v.isNull()) {
         options.setFile(nullptr);
     } else if (!v.isUndefined()) {
         s = ToString(cx, v);
         if (!s)
             return false;
         fileNameBytes = JS_EncodeString(cx, s);
-        char* fileName = fileNameBytes.get();
-        if (!fileName)
-            return false;
-        options.setFile(fileName);
+        if (!fileNameBytes)
+            return false;
+        options.setFile(fileNameBytes.get());
     }
 
     if (!JS_GetProperty(cx, opts, "element", &v))
         return false;
     if (v.isObject())
         options.setElement(&v.toObject());
 
     if (!JS_GetProperty(cx, opts, "elementAttributeName", &v))
@@ -4755,21 +4754,20 @@ BinParse(JSContext* cx, unsigned argc, V
             stringFormat = optionFormat.toString();
             JS::Rooted<JSLinearString*> linearFormat(cx);
             linearFormat = stringFormat->ensureLinear(cx);
             if (StringEqualsAscii(linearFormat, "multipart")) {
                 useMultipart = true;
             } else if (StringEqualsAscii(linearFormat, "simple")) {
                 useMultipart = false;
             } else {
-                UniqueChars printable;
+                UniqueChars printable = ValueToPrintableUTF8(cx, optionFormat);
                 JS_ReportErrorUTF8(cx,
                                    "Unknown value for option `format`, expected 'multipart' or "
-                                   "'simple', got %s",
-                                   ValueToPrintableUTF8(cx, optionFormat, &printable));
+                                   "'simple', got %s", printable.get());
                 return false;
             }
         } else {
             const char* typeName = InformalValueTypeName(optionFormat);
             JS_ReportErrorASCII(cx, "option `format` should be a string, got %s", typeName);
             return false;
         }
     }
--- a/js/src/vm/BytecodeUtil.cpp
+++ b/js/src/vm/BytecodeUtil.cpp
@@ -1125,67 +1125,63 @@ js::DumpScript(JSContext* cx, JSScript* 
     if (!sprinter.init())
         return false;
     RootedScript script(cx, scriptArg);
     bool ok = Disassemble(cx, script, true, &sprinter);
     fprintf(fp, "%s", sprinter.string());
     return ok;
 }
 
-static bool
-ToDisassemblySource(JSContext* cx, HandleValue v, UniqueChars* bytes)
+static UniqueChars
+ToDisassemblySource(JSContext* cx, HandleValue v)
 {
     if (v.isString()) {
         Sprinter sprinter(cx);
         if (!sprinter.init())
-            return false;
+            return nullptr;
         char* nbytes = QuoteString(&sprinter, v.toString(), '"');
         if (!nbytes)
-            return false;
+            return nullptr;
         UniqueChars copy = JS_smprintf("%s", nbytes);
         if (!copy) {
             ReportOutOfMemory(cx);
-            return false;
+            return nullptr;
         }
-        *bytes = std::move(copy);
-        return true;
+        return copy;
     }
 
     if (JS::RuntimeHeapIsBusy()) {
         UniqueChars source = JS_smprintf("<value>");
         if (!source) {
             ReportOutOfMemory(cx);
-            return false;
+            return nullptr;
         }
-        *bytes = std::move(source);
-        return true;
+        return source;
     }
 
     if (v.isObject()) {
         JSObject& obj = v.toObject();
 
         if (obj.is<JSFunction>()) {
             RootedFunction fun(cx, &obj.as<JSFunction>());
             JSString* str = JS_DecompileFunction(cx, fun);
             if (!str)
-                return false;
-            *bytes = JS_EncodeString(cx, str);
-            return !!*bytes;
+                return nullptr;
+            return JS_EncodeString(cx, str);
         }
 
         if (obj.is<RegExpObject>()) {
             JSString* source = obj.as<RegExpObject>().toString(cx);
             if (!source)
-                return false;
-            *bytes = JS_EncodeString(cx, source);
-            return !!*bytes;
+                return nullptr;
+            return JS_EncodeString(cx, source);
         }
     }
 
-    return !!ValueToPrintableLatin1(cx, v, bytes, true);
+    return ValueToPrintableLatin1(cx, v, true);
 }
 
 static bool
 ToDisassemblySource(JSContext* cx, HandleScope scope, UniqueChars* bytes)
 {
     UniqueChars source = JS_smprintf("%s {", ScopeKindString(scope->kind()));
     if (!source) {
         ReportOutOfMemory(cx);
@@ -1428,70 +1424,70 @@ Disassemble1(JSContext* cx, HandleScript
         if (!sp->jsprintf(" %s", bytes.get()))
             return 0;
         break;
       }
 
       case JOF_ENVCOORD: {
         RootedValue v(cx,
             StringValue(EnvironmentCoordinateName(cx->caches().envCoordinateNameCache, script, pc)));
-        UniqueChars bytes;
-        if (!ToDisassemblySource(cx, v, &bytes))
+        UniqueChars bytes = ToDisassemblySource(cx, v);
+        if (!bytes)
             return 0;
         EnvironmentCoordinate ec(pc);
         if (!sp->jsprintf(" %s (hops = %u, slot = %u)", bytes.get(), ec.hops(), ec.slot()))
             return 0;
         break;
       }
 
       case JOF_ATOM: {
         RootedValue v(cx, StringValue(script->getAtom(GET_UINT32_INDEX(pc))));
-        UniqueChars bytes;
-        if (!ToDisassemblySource(cx, v, &bytes))
+        UniqueChars bytes = ToDisassemblySource(cx, v);
+        if (!bytes)
             return 0;
         if (!sp->jsprintf(" %s", bytes.get()))
             return 0;
         break;
       }
 
       case JOF_DOUBLE: {
         RootedValue v(cx, script->getConst(GET_UINT32_INDEX(pc)));
-        UniqueChars bytes;
-        if (!ToDisassemblySource(cx, v, &bytes))
+        UniqueChars bytes = ToDisassemblySource(cx, v);
+        if (!bytes)
             return 0;
         if (!sp->jsprintf(" %s", bytes.get()))
             return 0;
         break;
       }
 
       case JOF_OBJECT: {
         /* Don't call obj.toSource if analysis/inference is active. */
         if (script->zone()->types.activeAnalysis) {
             if (!sp->jsprintf(" object"))
                 return 0;
             break;
         }
 
         JSObject* obj = script->getObject(GET_UINT32_INDEX(pc));
         {
-            UniqueChars bytes;
             RootedValue v(cx, ObjectValue(*obj));
-            if (!ToDisassemblySource(cx, v, &bytes))
+            UniqueChars bytes = ToDisassemblySource(cx, v);
+            if (!bytes)
                 return 0;
             if (!sp->jsprintf(" %s", bytes.get()))
                 return 0;
         }
         break;
       }
 
       case JOF_REGEXP: {
         js::RegExpObject* obj = script->getRegExp(pc);
-        UniqueChars bytes;
         RootedValue v(cx, ObjectValue(*obj));
-        if (!ToDisassemblySource(cx, v, &bytes))
+        UniqueChars bytes = ToDisassemblySource(cx, v);
+        if (!bytes)
             return 0;
         if (!sp->jsprintf(" %s", bytes.get()))
             return 0;
         break;
       }
 
       case JOF_TABLESWITCH:
       {
--- a/js/src/vm/EnvironmentObject.cpp
+++ b/js/src/vm/EnvironmentObject.cpp
@@ -1409,18 +1409,17 @@ LiveEnvironmentVal::staticAsserts()
 
 /*****************************************************************************/
 
 namespace {
 
 static void
 ReportOptimizedOut(JSContext* cx, HandleId id)
 {
-    UniqueChars printable;
-    if (ValueToPrintableLatin1(cx, IdToValue(id), &printable)) {
+    if (UniqueChars printable = ValueToPrintableLatin1(cx, IdToValue(id))) {
         JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_OPTIMIZED_OUT,
                                    printable.get());
     }
 }
 
 /*
  * DebugEnvironmentProxy is the handler for DebugEnvironmentProxy proxy
  * objects. Having a custom handler (rather than trying to reuse js::Wrapper)
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -5334,18 +5334,17 @@ js::NewArrayOperationWithTemplate(JSCont
     return obj;
 }
 
 void
 js::ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber, HandleId id)
 {
     MOZ_ASSERT(errorNumber == JSMSG_UNINITIALIZED_LEXICAL ||
                errorNumber == JSMSG_BAD_CONST_ASSIGN);
-    UniqueChars printable;
-    if (ValueToPrintableLatin1(cx, IdToValue(id), &printable))
+    if (UniqueChars printable = ValueToPrintableLatin1(cx, IdToValue(id)))
         JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, errorNumber, printable.get());
 }
 
 void
 js::ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber, HandlePropertyName name)
 {
     RootedId id(cx, NameToId(name));
     ReportRuntimeLexicalError(cx, errorNumber, id);
--- a/js/src/vm/JSContext.cpp
+++ b/js/src/vm/JSContext.cpp
@@ -887,20 +887,18 @@ js::ReportErrorNumberUCArray(JSContext* 
     ReportError(cx, &report, callback, userRef);
 
     return warning;
 }
 
 void
 js::ReportIsNotDefined(JSContext* cx, HandleId id)
 {
-    UniqueChars printable;
-    if (!ValueToPrintableUTF8(cx, IdToValue(id), &printable))
-        return;
-    JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_NOT_DEFINED, printable.get());
+    if (UniqueChars printable = ValueToPrintableUTF8(cx, IdToValue(id)))
+        JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_NOT_DEFINED, printable.get());
 }
 
 void
 js::ReportIsNotDefined(JSContext* cx, HandlePropertyName name)
 {
     RootedId id(cx, NameToId(name));
     ReportIsNotDefined(cx, id);
 }
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -298,20 +298,17 @@ ThrowErrorWithType(JSContext* cx, JSExnT
         if (val.isInt32()) {
             JSString* str = ToString<CanGC>(cx, val);
             if (!str)
                 return;
             errorArgs[i - 1] = JS_EncodeString(cx, str);
         } else if (val.isString()) {
             errorArgs[i - 1] = JS_EncodeString(cx, val.toString());
         } else {
-            UniqueChars bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, val, nullptr);
-            if (!bytes)
-                return;
-            errorArgs[i - 1] = std::move(bytes);
+            errorArgs[i - 1] = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, val, nullptr);
         }
         if (!errorArgs[i - 1])
             return;
     }
 
     JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, errorNumber,
                                errorArgs[0].get(), errorArgs[1].get(), errorArgs[2].get());
 }
--- a/js/src/vm/StringType.cpp
+++ b/js/src/vm/StringType.cpp
@@ -2057,48 +2057,45 @@ js::EncodeLatin1(JSContext* cx, JSString
     if (!buf)
         return nullptr;
 
     mozilla::PodCopy(buf, linear->latin1Chars(nogc), len);
     buf[len] = '\0';
     return UniqueChars(reinterpret_cast<char*>(buf));
 }
 
-const char*
-js::ValueToPrintableLatin1(JSContext* cx, const Value& vArg, UniqueChars* bytes,
-                           bool asSource)
+UniqueChars
+js::ValueToPrintableLatin1(JSContext* cx, const Value& vArg, bool asSource)
 {
     RootedValue v(cx, vArg);
     JSString* str;
     if (asSource)
         str = ValueToSource(cx, v);
     else
         str = ToString<CanGC>(cx, v);
     if (!str)
         return nullptr;
     str = QuoteString(cx, str, 0);
     if (!str)
         return nullptr;
-    *bytes = JS_EncodeString(cx, str);
-    return bytes->get();
+    return JS_EncodeString(cx, str);
 }
 
-const char*
-js::ValueToPrintableUTF8(JSContext* cx, const Value& vArg, UniqueChars* bytes, bool asSource)
+UniqueChars
+js::ValueToPrintableUTF8(JSContext* cx, const Value& vArg, bool asSource)
 {
     RootedValue v(cx, vArg);
-    JSString* str;
+    RootedString str(cx);
     if (asSource)
-        str = ValueToSource(cx, v);
+        str.set(ValueToSource(cx, v));
     else
-        str = ToString<CanGC>(cx, v);
+        str.set(ToString<CanGC>(cx, v));
     if (!str)
         return nullptr;
-    *bytes = JS_EncodeStringToUTF8(cx, RootedString(cx, str));
-    return bytes->get();
+    return JS_EncodeStringToUTF8(cx, str);
 }
 
 template <AllowGC allowGC>
 JSString*
 js::ToStringSlow(JSContext* cx, typename MaybeRooted<Value, allowGC>::HandleType arg)
 {
     /* As with ToObjectSlow, callers must verify that |arg| isn't a string. */
     MOZ_ASSERT(!arg.isString());
--- a/js/src/vm/StringType.h
+++ b/js/src/vm/StringType.h
@@ -1680,25 +1680,24 @@ EncodeLatin1(JSContext* cx, JSString* st
 /*
  * Convert a value to a printable C string.
  *
  * As the function name implies, any characters in a converted printable string will be Latin1
  * characters. If there are any non-Latin1 characters in the original value, then those characters
  * will be changed to Unicode escape sequences(I.e. \udddd, dddd are 4 hex digits) in the printable
  * string.
  */
-extern const char*
-ValueToPrintableLatin1(JSContext* cx, const Value&, UniqueChars* bytes,
-                       bool asSource = false);
+extern UniqueChars
+ValueToPrintableLatin1(JSContext* cx, const Value&, bool asSource = false);
 
 /*
  * Convert a value to a printable C string encoded in UTF-8.
  */
-extern const char*
-ValueToPrintableUTF8(JSContext* cx, const Value&, UniqueChars* bytes, bool asSource = false);
+extern UniqueChars
+ValueToPrintableUTF8(JSContext* cx, const Value&, bool asSource = false);
 
 /*
  * Convert a non-string value to a string, returning null after reporting an
  * error, otherwise returning a new string reference.
  */
 template <AllowGC allowGC>
 extern JSString*
 ToStringSlow(JSContext* cx, typename MaybeRooted<Value, allowGC>::HandleType arg);