Bug 1623957 - Part 1: Replace mozilla::IsSame with std::is_same. r=jwalden
authorAndré Bargull <andre.bargull@gmail.com>
Sat, 21 Mar 2020 15:08:24 +0000
changeset 520002 d6d34d4374a7642a3f9ddfa5efad7d6ad50927e6
parent 520001 63ce44e5ef6ebd36ebb66b2ab1d092b32a42612b
child 520003 eb49edf618494a8068af83f4cf4da7315a364182
push id110801
push usershindli@mozilla.com
push dateSat, 21 Mar 2020 15:31:45 +0000
treeherderautoland@61a44ad12b15 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs1623957
milestone76.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 1623957 - Part 1: Replace mozilla::IsSame with std::is_same. r=jwalden Differential Revision: https://phabricator.services.mozilla.com/D67648
js/public/CallArgs.h
js/public/MemoryMetrics.h
js/src/builtin/String.cpp
js/src/builtin/intl/CommonFunctions.h
js/src/frontend/BinASTParser.cpp
js/src/frontend/BinASTParserPerTokenizer.h
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/frontend/TokenStream.cpp
js/src/gc/AtomMarking-inl.h
js/src/gc/AtomMarking.cpp
js/src/gc/Marking-inl.h
js/src/gc/Marking.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/JitOptions.cpp
js/src/threading/Thread.h
js/src/vm/EnvironmentObject.h
js/src/vm/JSContext-inl.h
js/src/vm/RegExpObject.cpp
js/src/vm/StringType.cpp
--- a/js/public/CallArgs.h
+++ b/js/public/CallArgs.h
@@ -60,17 +60,18 @@
  * methods' implementations, potentially under time pressure.
  */
 
 #ifndef js_CallArgs_h
 #define js_CallArgs_h
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/TypeTraits.h"
+
+#include <type_traits>
 
 #include "jstypes.h"
 
 #include "js/RootingAPI.h"
 #include "js/Value.h"
 
 /* Typedef for native functions called by the JS VM. */
 using JSNative = bool (*)(JSContext* cx, unsigned argc, JS::Value* vp);
@@ -107,18 +108,18 @@ class MOZ_STACK_CLASS NoUsedRval {
   bool usedRval() const { return false; }
   void setUsedRval() const {}
   void clearUsedRval() const {}
   void assertUnusedRval() const {}
 };
 
 template <class WantUsedRval>
 class MOZ_STACK_CLASS CallArgsBase {
-  static_assert(mozilla::IsSame<WantUsedRval, IncludeUsedRval>::value ||
-                    mozilla::IsSame<WantUsedRval, NoUsedRval>::value,
+  static_assert(std::is_same_v<WantUsedRval, IncludeUsedRval> ||
+                    std::is_same_v<WantUsedRval, NoUsedRval>,
                 "WantUsedRval can only be IncludeUsedRval or NoUsedRval");
 
  protected:
   Value* argv_;
   unsigned argc_;
   bool constructing_ : 1;
 
   // True if the caller does not use the return value.
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -7,19 +7,19 @@
 #ifndef js_MemoryMetrics_h
 #define js_MemoryMetrics_h
 
 // These declarations are highly likely to change in the future. Depend on them
 // at your own risk.
 
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
-#include "mozilla/TypeTraits.h"
 
 #include <string.h>
+#include <type_traits>
 
 #include "jspubtd.h"
 
 #include "js/AllocPolicy.h"
 #include "js/HashTable.h"
 #include "js/TracingAPI.h"
 #include "js/Utility.h"
 #include "js/Vector.h"
@@ -152,18 +152,18 @@ struct InefficientNonFlatteningStringHas
 #define DECL_SIZE_ZERO(tabKind, servoKind, mSize) size_t mSize = 0;
 #define ADD_OTHER_SIZE(tabKind, servoKind, mSize) mSize += other.mSize;
 #define SUB_OTHER_SIZE(tabKind, servoKind, mSize) \
   MOZ_ASSERT(mSize >= other.mSize);               \
   mSize -= other.mSize;
 #define ADD_SIZE_TO_N(tabKind, servoKind, mSize) n += mSize;
 #define ADD_SIZE_TO_N_IF_LIVE_GC_THING(tabKind, servoKind, mSize)     \
   /* Avoid self-comparison warnings by comparing enums indirectly. */ \
-  n += (mozilla::IsSame<int[ServoSizes::servoKind],                   \
-                        int[ServoSizes::GCHeapUsed]>::value)          \
+  n += (std::is_same_v<int[ServoSizes::servoKind],                    \
+                       int[ServoSizes::GCHeapUsed]>)                  \
            ? mSize                                                    \
            : 0;
 #define ADD_TO_TAB_SIZES(tabKind, servoKind, mSize) \
   sizes->add(JS::TabSizes::tabKind, mSize);
 #define ADD_TO_SERVO_SIZES(tabKind, servoKind, mSize) \
   sizes->add(JS::ServoSizes::servoKind, mSize);
 
 }  // namespace js
--- a/js/src/builtin/String.cpp
+++ b/js/src/builtin/String.cpp
@@ -8,17 +8,16 @@
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/Range.h"
 #include "mozilla/TextUtils.h"
-#include "mozilla/TypeTraits.h"
 #include "mozilla/Unused.h"
 
 #include <algorithm>
 #include <limits>
 #include <string.h>
 #include <type_traits>
 
 #include "jsapi.h"
@@ -70,17 +69,16 @@ using namespace js;
 
 using JS::Symbol;
 using JS::SymbolCode;
 
 using mozilla::AsciiAlphanumericToNumber;
 using mozilla::CheckedInt;
 using mozilla::IsAsciiHexDigit;
 using mozilla::IsNaN;
-using mozilla::IsSame;
 using mozilla::PodCopy;
 using mozilla::RangedPtr;
 
 using JS::AutoCheckCannotGC;
 using JS::AutoStableStringChars;
 
 static JSLinearString* ArgToLinearString(JSContext* cx, const CallArgs& args,
                                          unsigned argno) {
@@ -701,22 +699,24 @@ static char16_t Final_Sigma(const char16
 // size to hold all lower case mapped characters, i.e.
 // |destLength == ToLowerCaseLength(srcChars, 0, srcLength)| is true.
 template <typename CharT>
 static size_t ToLowerCaseImpl(CharT* destChars, const CharT* srcChars,
                               size_t startIndex, size_t srcLength,
                               size_t destLength) {
   MOZ_ASSERT(startIndex < srcLength);
   MOZ_ASSERT(srcLength <= destLength);
-  MOZ_ASSERT_IF((IsSame<CharT, Latin1Char>::value), srcLength == destLength);
+  if constexpr (std::is_same_v<CharT, Latin1Char>) {
+    MOZ_ASSERT(srcLength == destLength);
+  }
 
   size_t j = startIndex;
   for (size_t i = startIndex; i < srcLength; i++) {
     CharT c = srcChars[i];
-    if constexpr (!IsSame<CharT, Latin1Char>::value) {
+    if constexpr (!std::is_same_v<CharT, Latin1Char>) {
       if (unicode::IsLeadSurrogate(c) && i + 1 < srcLength) {
         char16_t trail = srcChars[i + 1];
         if (unicode::IsTrailSurrogate(trail)) {
           trail = unicode::ToLowerCaseNonBMPTrail(c, trail);
           destChars[j++] = c;
           destChars[j++] = trail;
           i++;
           continue;
@@ -786,30 +786,30 @@ static JSString* ToLowerCase(JSContext* 
                    unicode::LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE),
                "U+0130 has a simple lower case mapping");
     MOZ_ASSERT(
         unicode::ChangesWhenLowerCased(unicode::GREEK_CAPITAL_LETTER_SIGMA),
         "U+03A3 has a simple lower case mapping");
 
     // One element Latin-1 strings can be directly retrieved from the
     // static strings cache.
-    if constexpr (IsSame<CharT, Latin1Char>::value) {
+    if constexpr (std::is_same_v<CharT, Latin1Char>) {
       if (length == 1) {
         CharT lower = unicode::ToLowerCase(chars[0]);
         MOZ_ASSERT(StaticStrings::hasUnit(lower));
 
         return cx->staticStrings().getUnit(lower);
       }
     }
 
     // Look for the first character that changes when lowercased.
     size_t i = 0;
     for (; i < length; i++) {
       CharT c = chars[i];
-      if constexpr (!IsSame<CharT, Latin1Char>::value) {
+      if constexpr (!std::is_same_v<CharT, Latin1Char>) {
         if (unicode::IsLeadSurrogate(c) && i + 1 < length) {
           CharT trail = chars[i + 1];
           if (unicode::IsTrailSurrogate(trail)) {
             if (unicode::ChangesWhenLowerCasedNonBMP(c, trail)) {
               break;
             }
 
             i++;
@@ -831,17 +831,17 @@ static JSString* ToLowerCase(JSContext* 
     if (!newChars.maybeAlloc(cx, resultLength)) {
       return nullptr;
     }
 
     PodCopy(newChars.get(), chars, i);
 
     size_t readChars =
         ToLowerCaseImpl(newChars.get(), chars, i, length, resultLength);
-    if constexpr (!IsSame<CharT, Latin1Char>::value) {
+    if constexpr (!std::is_same_v<CharT, Latin1Char>) {
       if (readChars < length) {
         resultLength = ToLowerCaseLength(chars, readChars, length);
 
         if (!newChars.maybeRealloc(cx, length, resultLength)) {
           return nullptr;
         }
 
         MOZ_ALWAYS_TRUE(length == ToLowerCaseImpl(newChars.get(), chars,
@@ -1066,26 +1066,26 @@ static inline void ToUpperCaseAppendUppe
   unicode::AppendUpperCaseSpecialCasing(charCode, elements, index);
 }
 
 // See ToLowerCaseImpl for an explanation of the parameters.
 template <typename DestChar, typename SrcChar>
 static size_t ToUpperCaseImpl(DestChar* destChars, const SrcChar* srcChars,
                               size_t startIndex, size_t srcLength,
                               size_t destLength) {
-  static_assert(IsSame<SrcChar, Latin1Char>::value ||
-                    !IsSame<DestChar, Latin1Char>::value,
+  static_assert(std::is_same_v<SrcChar, Latin1Char> ||
+                    !std::is_same_v<DestChar, Latin1Char>,
                 "cannot write non-Latin-1 characters into Latin-1 string");
   MOZ_ASSERT(startIndex < srcLength);
   MOZ_ASSERT(srcLength <= destLength);
 
   size_t j = startIndex;
   for (size_t i = startIndex; i < srcLength; i++) {
     char16_t c = srcChars[i];
-    if constexpr (!IsSame<DestChar, Latin1Char>::value) {
+    if constexpr (!std::is_same_v<DestChar, Latin1Char>) {
       if (unicode::IsLeadSurrogate(c) && i + 1 < srcLength) {
         char16_t trail = srcChars[i + 1];
         if (unicode::IsTrailSurrogate(trail)) {
           trail = unicode::ToUpperCaseNonBMPTrail(c, trail);
           destChars[j++] = c;
           destChars[j++] = trail;
           i++;
           continue;
@@ -1100,18 +1100,19 @@ static size_t ToUpperCaseImpl(DestChar* 
         return i;
       }
 
       ToUpperCaseAppendUpperCaseSpecialCasing(c, destChars, &j);
       continue;
     }
 
     c = unicode::ToUpperCase(c);
-    MOZ_ASSERT_IF((IsSame<DestChar, Latin1Char>::value),
-                  c <= JSString::MAX_LATIN1_CHAR);
+    if constexpr (std::is_same_v<DestChar, Latin1Char>) {
+      MOZ_ASSERT(c <= JSString::MAX_LATIN1_CHAR);
+    }
     destChars[j++] = c;
   }
 
   MOZ_ASSERT(j == destLength);
   return srcLength;
 }
 
 template <typename CharT>
@@ -1126,17 +1127,17 @@ static size_t ToUpperCaseLength(const Ch
     }
   }
   return upperLength;
 }
 
 template <typename DestChar, typename SrcChar>
 static inline void CopyChars(DestChar* destChars, const SrcChar* srcChars,
                              size_t length) {
-  static_assert(!IsSame<DestChar, SrcChar>::value,
+  static_assert(!std::is_same_v<DestChar, SrcChar>,
                 "PodCopy is used for the same type case");
   for (size_t i = 0; i < length; i++) {
     destChars[i] = srcChars[i];
   }
 }
 
 template <typename CharT>
 static inline void CopyChars(CharT* destChars, const CharT* srcChars,
@@ -1184,17 +1185,17 @@ static JSString* ToUpperCase(JSContext* 
   const size_t length = str->length();
   size_t resultLength;
   {
     AutoCheckCannotGC nogc;
     const CharT* chars = str->chars<CharT>(nogc);
 
     // Most one element Latin-1 strings can be directly retrieved from the
     // static strings cache.
-    if constexpr (IsSame<CharT, Latin1Char>::value) {
+    if constexpr (std::is_same_v<CharT, Latin1Char>) {
       if (length == 1) {
         Latin1Char c = chars[0];
         if (c != unicode::MICRO_SIGN &&
             c != unicode::LATIN_SMALL_LETTER_Y_WITH_DIAERESIS &&
             c != unicode::LATIN_SMALL_LETTER_SHARP_S) {
           char16_t upper = unicode::ToUpperCase(c);
           MOZ_ASSERT(upper <= JSString::MAX_LATIN1_CHAR);
           MOZ_ASSERT(StaticStrings::hasUnit(upper));
@@ -1206,17 +1207,17 @@ static JSString* ToUpperCase(JSContext* 
                    ToUpperCaseHasSpecialCasing(c));
       }
     }
 
     // Look for the first character that changes when uppercased.
     size_t i = 0;
     for (; i < length; i++) {
       CharT c = chars[i];
-      if constexpr (!IsSame<CharT, Latin1Char>::value) {
+      if constexpr (!std::is_same_v<CharT, Latin1Char>) {
         if (unicode::IsLeadSurrogate(c) && i + 1 < length) {
           CharT trail = chars[i + 1];
           if (unicode::IsTrailSurrogate(trail)) {
             if (unicode::ChangesWhenUpperCasedNonBMP(c, trail)) {
               break;
             }
 
             i++;
@@ -1243,17 +1244,17 @@ static JSString* ToUpperCase(JSContext* 
     // If the original string is Latin-1, it can -- unless the string
     // contains U+00B5 MICRO SIGN or U+00FF SMALL LETTER Y WITH DIAERESIS,
     // the only Latin-1 codepoints that don't uppercase within Latin-1.
     // Search for those codepoints to decide whether the new string can be
     // Latin-1.
     // If the original string is a two-byte string, its uppercase form is
     // so rarely Latin-1 that we don't even consider creating a new
     // Latin-1 string.
-    if constexpr (IsSame<CharT, Latin1Char>::value) {
+    if constexpr (std::is_same_v<CharT, Latin1Char>) {
       bool resultIsLatin1 = true;
       for (size_t j = i; j < length; j++) {
         Latin1Char c = chars[j];
         if (c == unicode::MICRO_SIGN ||
             c == unicode::LATIN_SMALL_LETTER_Y_WITH_DIAERESIS) {
           MOZ_ASSERT(unicode::ToUpperCase(c) > JSString::MAX_LATIN1_CHAR);
           resultIsLatin1 = false;
           break;
@@ -1920,17 +1921,17 @@ static MOZ_ALWAYS_INLINE int StringMatch
     }
   }
 
   /*
    * For big patterns with large potential overlap we want the SIMD-optimized
    * speed of memcmp. For small patterns, a simple loop is faster. We also can't
    * use memcmp if one of the strings is TwoByte and the other is Latin-1.
    */
-  return (patLen > 128 && IsSame<TextChar, PatChar>::value)
+  return (patLen > 128 && std::is_same_v<TextChar, PatChar>)
              ? Matcher<MemCmp<TextChar, PatChar>, TextChar, PatChar>(
                    text, textLen, pat, patLen)
              : Matcher<ManualCmp<TextChar, PatChar>, TextChar, PatChar>(
                    text, textLen, pat, patLen);
 }
 
 static int32_t StringMatch(JSLinearString* text, JSLinearString* pat,
                            uint32_t start = 0) {
@@ -3072,18 +3073,18 @@ static JSString* ReplaceAll(JSContext* c
 
   // Step 11 (moved below).
 
   // Step 12.
   uint32_t endOfLastMatch = 0;
 
   // Step 13.
   JSStringBuilder result(cx);
-  if (std::is_same<StrChar, char16_t>::value ||
-      std::is_same<RepChar, char16_t>::value) {
+  if constexpr (std::is_same_v<StrChar, char16_t> ||
+                std::is_same_v<RepChar, char16_t>) {
     if (!result.ensureTwoByteChars()) {
       return nullptr;
     }
   }
 
   {
     AutoCheckCannotGC nogc;
     const StrChar* strChars = string->chars<StrChar>(nogc);
@@ -3155,18 +3156,18 @@ static JSString* ReplaceAllInterleave(JS
   const size_t replaceLength = replaceString->length();
 
   // Step 8 (advanceBy is 1 when searchString is the empty string).
 
   // Steps 9-12 (trivial when searchString is the empty string).
 
   // Step 13.
   JSStringBuilder result(cx);
-  if (std::is_same<StrChar, char16_t>::value ||
-      std::is_same<RepChar, char16_t>::value) {
+  if constexpr (std::is_same_v<StrChar, char16_t> ||
+                std::is_same_v<RepChar, char16_t>) {
     if (!result.ensureTwoByteChars()) {
       return nullptr;
     }
   }
 
   {
     AutoCheckCannotGC nogc;
     const StrChar* strChars = string->chars<StrChar>(nogc);
@@ -4119,17 +4120,17 @@ static MOZ_NEVER_INLINE EncodeResult Enc
     if (c < 128 &&
         (js_isUriUnescaped[c] || (unescapedSet && unescapedSet[c]))) {
       continue;
     } else {
       if (!appendRange(startAppend, k)) {
         return Encode_Failure;
       }
 
-      if (mozilla::IsSame<CharT, Latin1Char>::value) {
+      if constexpr (std::is_same_v<CharT, Latin1Char>) {
         if (c < 0x80) {
           if (!appendEncoded(c)) {
             return Encode_Failure;
           }
         } else {
           if (!appendEncoded(0xC0 | (c >> 6)) ||
               !appendEncoded(0x80 | (c & 0x3F))) {
             return Encode_Failure;
--- a/js/src/builtin/intl/CommonFunctions.h
+++ b/js/src/builtin/intl/CommonFunctions.h
@@ -3,21 +3,21 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef builtin_intl_CommonFunctions_h
 #define builtin_intl_CommonFunctions_h
 
 #include "mozilla/Assertions.h"
-#include "mozilla/TypeTraits.h"
 
 #include <stddef.h>
 #include <stdint.h>
 #include <string.h>
+#include <type_traits>
 
 #include "js/RootingAPI.h"
 #include "js/Vector.h"
 #include "unicode/utypes.h"
 #include "vm/StringType.h"
 
 namespace js {
 
@@ -94,17 +94,17 @@ static inline const char* IcuLocale(cons
 
   return locale;
 }
 
 extern UniqueChars EncodeLocale(JSContext* cx, JSString* locale);
 
 // Starting with ICU 59, UChar defaults to char16_t.
 static_assert(
-    mozilla::IsSame<UChar, char16_t>::value,
+    std::is_same_v<UChar, char16_t>,
     "SpiderMonkey doesn't support redefining UChar to a different type");
 
 // The inline capacity we use for a Vector<char16_t>.  Use this to ensure that
 // our uses of ICU string functions, below and elsewhere, will try to fill the
 // buffer's entire inline capacity before growing it and heap-allocating.
 constexpr size_t INITIAL_CHAR_BUFFER_SIZE = 32;
 
 template <typename ICUStringFunction, typename CharT, size_t InlineCapacity>
--- a/js/src/frontend/BinASTParser.cpp
+++ b/js/src/frontend/BinASTParser.cpp
@@ -12,16 +12,17 @@
 #include "frontend/BinASTParser.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Casting.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/Vector.h"
 
+#include <type_traits>
 #include <utility>
 
 #include "frontend/BinAST-macros.h"
 #include "frontend/BinASTTokenReaderContext.h"
 #include "frontend/BinASTTokenReaderMultipart.h"
 #include "frontend/FullParseHandler.h"
 #include "frontend/ParseNode.h"
 #include "frontend/Parser.h"
@@ -3539,17 +3540,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
   RootedAtom pattern(cx_);
   MOZ_TRY_VAR(pattern,
               tokenizer_->readAtom(FieldContext(
                   BinASTInterfaceAndField::LiteralRegExpExpression__Pattern)));
   RegExpFlags reflags = JS::RegExpFlag::NoFlags;
   auto flagsContext =
       FieldContext(BinASTInterfaceAndField::LiteralRegExpExpression__Flags);
-  if (mozilla::IsSame<Tok, BinASTTokenReaderContext>::value) {
+  if constexpr (std::is_same_v<Tok, BinASTTokenReaderContext>) {
     // Hack: optimized `readChars` is not implemented for
     // `BinASTTokenReaderContext`.
     RootedAtom flags(cx_);
     MOZ_TRY_VAR(flags, tokenizer_->readAtom(flagsContext));
     if (!this->parseRegExpFlags(flags, &reflags)) {
       return raiseError("Invalid regexp flags");
     }
   } else {
--- a/js/src/frontend/BinASTParserPerTokenizer.h
+++ b/js/src/frontend/BinASTParserPerTokenizer.h
@@ -11,16 +11,18 @@
  * A Binary AST parser.
  *
  * At the time of this writing, this parser implements the grammar of ES5
  * and trusts its input (in particular, variable declarations).
  */
 
 #include "mozilla/Maybe.h"
 
+#include <type_traits>
+
 #include "frontend/BCEParserHandle.h"
 #include "frontend/BinASTEnum.h"
 #include "frontend/BinASTParserBase.h"
 #include "frontend/BinASTToken.h"
 #include "frontend/BinASTTokenReaderContext.h"
 #include "frontend/BinASTTokenReaderMultipart.h"
 #include "frontend/FullParseHandler.h"
 #include "frontend/ParseContext.h"
@@ -197,20 +199,20 @@ class BinASTParserPerTokenizer : public 
   // Optionally force a strict context without restarting the parse when we see
   // a strict directive.
   void forceStrictIfNecessary(SharedContext* sc, ListNode* directives);
 
   // Whether invalid BinASTKind/BinASTVariant can be encoded in the file.
   // This is used to avoid generating unnecessary branches for more
   // optimized format.
   static constexpr bool isInvalidKindPossible() {
-    return mozilla::IsSame<Tok, BinASTTokenReaderMultipart>::value;
+    return std::is_same_v<Tok, BinASTTokenReaderMultipart>;
   }
   static constexpr bool isInvalidVariantPossible() {
-    return mozilla::IsSame<Tok, BinASTTokenReaderMultipart>::value;
+    return std::is_same_v<Tok, BinASTTokenReaderMultipart>;
   }
 
  protected:
   // Implement ErrorReportMixin.
   const JS::ReadOnlyCompileOptions& options_;
 
   const JS::ReadOnlyCompileOptions& options() const override {
     return this->options_;
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -19,23 +19,23 @@
 
 #include "frontend/Parser.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Casting.h"
 #include "mozilla/Range.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Sprintf.h"
-#include "mozilla/TypeTraits.h"
 #include "mozilla/Unused.h"
 #include "mozilla/Utf8.h"
 #include "mozilla/Variant.h"
 
 #include <memory>
 #include <new>
+#include <type_traits>
 
 #include "jsnum.h"
 #include "jstypes.h"
 
 #include "builtin/ModuleObject.h"
 #include "builtin/SelfHostingDefines.h"
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/BytecodeSection.h"
@@ -810,41 +810,44 @@ bool PerHandlerParser<ParseHandler>::
     // Scopes are nullptr-delimited in the BaseScript closed over bindings
     // array.
     while (JSAtom* name = handler_.nextLazyClosedOverBinding()) {
       scope.lookupDeclaredName(name)->value()->setClosedOver();
     }
     return true;
   }
 
-  bool isSyntaxParser =
-      mozilla::IsSame<ParseHandler, SyntaxParseHandler>::value;
+  constexpr bool isSyntaxParser =
+      std::is_same_v<ParseHandler, SyntaxParseHandler>;
   uint32_t scriptId = pc_->scriptId();
   uint32_t scopeId = scope.id();
 
   for (BindingIter bi = scope.bindings(pc_); bi; bi++) {
     if (UsedNamePtr p = usedNames_.lookup(bi.name())) {
       bool closedOver;
       p->value().noteBoundInScope(scriptId, scopeId, &closedOver);
       if (closedOver) {
         bi.setClosedOver();
 
-        if (isSyntaxParser &&
-            !pc_->closedOverBindingsForLazy().append(bi.name())) {
-          ReportOutOfMemory(cx_);
-          return false;
+        if constexpr (isSyntaxParser) {
+          if (!pc_->closedOverBindingsForLazy().append(bi.name())) {
+            ReportOutOfMemory(cx_);
+            return false;
+          }
         }
       }
     }
   }
 
   // Append a nullptr to denote end-of-scope.
-  if (isSyntaxParser && !pc_->closedOverBindingsForLazy().append(nullptr)) {
-    ReportOutOfMemory(cx_);
-    return false;
+  if constexpr (isSyntaxParser) {
+    if (!pc_->closedOverBindingsForLazy().append(nullptr)) {
+      ReportOutOfMemory(cx_);
+      return false;
+    }
   }
 
   return true;
 }
 
 template <typename Unit>
 bool Parser<FullParseHandler, Unit>::checkStatementsEOF() {
   // This is designed to be paired with parsing a statement list at the top
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -168,17 +168,19 @@
  * So -- any parsing functionality that is differently defined for different
  * ParseHandlers, *but* is defined textually identically for different Unit
  * (even if different code ends up generated for them by the compiler), should
  * reside in Parser.
  */
 
 #include "mozilla/Array.h"
 #include "mozilla/Maybe.h"
-#include "mozilla/TypeTraits.h"
+
+#include <type_traits>
+#include <utility>
 
 #include "jspubtd.h"
 
 #include "ds/Nestable.h"
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/CompilationInfo.h"
 #include "frontend/ErrorReporter.h"
 #include "frontend/FullParseHandler.h"
@@ -203,17 +205,17 @@ class GeneralParser;
 
 class SourceParseContext : public ParseContext {
  public:
   template <typename ParseHandler, typename Unit>
   SourceParseContext(GeneralParser<ParseHandler, Unit>* prs, SharedContext* sc,
                      Directives* newDirectives)
       : ParseContext(prs->cx_, prs->pc_, sc, prs->tokenStream,
                      prs->getCompilationInfo(), newDirectives,
-                     mozilla::IsSame<ParseHandler, FullParseHandler>::value) {}
+                     std::is_same_v<ParseHandler, FullParseHandler>) {}
 };
 
 enum VarContext { HoistVars, DontHoistVars };
 enum PropListType { ObjectLiteral, ClassBody, DerivedClassBody };
 enum class PropertyType {
   Normal,
   Shorthand,
   CoverInitializedName,
@@ -1784,21 +1786,19 @@ ParserAnyCharsAccess<Parser>::anyChars(c
 
   static_assert(
       std::is_base_of<GeneralTokenStreamChars, TokenStreamSpecific>::value,
       "the static_cast<> below assumes a base-class relationship");
   const auto* tss = static_cast<const TokenStreamSpecific*>(ts);
 
   auto tssAddr = reinterpret_cast<uintptr_t>(tss);
 
-  using ActualTokenStreamType =
-      decltype(static_cast<Parser*>(nullptr)->tokenStream);
-  static_assert(
-      mozilla::IsSame<ActualTokenStreamType, TokenStreamSpecific>::value,
-      "Parser::tokenStream must have type TokenStreamSpecific");
+  using ActualTokenStreamType = decltype(std::declval<Parser>().tokenStream);
+  static_assert(std::is_same_v<ActualTokenStreamType, TokenStreamSpecific>,
+                "Parser::tokenStream must have type TokenStreamSpecific");
 
   uintptr_t parserAddr = tssAddr - offsetof(Parser, tokenStream);
 
   return reinterpret_cast<const Parser*>(parserAddr)->anyChars;
 }
 
 template <class Parser>
 /* static */ inline TokenStreamAnyChars& ParserAnyCharsAccess<Parser>::anyChars(
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -405,18 +405,18 @@ MOZ_ALWAYS_INLINE bool SourceCoords::add
   MOZ_ASSERT(lineStartOffsets_[sentinelIndex] == MAX_PTR);
 
   if (index == sentinelIndex) {
     // We haven't seen this newline before.  Update lineStartOffsets_
     // only if lineStartOffsets_.append succeeds, to keep sentinel.
     // Otherwise return false to tell TokenStream about OOM.
     uint32_t maxPtr = MAX_PTR;
     if (!lineStartOffsets_.append(maxPtr)) {
-      static_assert(mozilla::IsSame<decltype(lineStartOffsets_.allocPolicy()),
-                                    TempAllocPolicy&>::value,
+      static_assert(std::is_same_v<decltype(lineStartOffsets_.allocPolicy()),
+                                   TempAllocPolicy&>,
                     "this function's caller depends on it reporting an "
                     "error on failure, as TempAllocPolicy ensures");
       return false;
     }
 
     lineStartOffsets_[index] = lineStartOffset;
   } else {
     // We have seen this newline before (and ungot it).  Do nothing (other
--- a/js/src/gc/AtomMarking-inl.h
+++ b/js/src/gc/AtomMarking-inl.h
@@ -2,16 +2,19 @@
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gc/AtomMarking.h"
 
 #include "mozilla/Assertions.h"
+
+#include <type_traits>
+
 #include "vm/Realm.h"
 
 #include "gc/Heap-inl.h"
 
 namespace js {
 namespace gc {
 
 inline size_t GetAtomBit(TenuredCell* thing) {
@@ -26,18 +29,17 @@ inline bool ThingIsPermanent(JSAtom* ato
 
 inline bool ThingIsPermanent(JS::Symbol* symbol) {
   return symbol->isWellKnownSymbol();
 }
 
 template <typename T, bool Fallible>
 MOZ_ALWAYS_INLINE bool AtomMarkingRuntime::inlinedMarkAtomInternal(
     JSContext* cx, T* thing) {
-  static_assert(mozilla::IsSame<T, JSAtom>::value ||
-                    mozilla::IsSame<T, JS::Symbol>::value,
+  static_assert(std::is_same_v<T, JSAtom> || std::is_same_v<T, JS::Symbol>,
                 "Should only be called with JSAtom* or JS::Symbol* argument");
 
   MOZ_ASSERT(thing);
   js::gc::TenuredCell* cell = &thing->asTenured();
   MOZ_ASSERT(cell->zoneFromAnyThread()->isAtomsZone());
 
   // The context's zone will be null during initialization of the runtime.
   if (!cx->zone()) {
--- a/js/src/gc/AtomMarking.cpp
+++ b/js/src/gc/AtomMarking.cpp
@@ -1,16 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gc/AtomMarking-inl.h"
 
+#include <type_traits>
+
 #include "gc/PublicIterators.h"
 #include "vm/Realm.h"
 
 #include "gc/GC-inl.h"
 #include "gc/Heap-inl.h"
 
 namespace js {
 namespace gc {
@@ -193,18 +195,17 @@ void AtomMarkingRuntime::adoptMarkedAtom
   MOZ_ASSERT(CurrentThreadCanAccessZone(source));
   MOZ_ASSERT(CurrentThreadCanAccessZone(target));
   target->markedAtoms().bitwiseOrWith(source->markedAtoms());
 }
 
 #ifdef DEBUG
 template <typename T>
 bool AtomMarkingRuntime::atomIsMarked(Zone* zone, T* thing) {
-  static_assert(mozilla::IsSame<T, JSAtom>::value ||
-                    mozilla::IsSame<T, JS::Symbol>::value,
+  static_assert(std::is_same_v<T, JSAtom> || std::is_same_v<T, JS::Symbol>,
                 "Should only be called with JSAtom* or JS::Symbol* argument");
 
   MOZ_ASSERT(thing);
   MOZ_ASSERT(!IsInsideNursery(thing));
   MOZ_ASSERT(thing->zoneFromAnyThread()->isAtomsZone());
 
   if (!zone->runtimeFromAnyThread()->permanentAtomsPopulated()) {
     return true;
--- a/js/src/gc/Marking-inl.h
+++ b/js/src/gc/Marking-inl.h
@@ -6,16 +6,18 @@
 
 #ifndef gc_Marking_inl_h
 #define gc_Marking_inl_h
 
 #include "gc/Marking.h"
 
 #include "mozilla/Maybe.h"
 
+#include <type_traits>
+
 #include "gc/RelocationOverlay.h"
 #include "vm/BigIntType.h"
 #include "vm/RegExpShared.h"
 
 #include "gc/Nursery-inl.h"
 
 namespace js {
 namespace gc {
@@ -53,18 +55,17 @@ template <>
 struct TaggedPtr<TaggedProto> {
   static TaggedProto wrap(JSObject* obj) { return TaggedProto(obj); }
   static TaggedProto empty() { return TaggedProto(); }
 };
 
 template <typename T>
 struct MightBeForwarded {
   static_assert(std::is_base_of<Cell, T>::value, "T must derive from Cell");
-  static_assert(!mozilla::IsSame<Cell, T>::value &&
-                    !mozilla::IsSame<TenuredCell, T>::value,
+  static_assert(!std::is_same_v<Cell, T> && !std::is_same_v<TenuredCell, T>,
                 "T must not be Cell or TenuredCell");
 
   static const bool value = std::is_base_of<JSObject, T>::value ||
                             std::is_base_of<Shape, T>::value ||
                             std::is_base_of<BaseShape, T>::value ||
                             std::is_base_of<JSString, T>::value ||
                             std::is_base_of<JS::BigInt, T>::value ||
                             std::is_base_of<js::BaseScript, T>::value ||
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/DebugOnly.h"
 #include "mozilla/IntegerRange.h"
 #include "mozilla/ReentrancyGuard.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/TypeTraits.h"
 #include "mozilla/Unused.h"
 
 #include <algorithm>
+#include <type_traits>
 
 #include "jsfriendapi.h"
 
 #include "builtin/ModuleObject.h"
 #include "debugger/DebugAPI.h"
 #include "gc/GCInternals.h"
 #include "gc/Policy.h"
 #include "jit/IonCode.h"
@@ -52,17 +53,16 @@
 
 using namespace js;
 using namespace js::gc;
 
 using JS::MapTypeToTraceKind;
 
 using mozilla::DebugOnly;
 using mozilla::IntegerRange;
-using mozilla::IsSame;
 using mozilla::PodCopy;
 
 // [SMDOC] GC Tracing
 //
 // Tracing Overview
 // ================
 //
 // Tracing, in this context, refers to an abstract visitation of some or all of
@@ -693,21 +693,20 @@ void js::TraceGCCellPtrRoot(JSTracer* tr
   }
 }
 
 // This method is responsible for dynamic dispatch to the real tracer
 // implementation. Consider replacing this choke point with virtual dispatch:
 // a sufficiently smart C++ compiler may be able to devirtualize some paths.
 template <typename T>
 bool js::gc::TraceEdgeInternal(JSTracer* trc, T* thingp, const char* name) {
-#define IS_SAME_TYPE_OR(name, type, _, _1) mozilla::IsSame<type*, T>::value ||
+#define IS_SAME_TYPE_OR(name, type, _, _1) std::is_same_v<type*, T> ||
   static_assert(JS_FOR_EACH_TRACEKIND(IS_SAME_TYPE_OR)
-                        mozilla::IsSame<T, JS::Value>::value ||
-                    mozilla::IsSame<T, jsid>::value ||
-                    mozilla::IsSame<T, TaggedProto>::value,
+                        std::is_same_v<T, JS::Value> ||
+                    std::is_same_v<T, jsid> || std::is_same_v<T, TaggedProto>,
                 "Only the base cell layout types are allowed into "
                 "marking/tracing internals");
 #undef IS_SAME_TYPE_OR
   if (trc->isMarkingTracer()) {
     DoMarking(GCMarker::fromTracer(trc), *thingp);
     return true;
   }
   if (trc->isTenuringTracer()) {
@@ -3511,17 +3510,17 @@ size_t js::TenuringTracer::moveBigIntToT
 
   return size;
 }
 
 /*** IsMarked / IsAboutToBeFinalized ****************************************/
 
 template <typename T>
 static inline void CheckIsMarkedThing(T* thingp) {
-#define IS_SAME_TYPE_OR(name, type, _, _1) mozilla::IsSame<type*, T>::value ||
+#define IS_SAME_TYPE_OR(name, type, _, _1) std::is_same_v<type*, T> ||
   static_assert(JS_FOR_EACH_TRACEKIND(IS_SAME_TYPE_OR) false,
                 "Only the base cell layout types are allowed into "
                 "marking/tracing internals");
 #undef IS_SAME_TYPE_OR
 
 #ifdef DEBUG
   MOZ_ASSERT(thingp);
   MOZ_ASSERT(*thingp);
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -523,17 +523,17 @@ OutOfLineCode* CodeGenerator::oolCallVM(
   MOZ_ASSERT(lir->mirRaw());
   MOZ_ASSERT(lir->mirRaw()->isInstruction());
 
 #ifdef DEBUG
   VMFunctionId id = VMFunctionToId<Fn, fn>::id;
   const VMFunctionData& fun = GetVMFunction(id);
   MOZ_ASSERT(fun.explicitArgs == args.numArgs);
   MOZ_ASSERT(fun.returnsData() !=
-             (mozilla::IsSame<StoreOutputTo, StoreNothing>::value));
+             (std::is_same_v<StoreOutputTo, StoreNothing>));
 #endif
 
   OutOfLineCode* ool = new (alloc())
       OutOfLineCallVM<Fn, fn, ArgSeq, StoreOutputTo>(lir, args, out);
   addOutOfLineCode(ool, lir->mirRaw()->toInstruction());
   return ool;
 }
 
--- a/js/src/jit/JitOptions.cpp
+++ b/js/src/jit/JitOptions.cpp
@@ -1,18 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/JitOptions.h"
-#include "mozilla/TypeTraits.h"
 
 #include <cstdlib>
+#include <type_traits>
 
 #include "vm/JSFunction.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::Maybe;
 
@@ -20,37 +20,32 @@ namespace js {
 namespace jit {
 
 DefaultJitOptions JitOptions;
 
 static void Warn(const char* env, const char* value) {
   fprintf(stderr, "Warning: I didn't understand %s=\"%s\"\n", env, value);
 }
 
-template <typename T>
-struct IsBool : mozilla::FalseType {};
-template <>
-struct IsBool<bool> : mozilla::TrueType {};
-
 static Maybe<int> ParseInt(const char* str) {
   char* endp;
   int retval = strtol(str, &endp, 0);
   if (*endp == '\0') {
     return mozilla::Some(retval);
   }
   return mozilla::Nothing();
 }
 
 template <typename T>
 T overrideDefault(const char* param, T dflt) {
   char* str = getenv(param);
   if (!str) {
     return dflt;
   }
-  if (IsBool<T>::value) {
+  if constexpr (std::is_same_v<T, bool>) {
     if (strcmp(str, "true") == 0 || strcmp(str, "yes") == 0) {
       return true;
     }
     if (strcmp(str, "false") == 0 || strcmp(str, "no") == 0) {
       return false;
     }
     Warn(param, str);
   } else {
--- a/js/src/threading/Thread.h
+++ b/js/src/threading/Thread.h
@@ -8,16 +8,17 @@
 #define threading_Thread_h
 
 #include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Tuple.h"
 
 #include <stdint.h>
+#include <type_traits>
 #include <utility>
 
 #include "js/Initialization.h"
 #include "js/Utility.h"
 #include "threading/LockGuard.h"
 #include "threading/Mutex.h"
 #include "threading/ThreadId.h"
 #include "vm/MutexIDs.h"
@@ -58,18 +59,18 @@ class Thread {
   // be created for this Thread by calling |init|. Some of the thread's
   // properties may be controlled by passing options to this constructor.
   template <
       typename O = Options,
       // SFINAE to make sure we don't try and treat functors for the other
       // constructor as an Options and vice versa.
       typename NonConstO = typename mozilla::RemoveConst<O>::Type,
       typename DerefO = typename mozilla::RemoveReference<NonConstO>::Type,
-      typename = typename mozilla::EnableIf<
-          mozilla::IsSame<DerefO, Options>::value, void*>::Type>
+      typename = typename mozilla::EnableIf<std::is_same_v<DerefO, Options>,
+                                            void*>::Type>
   explicit Thread(O&& options = Options())
       : id_(ThreadId()), options_(std::forward<O>(options)) {
     MOZ_ASSERT(isInitialized());
   }
 
   // Start a thread of execution at functor |f| with parameters |args|. This
   // method will return false if thread creation fails. This Thread must not
   // already have been created. Note that the arguments must be either POD or
--- a/js/src/vm/EnvironmentObject.h
+++ b/js/src/vm/EnvironmentObject.h
@@ -2,16 +2,18 @@
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef vm_EnvironmentObject_h
 #define vm_EnvironmentObject_h
 
+#include <type_traits>
+
 #include "builtin/ModuleObject.h"
 #include "frontend/NameAnalysisTypes.h"
 #include "gc/Barrier.h"
 #include "gc/WeakMap.h"
 #include "js/GCHashTable.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/GeneratorObject.h"
 #include "vm/GlobalObject.h"
@@ -1113,37 +1115,39 @@ inline bool IsFrameInitialEnvironment(Ab
   // chain for the environment chain to fully match the scope chain at the
   // start of execution in the frame.
   //
   // This logic must be in sync with the HAS_INITIAL_ENV logic in
   // InitFromBailout.
 
   // A function frame's CallObject, if present, is always the initial
   // environment.
-  if (mozilla::IsSame<SpecificEnvironment, CallObject>::value) {
+  if constexpr (std::is_same_v<SpecificEnvironment, CallObject>) {
     return true;
   }
 
   // For an eval frame, the VarEnvironmentObject, if present, is always the
   // initial environment.
-  if (mozilla::IsSame<SpecificEnvironment, VarEnvironmentObject>::value &&
-      frame.isEvalFrame()) {
-    return true;
+  if constexpr (std::is_same_v<SpecificEnvironment, VarEnvironmentObject>) {
+    if (frame.isEvalFrame()) {
+      return true;
+    }
   }
 
   // For named lambda frames without CallObjects (i.e., no binding in the
   // body of the function was closed over), the LexicalEnvironmentObject
   // corresponding to the named lambda scope is the initial environment.
-  if (mozilla::IsSame<SpecificEnvironment, NamedLambdaObject>::value &&
-      frame.isFunctionFrame() &&
-      frame.callee()->needsNamedLambdaEnvironment() &&
-      !frame.callee()->needsCallObject()) {
-    LexicalScope* namedLambdaScope = frame.script()->maybeNamedLambdaScope();
-    return &env.template as<LexicalEnvironmentObject>().scope() ==
-           namedLambdaScope;
+  if constexpr (std::is_same_v<SpecificEnvironment, NamedLambdaObject>) {
+    if (frame.isFunctionFrame() &&
+        frame.callee()->needsNamedLambdaEnvironment() &&
+        !frame.callee()->needsCallObject()) {
+      LexicalScope* namedLambdaScope = frame.script()->maybeNamedLambdaScope();
+      return &env.template as<LexicalEnvironmentObject>().scope() ==
+             namedLambdaScope;
+    }
   }
 
   return false;
 }
 
 extern bool CreateObjectsForEnvironmentChain(JSContext* cx,
                                              HandleObjectVector chain,
                                              HandleObject terminatingEnv,
--- a/js/src/vm/JSContext-inl.h
+++ b/js/src/vm/JSContext-inl.h
@@ -4,16 +4,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef vm_JSContext_inl_h
 #define vm_JSContext_inl_h
 
 #include "vm/JSContext.h"
 
+#include <type_traits>
+
 #include "builtin/Object.h"
 #include "gc/Zone.h"
 #include "jit/JitFrames.h"
 #include "proxy/Proxy.h"
 #include "util/DiagnosticAssertions.h"
 #include "vm/BigIntType.h"
 #include "vm/GlobalObject.h"
 #include "vm/HelperThreads.h"
@@ -89,18 +91,17 @@ class ContextChecks {
 
   void checkObject(JSObject* obj) {
     JS::AssertObjectIsNotGray(obj);
     MOZ_ASSERT(!js::gc::IsAboutToBeFinalizedUnbarriered(&obj));
   }
 
   template <typename T>
   void checkAtom(T* thing, int argIndex) {
-    static_assert(mozilla::IsSame<T, JSAtom>::value ||
-                      mozilla::IsSame<T, JS::Symbol>::value,
+    static_assert(std::is_same_v<T, JSAtom> || std::is_same_v<T, JS::Symbol>,
                   "Should only be called with JSAtom* or JS::Symbol* argument");
 
 #ifdef DEBUG
     // Atoms which move across zone boundaries need to be marked in the new
     // zone, see JS_MarkCrossZoneId.
     if (zone()) {
       if (!cx->runtime()->gc.atomMarking.atomIsMarked(zone(), thing)) {
         MOZ_CRASH_UNSAFE_PRINTF(
@@ -134,18 +135,18 @@ class ContextChecks {
       check(v.toBigInt(), argIndex);
     }
   }
 
   // Check the contents of any container class that supports the C++
   // iteration protocol, eg GCVector<jsid>.
   template <typename Container>
   typename mozilla::EnableIf<
-      mozilla::IsSame<decltype(((Container*)nullptr)->begin()),
-                      decltype(((Container*)nullptr)->end())>::value>::Type
+      std::is_same_v<decltype(((Container*)nullptr)->begin()),
+                     decltype(((Container*)nullptr)->end())>>::Type
   check(const Container& container, int argIndex) {
     for (auto i : container) {
       check(i, argIndex);
     }
   }
 
   void check(const JS::HandleValueArray& arr, int argIndex) {
     for (size_t i = 0; i < arr.length(); i++) {
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "vm/RegExpObject.h"
 
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/PodOperations.h"
 
 #include <algorithm>
+#include <type_traits>
 
 #include "builtin/RegExp.h"
 #include "builtin/SelfHostingDefines.h"  // REGEXP_*_FLAG
 #include "frontend/TokenStream.h"
 #include "gc/HashUtil.h"
 #ifdef DEBUG
 #  include "irregexp/RegExpBytecode.h"
 #endif
@@ -197,17 +198,17 @@ const JSClass RegExpObject::protoClass_ 
     js_Object_str, JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp), JS_NULL_CLASS_OPS,
     &RegExpObjectClassSpec};
 
 template <typename CharT>
 RegExpObject* RegExpObject::create(JSContext* cx, const CharT* chars,
                                    size_t length, RegExpFlags flags,
                                    frontend::TokenStreamAnyChars& tokenStream,
                                    NewObjectKind newKind) {
-  static_assert(mozilla::IsSame<CharT, char16_t>::value,
+  static_assert(std::is_same_v<CharT, char16_t>,
                 "this code may need updating if/when CharT encodes UTF-8");
 
   RootedAtom source(cx, AtomizeChars(cx, chars, length));
   if (!source) {
     return nullptr;
   }
 
   return create(cx, source, flags, tokenStream, newKind);
@@ -216,17 +217,17 @@ RegExpObject* RegExpObject::create(JSCon
 template RegExpObject* RegExpObject::create(
     JSContext* cx, const char16_t* chars, size_t length, RegExpFlags flags,
     frontend::TokenStreamAnyChars& tokenStream, NewObjectKind newKind);
 
 template <typename CharT>
 RegExpObject* RegExpObject::create(JSContext* cx, const CharT* chars,
                                    size_t length, RegExpFlags flags,
                                    NewObjectKind newKind) {
-  static_assert(mozilla::IsSame<CharT, char16_t>::value,
+  static_assert(std::is_same_v<CharT, char16_t>,
                 "this code may need updating if/when CharT encodes UTF-8");
 
   RootedAtom source(cx, AtomizeChars(cx, chars, length));
   if (!source) {
     return nullptr;
   }
 
   return create(cx, source, flags, newKind);
@@ -395,18 +396,20 @@ static MOZ_ALWAYS_INLINE bool AppendEsca
   }
   return true;
 }
 
 template <typename CharT>
 static MOZ_ALWAYS_INLINE bool SetupBuffer(StringBuffer& sb,
                                           const CharT* oldChars, size_t oldLen,
                                           const CharT* it) {
-  if (mozilla::IsSame<CharT, char16_t>::value && !sb.ensureTwoByteChars()) {
-    return false;
+  if constexpr (std::is_same_v<CharT, char16_t>) {
+    if (!sb.ensureTwoByteChars()) {
+      return false;
+    }
   }
 
   if (!sb.reserve(oldLen + 1)) {
     return false;
   }
 
   sb.infallibleAppend(oldChars, size_t(it - oldChars));
   return true;
--- a/js/src/vm/StringType.cpp
+++ b/js/src/vm/StringType.cpp
@@ -11,23 +11,22 @@
 #include "mozilla/EndianUtils.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/Latin1.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/RangedPtr.h"
 #include "mozilla/TextUtils.h"
-#include "mozilla/TypeTraits.h"
 #include "mozilla/Unused.h"
 #include "mozilla/Utf8.h"
 #include "mozilla/Vector.h"
 
 #include <algorithm>    // std::{all_of,copy_n,enable_if,is_const,move}
-#include <type_traits>  // std::is_unsigned
+#include <type_traits>  // std::is_same, std::is_unsigned
 
 #include "jsfriendapi.h"
 
 #include "frontend/BytecodeCompiler.h"
 #include "gc/Marking.h"
 #include "gc/MaybeRooted.h"
 #include "gc/Nursery.h"
 #include "js/CharacterEncoding.h"
@@ -46,17 +45,16 @@
 
 using namespace js;
 
 using mozilla::ArrayEqual;
 using mozilla::AssertedCast;
 using mozilla::AsWritableChars;
 using mozilla::ConvertLatin1toUtf16;
 using mozilla::IsAsciiDigit;
-using mozilla::IsSame;
 using mozilla::IsUtf16Latin1;
 using mozilla::LossyConvertUtf16toLatin1;
 using mozilla::MakeSpan;
 using mozilla::PodCopy;
 using mozilla::RangedPtr;
 using mozilla::RoundUpPow2;
 using mozilla::Unused;
 
@@ -638,17 +636,17 @@ JSLinearString* JSRope::flattenInternal(
   while (leftMostRope->leftChild()->isRope()) {
     leftMostRope = &leftMostRope->leftChild()->asRope();
   }
 
   if (leftMostRope->leftChild()->isExtensible()) {
     JSExtensibleString& left = leftMostRope->leftChild()->asExtensible();
     size_t capacity = left.capacity();
     if (capacity >= wholeLength &&
-        left.hasTwoByteChars() == IsSame<CharT, char16_t>::value) {
+        left.hasTwoByteChars() == std::is_same_v<CharT, char16_t>) {
       wholeChars = const_cast<CharT*>(left.nonInlineChars<CharT>(nogc));
       wholeCapacity = capacity;
 
       // registerMallocedBuffer is fallible, so attempt it first before doing
       // anything irreversible.
       Nursery& nursery = runtimeFromMainThread()->gc.nursery();
       bool inTenured = !bufferIfNursery;
       if (!inTenured && left.isTenured()) {
@@ -694,17 +692,17 @@ JSLinearString* JSRope::flattenInternal(
       pos = wholeChars + left_len;
 
       // Remove memory association for left node we're about to make into a
       // dependent string.
       if (left.isTenured()) {
         RemoveCellMemory(&left, left.allocSize(), MemoryUse::StringContents);
       }
 
-      if (IsSame<CharT, char16_t>::value) {
+      if constexpr (std::is_same_v<CharT, char16_t>) {
         left.setLengthAndFlags(left_len, INIT_DEPENDENT_FLAGS);
       } else {
         left.setLengthAndFlags(left_len,
                                INIT_DEPENDENT_FLAGS | LATIN1_CHARS_BIT);
       }
       left.d.s.u3.base = (JSLinearString*)this; /* will be true on exit */
       goto visit_right_child;
     }
@@ -756,34 +754,34 @@ visit_right_child : {
   }
   CopyChars(pos, right.asLinear());
   pos += right.length();
 }
 
 finish_node : {
   if (str == this) {
     MOZ_ASSERT(pos == wholeChars + wholeLength);
-    if (IsSame<CharT, char16_t>::value) {
+    if constexpr (std::is_same_v<CharT, char16_t>) {
       str->setLengthAndFlags(wholeLength, EXTENSIBLE_FLAGS);
     } else {
       str->setLengthAndFlags(wholeLength, EXTENSIBLE_FLAGS | LATIN1_CHARS_BIT);
     }
     str->setNonInlineChars(wholeChars);
     str->d.s.u3.capacity = wholeCapacity;
 
     if (str->isTenured()) {
       AddCellMemory(str, str->asLinear().allocSize(),
                     MemoryUse::StringContents);
     }
 
     return &this->asLinear();
   }
   uintptr_t flattenData;
   uint32_t len = pos - str->nonInlineCharsRaw<CharT>();
-  if (IsSame<CharT, char16_t>::value) {
+  if constexpr (std::is_same_v<CharT, char16_t>) {
     flattenData = str->unsetFlattenData(len, INIT_DEPENDENT_FLAGS);
   } else {
     flattenData =
         str->unsetFlattenData(len, INIT_DEPENDENT_FLAGS | LATIN1_CHARS_BIT);
   }
   str->d.s.u3.base = (JSLinearString*)this; /* will be true on exit */
 
   // Every interior (rope) node in the rope's tree will be visited during
@@ -1602,17 +1600,17 @@ template JSLinearString* js::NewStringDo
 template JSLinearString* js::NewStringDontDeflate(JSContext* cx,
                                                   UniqueLatin1Chars chars,
                                                   size_t length);
 
 template <typename CharT>
 JSLinearString* js::NewString(JSContext* cx,
                               UniquePtr<CharT[], JS::FreePolicy> chars,
                               size_t length) {
-  if constexpr (IsSame<CharT, char16_t>::value) {
+  if constexpr (std::is_same_v<CharT, char16_t>) {
     if (CanStoreCharsAsLatin1(chars.get(), length)) {
       // Deflating copies from |chars.get()| and lets |chars| be freed on
       // return.
       return NewStringDeflated<CanGC>(cx, chars.get(), length);
     }
   }
 
   return NewStringDontDeflate(cx, std::move(chars), length);
@@ -1651,17 +1649,17 @@ template JSLinearString* js::NewStringDo
 template JSLinearString* js::NewStringDontDeflate<NoGC>(JSContext* cx,
                                                         UniqueLatin1Chars chars,
                                                         size_t length);
 
 template <AllowGC allowGC, typename CharT>
 JSLinearString* js::NewString(JSContext* cx,
                               UniquePtr<CharT[], JS::FreePolicy> chars,
                               size_t length) {
-  if constexpr (IsSame<CharT, char16_t>::value) {
+  if constexpr (std::is_same_v<CharT, char16_t>) {
     if (CanStoreCharsAsLatin1(chars.get(), length)) {
       return NewStringDeflated<allowGC>(cx, chars.get(), length);
     }
   }
 
   return NewStringDontDeflate<allowGC>(cx, std::move(chars), length);
 }
 
@@ -1750,17 +1748,17 @@ static JSLinearString* NewUndeflatedStri
 JSLinearString* NewLatin1StringZ(JSContext* cx, UniqueChars chars) {
   size_t length = strlen(chars.get());
   UniqueLatin1Chars latin1(reinterpret_cast<Latin1Char*>(chars.release()));
   return NewString<CanGC>(cx, std::move(latin1), length);
 }
 
 template <AllowGC allowGC, typename CharT>
 JSLinearString* NewStringCopyN(JSContext* cx, const CharT* s, size_t n) {
-  if constexpr (IsSame<CharT, char16_t>::value) {
+  if constexpr (std::is_same_v<CharT, char16_t>) {
     if (CanStoreCharsAsLatin1(s, n)) {
       return NewStringDeflated<allowGC>(cx, s, n);
     }
   }
 
   return NewStringCopyNDontDeflate<allowGC>(cx, s, n);
 }
 
@@ -2024,17 +2022,17 @@ static bool FillWithRepresentatives(JSCo
   }
   if (!AppendString(cx, array, index, extensible)) {
     return false;
   }
   MOZ_ASSERT(extensible->isExtensible());
 
   // External. Note that we currently only support TwoByte external strings.
   RootedString external1(cx), external2(cx);
-  if (IsSame<CharT, char16_t>::value) {
+  if constexpr (std::is_same_v<CharT, char16_t>) {
     external1 = JS_NewExternalString(cx, (const char16_t*)chars, len,
                                      &RepresentativeExternalStringCallbacks);
     if (!external1 || !AppendString(cx, array, index, external1)) {
       return false;
     }
     MOZ_ASSERT(external1->isExternal());
 
     external2 = JS_NewExternalString(cx, (const char16_t*)chars, 2,