Bug 1490605 - Part 1: Reduce code duplication when stringifying error arguments in ctypes code. r=arai
☠☠ backed out by 0c6b0c2d4c82 ☠ ☠
authorAndré Bargull <andre.bargull@gmail.com>
Thu, 13 Sep 2018 01:26:40 -0700
changeset 436143 e54bd8035b432be2957306fb318aeb821b842dc0
parent 436142 72f155506bf6a902b640e4e20122d175edfeca33
child 436144 e911dd693280b7e00716c32f56fe1a946386bd56
push id107794
push userapavel@mozilla.com
push dateThu, 13 Sep 2018 12:35:45 +0000
treeherdermozilla-inbound@29c2fa7d40f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1490605
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 1490605 - Part 1: Reduce code duplication when stringifying error arguments in ctypes code. r=arai
js/src/ctypes/CTypes.cpp
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -1170,16 +1170,65 @@ GetFieldName(HandleObject structObj, uns
   }
   return nullptr;
 }
 
 static void
 BuildTypeSource(JSContext* cx, JSObject* typeObj_, bool makeShort,
                 AutoString& result);
 
+static JS::UniqueChars
+TypeSourceForError(JSContext* cx, JSObject* typeObj)
+{
+  AutoString source;
+  BuildTypeSource(cx, typeObj, true, source);
+  if (!source)
+    return nullptr;
+  return EncodeLatin1(cx, source);
+}
+
+static JS::UniqueChars
+FunctionTypeSourceForError(JSContext* cx, HandleObject funObj)
+{
+  AutoString funSource;
+  BuildFunctionTypeSource(cx, funObj, funSource);
+  if (!funSource)
+    return nullptr;
+  return EncodeLatin1(cx, funSource);
+}
+
+static JS::UniqueChars
+ConversionPositionForError(JSContext* cx, ConversionType convType, HandleObject funObj,
+                           unsigned argIndex)
+{
+  AutoString posSource;
+  BuildConversionPosition(cx, convType, funObj, argIndex, posSource);
+  if (!posSource)
+    return nullptr;
+  return EncodeLatin1(cx, posSource);
+}
+
+class IndexCString final
+{
+    char indexStr[21]; // space for UINT64_MAX plus terminating null
+
+  public:
+    explicit IndexCString(unsigned index)
+    {
+      SprintfLiteral(indexStr, "%u", index);
+    }
+
+    explicit IndexCString(size_t index)
+    {
+      SprintfLiteral(indexStr, "%zu", index);
+    }
+
+    const char* get() const { return indexStr; }
+};
+
 static bool
 ConvError(JSContext* cx, const char* expectedStr, HandleValue actual,
           ConversionType convType,
           HandleObject funObj = nullptr, unsigned argIndex = 0,
           HandleObject arrObj = nullptr, unsigned arrIndex = 0)
 {
   JS::UniqueChars valBytes;
   const char* valStr = CTypesToSourceForError(cx, actual, valBytes);
@@ -1188,54 +1237,41 @@ ConvError(JSContext* cx, const char* exp
 
   if (arrObj) {
     MOZ_ASSERT(CType::IsCType(arrObj));
 
     switch (CType::GetTypeCode(arrObj)) {
     case TYPE_array: {
       MOZ_ASSERT(!funObj);
 
-      char indexStr[16];
-      SprintfLiteral(indexStr, "%u", arrIndex);
-
-      AutoString arrSource;
-      BuildTypeSource(cx, arrObj, true, arrSource);
-      if (!arrSource)
-          return false;
-      JS::UniqueChars arrStr = EncodeLatin1(cx, arrSource);
+      IndexCString indexStr(arrIndex);
+
+      JS::UniqueChars arrStr = TypeSourceForError(cx, arrObj);
       if (!arrStr)
         return false;
 
       JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                                  CTYPESMSG_CONV_ERROR_ARRAY,
-                                 valStr, indexStr, arrStr.get());
+                                 valStr, indexStr.get(), arrStr.get());
       break;
     }
     case TYPE_struct: {
       JSFlatString* name = GetFieldName(arrObj, arrIndex);
       MOZ_ASSERT(name);
       JS::UniqueChars nameStr = JS_EncodeStringToLatin1(cx, name);
       if (!nameStr)
         return false;
 
-      AutoString structSource;
-      BuildTypeSource(cx, arrObj, true, structSource);
-      if (!structSource)
-          return false;
-      JS::UniqueChars structStr = EncodeLatin1(cx, structSource);
+      JS::UniqueChars structStr = TypeSourceForError(cx, arrObj);
       if (!structStr)
         return false;
 
       JS::UniqueChars posStr;
       if (funObj) {
-        AutoString posSource;
-        BuildConversionPosition(cx, convType, funObj, argIndex, posSource);
-        if (!posSource)
-            return false;
-        posStr = EncodeLatin1(cx, posSource);
+        posStr = ConversionPositionForError(cx, convType, funObj, argIndex);
         if (!posStr)
           return false;
       }
 
       JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                                  CTYPESMSG_CONV_ERROR_STRUCT,
                                  valStr, nameStr.get(), expectedStr, structStr.get(),
                                  (posStr ? posStr.get() : ""));
@@ -1246,55 +1282,42 @@ ConvError(JSContext* cx, const char* exp
     }
     return false;
   }
 
   switch (convType) {
   case ConversionType::Argument: {
     MOZ_ASSERT(funObj);
 
-    char indexStr[16];
-    SprintfLiteral(indexStr, "%u", argIndex + 1);
-
-    AutoString funSource;
-    BuildFunctionTypeSource(cx, funObj, funSource);
-    if (!funSource)
-        return false;
-    JS::UniqueChars funStr = EncodeLatin1(cx, funSource);
+    IndexCString indexStr(argIndex + 1);
+
+    JS::UniqueChars funStr = FunctionTypeSourceForError(cx, funObj);
     if (!funStr)
       return false;
 
     JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                                CTYPESMSG_CONV_ERROR_ARG,
-                               valStr, indexStr, funStr.get());
+                               valStr, indexStr.get(), funStr.get());
     break;
   }
   case ConversionType::Finalizer: {
     MOZ_ASSERT(funObj);
 
-    AutoString funSource;
-    BuildFunctionTypeSource(cx, funObj, funSource);
-    if (!funSource)
-        return false;
-    JS::UniqueChars funStr = EncodeLatin1(cx, funSource);
+    JS::UniqueChars funStr = FunctionTypeSourceForError(cx, funObj);
     if (!funStr)
       return false;
 
     JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                                CTYPESMSG_CONV_ERROR_FIN, valStr, funStr.get());
     break;
   }
   case ConversionType::Return: {
     MOZ_ASSERT(funObj);
 
-    AutoString funSource;
-    BuildFunctionTypeSource(cx, funObj, funSource);
-    if (!funSource)
-        return false;
-    JS::UniqueChars funStr = EncodeLatin1(cx, funSource);
+    JS::UniqueChars funStr = FunctionTypeSourceForError(cx, funObj);
     if (!funStr)
       return false;
 
     JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                                CTYPESMSG_CONV_ERROR_RET, valStr, funStr.get());
     break;
   }
   case ConversionType::Setter:
@@ -1312,42 +1335,37 @@ ConvError(JSContext* cx, const char* exp
 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;
-  BuildTypeSource(cx, expectedType, true, expectedSource);
-  if (!expectedSource)
-      return false;
-  JS::UniqueChars expectedStr = EncodeLatin1(cx, expectedSource);
+  JS::UniqueChars expectedStr = TypeSourceForError(cx, expectedType);
   if (!expectedStr)
     return false;
 
   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;
   const char* valStr = CTypesToSourceForError(cx, actual, valBytes);
   if (!valStr)
     return false;
 
-  char indexStr[16];
-  SprintfLiteral(indexStr, "%u", argIndex + 1);
+  IndexCString indexStr(argIndex + 1);
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                             CTYPESMSG_CONV_ERROR_ARG, valStr, indexStr, funStr);
+                             CTYPESMSG_CONV_ERROR_ARG, valStr, indexStr.get(), funStr);
   return false;
 }
 
 static bool
 ArgumentLengthError(JSContext* cx, const char* fun, const char* count,
                     const char* s)
 {
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
@@ -1362,63 +1380,51 @@ ArrayLengthMismatch(JSContext* cx, unsig
 {
   MOZ_ASSERT(arrObj && CType::IsCType(arrObj));
 
   JS::UniqueChars valBytes;
   const char* valStr = CTypesToSourceForError(cx, actual, valBytes);
   if (!valStr)
     return false;
 
-  char expectedLengthStr[16];
-  SprintfLiteral(expectedLengthStr, "%u", expectedLength);
-  char actualLengthStr[16];
-  SprintfLiteral(actualLengthStr, "%u", actualLength);
-
-  AutoString arrSource;
-  BuildTypeSource(cx, arrObj, true, arrSource);
-  if (!arrSource)
-      return false;
-  JS::UniqueChars arrStr = EncodeLatin1(cx, arrSource);
+  IndexCString expectedLengthStr(expectedLength);
+  IndexCString actualLengthStr(actualLength);
+
+  JS::UniqueChars arrStr = TypeSourceForError(cx, arrObj);
   if (!arrStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_ARRAY_MISMATCH,
-                             valStr, arrStr.get(), expectedLengthStr, actualLengthStr);
+                             valStr, arrStr.get(), expectedLengthStr.get(), actualLengthStr.get());
   return false;
 }
 
 static bool
 ArrayLengthOverflow(JSContext* cx, unsigned expectedLength, HandleObject arrObj,
                     unsigned actualLength, HandleValue actual,
                     ConversionType convType)
 {
   MOZ_ASSERT(arrObj && CType::IsCType(arrObj));
 
   JS::UniqueChars valBytes;
   const char* valStr = CTypesToSourceForError(cx, actual, valBytes);
   if (!valStr)
     return false;
 
-  char expectedLengthStr[16];
-  SprintfLiteral(expectedLengthStr, "%u", expectedLength);
-  char actualLengthStr[16];
-  SprintfLiteral(actualLengthStr, "%u", actualLength);
-
-  AutoString arrSource;
-  BuildTypeSource(cx, arrObj, true, arrSource);
-  if (!arrSource)
-      return false;
-  JS::UniqueChars arrStr = EncodeLatin1(cx, arrSource);
+  IndexCString expectedLengthStr(expectedLength);
+  IndexCString actualLengthStr(actualLength);
+
+  JS::UniqueChars arrStr = TypeSourceForError(cx, arrObj);
   if (!arrStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_ARRAY_OVERFLOW,
-                             valStr, arrStr.get(), expectedLengthStr, actualLengthStr);
+                             valStr, arrStr.get(), expectedLengthStr.get(), actualLengthStr.get());
   return false;
 }
 
 static bool
 ArgumentRangeMismatch(JSContext* cx, const char* func, const char* range)
 {
   JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                             CTYPESMSG_ARG_RANGE_MISMATCH, func, range);
@@ -1463,21 +1469,17 @@ EmptyFinalizerCallError(JSContext* cx, c
 }
 
 static bool
 EmptyFinalizerError(JSContext* cx, ConversionType convType,
                     HandleObject funObj = nullptr, unsigned argIndex = 0)
 {
   JS::UniqueChars posStr;
   if (funObj) {
-    AutoString posSource;
-    BuildConversionPosition(cx, convType, funObj, argIndex, posSource);
-    if (!posSource)
-        return false;
-    posStr = EncodeLatin1(cx, posSource);
+    posStr = ConversionPositionForError(cx, convType, funObj, argIndex);
     if (!posStr)
       return false;
   }
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_EMPTY_FIN, (posStr ? posStr.get() : ""));
   return false;
 }
@@ -1491,60 +1493,49 @@ 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;
-  BuildTypeSource(cx, structObj, true, structSource);
-  if (!structSource)
-      return false;
-  JS::UniqueChars structStr = EncodeLatin1(cx, structSource);
+  JS::UniqueChars structStr = TypeSourceForError(cx, structObj);
   if (!structStr)
     return false;
 
-  char expectedCountStr[16];
-  SprintfLiteral(expectedCountStr, "%u", expectedCount);
-  char actualCountStr[16];
-  SprintfLiteral(actualCountStr, "%u", actualCount);
+  IndexCString expectedCountStr(expectedCount);
+  IndexCString actualCountStr(actualCount);
 
   JS::UniqueChars posStr;
   if (funObj) {
-    AutoString posSource;
-    BuildConversionPosition(cx, convType, funObj, argIndex, posSource);
-    if (!posSource)
-        return false;
-    posStr = EncodeLatin1(cx, posSource);
+    posStr = ConversionPositionForError(cx, convType, funObj, argIndex);
     if (!posStr)
       return false;
   }
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_FIELD_MISMATCH,
-                             valStr, structStr.get(), expectedCountStr, actualCountStr,
+                             valStr, structStr.get(), expectedCountStr.get(), actualCountStr.get(),
                              (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);
   if (!valStr)
     return false;
 
-  char lengthStr[16];
-  SprintfLiteral(lengthStr, "%zu", length);
+  IndexCString lengthStr(length);
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                             CTYPESMSG_FIELD_DESC_COUNT, valStr, lengthStr);
+                             CTYPESMSG_FIELD_DESC_COUNT, valStr, lengthStr.get());
   return false;
 }
 
 static bool
 FieldDescriptorNameError(JSContext* cx, HandleId id)
 {
   JS::UniqueChars idBytes;
   RootedValue idVal(cx, IdToValue(id));
@@ -1631,77 +1622,67 @@ FinalizerSizeError(JSContext* cx, Handle
 {
   MOZ_ASSERT(CType::IsCType(funObj));
 
   JS::UniqueChars valBytes;
   const char* valStr = CTypesToSourceForError(cx, actual, valBytes);
   if (!valStr)
     return false;
 
-  AutoString funSource;
-  BuildFunctionTypeSource(cx, funObj, funSource);
-  if (!funSource)
-      return false;
-  JS::UniqueChars funStr = EncodeLatin1(cx, funSource);
+  JS::UniqueChars funStr = FunctionTypeSourceForError(cx, funObj);
   if (!funStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              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 funStr;
   Value slot = JS_GetReservedSlot(funObj, SLOT_REFERENT);
   if (!slot.isUndefined() && Library::IsLibrary(&slot.toObject())) {
-    BuildFunctionTypeSource(cx, funObj, funSource);
+    funStr = FunctionTypeSourceForError(cx, funObj);
   } else {
-    BuildFunctionTypeSource(cx, typeObj, funSource);
-  }
-  if (!funSource)
-      return false;
-  JS::UniqueChars funStr = EncodeLatin1(cx, funSource);
+    funStr = FunctionTypeSourceForError(cx, typeObj);
+  }
   if (!funStr)
     return false;
 
-  char expectedCountStr[16];
-  SprintfLiteral(expectedCountStr, "%u", expectedCount);
-  char actualCountStr[16];
-  SprintfLiteral(actualCountStr, "%u", actualCount);
+  IndexCString expectedCountStr(expectedCount);
+  IndexCString actualCountStr(actualCount);
 
   const char* variadicStr = isVariadic ? " or more": "";
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_ARG_COUNT_MISMATCH,
-                             funStr.get(), expectedCountStr, variadicStr,
-                             actualCountStr);
+                             funStr.get(), expectedCountStr.get(), variadicStr,
+                             actualCountStr.get());
   return false;
 }
 
 static bool
 FunctionArgumentTypeError(JSContext* cx,
                           uint32_t index, HandleValue typeVal, const char* reason)
 {
   JS::UniqueChars valBytes;
   const char* valStr = CTypesToSourceForError(cx, typeVal, valBytes);
   if (!valStr)
     return false;
 
-  char indexStr[16];
-  SprintfLiteral(indexStr, "%u", index + 1);
+  IndexCString indexStr(index + 1);
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_ARG_TYPE_ERROR,
-                             indexStr, reason, valStr);
+                             indexStr.get(), reason, valStr);
   return false;
 }
 
 static bool
 FunctionReturnTypeError(JSContext* cx, HandleValue type, const char* reason)
 {
   JS::UniqueChars valBytes;
   const char* valStr = CTypesToSourceForError(cx, type, valBytes);
@@ -1793,37 +1774,30 @@ InvalidIndexError(JSContext* cx, HandleI
 {
   RootedValue idVal(cx, IdToValue(id));
   return InvalidIndexError(cx, idVal);
 }
 
 static bool
 InvalidIndexRangeError(JSContext* cx, size_t index, size_t length)
 {
-  char indexStr[16];
-  SprintfLiteral(indexStr, "%zu", index);
-
-  char lengthStr[16];
-  SprintfLiteral(lengthStr,"%zu", length);
+  IndexCString indexStr(index);
+  IndexCString lengthStr(length);
 
   JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                            CTYPESMSG_INVALID_RANGE, indexStr, lengthStr);
+                            CTYPESMSG_INVALID_RANGE, indexStr.get(), lengthStr.get());
   return false;
 }
 
 static bool
 NonPrimitiveError(JSContext* cx, HandleObject typeObj)
 {
   MOZ_ASSERT(CType::IsCType(typeObj));
 
-  AutoString typeSource;
-  BuildTypeSource(cx, typeObj, true, typeSource);
-  if (!typeSource)
-      return false;
-  JS::UniqueChars typeStr = EncodeLatin1(cx, typeSource);
+  JS::UniqueChars typeStr = TypeSourceForError(cx, typeObj);
   if (!typeStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_NON_PRIMITIVE, typeStr.get());
   return false;
 }
 
@@ -1867,21 +1841,17 @@ PropNameNonStringError(JSContext* cx, Ha
   JS::UniqueChars idBytes;
   RootedValue idVal(cx, IdToValue(id));
   const char* propStr = CTypesToSourceForError(cx, idVal, idBytes);
   if (!propStr)
     return false;
 
   JS::UniqueChars posStr;
   if (funObj) {
-    AutoString posSource;
-    BuildConversionPosition(cx, convType, funObj, argIndex, posSource);
-    if (!posSource)
-        return false;
-    posStr = EncodeLatin1(cx, posSource);
+    posStr = ConversionPositionForError(cx, convType, funObj, argIndex);
     if (!posStr)
       return false;
   }
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_PROP_NONSTRING, propStr, valStr,
                              (posStr ? posStr.get() : ""));
   return false;
@@ -1919,59 +1889,45 @@ TypeOverflow(JSContext* cx, const char* 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_TYPE_OVERFLOW, valStr, expected);
   return false;
 }
 
 static bool
 UndefinedSizeCastError(JSContext* cx, HandleObject targetTypeObj)
 {
-  AutoString targetTypeSource;
-  BuildTypeSource(cx, targetTypeObj, true, targetTypeSource);
-  if (!targetTypeSource)
-      return false;
-  JS::UniqueChars targetTypeStr = EncodeLatin1(cx, targetTypeSource);
+  JS::UniqueChars targetTypeStr = TypeSourceForError(cx, targetTypeObj);
   if (!targetTypeStr)
     return false;
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              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;
-  BuildTypeSource(cx, sourceTypeObj, true, sourceTypeSource);
-  if (!sourceTypeSource)
-      return false;
-  JS::UniqueChars sourceTypeStr = EncodeLatin1(cx, sourceTypeSource);
+  JS::UniqueChars sourceTypeStr = TypeSourceForError(cx, sourceTypeObj);
   if (!sourceTypeStr)
     return false;
 
-  AutoString targetTypeSource;
-  BuildTypeSource(cx, targetTypeObj, true, targetTypeSource);
-  if (!targetTypeSource)
-      return false;
-  JS::UniqueChars targetTypeStr = EncodeLatin1(cx, targetTypeSource);
+  JS::UniqueChars targetTypeStr = TypeSourceForError(cx, targetTypeObj);
   if (!targetTypeStr)
     return false;
 
-  char sourceSizeStr[16];
-  char targetSizeStr[16];
-  SprintfLiteral(sourceSizeStr, "%zu", sourceSize);
-  SprintfLiteral(targetSizeStr, "%zu", targetSize);
+  IndexCString sourceSizeStr(sourceSize);
+  IndexCString targetSizeStr(targetSize);
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
                              CTYPESMSG_SIZE_MISMATCH_CAST,
                              targetTypeStr.get(), sourceTypeStr.get(),
-                             targetSizeStr, sourceSizeStr);
+                             targetSizeStr.get(), sourceSizeStr.get());
   return false;
 }
 
 static bool
 UndefinedSizePointerError(JSContext* cx, const char* action, HandleObject obj)
 {
   JS::UniqueChars valBytes;
   RootedValue val(cx, ObjectValue(*obj));
@@ -1987,21 +1943,20 @@ UndefinedSizePointerError(JSContext* cx,
 static bool
 VariadicArgumentTypeError(JSContext* cx, uint32_t index, HandleValue actual)
 {
   JS::UniqueChars valBytes;
   const char* valStr = CTypesToSourceForError(cx, actual, valBytes);
   if (!valStr)
     return false;
 
-  char indexStr[16];
-  SprintfLiteral(indexStr, "%u", index + 1);
+  IndexCString indexStr(index + 1);
 
   JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
-                             CTYPESMSG_VARG_TYPE_ERROR, indexStr, valStr);
+                             CTYPESMSG_VARG_TYPE_ERROR, indexStr.get(), valStr);
   return false;
 }
 
 MOZ_MUST_USE JSObject*
 GetThisObject(JSContext* cx, const CallArgs& args, const char* msg)
 {
   if (!args.thisv().isObject()) {
     IncompatibleThisProto(cx, msg, args.thisv());