Backed out changeset a08637fb30c8 (bug 1143478) for causing bustages in /builds/worker/checkouts/gecko/ipc/mscom/Registration.cpp CLOSED TREE
authorshindli <shindli@mozilla.com>
Wed, 11 Mar 2020 14:30:54 +0200
changeset 518142 7a6232e87e8f0baba044f7cac60c0f5547a11426
parent 518141 005382a5a58ff70933c9f535b3a8e6158ccccea6
child 518143 66950fa024e1fb5919e822889f0bd07c1816c477
push id109799
push usershindli@mozilla.com
push dateWed, 11 Mar 2020 12:40:27 +0000
treeherderautoland@66950fa024e1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1143478
milestone76.0a1
backs outa08637fb30c82ac079d5422422edbe47d0d101af
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
Backed out changeset a08637fb30c8 (bug 1143478) for causing bustages in /builds/worker/checkouts/gecko/ipc/mscom/Registration.cpp CLOSED TREE
dom/base/Document.h
dom/base/PlacesObservers.h
dom/base/PlacesWeakCallbackWrapper.h
dom/canvas/ProducerConsumerQueue.h
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/ipc/ContentParent.cpp
dom/media/VideoOutput.h
dom/media/gmp/ChromiumCDMAdapter.cpp
dom/media/gmp/ChromiumCDMAdapter.h
dom/media/gmp/GMPChild.cpp
dom/media/gmp/GMPChild.h
dom/media/gtest/TestVideoFrameConverter.cpp
dom/media/mediasource/SourceBuffer.cpp
dom/media/mediasource/SourceBufferTask.h
dom/media/mp3/MP3FrameParser.cpp
dom/media/platforms/SimpleMap.h
dom/media/systemservices/CamerasChild.h
dom/plugins/base/PluginFinder.cpp
dom/plugins/base/PluginFinder.h
dom/plugins/base/nsPluginHost.cpp
dom/security/nsContentSecurityUtils.cpp
dom/security/nsContentSecurityUtils.h
dom/security/test/gtest/TestFilenameEvalParser.cpp
dom/serviceworkers/FetchEventOpProxyChild.cpp
dom/serviceworkers/ServiceWorkerOpPromise.h
extensions/permissions/nsPermissionManager.cpp
extensions/permissions/nsPermissionManager.h
gfx/layers/opengl/OGLShaderConfig.h
gfx/layers/opengl/OGLShaderProgram.cpp
gfx/layers/opengl/OGLShaderProgram.h
gfx/layers/wr/WebRenderCommandBuilder.cpp
image/ClippedImage.cpp
image/ClippedImage.h
image/SurfaceCache.cpp
js/src/wasm/WasmOpIter.h
layout/base/nsLayoutUtils.cpp
layout/generic/nsBlockFrame.cpp
layout/generic/nsGridContainerFrame.cpp
layout/painting/nsCSSRenderingGradients.cpp
layout/painting/nsDisplayList.cpp
layout/style/FontFace.h
layout/style/ServoStyleSet.cpp
layout/style/nsFontFaceUtils.cpp
mfbt/CompactPair.h
mfbt/Pair.h
mfbt/Tuple.h
mfbt/UniquePtr.h
mfbt/moz.build
mfbt/tests/TestCompactPair.cpp
mfbt/tests/TestPair.cpp
mfbt/tests/TestTuple.cpp
mfbt/tests/moz.build
mozglue/baseprofiler/core/platform.cpp
mozglue/baseprofiler/public/BlocksRingBuffer.h
mozglue/tests/TestBaseProfiler.cpp
netwerk/dns/IDNBlocklistUtils.cpp
netwerk/dns/IDNBlocklistUtils.h
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/HttpBaseChannel.h
other-licenses/nsis/Contrib/CityHash/cityhash/city.h
startupcache/StartupCache.cpp
startupcache/StartupCache.h
testing/cppunittest.ini
toolkit/components/antitracking/ContentBlockingAllowList.cpp
toolkit/components/antitracking/TemporaryAccessGrantObserver.cpp
toolkit/components/antitracking/TemporaryAccessGrantObserver.h
toolkit/components/places/Database.cpp
toolkit/components/telemetry/core/TelemetryEvent.cpp
toolkit/components/telemetry/core/TelemetryOrigin.cpp
toolkit/components/telemetry/core/TelemetryScalar.cpp
tools/profiler/core/platform.cpp
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -4,16 +4,17 @@
  * 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 mozilla_dom_Document_h___
 #define mozilla_dom_Document_h___
 
 #include "mozilla/EventStates.h"  // for EventStates
 #include "mozilla/FlushType.h"    // for enum
 #include "mozilla/MozPromise.h"   // for MozPromise
+#include "mozilla/Pair.h"         // for Pair
 #include "mozilla/Saturate.h"     // for SaturateUint32
 #include "nsAutoPtr.h"            // for member
 #include "nsCOMArray.h"           // for member
 #include "nsCompatibility.h"      // for member
 #include "nsCOMPtr.h"             // for member
 #include "nsICookieJarSettings.h"
 #include "nsGkAtoms.h"           // for static class members
 #include "nsNameSpaceManager.h"  // for static class members
--- a/dom/base/PlacesObservers.h
+++ b/dom/base/PlacesObservers.h
@@ -7,16 +7,17 @@
 #ifndef mozilla_dom_PlacesObservers__
 #define mozilla_dom_PlacesObservers__
 
 #include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/PlacesObserversBinding.h"
 #include "mozilla/dom/PlacesEvent.h"
 #include "mozilla/ErrorResult.h"
+#include "mozilla/Pair.h"
 #include "mozilla/places/INativePlacesEventCallback.h"
 #include "nsIWeakReferenceUtils.h"
 
 namespace mozilla {
 
 namespace dom {
 
 class PlacesObservers {
--- a/dom/base/PlacesWeakCallbackWrapper.h
+++ b/dom/base/PlacesWeakCallbackWrapper.h
@@ -4,16 +4,17 @@
  * 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 mozilla_dom_PlacesWeakCallbackWrapper_h
 #define mozilla_dom_PlacesWeakCallbackWrapper_h
 
 #include "mozilla/dom/PlacesObserversBinding.h"
 #include "mozilla/ErrorResult.h"
+#include "mozilla/Pair.h"
 #include "nsWrapperCache.h"
 
 namespace mozilla {
 namespace dom {
 
 class PlacesWeakCallbackWrapper final
     : public nsWrapperCache,
       public SupportsWeakPtr<PlacesWeakCallbackWrapper> {
--- a/dom/canvas/ProducerConsumerQueue.h
+++ b/dom/canvas/ProducerConsumerQueue.h
@@ -5,17 +5,16 @@
  * 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 mozilla_ipc_ProducerConsumerQueue_h
 #define mozilla_ipc_ProducerConsumerQueue_h 1
 
 #include <atomic>
 #include <tuple>
-#include <utility>
 #include <vector>
 #include "mozilla/ipc/SharedMemoryBasic.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/ipc/Shmem.h"
 #include "mozilla/ipc/ProtocolUtils.h"
 #include "mozilla/Logging.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/TypeTraits.h"
@@ -1980,33 +1979,33 @@ struct PcqParamTraits<Maybe<Variant<T, T
     return aView.template MinSizeParam<bool>(nullptr) +
            ((aArg && aArg->isSome()) ? aView.MinSizeParam(&aArg->ref()) : 0);
   }
 };
 
 // ---------------------------------------------------------------
 
 template <typename TypeA, typename TypeB>
-struct PcqParamTraits<std::pair<TypeA, TypeB>> {
-  using ParamType = std::pair<TypeA, TypeB>;
+struct PcqParamTraits<Pair<TypeA, TypeB>> {
+  using ParamType = Pair<TypeA, TypeB>;
 
   static PcqStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
-    aProducerView.WriteParam(aArg.first);
-    return aProducerView.WriteParam(aArg.second);
+    aProducerView.WriteParam(aArg.first());
+    return aProducerView.WriteParam(aArg.second());
   }
 
   static PcqStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
-    aConsumerView.ReadParam(aArg ? (&aArg->first) : nullptr);
-    return aConsumerView.ReadParam(aArg ? (&aArg->second) : nullptr);
+    aConsumerView.ReadParam(aArg ? (&aArg->first()) : nullptr);
+    return aConsumerView.ReadParam(aArg ? (&aArg->second()) : nullptr);
   }
 
   template <typename View>
   static size_t MinSize(View& aView, const ParamType* aArg) {
-    return aView.MinSizeParam(aArg ? aArg->first : nullptr) +
-           aView.MinSizeParam(aArg ? aArg->second : nullptr);
+    return aView.MinSizeParam(aArg ? aArg->first() : nullptr) +
+           aView.MinSizeParam(aArg ? aArg->second() : nullptr);
   }
 };
 
 // ---------------------------------------------------------------
 
 template <typename T>
 struct PcqParamTraits<UniquePtr<T>> {
   using ParamType = UniquePtr<T>;
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3999,17 +3999,17 @@ HTMLMediaElement::HTMLMediaElement(
       mMainThreadEventTarget(OwnerDoc()->EventTargetFor(TaskCategory::Other)),
       mAbstractMainThread(
           OwnerDoc()->AbstractMainThreadFor(TaskCategory::Other)),
       mShutdownObserver(new ShutdownObserver),
       mPlayed(new TimeRanges(ToSupports(OwnerDoc()))),
       mTracksCaptured(nullptr, "HTMLMediaElement::mTracksCaptured"),
       mErrorSink(new ErrorSink(this)),
       mAudioChannelWrapper(new AudioChannelAgentCallback(this)),
-      mSink(std::pair(nsString(), RefPtr<AudioDeviceInfo>())),
+      mSink(MakePair(nsString(), RefPtr<AudioDeviceInfo>())),
       mShowPoster(IsVideo()) {
   MOZ_ASSERT(mMainThreadEventTarget);
   MOZ_ASSERT(mAbstractMainThread);
   // Please don't add anything to this constructor or the initialization
   // list that can cause AddRef to be called. This prevents subclasses
   // from overriding AddRef in a way that works with our refcount
   // logging mechanisms. Put these things inside of the ::Init method
   // instead.
@@ -4992,19 +4992,19 @@ nsresult HTMLMediaElement::FinishDecoder
   // Notify the decoder of the initial activity status.
   NotifyDecoderActivityChanges();
 
   // Update decoder principal before we start decoding, since it
   // can affect how we feed data to MediaStreams
   NotifyDecoderPrincipalChanged();
 
   // Set sink device if we have one. Otherwise the default is used.
-  if (mSink.second) {
+  if (mSink.second()) {
     mDecoder
-        ->SetSink(mSink.second)
+        ->SetSink(mSink.second())
 #ifdef DEBUG
         ->Then(mAbstractMainThread, __func__,
                [](const GenericPromise::ResolveOrRejectValue& aValue) {
                  MOZ_ASSERT(aValue.IsResolve() && !aValue.ResolveValue());
                });
 #else
         ;
 #endif
@@ -5072,17 +5072,17 @@ void HTMLMediaElement::UpdateSrcMediaStr
   if (shouldPlay) {
     mSrcStreamPlaybackEnded = false;
     mSrcStreamReportPlaybackEnded = false;
 
     if (mMediaStreamRenderer) {
       mMediaStreamRenderer->Start();
     }
 
-    if (mSink.second) {
+    if (mSink.second()) {
       NS_WARNING(
           "setSinkId() when playing a MediaStream is not supported yet and "
           "will be ignored");
     }
 
     if (mSelectedVideoStreamTrack && GetVideoFrameContainer()) {
       MaybeBeginCloningVisually();
     }
@@ -7542,17 +7542,17 @@ already_AddRefed<Promise> HTMLMediaEleme
     return nullptr;
   }
 
   RefPtr<Promise> promise = Promise::Create(win->AsGlobal(), aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  if (mSink.first.Equals(aSinkId)) {
+  if (mSink.first().Equals(aSinkId)) {
     promise->MaybeResolveWithUndefined();
     return promise.forget();
   }
 
   nsString sinkId(aSinkId);
   MediaManager::Get()
       ->GetSinkDevice(win, sinkId)
       ->Then(
@@ -7583,17 +7583,17 @@ already_AddRefed<Promise> HTMLMediaEleme
           [](nsresult res) {
             // Promise is rejected, sink not found.
             return SinkInfoPromise::CreateAndReject(res, __func__);
           })
       ->Then(mAbstractMainThread, __func__,
              [promise, self = RefPtr<HTMLMediaElement>(this),
               sinkId](const SinkInfoPromise::ResolveOrRejectValue& aValue) {
                if (aValue.IsResolve()) {
-                 self->mSink = std::pair(sinkId, aValue.ResolveValue());
+                 self->mSink = MakePair(sinkId, aValue.ResolveValue());
                  promise->MaybeResolveWithUndefined();
                } else {
                  switch (aValue.RejectValue()) {
                    case NS_ERROR_ABORT:
                      promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
                      break;
                    case NS_ERROR_NOT_AVAILABLE: {
                      promise->MaybeRejectWithNotFoundError(
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -26,18 +26,16 @@
 #include "mozilla/dom/MediaDebugInfoBinding.h"
 #include "mozilla/dom/MediaKeys.h"
 #include "mozilla/dom/TextTrackManager.h"
 #include "nsGkAtoms.h"
 #include "PrincipalChangeObserver.h"
 #include "nsStubMutationObserver.h"
 #include "MediaSegment.h"  // for PrincipalHandle, GraphTime
 
-#include <utility>
-
 // X.h on Linux #defines CurrentTime as 0L, so we have to #undef it here.
 #ifdef CurrentTime
 #  undef CurrentTime
 #endif
 
 // Define to output information on decoding and painting framerate
 /* #define DEBUG_FRAME_RATE 1 */
 
@@ -732,17 +730,17 @@ class HTMLMediaElement : public nsGeneri
   // Set the sink id (of the output device) that the audio will play. If aSinkId
   // is empty the default device will be set.
   already_AddRefed<Promise> SetSinkId(const nsAString& aSinkId,
                                       ErrorResult& aRv);
   // Get the sink id of the device that audio is being played. Initial value is
   // empty and the default device is being used.
   void GetSinkId(nsString& aSinkId) {
     MOZ_ASSERT(NS_IsMainThread());
-    aSinkId = mSink.first;
+    aSinkId = mSink.first();
   }
 
   // This is used to notify MediaElementAudioSourceNode that media element is
   // allowed to play when media element is used as a source for web audio, so
   // that we can start AudioContext if it was not allowed to start.
   RefPtr<GenericNonExclusivePromise> GetAllowedToPlayPromise();
 
   bool GetShowPosterFlag() const { return mShowPoster; }
@@ -1899,17 +1897,17 @@ class HTMLMediaElement : public nsGeneri
   void AssertReadyStateIsNothing();
 
   // Contains the unique id of the sink device and the device info.
   // The initial value is ("", nullptr) and the default output device is used.
   // It can contain an invalid id and info if the device has been
   // unplugged. It can be set to ("", nullptr). It follows the spec attribute:
   // https://w3c.github.io/mediacapture-output/#htmlmediaelement-extensions
   // Read/Write from the main thread only.
-  std::pair<nsString, RefPtr<AudioDeviceInfo>> mSink;
+  Pair<nsString, RefPtr<AudioDeviceInfo>> mSink;
 
   // This flag is used to control when the user agent is to show a poster frame
   // for a video element instead of showing the video contents.
   // https://html.spec.whatwg.org/multipage/media.html#show-poster-flag
   bool mShowPoster;
 
   // We may delay starting playback of a media for an unvisited tab until it's
   // going to foreground. We would create ResumeDelayedMediaPlaybackAgent to
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -5469,21 +5469,21 @@ nsresult ContentParent::AboutToLoadHttpF
   }
 
   return NS_OK;
 }
 
 nsresult ContentParent::TransmitPermissionsForPrincipal(
     nsIPrincipal* aPrincipal) {
   // Create the key, and send it down to the content process.
-  nsTArray<std::pair<nsCString, nsCString>> pairs =
+  nsTArray<Pair<nsCString, nsCString>> pairs =
       nsPermissionManager::GetAllKeysForPrincipal(aPrincipal);
   MOZ_ASSERT(pairs.Length() >= 1);
   for (auto& pair : pairs) {
-    EnsurePermissionsByKey(pair.first, pair.second);
+    EnsurePermissionsByKey(pair.first(), pair.second());
   }
 
   return NS_OK;
 }
 
 void ContentParent::TransmitBlobURLsForPrincipal(nsIPrincipal* aPrincipal) {
   uint64_t originHash = ComputeLoadedOriginHash(aPrincipal);
 
--- a/dom/media/VideoOutput.h
+++ b/dom/media/VideoOutput.h
@@ -36,17 +36,17 @@ static bool SetImageToBlackPixel(PlanarY
 class VideoOutput : public DirectMediaTrackListener {
  protected:
   virtual ~VideoOutput() = default;
 
   void DropPastFrames() {
     TimeStamp now = TimeStamp::Now();
     size_t nrChunksInPast = 0;
     for (const auto& idChunkPair : mFrames) {
-      const VideoChunk& chunk = idChunkPair.second;
+      const VideoChunk& chunk = idChunkPair.second();
       if (chunk.mTimeStamp > now) {
         break;
       }
       ++nrChunksInPast;
     }
     if (nrChunksInPast > 1) {
       // We need to keep one frame that starts in the past, because it only ends
       // when the next frame starts (which also needs to be in the past for it
@@ -67,18 +67,18 @@ class VideoOutput : public DirectMediaTr
       return;
     }
 
     // Collect any new frames produced in this iteration.
     AutoTArray<ImageContainer::NonOwningImage, 16> images;
     PrincipalHandle lastPrincipalHandle = PRINCIPAL_HANDLE_NONE;
 
     for (const auto& idChunkPair : mFrames) {
-      ImageContainer::FrameID frameId = idChunkPair.first;
-      const VideoChunk& chunk = idChunkPair.second;
+      ImageContainer::FrameID frameId = idChunkPair.first();
+      const VideoChunk& chunk = idChunkPair.second();
       const VideoFrame& frame = chunk.mFrame;
       Image* image = frame.GetImage();
       if (frame.GetForceBlack() || !mEnabled) {
         if (!mBlackImage) {
           RefPtr<Image> blackImage = mVideoFrameContainer->GetImageContainer()
                                          ->CreatePlanarYCbCrImage();
           if (blackImage) {
             // Sets the image to a single black pixel, which will be scaled to
@@ -114,17 +114,17 @@ class VideoOutput : public DirectMediaTr
         lastPrincipalHandle != mVideoFrameContainer->GetLastPrincipalHandle();
 
     if (principalHandleChanged) {
       mVideoFrameContainer->UpdatePrincipalHandleForFrameID(
           lastPrincipalHandle, images.LastElement().mFrameID);
     }
 
     mVideoFrameContainer->SetCurrentFrames(
-        mFrames[0].second.mFrame.GetIntrinsicSize(), images);
+        mFrames[0].second().mFrame.GetIntrinsicSize(), images);
     mMainThread->Dispatch(NewRunnableMethod("VideoFrameContainer::Invalidate",
                                             mVideoFrameContainer,
                                             &VideoFrameContainer::Invalidate));
   }
 
  public:
   VideoOutput(VideoFrameContainer* aContainer, AbstractThread* aMainThread)
       : mMutex("VideoOutput::mMutex"),
@@ -137,18 +137,17 @@ class VideoOutput : public DirectMediaTr
     MutexAutoLock lock(mMutex);
     for (VideoSegment::ConstChunkIterator i(video); !i.IsEnded(); i.Next()) {
       if (!mLastFrameTime.IsNull() && i->mTimeStamp < mLastFrameTime) {
         // Time can go backwards if the source is a captured MediaDecoder and
         // it seeks, as the previously buffered frames would stretch into the
         // future. If this happens, we clear the buffered frames and start over.
         mFrames.ClearAndRetainStorage();
       }
-      mFrames.AppendElement(
-          std::make_pair(mVideoFrameContainer->NewFrameID(), *i));
+      mFrames.AppendElement(MakePair(mVideoFrameContainer->NewFrameID(), *i));
       mLastFrameTime = i->mTimeStamp;
     }
 
     SendFramesEnsureLocked();
   }
   void NotifyRemoved(MediaTrackGraph* aGraph) override {
     // Doesn't need locking by mMutex, since the direct listener is removed from
     // the track before we get notified.
@@ -183,30 +182,30 @@ class VideoOutput : public DirectMediaTr
   }
   void NotifyEnabledStateChanged(MediaTrackGraph* aGraph,
                                  bool aEnabled) override {
     MutexAutoLock lock(mMutex);
     mEnabled = aEnabled;
     // Since mEnabled will affect whether frames are real, or black, we assign
     // new FrameIDs whenever this changes.
     for (auto& idChunkPair : mFrames) {
-      idChunkPair.first = mVideoFrameContainer->NewFrameID();
+      idChunkPair.first() = mVideoFrameContainer->NewFrameID();
     }
     SendFramesEnsureLocked();
   }
 
   Mutex mMutex;
   TimeStamp mLastFrameTime;
   // Once the frame is forced to black, we initialize mBlackImage for use in any
   // following forced-black frames.
   RefPtr<Image> mBlackImage;
   bool mEnabled = true;
   // This array is accessed from both the direct video thread, and the graph
   // thread. Protected by mMutex.
-  nsTArray<std::pair<ImageContainer::FrameID, VideoChunk>> mFrames;
+  nsTArray<Pair<ImageContainer::FrameID, VideoChunk>> mFrames;
   const RefPtr<VideoFrameContainer> mVideoFrameContainer;
   const RefPtr<AbstractThread> mMainThread;
   const layers::ImageContainer::ProducerID mProducerID =
       layers::ImageContainer::AllocateProducerID();
 };
 
 }  // namespace mozilla
 
--- a/dom/media/gmp/ChromiumCDMAdapter.cpp
+++ b/dom/media/gmp/ChromiumCDMAdapter.cpp
@@ -34,17 +34,17 @@ const GMPPlatformAPI* sPlatform = nullpt
 
 namespace mozilla {
 
 #ifdef XP_WIN
 static void InitializeHooks();
 #endif
 
 ChromiumCDMAdapter::ChromiumCDMAdapter(
-    nsTArray<std::pair<nsCString, nsCString>>&& aHostPathPairs) {
+    nsTArray<Pair<nsCString, nsCString>>&& aHostPathPairs) {
 #ifdef XP_WIN
   InitializeHooks();
 #endif
   PopulateHostFiles(std::move(aHostPathPairs));
 }
 
 void ChromiumCDMAdapter::SetAdaptee(PRLibrary* aLib) { mLib = aLib; }
 
@@ -277,16 +277,16 @@ HostFile::HostFile(const nsCString& aPat
 
 cdm::PlatformFile HostFile::TakePlatformFile() {
   cdm::PlatformFile f = mFile;
   mFile = cdm::kInvalidPlatformFile;
   return f;
 }
 
 void ChromiumCDMAdapter::PopulateHostFiles(
-    nsTArray<std::pair<nsCString, nsCString>>&& aHostPathPairs) {
+    nsTArray<Pair<nsCString, nsCString>>&& aHostPathPairs) {
   for (const auto& pair : aHostPathPairs) {
-    mHostFiles.AppendElement(HostFileData(mozilla::HostFile(pair.first),
-                                          mozilla::HostFile(pair.second)));
+    mHostFiles.AppendElement(HostFileData(mozilla::HostFile(pair.first()),
+                                          mozilla::HostFile(pair.second())));
   }
 }
 
 }  // namespace mozilla
--- a/dom/media/gmp/ChromiumCDMAdapter.h
+++ b/dom/media/gmp/ChromiumCDMAdapter.h
@@ -7,18 +7,17 @@
 #define ChromiumAdapter_h_
 
 #include "GMPLoader.h"
 #include "prlink.h"
 #include "GMPUtils.h"
 #include "nsTArray.h"
 #include "content_decryption_module_ext.h"
 #include "nsString.h"
-
-#include <utility>
+#include "mozilla/Pair.h"
 
 struct GMPPlatformAPI;
 
 namespace mozilla {
 
 #if defined(XP_WIN)
 typedef nsString HostFileString;
 #else
@@ -50,32 +49,31 @@ struct HostFileData {
 
   HostFile mBinary;
   HostFile mSig;
 };
 
 class ChromiumCDMAdapter : public gmp::GMPAdapter {
  public:
   explicit ChromiumCDMAdapter(
-      nsTArray<std::pair<nsCString, nsCString>>&& aHostPathPairs);
+      nsTArray<Pair<nsCString, nsCString>>&& aHostPathPairs);
 
   void SetAdaptee(PRLibrary* aLib) override;
 
   // These are called in place of the corresponding GMP API functions.
   GMPErr GMPInit(const GMPPlatformAPI* aPlatformAPI) override;
   GMPErr GMPGetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI,
                    uint32_t aDecryptorId) override;
   void GMPShutdown() override;
 
   static bool Supports(int32_t aModuleVersion, int32_t aInterfaceVersion,
                        int32_t aHostVersion);
 
  private:
-  void PopulateHostFiles(
-      nsTArray<std::pair<nsCString, nsCString>>&& aHostFilePaths);
+  void PopulateHostFiles(nsTArray<Pair<nsCString, nsCString>>&& aHostFilePaths);
 
   PRLibrary* mLib = nullptr;
   nsTArray<HostFileData> mHostFiles;
 };
 
 }  // namespace mozilla
 
 #endif  // ChromiumAdapter_h_
--- a/dom/media/gmp/GMPChild.cpp
+++ b/dom/media/gmp/GMPChild.cpp
@@ -375,17 +375,17 @@ static bool GetSigPath(const int aRelati
   MOZ_ASSERT(path);
   aOutSigPath = path;
   return NS_SUCCEEDED(path->Append(NS_LITERAL_STRING("Resources"))) &&
          NS_SUCCEEDED(path->Append(aTargetSigFileName));
 }
 #endif
 
 static bool AppendHostPath(nsCOMPtr<nsIFile>& aFile,
-                           nsTArray<std::pair<nsCString, nsCString>>& aPaths) {
+                           nsTArray<Pair<nsCString, nsCString>>& aPaths) {
   nsString str;
   if (!FileExists(aFile) || !ResolveLinks(aFile) ||
       NS_FAILED(aFile->GetPath(str))) {
     return false;
   }
 
   nsCString filePath = NS_ConvertUTF16toUTF8(str);
   nsCString sigFilePath;
@@ -405,31 +405,29 @@ static bool AppendHostPath(nsCOMPtr<nsIF
     // alternatively.
     sigFilePath =
         nsCString(NS_ConvertUTF16toUTF8(str) + NS_LITERAL_CSTRING(".sig"));
   }
 #else
   sigFilePath =
       nsCString(NS_ConvertUTF16toUTF8(str) + NS_LITERAL_CSTRING(".sig"));
 #endif
-  aPaths.AppendElement(
-      std::make_pair(std::move(filePath), std::move(sigFilePath)));
+  aPaths.AppendElement(MakePair(std::move(filePath), std::move(sigFilePath)));
   return true;
 }
 
-nsTArray<std::pair<nsCString, nsCString>>
-GMPChild::MakeCDMHostVerificationPaths() {
+nsTArray<Pair<nsCString, nsCString>> GMPChild::MakeCDMHostVerificationPaths() {
   // Record the file path and its sig file path.
-  nsTArray<std::pair<nsCString, nsCString>> paths;
+  nsTArray<Pair<nsCString, nsCString>> paths;
   // Plugin binary path.
   nsCOMPtr<nsIFile> path;
   nsString str;
   if (GetPluginFile(mPluginPath, path) && FileExists(path) &&
       ResolveLinks(path) && NS_SUCCEEDED(path->GetPath(str))) {
-    paths.AppendElement(std::make_pair(
+    paths.AppendElement(MakePair(
         nsCString(NS_ConvertUTF16toUTF8(str)),
         nsCString(NS_ConvertUTF16toUTF8(str) + NS_LITERAL_CSTRING(".sig"))));
   }
 
   // Plugin-container binary path.
   // Note: clang won't let us initialize an nsString from a wstring, so we
   // need to go through UTF8 to get to an nsString.
   const std::string pluginContainer =
@@ -471,24 +469,24 @@ GMPChild::MakeCDMHostVerificationPaths()
   path = AppendFile(CloneFile(appDir), XUL_LIB_FILE);
   if (!AppendHostPath(path, paths)) {
     return paths;
   }
 
   return paths;
 }
 
-static nsCString ToCString(
-    const nsTArray<std::pair<nsCString, nsCString>>& aPairs) {
+static nsCString ToCString(const nsTArray<Pair<nsCString, nsCString>>& aPairs) {
   nsCString result;
   for (const auto& p : aPairs) {
     if (!result.IsEmpty()) {
       result.AppendLiteral(",");
     }
-    result.Append(nsPrintfCString("(%s,%s)", p.first.get(), p.second.get()));
+    result.Append(
+        nsPrintfCString("(%s,%s)", p.first().get(), p.second().get()));
   }
   return result;
 }
 
 mozilla::ipc::IPCResult GMPChild::AnswerStartPlugin(const nsString& aAdapter) {
   GMP_CHILD_LOG_DEBUG("%s", __FUNCTION__);
 
   nsCString libPath;
--- a/dom/media/gmp/GMPChild.h
+++ b/dom/media/gmp/GMPChild.h
@@ -2,16 +2,17 @@
 /* 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 GMPChild_h_
 #define GMPChild_h_
 
 #include "mozilla/gmp/PGMPChild.h"
+#include "mozilla/Pair.h"
 #include "GMPTimerChild.h"
 #include "GMPStorageChild.h"
 #include "GMPLoader.h"
 #include "gmp-entrypoints.h"
 #include "prlink.h"
 
 namespace mozilla {
 namespace gmp {
@@ -62,17 +63,17 @@ class GMPChild : public PGMPChild {
       Endpoint<PGMPContentChild>&& aEndpoint);
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
   void ProcessingError(Result aCode, const char* aReason) override;
 
   GMPErr GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI,
                 uint32_t aDecryptorId = 0);
 
-  nsTArray<std::pair<nsCString, nsCString>> MakeCDMHostVerificationPaths();
+  nsTArray<Pair<nsCString, nsCString>> MakeCDMHostVerificationPaths();
 
   nsTArray<UniquePtr<GMPContentChild>> mGMPContentChildren;
 
   RefPtr<GMPTimerChild> mTimerChild;
   RefPtr<GMPStorageChild> mStorage;
 
   MessageLoop* mGMPMessageLoop;
   nsString mPluginPath;
--- a/dom/media/gtest/TestVideoFrameConverter.cpp
+++ b/dom/media/gtest/TestVideoFrameConverter.cpp
@@ -17,17 +17,17 @@ class FrameListener : public VideoConver
   void OnVideoFrameConverted(const webrtc::VideoFrame& aVideoFrame) override;
 
  private:
   VideoFrameConverterTest* mTest;
 };
 
 class VideoFrameConverterTest : public ::testing::Test {
  protected:
-  using FrameType = std::pair<webrtc::VideoFrame, TimeStamp>;
+  using FrameType = Pair<webrtc::VideoFrame, TimeStamp>;
   Monitor mMonitor;
   RefPtr<VideoFrameConverter> mConverter;
   RefPtr<FrameListener> mListener;
   std::vector<FrameType> mConvertedFrames;
 
   VideoFrameConverterTest()
       : mMonitor("PacingFixture::mMonitor"),
         mConverter(MakeAndAddRef<VideoFrameConverter>()),
@@ -51,17 +51,17 @@ class VideoFrameConverterTest : public :
                              mConvertedFrames.begin() + aN);
     return v;
   }
 
  public:
   void OnVideoFrameConverted(const webrtc::VideoFrame& aVideoFrame) {
     MonitorAutoLock lock(mMonitor);
     EXPECT_NE(aVideoFrame.timestamp_us(), 0);
-    mConvertedFrames.push_back(std::make_pair(aVideoFrame, TimeStamp::Now()));
+    mConvertedFrames.push_back(MakePair(aVideoFrame, TimeStamp::Now()));
     mMonitor.Notify();
   }
 };
 
 FrameListener::FrameListener(VideoFrameConverterTest* aTest) : mTest(aTest) {}
 void FrameListener::OnVideoFrameConverted(
     const webrtc::VideoFrame& aVideoFrame) {
   mTest->OnVideoFrameConverted(aVideoFrame);
@@ -80,90 +80,90 @@ VideoChunk GenerateChunk(int32_t aWidth,
 
 TEST_F(VideoFrameConverterTest, BasicConversion) {
   TimeStamp now = TimeStamp::Now();
   VideoChunk chunk = GenerateChunk(640, 480, now);
   mConverter->SetActive(true);
   mConverter->QueueVideoChunk(chunk, false);
   auto frames = WaitForNConverted(1);
   ASSERT_EQ(frames.size(), 1U);
-  EXPECT_EQ(frames[0].first.width(), 640);
-  EXPECT_EQ(frames[0].first.height(), 480);
-  EXPECT_GT(frames[0].second - now, TimeDuration::FromMilliseconds(0));
+  EXPECT_EQ(frames[0].first().width(), 640);
+  EXPECT_EQ(frames[0].first().height(), 480);
+  EXPECT_GT(frames[0].second() - now, TimeDuration::FromMilliseconds(0));
 }
 
 TEST_F(VideoFrameConverterTest, BasicPacing) {
   TimeStamp now = TimeStamp::Now();
   TimeStamp future = now + TimeDuration::FromMilliseconds(100);
   VideoChunk chunk = GenerateChunk(640, 480, future);
   mConverter->SetActive(true);
   mConverter->QueueVideoChunk(chunk, false);
   auto frames = WaitForNConverted(1);
   EXPECT_GT(TimeStamp::Now(), future);
   ASSERT_EQ(frames.size(), 1U);
-  EXPECT_EQ(frames[0].first.width(), 640);
-  EXPECT_EQ(frames[0].first.height(), 480);
-  EXPECT_GT(frames[0].second - now, future - now);
+  EXPECT_EQ(frames[0].first().width(), 640);
+  EXPECT_EQ(frames[0].first().height(), 480);
+  EXPECT_GT(frames[0].second() - now, future - now);
 }
 
 TEST_F(VideoFrameConverterTest, MultiPacing) {
   TimeStamp now = TimeStamp::Now();
   TimeStamp future1 = now + TimeDuration::FromMilliseconds(100);
   TimeStamp future2 = now + TimeDuration::FromMilliseconds(200);
   VideoChunk chunk = GenerateChunk(640, 480, future1);
   mConverter->SetActive(true);
   mConverter->QueueVideoChunk(chunk, false);
   chunk = GenerateChunk(640, 480, future2);
   mConverter->QueueVideoChunk(chunk, false);
   auto frames = WaitForNConverted(2);
   EXPECT_GT(TimeStamp::Now(), future2);
   ASSERT_EQ(frames.size(), 2U);
-  EXPECT_EQ(frames[0].first.width(), 640);
-  EXPECT_EQ(frames[0].first.height(), 480);
-  EXPECT_GT(frames[0].second - now, future1 - now);
-  EXPECT_EQ(frames[1].first.width(), 640);
-  EXPECT_EQ(frames[1].first.height(), 480);
-  EXPECT_GT(frames[1].second, future2);
-  EXPECT_GT(frames[1].second - now, frames[0].second - now);
+  EXPECT_EQ(frames[0].first().width(), 640);
+  EXPECT_EQ(frames[0].first().height(), 480);
+  EXPECT_GT(frames[0].second() - now, future1 - now);
+  EXPECT_EQ(frames[1].first().width(), 640);
+  EXPECT_EQ(frames[1].first().height(), 480);
+  EXPECT_GT(frames[1].second(), future2);
+  EXPECT_GT(frames[1].second() - now, frames[0].second() - now);
 }
 
 TEST_F(VideoFrameConverterTest, Duplication) {
   TimeStamp now = TimeStamp::Now();
   TimeStamp future1 = now + TimeDuration::FromMilliseconds(100);
   VideoChunk chunk = GenerateChunk(640, 480, future1);
   mConverter->SetActive(true);
   mConverter->QueueVideoChunk(chunk, false);
   auto frames = WaitForNConverted(2);
   EXPECT_GT(TimeStamp::Now() - now, TimeDuration::FromMilliseconds(1100));
   ASSERT_EQ(frames.size(), 2U);
-  EXPECT_EQ(frames[0].first.width(), 640);
-  EXPECT_EQ(frames[0].first.height(), 480);
-  EXPECT_GT(frames[0].second, future1);
-  EXPECT_EQ(frames[1].first.width(), 640);
-  EXPECT_EQ(frames[1].first.height(), 480);
-  EXPECT_GT(frames[1].second - now, TimeDuration::FromMilliseconds(1100));
+  EXPECT_EQ(frames[0].first().width(), 640);
+  EXPECT_EQ(frames[0].first().height(), 480);
+  EXPECT_GT(frames[0].second(), future1);
+  EXPECT_EQ(frames[1].first().width(), 640);
+  EXPECT_EQ(frames[1].first().height(), 480);
+  EXPECT_GT(frames[1].second() - now, TimeDuration::FromMilliseconds(1100));
   // Check that the second frame comes between 1s and 2s after the first.
-  EXPECT_NEAR(frames[1].first.timestamp_us(),
-              frames[0].first.timestamp_us() + ((PR_USEC_PER_SEC * 3) / 2),
+  EXPECT_NEAR(frames[1].first().timestamp_us(),
+              frames[0].first().timestamp_us() + ((PR_USEC_PER_SEC * 3) / 2),
               PR_USEC_PER_SEC / 2);
 }
 
 TEST_F(VideoFrameConverterTest, DropsOld) {
   TimeStamp now = TimeStamp::Now();
   TimeStamp future1 = now + TimeDuration::FromMilliseconds(1000);
   TimeStamp future2 = now + TimeDuration::FromMilliseconds(100);
   mConverter->SetActive(true);
   mConverter->QueueVideoChunk(GenerateChunk(800, 600, future1), false);
   mConverter->QueueVideoChunk(GenerateChunk(640, 480, future2), false);
   auto frames = WaitForNConverted(1);
   EXPECT_GT(TimeStamp::Now(), future2);
   ASSERT_EQ(frames.size(), 1U);
-  EXPECT_EQ(frames[0].first.width(), 640);
-  EXPECT_EQ(frames[0].first.height(), 480);
-  EXPECT_GT(frames[0].second - now, future2 - now);
+  EXPECT_EQ(frames[0].first().width(), 640);
+  EXPECT_EQ(frames[0].first().height(), 480);
+  EXPECT_GT(frames[0].second() - now, future2 - now);
 }
 
 // We check that the disabling code was triggered by sending multiple,
 // different, frames to the converter within one second. While black, it shall
 // treat all frames identical and issue one black frame per second.
 TEST_F(VideoFrameConverterTest, BlackOnDisable) {
   TimeStamp now = TimeStamp::Now();
   TimeStamp future1 = now + TimeDuration::FromMilliseconds(100);
@@ -172,26 +172,26 @@ TEST_F(VideoFrameConverterTest, BlackOnD
   mConverter->SetActive(true);
   mConverter->SetTrackEnabled(false);
   mConverter->QueueVideoChunk(GenerateChunk(640, 480, future1), false);
   mConverter->QueueVideoChunk(GenerateChunk(640, 480, future2), false);
   mConverter->QueueVideoChunk(GenerateChunk(640, 480, future3), false);
   auto frames = WaitForNConverted(2);
   EXPECT_GT(TimeStamp::Now() - now, TimeDuration::FromMilliseconds(1100));
   ASSERT_EQ(frames.size(), 2U);
-  EXPECT_EQ(frames[0].first.width(), 640);
-  EXPECT_EQ(frames[0].first.height(), 480);
-  EXPECT_GT(frames[0].second - now, future1 - now);
-  EXPECT_EQ(frames[1].first.width(), 640);
-  EXPECT_EQ(frames[1].first.height(), 480);
-  EXPECT_GT(frames[1].second - now,
+  EXPECT_EQ(frames[0].first().width(), 640);
+  EXPECT_EQ(frames[0].first().height(), 480);
+  EXPECT_GT(frames[0].second() - now, future1 - now);
+  EXPECT_EQ(frames[1].first().width(), 640);
+  EXPECT_EQ(frames[1].first().height(), 480);
+  EXPECT_GT(frames[1].second() - now,
             future1 - now + TimeDuration::FromSeconds(1));
   // Check that the second frame comes between 1s and 2s after the first.
-  EXPECT_NEAR(frames[1].first.timestamp_us(),
-              frames[0].first.timestamp_us() + ((PR_USEC_PER_SEC * 3) / 2),
+  EXPECT_NEAR(frames[1].first().timestamp_us(),
+              frames[0].first().timestamp_us() + ((PR_USEC_PER_SEC * 3) / 2),
               PR_USEC_PER_SEC / 2);
 }
 
 TEST_F(VideoFrameConverterTest, ClearFutureFramesOnJumpingBack) {
   TimeStamp start = TimeStamp::Now();
   TimeStamp future1 = start + TimeDuration::FromMilliseconds(100);
 
   mConverter->SetActive(true);
@@ -216,22 +216,22 @@ TEST_F(VideoFrameConverterTest, ClearFut
   // second for the same-frame timer. It has a different time and resolution
   // so we can differentiate them.
   mConverter->QueueVideoChunk(GenerateChunk(320, 240, future3), false);
 
   auto frames = WaitForNConverted(2);
   TimeStamp step2 = TimeStamp::Now();
   EXPECT_GT(step2 - start, future3 - start);
   ASSERT_EQ(frames.size(), 2U);
-  EXPECT_EQ(frames[0].first.width(), 640);
-  EXPECT_EQ(frames[0].first.height(), 480);
-  EXPECT_GT(frames[0].second - start, future1 - start);
-  EXPECT_EQ(frames[1].first.width(), 320);
-  EXPECT_EQ(frames[1].first.height(), 240);
-  EXPECT_GT(frames[1].second - start, future3 - start);
+  EXPECT_EQ(frames[0].first().width(), 640);
+  EXPECT_EQ(frames[0].first().height(), 480);
+  EXPECT_GT(frames[0].second() - start, future1 - start);
+  EXPECT_EQ(frames[1].first().width(), 320);
+  EXPECT_EQ(frames[1].first().height(), 240);
+  EXPECT_GT(frames[1].second() - start, future3 - start);
 }
 
 // We check that the no frame is converted while inactive, and that on
 // activating the most recently queued frame gets converted.
 TEST_F(VideoFrameConverterTest, NoConversionsWhileInactive) {
   TimeStamp now = TimeStamp::Now();
   TimeStamp future1 = now - TimeDuration::FromMilliseconds(1);
   TimeStamp future2 = now;
@@ -244,11 +244,11 @@ TEST_F(VideoFrameConverterTest, NoConver
                             "VideoFrameConverterTest");
   auto timer = MakeRefPtr<MediaTimer>(false);
   timer->WaitFor(TimeDuration::FromMilliseconds(100), __func__)
       ->Then(q, __func__,
              [converter = mConverter] { converter->SetActive(true); });
 
   auto frames = WaitForNConverted(1);
   ASSERT_EQ(frames.size(), 1U);
-  EXPECT_EQ(frames[0].first.width(), 800);
-  EXPECT_EQ(frames[0].first.height(), 600);
+  EXPECT_EQ(frames[0].first().width(), 800);
+  EXPECT_EQ(frames[0].first().height(), 600);
 }
--- a/dom/media/mediasource/SourceBuffer.cpp
+++ b/dom/media/mediasource/SourceBuffer.cpp
@@ -592,17 +592,17 @@ already_AddRefed<Promise> SourceBuffer::
 }
 
 void SourceBuffer::AppendDataCompletedWithSuccess(
     const SourceBufferTask::AppendBufferResult& aResult) {
   MOZ_ASSERT(mUpdating);
   mPendingAppend.Complete();
   DDLOG(DDLogCategory::API, "AppendBuffer-completed", NS_OK);
 
-  if (aResult.first) {
+  if (aResult.first()) {
     if (!mActive) {
       mActive = true;
       MSE_DEBUG("Init segment received");
       RefPtr<SourceBuffer> self = this;
       mMediaSource->SourceBufferIsActive(this)
           ->Then(mAbstractMainThread, __func__,
                  [self, this]() {
                    MSE_DEBUG("Complete AppendBuffer operation");
@@ -613,17 +613,17 @@ void SourceBuffer::AppendDataCompletedWi
     }
   }
   if (mActive) {
     // Tell our parent decoder that we have received new data
     // and send progress event.
     mMediaSource->GetDecoder()->NotifyDataArrived();
   }
 
-  mCurrentAttributes = aResult.second;
+  mCurrentAttributes = aResult.second();
 
   CheckEndTime();
 
   if (!mCompletionPromise.Exists()) {
     StopUpdating();
   }
 }
 
--- a/dom/media/mediasource/SourceBufferTask.h
+++ b/dom/media/mediasource/SourceBufferTask.h
@@ -3,38 +3,37 @@
 /* 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 MOZILLA_SOURCEBUFFERTASK_H_
 #define MOZILLA_SOURCEBUFFERTASK_H_
 
 #include "mozilla/MozPromise.h"
+#include "mozilla/Pair.h"
 #include "SourceBufferAttributes.h"
 #include "TimeUnits.h"
 #include "MediaResult.h"
 
-#include <utility>
-
 namespace mozilla {
 
 class SourceBufferTask {
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SourceBufferTask);
   enum class Type {
     AppendBuffer,
     Abort,
     Reset,
     RangeRemoval,
     EvictData,
     Detach,
     ChangeType
   };
 
-  typedef std::pair<bool, SourceBufferAttributes> AppendBufferResult;
+  typedef Pair<bool, SourceBufferAttributes> AppendBufferResult;
   typedef MozPromise<AppendBufferResult, MediaResult, /* IsExclusive = */ true>
       AppendPromise;
   typedef MozPromise<bool, nsresult, /* IsExclusive = */ true>
       RangeRemovalPromise;
 
   virtual Type GetType() const = 0;
   virtual const char* GetTypeName() const = 0;
 
--- a/dom/media/mp3/MP3FrameParser.cpp
+++ b/dom/media/mp3/MP3FrameParser.cpp
@@ -6,16 +6,17 @@
 
 #include "MP3FrameParser.h"
 
 #include <algorithm>
 #include <inttypes.h>
 
 #include "mozilla/Assertions.h"
 #include "mozilla/EndianUtils.h"
+#include "mozilla/Pair.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/ScopeExit.h"
 #include "VideoUtils.h"
 
 extern mozilla::LazyLogModule gMediaDemuxerLog;
 #define MP3LOG(msg, ...) \
   MOZ_LOG(gMediaDemuxerLog, LogLevel::Debug, ("MP3Demuxer " msg, ##__VA_ARGS__))
 #define MP3LOGV(msg, ...)                      \
@@ -439,19 +440,19 @@ Result<bool, nsresult> FrameParser::VBRH
       mType = VBRI;
       return true;
     }
   }
   return false;
 }
 
 bool FrameParser::VBRHeader::Parse(BufferReader* aReader) {
-  auto res = std::make_pair(ParseVBRI(aReader), ParseXing(aReader));
-  const bool rv = (res.first.isOk() && res.first.unwrap()) ||
-                  (res.second.isOk() && res.second.unwrap());
+  auto res = MakePair(ParseVBRI(aReader), ParseXing(aReader));
+  const bool rv = (res.first().isOk() && res.first().unwrap()) ||
+                  (res.second().isOk() && res.second().unwrap());
   if (rv) {
     MP3LOG(
         "VBRHeader::Parse found valid VBR/CBR header: type=%s"
         " NumAudioFrames=%u NumBytes=%u Scale=%u TOC-size=%zu",
         vbr_header::TYPE_STR[Type()], NumAudioFrames().valueOr(0),
         NumBytes().valueOr(0), Scale().valueOr(0), mTOC.size());
   }
   return rv;
--- a/dom/media/platforms/SimpleMap.h
+++ b/dom/media/platforms/SimpleMap.h
@@ -1,42 +1,41 @@
 /* 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 mozilla_SimpleMap_h
 #define mozilla_SimpleMap_h
 
+#include "mozilla/Pair.h"
 #include "nsTArray.h"
 
-#include <utility>
-
 namespace mozilla {
 
 template <typename T>
 class SimpleMap {
  public:
-  typedef std::pair<int64_t, T> Element;
+  typedef Pair<int64_t, T> Element;
 
   SimpleMap() : mMutex("SimpleMap") {}
 
   // Insert Key and Value pair at the end of our map.
   void Insert(int64_t aKey, const T& aValue) {
     MutexAutoLock lock(mMutex);
-    mMap.AppendElement(std::make_pair(aKey, aValue));
+    mMap.AppendElement(MakePair(aKey, aValue));
   }
   // Sets aValue matching aKey and remove it from the map if found.
   // The element returned is the first one found.
   // Returns true if found, false otherwise.
   bool Find(int64_t aKey, T& aValue) {
     MutexAutoLock lock(mMutex);
     for (uint32_t i = 0; i < mMap.Length(); i++) {
       Element& element = mMap[i];
-      if (element.first == aKey) {
-        aValue = element.second;
+      if (element.first() == aKey) {
+        aValue = element.second();
         mMap.RemoveElementAt(i);
         return true;
       }
     }
     return false;
   }
   // Remove all elements of the map.
   void Clear() {
--- a/dom/media/systemservices/CamerasChild.h
+++ b/dom/media/systemservices/CamerasChild.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_CamerasChild_h
 #define mozilla_CamerasChild_h
 
 #include <utility>
 
 #include "MediaEventSource.h"
 #include "mozilla/Mutex.h"
+#include "mozilla/Pair.h"
 #include "mozilla/camera/PCamerasChild.h"
 #include "mozilla/camera/PCamerasParent.h"
 #include "nsCOMPtr.h"
 
 // conflicts with #include of scoped_ptr.h
 #undef FF
 #include "webrtc/modules/video_capture/video_capture_defines.h"
 
--- a/dom/plugins/base/PluginFinder.cpp
+++ b/dom/plugins/base/PluginFinder.cpp
@@ -174,17 +174,17 @@ nsresult PluginFinder::DoFullSearch(cons
   MOZ_TRY(DeterminePluginDirs());
   // If we're only interested in flash, provide an initial update from
   // cache. We'll do a scan async, away from the main thread, and if
   // there are updates then we'll pass them in.
   if (mFlashOnly) {
     ReadFlashInfo();
     // Don't do a blocklist check until we're done scanning,
     // as the version might change anyway.
-    nsTArray<std::pair<bool, RefPtr<nsPluginTag>>> arr;
+    nsTArray<mozilla::Pair<bool, RefPtr<nsPluginTag>>> arr;
     mFoundPluginCallback(!!mPlugins, mPlugins, arr);
     // We've passed ownership of the flash plugin to the host, so make sure
     // we don't accidentally try to use it when we leave the mainthread.
     mPlugins = nullptr;
   }
   return NS_OK;
 }
 
@@ -597,18 +597,17 @@ nsresult PluginFinder::ScanPluginsDirect
         continue;
       }
 
       pluginTag = new nsPluginTag(&info, fileModTime, blocklistState);
       pluginTag->mLibrary = library;
       pluginFile.FreePluginInfo(info);
 
       // We'll need to do a blocklist request later.
-      mPluginBlocklistRequests.AppendElement(
-          std::make_pair(!seenBefore, pluginTag));
+      mPluginBlocklistRequests.AppendElement(MakePair(!seenBefore, pluginTag));
 
       // Plugin unloading is tag-based. If we created a new tag and loaded
       // the library in the process then we want to attempt to unload it here.
       // Only do this if the pref is set for aggressive unloading.
       if (UnloadPluginsASAP()) {
         if (NS_IsMainThread()) {
           pluginTag->TryUnloadPlugin(false);
         } else {
--- a/dom/plugins/base/PluginFinder.h
+++ b/dom/plugins/base/PluginFinder.h
@@ -54,18 +54,18 @@ class PluginFinder final : public nsIRun
   explicit PluginFinder(bool aFlashOnly);
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSIASYNCSHUTDOWNBLOCKER
 
   typedef std::function<void(
       bool /* aPluginsChanged */, RefPtr<nsPluginTag> /* aNewPlugins */,
-      nsTArray<
-          std::pair<bool, RefPtr<nsPluginTag>>>&) /* aBlocklistRequestPairs */>
+      nsTArray<mozilla::Pair<
+          bool, RefPtr<nsPluginTag>>>&) /* aBlocklistRequestPairs */>
       FoundPluginCallback;
   typedef std::function<void(bool /* aPluginsChanged */)> PluginChangeCallback;
 
   // The expectation is that one (and only one) of these gets called
   // by the plugin host. We can't easily do the work in the constructor
   // because in some cases we'll fail early (e.g. if we're called before
   // the profile is ready) and want to signal that to the consumer via
   // the nsresult return value, which we can't do in a constructor.
@@ -104,17 +104,17 @@ class PluginFinder final : public nsIRun
   // examining the disk; this is a performance optimization to avoid trying
   // to load files that aren't plugins on every browser startup.
   RefPtr<nsInvalidPluginTag> mInvalidPlugins;
 
   // The bool (shouldSoftBlock) indicates whether we should disable the plugin
   // if it's soft-blocked in the blocklist
   // The plugintag is a reference to the actual plugin whose blocklist state
   // needs checking.
-  nsTArray<std::pair<bool, RefPtr<nsPluginTag>>> mPluginBlocklistRequests;
+  nsTArray<mozilla::Pair<bool, RefPtr<nsPluginTag>>> mPluginBlocklistRequests;
 
   FoundPluginCallback mFoundPluginCallback;
   PluginChangeCallback mChangeCallback;
   RefPtr<nsPluginHost> mHost;
 
   bool mFlashOnly;
   bool mCreateList;
   bool mPluginsChanged;
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -1894,37 +1894,37 @@ nsresult nsPluginHost::LoadPlugins() {
   mDoReloadOnceFindingFinished = false;
   mAddedFinderShutdownBlocker = false;
   RefPtr<nsPluginHost> self = this;
   // Note that if we're in flash only mode, which is the default, then the
   // callback will be called twice. Once for flash (or nothing, if we're not
   // (yet) aware of flash being present), and then again after we've actually
   // looked for it on disk.
   nsresult rv = mPendingFinder->DoFullSearch(
-      [self](bool aPluginsChanged, RefPtr<nsPluginTag> aPlugins,
-             const nsTArray<std::pair<bool, RefPtr<nsPluginTag>>>&
-                 aBlocklistRequests) {
+      [self](
+          bool aPluginsChanged, RefPtr<nsPluginTag> aPlugins,
+          const nsTArray<Pair<bool, RefPtr<nsPluginTag>>>& aBlocklistRequests) {
         MOZ_ASSERT(NS_IsMainThread(),
                    "Callback should only be called on the main thread.");
         self->mPluginsLoaded = true;
         if (aPluginsChanged) {
           self->ClearNonRunningPlugins();
           while (aPlugins) {
             RefPtr<nsPluginTag> pluginTag = aPlugins;
             aPlugins = aPlugins->mNext;
             self->AddPluginTag(pluginTag);
           }
           self->IncrementChromeEpoch();
           self->BroadcastPluginsToContent();
         }
 
         // Do blocklist queries immediately after.
         for (auto pair : aBlocklistRequests) {
-          RefPtr<nsPluginTag> pluginTag = pair.second;
-          bool shouldSoftblock = pair.first;
+          RefPtr<nsPluginTag> pluginTag = pair.second();
+          bool shouldSoftblock = pair.first();
           self->UpdatePluginBlocklistState(pluginTag, shouldSoftblock);
         }
 
         if (aPluginsChanged) {
           nsCOMPtr<nsIObserverService> obsService =
               mozilla::services::GetObserverService();
           if (obsService) {
             obsService->NotifyObservers(nullptr, "plugins-list-updated",
--- a/dom/security/nsContentSecurityUtils.cpp
+++ b/dom/security/nsContentSecurityUtils.cpp
@@ -520,29 +520,29 @@ void nsContentSecurityUtils::NotifyEvalU
   // Send Telemetry
   Telemetry::EventID eventType =
       aIsSystemPrincipal ? Telemetry::EventID::Security_Evalusage_Systemcontext
                          : Telemetry::EventID::Security_Evalusage_Parentprocess;
 
   FilenameTypeAndDetails fileNameTypeAndDetails =
       FilenameToFilenameType(aFileNameA, false);
   mozilla::Maybe<nsTArray<EventExtraEntry>> extra;
-  if (fileNameTypeAndDetails.second.isSome()) {
+  if (fileNameTypeAndDetails.second().isSome()) {
     extra = Some<nsTArray<EventExtraEntry>>({EventExtraEntry{
         NS_LITERAL_CSTRING("fileinfo"),
-        NS_ConvertUTF16toUTF8(fileNameTypeAndDetails.second.value())}});
+        NS_ConvertUTF16toUTF8(fileNameTypeAndDetails.second().value())}});
   } else {
     extra = Nothing();
   }
   if (!sTelemetryEventEnabled.exchange(true)) {
     sTelemetryEventEnabled = true;
     Telemetry::SetEventRecordingEnabled(NS_LITERAL_CSTRING("security"), true);
   }
-  Telemetry::RecordEvent(eventType, mozilla::Some(fileNameTypeAndDetails.first),
-                         extra);
+  Telemetry::RecordEvent(eventType,
+                         mozilla::Some(fileNameTypeAndDetails.first()), extra);
 
   // Report an error to console
   nsCOMPtr<nsIConsoleService> console(
       do_GetService(NS_CONSOLESERVICE_CONTRACTID));
   if (!console) {
     return;
   }
   nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
@@ -828,28 +828,28 @@ bool nsContentSecurityUtils::ValidateScr
   // Send Telemetry
   FilenameTypeAndDetails fileNameTypeAndDetails =
       FilenameToFilenameType(filenameU, true);
 
   Telemetry::EventID eventType =
       Telemetry::EventID::Security_Javascriptload_Parentprocess;
 
   mozilla::Maybe<nsTArray<EventExtraEntry>> extra;
-  if (fileNameTypeAndDetails.second.isSome()) {
+  if (fileNameTypeAndDetails.second().isSome()) {
     extra = Some<nsTArray<EventExtraEntry>>({EventExtraEntry{
         NS_LITERAL_CSTRING("fileinfo"),
-        NS_ConvertUTF16toUTF8(fileNameTypeAndDetails.second.value())}});
+        NS_ConvertUTF16toUTF8(fileNameTypeAndDetails.second().value())}});
   } else {
     extra = Nothing();
   }
 
   if (!sTelemetryEventEnabled.exchange(true)) {
     sTelemetryEventEnabled = true;
     Telemetry::SetEventRecordingEnabled(NS_LITERAL_CSTRING("security"), true);
   }
-  Telemetry::RecordEvent(eventType, mozilla::Some(fileNameTypeAndDetails.first),
-                         extra);
+  Telemetry::RecordEvent(eventType,
+                         mozilla::Some(fileNameTypeAndDetails.first()), extra);
 
   // Presently we are not enforcing any restrictions for the script filename,
   // we're only reporting Telemetry. In the future we will assert in debug
   // builds and return false to prevent execution in non-debug builds.
   return true;
 }
--- a/dom/security/nsContentSecurityUtils.h
+++ b/dom/security/nsContentSecurityUtils.h
@@ -13,17 +13,18 @@ class nsIChannel;
 class nsIHttpChannel;
 
 namespace mozilla {
 namespace dom {
 class Document;
 }  // namespace dom
 }  // namespace mozilla
 
-typedef std::pair<nsCString, mozilla::Maybe<nsString>> FilenameTypeAndDetails;
+typedef mozilla::Pair<nsCString, mozilla::Maybe<nsString>>
+    FilenameTypeAndDetails;
 
 class nsContentSecurityUtils {
  public:
   static FilenameTypeAndDetails FilenameToFilenameType(
       const nsString& fileName, bool collectAdditionalExtensionData);
   static bool IsEvalAllowed(JSContext* cx, bool aIsSystemPrincipal,
                             const nsAString& aScript);
   static void NotifyEvalUsage(bool aIsSystemPrincipal,
--- a/dom/security/test/gtest/TestFilenameEvalParser.cpp
+++ b/dom/security/test/gtest/TestFilenameEvalParser.cpp
@@ -37,256 +37,261 @@ static NS_NAMED_LITERAL_CSTRING(kOther, 
 // Usage: ASSERT_AND_PRINT(ret.first(), ret.second().value(), ...
 
 TEST(FilenameEvalParser, ResourceChrome)
 {
   {
     NS_NAMED_LITERAL_STRING(str, "chrome://firegestures/content/browser.js");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kChromeURI && ret.second.isSome() &&
-                ret.second.value() == str);
+    ASSERT_TRUE(ret.first() == kChromeURI && ret.second().isSome() &&
+                ret.second().value() == str);
   }
   {
     NS_NAMED_LITERAL_STRING(str, "resource://firegestures/content/browser.js");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kResourceURI && ret.second.isSome() &&
-                ret.second.value() == str);
+    ASSERT_TRUE(ret.first() == kResourceURI && ret.second().isSome() &&
+                ret.second().value() == str);
   }
 }
 
 TEST(FilenameEvalParser, BlobData)
 {
   {
     NS_NAMED_LITERAL_STRING(str, "blob://000-000");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kBlobUri && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kBlobUri && !ret.second().isSome());
   }
   {
     NS_NAMED_LITERAL_STRING(str, "blob:000-000");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kBlobUri && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kBlobUri && !ret.second().isSome());
   }
   {
     NS_NAMED_LITERAL_STRING(str, "data://blahblahblah");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kDataUri && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kDataUri && !ret.second().isSome());
   }
   {
     NS_NAMED_LITERAL_STRING(str, "data:blahblahblah");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kDataUri && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kDataUri && !ret.second().isSome());
   }
 }
 
 TEST(FilenameEvalParser, MozExtension)
 {
   {  // Test shield.mozilla.org replacing
     NS_NAMED_LITERAL_STRING(
         str,
         "jar:file:///c:/users/bob/appdata/roaming/mozilla/firefox/profiles/foo/"
         "extensions/federated-learning@shield.mozilla.org.xpi!/experiments/"
         "study/api.js");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kMozillaExtension &&
-                ret.second.value() ==
+    ASSERT_TRUE(ret.first() == kMozillaExtension &&
+                ret.second().value() ==
                     NS_LITERAL_STRING(
                         "federated-learning@s!/experiments/study/api.js"));
   }
   {  // Test mozilla.org replacing
     NS_NAMED_LITERAL_STRING(
         str,
         "jar:file:///c:/users/bob/appdata/roaming/mozilla/firefox/profiles/foo/"
         "extensions/federated-learning@shigeld.mozilla.org.xpi!/experiments/"
         "study/api.js");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
     ASSERT_TRUE(
-        ret.first == kMozillaExtension &&
-        ret.second.value() ==
+        ret.first() == kMozillaExtension &&
+        ret.second().value() ==
             NS_LITERAL_STRING(
                 "federated-learning@shigeld.m!/experiments/study/api.js"));
   }
   {  // Test truncating
     NS_NAMED_LITERAL_STRING(
         str,
         "jar:file:///c:/users/bob/appdata/roaming/mozilla/firefox/profiles/foo/"
         "extensions/federated-learning@shigeld.mozilla.org.xpi!/experiments/"
         "study/apiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.js");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
     ASSERT_TRUE(
-        ret.first == kMozillaExtension &&
-        ret.second.value() ==
+        ret.first() == kMozillaExtension &&
+        ret.second().value() ==
             NS_LITERAL_STRING("federated-learning@shigeld.m!/experiments/"
                               "study/apiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"));
   }
 }
 
 TEST(FilenameEvalParser, UserChromeJS)
 {
   {
     NS_NAMED_LITERAL_STRING(str, "firegestures/content/browser.uc.js");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kSuspectedUserChromeJS && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kSuspectedUserChromeJS &&
+                !ret.second().isSome());
   }
   {
     NS_NAMED_LITERAL_STRING(str, "firegestures/content/browser.uc.js?");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kSuspectedUserChromeJS && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kSuspectedUserChromeJS &&
+                !ret.second().isSome());
   }
   {
     nsLiteralString str =
         NS_LITERAL_STRING("firegestures/content/browser.uc.js?243244224");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kSuspectedUserChromeJS && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kSuspectedUserChromeJS &&
+                !ret.second().isSome());
   }
   {
     NS_NAMED_LITERAL_STRING(
         str,
         "file:///b:/fxprofiles/mark/chrome/"
         "addbookmarkherewithmiddleclick.uc.js?1558444389291");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kSuspectedUserChromeJS && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kSuspectedUserChromeJS &&
+                !ret.second().isSome());
   }
 }
 
 TEST(FilenameEvalParser, SingleFile)
 {
   {
     NS_NAMED_LITERAL_STRING(str, "browser.uc.js?2456");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kSingleString && ret.second.isSome() &&
-                ret.second.value() == str);
+    ASSERT_TRUE(ret.first() == kSingleString && ret.second().isSome() &&
+                ret.second().value() == str);
   }
   {
     NS_NAMED_LITERAL_STRING(str, "debugger");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kSingleString && ret.second.isSome() &&
-                ret.second.value() == str);
+    ASSERT_TRUE(ret.first() == kSingleString && ret.second().isSome() &&
+                ret.second().value() == str);
   }
 }
 
 TEST(FilenameEvalParser, Other)
 {
   {
     NS_NAMED_LITERAL_STRING(str, "firegestures--content");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
-    ASSERT_TRUE(ret.first == kOther && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kOther && !ret.second().isSome());
   }
   {
     NS_NAMED_LITERAL_STRING(str, "gallop://thing/fire");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
 #if defined(XP_WIN)
-    ASSERT_TRUE(ret.first == kSanitizedWindowsURL &&
-                ret.second.value() == NS_LITERAL_STRING("gallop"));
+    ASSERT_TRUE(ret.first() == kSanitizedWindowsURL &&
+                ret.second().value() == NS_LITERAL_STRING("gallop"));
 #else
-    ASSERT_TRUE(ret.first == kOther && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kOther && !ret.second().isSome());
 #endif
   }
   {
     NS_NAMED_LITERAL_STRING(str, "gallop://fire");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
 #if defined(XP_WIN)
-    ASSERT_TRUE(ret.first == kSanitizedWindowsURL &&
-                ret.second.value() == NS_LITERAL_STRING("gallop"));
+    ASSERT_TRUE(ret.first() == kSanitizedWindowsURL &&
+                ret.second().value() == NS_LITERAL_STRING("gallop"));
 #else
-    ASSERT_TRUE(ret.first == kOther && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kOther && !ret.second().isSome());
 #endif
   }
   {
     NS_NAMED_LITERAL_STRING(str, "firegestures/content");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
 #if defined(XP_WIN)
-    ASSERT_TRUE(ret.first == kSanitizedWindowsPath &&
-                ret.second.value() == NS_LITERAL_STRING("content"));
+    ASSERT_TRUE(ret.first() == kSanitizedWindowsPath &&
+                ret.second().value() == NS_LITERAL_STRING("content"));
 #else
-    ASSERT_TRUE(ret.first == kOther && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kOther && !ret.second().isSome());
 #endif
   }
   {
     NS_NAMED_LITERAL_STRING(str, "firegestures\\content");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
 #if defined(XP_WIN)
-    ASSERT_TRUE(ret.first == kSanitizedWindowsPath &&
-                ret.second.value() == NS_LITERAL_STRING("content"));
+    ASSERT_TRUE(ret.first() == kSanitizedWindowsPath &&
+                ret.second().value() == NS_LITERAL_STRING("content"));
 #else
-    ASSERT_TRUE(ret.first == kOther && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kOther && !ret.second().isSome());
 #endif
   }
   {
     NS_NAMED_LITERAL_STRING(str, "/home/tom/files/thing");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
 #if defined(XP_WIN)
-    ASSERT_TRUE(ret.first == kSanitizedWindowsPath &&
-                ret.second.value() == NS_LITERAL_STRING("thing"));
+    ASSERT_TRUE(ret.first() == kSanitizedWindowsPath &&
+                ret.second().value() == NS_LITERAL_STRING("thing"));
 #else
-    ASSERT_TRUE(ret.first == kOther && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kOther && !ret.second().isSome());
 #endif
   }
   {
     NS_NAMED_LITERAL_STRING(str, "file://c/uers/tom/file.txt");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
 #if defined(XP_WIN)
-    ASSERT_TRUE(ret.first == kSanitizedWindowsURL &&
-                ret.second.value() == NS_LITERAL_STRING("file://.../file.txt"));
+    ASSERT_TRUE(ret.first() == kSanitizedWindowsURL &&
+                ret.second().value() ==
+                    NS_LITERAL_STRING("file://.../file.txt"));
 #else
-    ASSERT_TRUE(ret.first == kOther && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kOther && !ret.second().isSome());
 #endif
   }
   {
     NS_NAMED_LITERAL_STRING(str, "c:/uers/tom/file.txt");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
 #if defined(XP_WIN)
-    ASSERT_TRUE(ret.first == kSanitizedWindowsPath &&
-                ret.second.value() == NS_LITERAL_STRING("file.txt"));
+    ASSERT_TRUE(ret.first() == kSanitizedWindowsPath &&
+                ret.second().value() == NS_LITERAL_STRING("file.txt"));
 #else
-    ASSERT_TRUE(ret.first == kOther && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kOther && !ret.second().isSome());
 #endif
   }
   {
     NS_NAMED_LITERAL_STRING(str, "http://example.com/");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
 #if defined(XP_WIN)
-    ASSERT_TRUE(ret.first == kSanitizedWindowsURL &&
-                ret.second.value() == NS_LITERAL_STRING("http"));
+    ASSERT_TRUE(ret.first() == kSanitizedWindowsURL &&
+                ret.second().value() == NS_LITERAL_STRING("http"));
 #else
-    ASSERT_TRUE(ret.first == kOther && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kOther && !ret.second().isSome());
 #endif
   }
   {
     NS_NAMED_LITERAL_STRING(str, "http://example.com/thing.html");
     FilenameTypeAndDetails ret =
         nsContentSecurityUtils::FilenameToFilenameType(str, false);
 #if defined(XP_WIN)
-    ASSERT_TRUE(ret.first == kSanitizedWindowsURL &&
-                ret.second.value() == NS_LITERAL_STRING("http"));
+    ASSERT_TRUE(ret.first() == kSanitizedWindowsURL &&
+                ret.second().value() == NS_LITERAL_STRING("http"));
 #else
-    ASSERT_TRUE(ret.first == kOther && !ret.second.isSome());
+    ASSERT_TRUE(ret.first() == kOther && !ret.second().isSome());
 #endif
   }
 }
 
 #if defined(XP_WIN)
 TEST(FilenameEvalParser, WebExtensionPathParser)
 {
   {
--- a/dom/serviceworkers/FetchEventOpProxyChild.cpp
+++ b/dom/serviceworkers/FetchEventOpProxyChild.cpp
@@ -38,19 +38,19 @@ nsresult GetIPCSynthesizeResponseArgs(
   MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread());
 
   PBackgroundChild* bgChild = BackgroundChild::GetOrCreateForCurrentThread();
 
   if (NS_WARN_IF(!bgChild)) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
-  aArgs.first->ToIPC(&aIPCArgs->internalResponse(), bgChild, aAutoBodyStream,
-                     aAutoAlternativeBodyStream);
-  aIPCArgs->closure() = std::move(aArgs.second);
+  aArgs.first()->ToIPC(&aIPCArgs->internalResponse(), bgChild, aAutoBodyStream,
+                       aAutoAlternativeBodyStream);
+  aIPCArgs->closure() = std::move(aArgs.second());
 
   return NS_OK;
 }
 
 }  // anonymous namespace
 
 void FetchEventOpProxyChild::Initialize(
     const ServiceWorkerFetchEventOpArgs& aArgs) {
--- a/dom/serviceworkers/ServiceWorkerOpPromise.h
+++ b/dom/serviceworkers/ServiceWorkerOpPromise.h
@@ -2,29 +2,28 @@
 /* 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 mozilla_dom_serviceworkeroppromise_h__
 #define mozilla_dom_serviceworkeroppromise_h__
 
-#include <utility>
-
 #include "mozilla/MozPromise.h"
+#include "mozilla/Pair.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/dom/ServiceWorkerOpArgs.h"
 
 namespace mozilla {
 namespace dom {
 
 class InternalResponse;
 
 using SynthesizeResponseArgs =
-    std::pair<RefPtr<InternalResponse>, FetchEventRespondWithClosure>;
+    Pair<RefPtr<InternalResponse>, FetchEventRespondWithClosure>;
 
 using FetchEventRespondWithResult =
     Variant<SynthesizeResponseArgs, ResetInterceptionArgs,
             CancelInterceptionArgs>;
 
 using FetchEventRespondWithPromise =
     MozPromise<FetchEventRespondWithResult, nsresult, true>;
 
--- a/extensions/permissions/nsPermissionManager.cpp
+++ b/extensions/permissions/nsPermissionManager.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/ContentBlockingUserInteraction.h"
 #include "mozilla/ContentPrincipal.h"
 #include "mozilla/DebugOnly.h"
+#include "mozilla/Pair.h"
 #include "mozilla/Services.h"
 #include "mozilla/SystemGroup.h"
 #include "nsPermissionManager.h"
 #include "nsPermission.h"
 #include "nsCRT.h"
 #include "nsNetUtil.h"
 #include "nsTArray.h"
 #include "nsReadableUtils.h"
@@ -3273,31 +3274,31 @@ void nsPermissionManager::GetKeyForPermi
     aKey.Truncate();
     return;
   }
 
   GetKeyForPrincipal(aPrincipal, IsOAForceStripPermission(aType), aKey);
 }
 
 /* static */
-nsTArray<std::pair<nsCString, nsCString>>
+nsTArray<Pair<nsCString, nsCString>>
 nsPermissionManager::GetAllKeysForPrincipal(nsIPrincipal* aPrincipal) {
   MOZ_ASSERT(aPrincipal);
 
-  nsTArray<std::pair<nsCString, nsCString>> pairs;
+  nsTArray<Pair<nsCString, nsCString>> pairs;
   nsCOMPtr<nsIPrincipal> prin = aPrincipal;
   while (prin) {
     // Add the pair to the list
-    std::pair<nsCString, nsCString>* pair =
-        pairs.AppendElement(std::make_pair(EmptyCString(), EmptyCString()));
+    Pair<nsCString, nsCString>* pair =
+        pairs.AppendElement(MakePair(EmptyCString(), EmptyCString()));
     // We can't check for individual OA strip perms here.
     // Don't force strip origin attributes.
-    GetKeyForPrincipal(prin, false, pair->first);
-
-    Unused << GetOriginFromPrincipal(prin, false, pair->second);
+    GetKeyForPrincipal(prin, false, pair->first());
+
+    Unused << GetOriginFromPrincipal(prin, false, pair->second());
 
     // Get the next subdomain principal and loop back around.
     prin = GetNextSubDomainPrincipal(prin);
   }
 
   MOZ_ASSERT(pairs.Length() >= 1,
              "Every principal should have at least one pair item.");
   return pairs;
@@ -3347,23 +3348,23 @@ void nsPermissionManager::WhenPermission
   if (!XRE_IsContentProcess()) {
     aRunnable->Run();
     return;
   }
 
   nsTArray<RefPtr<GenericNonExclusivePromise>> promises;
   for (auto& pair : GetAllKeysForPrincipal(aPrincipal)) {
     RefPtr<GenericNonExclusivePromise::Private> promise;
-    if (!mPermissionKeyPromiseMap.Get(pair.first, getter_AddRefs(promise))) {
+    if (!mPermissionKeyPromiseMap.Get(pair.first(), getter_AddRefs(promise))) {
       // In this case we have found a permission which isn't available in the
       // content process and hasn't been requested yet. We need to create a new
       // promise, and send the request to the parent (if we have not already
       // done so).
       promise = new GenericNonExclusivePromise::Private(__func__);
-      mPermissionKeyPromiseMap.Put(pair.first, RefPtr{promise});
+      mPermissionKeyPromiseMap.Put(pair.first(), RefPtr{promise});
     }
 
     if (promise) {
       promises.AppendElement(std::move(promise));
     }
   }
 
   // If all of our permissions are available, immediately run the runnable. This
--- a/extensions/permissions/nsPermissionManager.h
+++ b/extensions/permissions/nsPermissionManager.h
@@ -19,22 +19,21 @@
 #include "nsIPrefBranch.h"
 #include "nsHashKeys.h"
 #include "nsCOMArray.h"
 #include "nsDataHashtable.h"
 #include "nsRefPtrHashtable.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/ExpandedPrincipal.h"
 #include "mozilla/MozPromise.h"
+#include "mozilla/Pair.h"
 #include "mozilla/Unused.h"
 #include "mozilla/Variant.h"
 #include "mozilla/Vector.h"
 
-#include <utility>
-
 namespace IPC {
 struct Permission;
 }
 
 namespace mozilla {
 class OriginAttributesPattern;
 }
 
@@ -286,17 +285,17 @@ class nsPermissionManager final : public
    * Unlike GetKeyForPrincipal, this method also gets the keys for base domains
    * of the given principal. All keys returned by this method must be available
    * in the content process for a given URL to successfully have its permissions
    * checked in the `aExactHostMatch = false` situation.
    *
    * @param aPrincipal  The Principal which the key is to be extracted from.
    * @return returns an array of (key, origin) pairs.
    */
-  static nsTArray<std::pair<nsCString, nsCString>> GetAllKeysForPrincipal(
+  static nsTArray<mozilla::Pair<nsCString, nsCString>> GetAllKeysForPrincipal(
       nsIPrincipal* aPrincipal);
 
   // From ContentChild.
   nsresult RemoveAllFromIPC();
 
   /**
    * Returns false if this permission manager wouldn't have the permission
    * requested available.
--- a/gfx/layers/opengl/OGLShaderConfig.h
+++ b/gfx/layers/opengl/OGLShaderConfig.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_OGLSHADERCONFIG_H
 #define GFX_OGLSHADERCONFIG_H
 
 #include "gfxTypes.h"
 #include "ImageTypes.h"
 #include "mozilla/Assertions.h"  // for MOZ_ASSERT, etc
+#include "mozilla/Pair.h"        // for Pair
 #include "mozilla/RefPtr.h"      // for RefPtr
 #include "mozilla/gfx/Matrix.h"  // for Matrix4x4
 #include "mozilla/gfx/Rect.h"    // for Rect
 #include "mozilla/gfx/Types.h"
 #include "nsDebug.h"   // for NS_ASSERTION
 #include "nsPoint.h"   // for nsIntPoint
 #include "nsTArray.h"  // for nsTArray
 #include "mozilla/layers/CompositorTypes.h"
--- a/gfx/layers/opengl/OGLShaderProgram.cpp
+++ b/gfx/layers/opengl/OGLShaderProgram.cpp
@@ -183,27 +183,26 @@ ProgramProfileOGL ProgramProfileOGL::Get
   vs << "uniform vec2 uRenderTargetOffset;" << endl;
 
   if (!(aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY)) {
     vs << "attribute vec4 aCoord;" << endl;
   } else {
     vs << "attribute vec2 aCoord;" << endl;
   }
 
-  result.mAttributes.AppendElement(std::pair<nsCString, GLuint>{"aCoord", 0});
+  result.mAttributes.AppendElement(Pair<nsCString, GLuint>{"aCoord", 0});
 
   if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
     vs << "uniform mat4 uTextureTransform;" << endl;
     vs << "uniform vec4 uTextureRects[4];" << endl;
     vs << "varying vec2 vTexCoord;" << endl;
 
     if (aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY) {
       vs << "attribute vec2 aTexCoord;" << endl;
-      result.mAttributes.AppendElement(
-          std::pair<nsCString, GLuint>{"aTexCoord", 1});
+      result.mAttributes.AppendElement(Pair<nsCString, GLuint>{"aTexCoord", 1});
     }
   }
 
   if (BlendOpIsMixBlendMode(blendOp)) {
     vs << "uniform mat4 uBackdropTransform;" << endl;
     vs << "varying vec2 vBackdropCoord;" << endl;
   }
 
@@ -941,18 +940,19 @@ bool ShaderProgramOGL::CreateProgram(con
       CreateShader(LOCAL_GL_FRAGMENT_SHADER, aFragmentShaderString);
 
   if (!vertexShader || !fragmentShader) return false;
 
   GLint result = mGL->fCreateProgram();
   mGL->fAttachShader(result, vertexShader);
   mGL->fAttachShader(result, fragmentShader);
 
-  for (std::pair<nsCString, GLuint>& attribute : mProfile.mAttributes) {
-    mGL->fBindAttribLocation(result, attribute.second, attribute.first.get());
+  for (Pair<nsCString, GLuint>& attribute : mProfile.mAttributes) {
+    mGL->fBindAttribLocation(result, attribute.second(),
+                             attribute.first().get());
   }
 
   mGL->fLinkProgram(result);
 
   GLint success, len;
   mGL->fGetProgramiv(result, LOCAL_GL_LINK_STATUS, &success);
   mGL->fGetProgramiv(result, LOCAL_GL_INFO_LOG_LENGTH, (GLint*)&len);
   /* Even if linking is successful, there may still be warnings.  Print them
--- a/gfx/layers/opengl/OGLShaderProgram.h
+++ b/gfx/layers/opengl/OGLShaderProgram.h
@@ -6,17 +6,16 @@
 
 #ifndef GFX_OGLSHADERPROGRAM_H
 #define GFX_OGLSHADERPROGRAM_H
 
 #include "GLContext.h"  // for fast inlines of glUniform*
 #include "OGLShaderConfig.h"
 
 #include <string>
-#include <utility>
 
 namespace mozilla {
 namespace layers {
 
 #if defined(DEBUG)
 #  define CHECK_CURRENT_PROGRAM 1
 #  define ASSERT_THIS_PROGRAM                                       \
     do {                                                            \
@@ -44,17 +43,17 @@ struct ProgramProfileOGL {
    */
   static ProgramProfileOGL GetProfileFor(ShaderConfigOGL aConfig);
 
   // the source code for the program's shaders
   std::string mVertexShaderString;
   std::string mFragmentShaderString;
 
   // the vertex attributes
-  nsTArray<std::pair<nsCString, GLuint>> mAttributes;
+  nsTArray<Pair<nsCString, GLuint>> mAttributes;
 
   KnownUniform mUniforms[KnownUniform::KnownUniformCount];
   nsTArray<const char*> mDefines;
   size_t mTextureCount;
 
   ProgramProfileOGL() : mTextureCount(0) {}
 
  private:
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -303,17 +303,17 @@ struct DIGroup {
   gfx::Size mScale;
   ScrollableLayerGuid::ViewID mScrollId;
   LayerPoint mResidualOffset;
   LayerIntRect mLayerBounds;  // mGroupBounds converted to Layer space
   // mLayerBounds clipped to the container/parent of the
   // current item being processed.
   IntRect mClippedImageBounds;  // mLayerBounds with the clipping of any
                                 // containers applied
-  Maybe<std::pair<wr::RenderRoot, wr::BlobImageKey>> mKey;
+  Maybe<mozilla::Pair<wr::RenderRoot, wr::BlobImageKey>> mKey;
   std::vector<RefPtr<ScaledFont>> mFonts;
 
   DIGroup()
       : mAppUnitsPerDevPixel(0),
         mScrollId(ScrollableLayerGuid::NULL_SCROLL_ID) {}
 
   void InvalidateRect(const IntRect& aRect) {
     auto r = aRect.Intersect(mPreservedRect);
@@ -336,17 +336,17 @@ struct DIGroup {
       iter.Remove();
       delete data;
     }
   }
 
   void ClearImageKey(RenderRootStateManager* aManager, bool aForce = false) {
     if (mKey) {
       MOZ_RELEASE_ASSERT(aForce || mInvalidRect.IsEmpty());
-      aManager->AddBlobImageKeyForDiscard(mKey.value().second);
+      aManager->AddBlobImageKeyForDiscard(mKey.value().second());
       mKey = Nothing();
     }
     mFonts.clear();
   }
 
   static IntRect ToDeviceSpace(nsRect aBounds, Matrix& aMatrix,
                                int32_t aAppUnitsPerDevPixel) {
     // RoundedOut can convert empty rectangles to non-empty ones
@@ -608,17 +608,17 @@ struct DIGroup {
     if (mInvalidRect.IsEmpty() && mVisibleRect.IsEqualEdges(mLastVisibleRect)) {
       GP("Not repainting group because it's empty\n");
       GP("End EndGroup\n");
       if (mKey) {
         // Although the contents haven't changed, the visible area *may* have,
         // so request it be updated unconditionally (wr should be able to easily
         // detect if this is a no-op on its side, if that matters)
         aResources.SetBlobImageVisibleArea(
-            mKey.value().second,
+            mKey.value().second(),
             ViewAs<ImagePixel>(mVisibleRect,
                                PixelCastJustification::LayerIsImage));
         mLastVisibleRect = mVisibleRect;
         PushImage(aBuilder, itemBounds);
       }
       return;
     }
 
@@ -696,40 +696,40 @@ struct DIGroup {
       wr::ImageDescriptor descriptor(dtSize, 0, dt->GetFormat(), opacity);
       MOZ_RELEASE_ASSERT(bytes.length() > sizeof(size_t));
       if (!aResources.AddBlobImage(
               key, descriptor, bytes,
               ViewAs<ImagePixel>(mVisibleRect,
                                  PixelCastJustification::LayerIsImage))) {
         return;
       }
-      mKey = Some(std::make_pair(aBuilder.GetRenderRoot(), key));
+      mKey = Some(MakePair(aBuilder.GetRenderRoot(), key));
     } else {
       wr::ImageDescriptor descriptor(dtSize, 0, dt->GetFormat(), opacity);
 
       // Convert mInvalidRect to image space by subtracting the corner of the
       // image bounds
       auto dirtyRect = ViewAs<ImagePixel>(mInvalidRect);
 
       auto bottomRight = dirtyRect.BottomRight();
       GP("check invalid %d %d - %d %d\n", bottomRight.x, bottomRight.y,
          dtSize.width, dtSize.height);
       GP("Update Blob %d %d %d %d\n", mInvalidRect.x, mInvalidRect.y,
          mInvalidRect.width, mInvalidRect.height);
       if (!aResources.UpdateBlobImage(
-              mKey.value().second, descriptor, bytes,
+              mKey.value().second(), descriptor, bytes,
               ViewAs<ImagePixel>(mVisibleRect,
                                  PixelCastJustification::LayerIsImage),
               dirtyRect)) {
         return;
       }
     }
     mFonts = std::move(fonts);
     aResources.SetBlobImageVisibleArea(
-        mKey.value().second,
+        mKey.value().second(),
         ViewAs<ImagePixel>(mVisibleRect, PixelCastJustification::LayerIsImage));
     mLastVisibleRect = mVisibleRect;
     PushImage(aBuilder, itemBounds);
     GP("End EndGroup\n\n");
   }
 
   void PushImage(wr::DisplayListBuilder& aBuilder,
                  const LayoutDeviceRect& bounds) {
@@ -747,17 +747,17 @@ struct DIGroup {
 
     // XXX - clipping the item against the paint rect breaks some content.
     // cf. Bug 1455422.
     // wr::LayoutRect clip = wr::ToLayoutRect(bounds.Intersect(mVisibleRect));
 
     aBuilder.SetHitTestInfo(mScrollId, hitInfo, SideBits::eNone);
     aBuilder.PushImage(dest, dest, !backfaceHidden,
                        wr::ToImageRendering(sampleFilter),
-                       wr::AsImageKey(mKey.value().second));
+                       wr::AsImageKey(mKey.value().second()));
     aBuilder.ClearHitTestInfo();
   }
 
   void PaintItemRange(Grouper* aGrouper, nsDisplayItem* aStartItem,
                       nsDisplayItem* aEndItem, gfxContext* aContext,
                       WebRenderDrawEventRecorder* aRecorder,
                       RenderRootStateManager* aRootManager,
                       wr::IpcResourceUpdateQueue& aResources) {
--- a/image/ClippedImage.cpp
+++ b/image/ClippedImage.cpp
@@ -11,16 +11,17 @@
 #include <utility>
 
 #include "ImageRegion.h"
 #include "Orientation.h"
 #include "SVGImageContext.h"
 #include "gfxDrawable.h"
 #include "gfxPlatform.h"
 #include "gfxUtils.h"
+#include "mozilla/Pair.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Tuple.h"
 #include "mozilla/gfx/2D.h"
 
 namespace mozilla {
 
 using namespace gfx;
 using layers::ImageContainer;
@@ -231,38 +232,36 @@ ClippedImage::GetFrame(uint32_t aWhichFr
 NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
 ClippedImage::GetFrameAtSize(const IntSize& aSize, uint32_t aWhichFrame,
                              uint32_t aFlags) {
   // XXX(seth): It'd be nice to support downscale-during-decode for this case,
   // but right now we just fall back to the intrinsic size.
   return GetFrame(aWhichFrame, aFlags);
 }
 
-std::pair<ImgDrawResult, RefPtr<SourceSurface>> ClippedImage::GetFrameInternal(
+Pair<ImgDrawResult, RefPtr<SourceSurface>> ClippedImage::GetFrameInternal(
     const nsIntSize& aSize, const Maybe<SVGImageContext>& aSVGContext,
     uint32_t aWhichFrame, uint32_t aFlags, float aOpacity) {
   if (!ShouldClip()) {
     RefPtr<SourceSurface> surface = InnerImage()->GetFrame(aWhichFrame, aFlags);
-    return std::make_pair(
-        surface ? ImgDrawResult::SUCCESS : ImgDrawResult::NOT_READY,
-        std::move(surface));
+    return MakePair(surface ? ImgDrawResult::SUCCESS : ImgDrawResult::NOT_READY,
+                    std::move(surface));
   }
 
   float frameToDraw = InnerImage()->GetFrameIndex(aWhichFrame);
   if (!mCachedSurface ||
       !mCachedSurface->Matches(aSize, aSVGContext, frameToDraw, aFlags) ||
       mCachedSurface->NeedsRedraw()) {
     // Create a surface to draw into.
     RefPtr<DrawTarget> target =
         gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
             IntSize(aSize.width, aSize.height), SurfaceFormat::OS_RGBA);
     if (!target || !target->IsValid()) {
       NS_ERROR("Could not create a DrawTarget");
-      return std::make_pair(ImgDrawResult::TEMPORARY_ERROR,
-                            RefPtr<SourceSurface>());
+      return MakePair(ImgDrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
     }
 
     RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(target);
     MOZ_ASSERT(ctx);  // already checked the draw target above
 
     // Create our callback.
     RefPtr<DrawSingleTileCallback> drawTileCallback =
         new DrawSingleTileCallback(this, aSize, aSVGContext, aWhichFrame,
@@ -279,17 +278,17 @@ std::pair<ImgDrawResult, RefPtr<SourceSu
     // Cache the resulting surface.
     mCachedSurface = MakeUnique<ClippedImageCachedSurface>(
         target->Snapshot(), aSize, aSVGContext, frameToDraw, aFlags,
         drawTileCallback->GetDrawResult());
   }
 
   MOZ_ASSERT(mCachedSurface, "Should have a cached surface now");
   RefPtr<SourceSurface> surface = mCachedSurface->Surface();
-  return std::make_pair(mCachedSurface->GetDrawResult(), std::move(surface));
+  return MakePair(mCachedSurface->GetDrawResult(), std::move(surface));
 }
 
 NS_IMETHODIMP_(bool)
 ClippedImage::IsImageContainerAvailable(LayerManager* aManager,
                                         uint32_t aFlags) {
   if (!ShouldClip()) {
     return InnerImage()->IsImageContainerAvailable(aManager, aFlags);
   }
--- a/image/ClippedImage.h
+++ b/image/ClippedImage.h
@@ -7,18 +7,16 @@
 #define mozilla_image_ClippedImage_h
 
 #include "ImageWrapper.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 
-#include <utility>
-
 namespace mozilla {
 namespace image {
 
 class ClippedImageCachedSurface;
 class DrawSingleTileCallback;
 
 /**
  * An Image wrapper that clips an image against a rectangle. Right now only
@@ -72,17 +70,17 @@ class ClippedImage : public ImageWrapper
 
  protected:
   ClippedImage(Image* aImage, nsIntRect aClip,
                const Maybe<nsSize>& aSVGViewportSize);
 
   virtual ~ClippedImage();
 
  private:
-  std::pair<ImgDrawResult, RefPtr<SourceSurface>> GetFrameInternal(
+  Pair<ImgDrawResult, RefPtr<SourceSurface>> GetFrameInternal(
       const nsIntSize& aSize, const Maybe<SVGImageContext>& aSVGContext,
       uint32_t aWhichFrame, uint32_t aFlags, float aOpacity);
   bool ShouldClip();
   ImgDrawResult DrawSingleTile(gfxContext* aContext, const nsIntSize& aSize,
                                const ImageRegion& aRegion, uint32_t aWhichFrame,
                                gfx::SamplingFilter aSamplingFilter,
                                const Maybe<SVGImageContext>& aSVGContext,
                                uint32_t aFlags, float aOpacity);
--- a/image/SurfaceCache.cpp
+++ b/image/SurfaceCache.cpp
@@ -19,16 +19,17 @@
 #include "gfx2DGlue.h"
 #include "gfxPlatform.h"
 #include "imgFrame.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Likely.h"
+#include "mozilla/Pair.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/StaticMutex.h"
 #include "mozilla/StaticPrefs_image.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Tuple.h"
 #include "nsExpirationTracker.h"
 #include "nsHashKeys.h"
 #include "nsIMemoryReporter.h"
--- a/js/src/wasm/WasmOpIter.h
+++ b/js/src/wasm/WasmOpIter.h
@@ -14,17 +14,17 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef wasm_op_iter_h
 #define wasm_op_iter_h
 
-#include "mozilla/CompactPair.h"
+#include "mozilla/Pair.h"
 #include "mozilla/Poison.h"
 
 #include "jit/AtomicOp.h"
 #include "js/Printf.h"
 #include "wasm/WasmUtility.h"
 #include "wasm/WasmValidate.h"
 
 namespace js {
@@ -486,18 +486,18 @@ struct LinearMemoryAddress {
 
   LinearMemoryAddress() : offset(0), align(0) {}
   LinearMemoryAddress(Value base, uint32_t offset, uint32_t align)
       : base(base), offset(offset), align(align) {}
 };
 
 template <typename ControlItem>
 class ControlStackEntry {
-  // Use a pair to optimize away empty ControlItem.
-  mozilla::CompactPair<BlockType, ControlItem> typeAndItem_;
+  // Use a Pair to optimize away empty ControlItem.
+  mozilla::Pair<BlockType, ControlItem> typeAndItem_;
 
   // The "base" of a control stack entry is valueStack_.length() minus
   // type().params().length(), i.e., the size of the value stack "below"
   // this block.
   uint32_t valueStackBase_;
   bool polymorphicBase_;
 
   LabelKind kind_;
@@ -527,17 +527,17 @@ class ControlStackEntry {
     kind_ = LabelKind::Else;
     polymorphicBase_ = false;
   }
 };
 
 template <typename Value>
 class TypeAndValueT {
   // Use a Pair to optimize away empty Value.
-  mozilla::CompactPair<StackType, Value> tv_;
+  mozilla::Pair<StackType, Value> tv_;
 
  public:
   TypeAndValueT() : tv_(StackType::bottom(), Value()) {}
   explicit TypeAndValueT(StackType type) : tv_(type, Value()) {}
   explicit TypeAndValueT(ValType type) : tv_(StackType(type), Value()) {}
   TypeAndValueT(StackType type, Value value) : tv_(type, value) {}
   TypeAndValueT(ValType type, Value value) : tv_(StackType(type), value) {}
   StackType type() const { return tv_.first(); }
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -344,24 +344,24 @@ static float GetSuitableScale(float aMax
     // (avoiding visually clunky delayerization).
     return aMaxScale;
   }
   return std::max(std::min(aMaxScale, displayVisibleRatio), aMinScale);
 }
 
 // The first value in this pair is the min scale, and the second one is the max
 // scale.
-using MinAndMaxScale = std::pair<Size, Size>;
+using MinAndMaxScale = Pair<Size, Size>;
 
 static inline void UpdateMinMaxScale(const nsIFrame* aFrame,
                                      const AnimationValue& aValue,
                                      MinAndMaxScale& aMinAndMaxScale) {
   Size size = aValue.GetScaleValue(aFrame);
-  Size& minScale = aMinAndMaxScale.first;
-  Size& maxScale = aMinAndMaxScale.second;
+  Size& minScale = aMinAndMaxScale.first();
+  Size& maxScale = aMinAndMaxScale.second();
 
   minScale = Min(minScale, size);
   maxScale = Max(maxScale, size);
 }
 
 // The final transform matrix is calculated by merging the final results of each
 // transform-like properties, so do the scale factors. In other words, the
 // potential min/max scales could be gotten by multiplying the max/min scales of
@@ -377,20 +377,20 @@ static inline void UpdateMinMaxScale(con
 // min/max scale factor of scale property to get the final max/min scale factor.
 static Array<MinAndMaxScale, 2> GetMinAndMaxScaleForAnimationProperty(
     const nsIFrame* aFrame,
     const nsTArray<RefPtr<dom::Animation>>& aAnimations) {
   // We use a fixed array to store the min/max scales for each property.
   // The first element in the array is for eCSSProperty_transform, and the
   // second one is for eCSSProperty_scale.
   const MinAndMaxScale defaultValue =
-      std::make_pair(Size(std::numeric_limits<float>::max(),
-                          std::numeric_limits<float>::max()),
-                     Size(std::numeric_limits<float>::min(),
-                          std::numeric_limits<float>::min()));
+      MakePair(Size(std::numeric_limits<float>::max(),
+                    std::numeric_limits<float>::max()),
+               Size(std::numeric_limits<float>::min(),
+                    std::numeric_limits<float>::min()));
   Array<MinAndMaxScale, 2> minAndMaxScales(defaultValue, defaultValue);
 
   for (dom::Animation* anim : aAnimations) {
     // This method is only expected to be passed animations that are running on
     // the compositor and we only pass playing animations to the compositor,
     // which are, by definition, "relevant" animations (animations that are
     // not yet finished or which are filling forwards).
     MOZ_ASSERT(anim->IsRelevant());
@@ -461,18 +461,18 @@ Size nsLayoutUtils::ComputeSuitableScale
     return aMax.width == std::numeric_limits<float>::min() &&
            aMax.height == std::numeric_limits<float>::min() &&
            aMin.width == std::numeric_limits<float>::max() &&
            aMin.height == std::numeric_limits<float>::max();
   };
 
   // Iterate the slots to get the final scale value.
   for (const auto& pair : minAndMaxScales) {
-    const Size& currMinScale = pair.first;
-    const Size& currMaxScale = pair.second;
+    const Size& currMinScale = pair.first();
+    const Size& currMaxScale = pair.second();
 
     if (isUnset(currMaxScale, currMinScale)) {
       // We don't have this animation property, so skip.
       continue;
     }
 
     if (isUnset(maxScale, minScale)) {
       // Initialize maxScale and minScale.
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1168,24 +1168,24 @@ class MOZ_RAII LineClampLineIterator {
       if (mCur == mEnd) {
         // Reached the end of the current block.  Pop the parent off the
         // stack; if there isn't one, then we've reached the end.
         if (mStack.IsEmpty()) {
           mCurrentFrame = nullptr;
           break;
         }
         auto entry = mStack.PopLastElement();
-        mCurrentFrame = entry.first;
-        mCur = entry.second;
+        mCurrentFrame = entry.first();
+        mCur = entry.second();
         mEnd = mCurrentFrame->LinesEnd();
       } else if (mCur->IsBlock()) {
         if (nsBlockFrame* child = GetAsLineClampDescendant(mCur->mFirstChild)) {
           nsBlockFrame::LineIterator next = mCur;
           ++next;
-          mStack.AppendElement(std::make_pair(mCurrentFrame, next));
+          mStack.AppendElement(MakePair(mCurrentFrame, next));
           mCur = child->LinesBegin();
           mEnd = child->LinesEnd();
           mCurrentFrame = child;
         } else {
           // Some kind of frame we shouldn't descend into.
           ++mCur;
         }
       } else {
@@ -1204,17 +1204,17 @@ class MOZ_RAII LineClampLineIterator {
   // The iterator end for the current block.
   nsBlockFrame::LineIterator mEnd;
 
   // The current block.
   nsBlockFrame* mCurrentFrame;
 
   // Stack of mCurrentFrame and mEnd values that we push and pop as we enter and
   // exist blocks.
-  AutoTArray<std::pair<nsBlockFrame*, nsBlockFrame::LineIterator>, 8> mStack;
+  AutoTArray<Pair<nsBlockFrame*, nsBlockFrame::LineIterator>, 8> mStack;
 };
 
 static bool ClearLineClampEllipsis(nsBlockFrame* aFrame) {
   if (!aFrame->HasAnyStateBits(NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS)) {
     for (nsIFrame* f : aFrame->PrincipalChildList()) {
       if (nsBlockFrame* child = GetAsLineClampDescendant(f)) {
         if (ClearLineClampEllipsis(child)) {
           return true;
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -1185,22 +1185,22 @@ struct nsGridContainerFrame::TrackSizing
       } else {
         index -= RepeatEndDelta();
       }
     }
     if (index >= mExpandedTracks.Length()) {
       return getImplicitSize(index - mExpandedTracks.Length());
     }
     auto& indices = mExpandedTracks[index];
-    const TrackListValue& value = mTrackListValues[indices.first];
+    const TrackListValue& value = mTrackListValues[indices.first()];
     if (value.IsTrackSize()) {
-      MOZ_ASSERT(indices.second == 0);
+      MOZ_ASSERT(indices.second() == 0);
       return value.AsTrackSize();
     }
-    return value.AsTrackRepeat().track_sizes.AsSpan()[indices.second];
+    return value.AsTrackRepeat().track_sizes.AsSpan()[indices.second()];
   }
   const StyleTrackBreadth& MaxSizingFor(uint32_t aTrackIndex) const {
     return SizingFor(aTrackIndex).GetMax();
   }
   const StyleTrackBreadth& MinSizingFor(uint32_t aTrackIndex) const {
     return SizingFor(aTrackIndex).GetMin();
   }
   uint32_t NumExplicitTracks() const {
@@ -1217,34 +1217,34 @@ struct nsGridContainerFrame::TrackSizing
   }
 
   // Store mTrackListValues into mExpandedTracks with `repeat(INTEGER, ...)`
   // tracks expanded.
   void ExpandNonRepeatAutoTracks() {
     for (size_t i = 0; i < mTrackListValues.Length(); ++i) {
       auto& value = mTrackListValues[i];
       if (value.IsTrackSize()) {
-        mExpandedTracks.AppendElement(std::make_pair(i, size_t(0)));
+        mExpandedTracks.AppendElement(MakePair(i, size_t(0)));
         continue;
       }
       auto& repeat = value.AsTrackRepeat();
       if (!repeat.count.IsNumber()) {
         MOZ_ASSERT(i == mRepeatAutoStart);
         mRepeatAutoStart = mExpandedTracks.Length();
         // The + 1 indicates the number of values in the repeat.
         // TODO: This will need to be updated in bug 1341507
         mRepeatAutoEnd = mRepeatAutoStart + 1;
-        mExpandedTracks.AppendElement(std::make_pair(i, size_t(0)));
+        mExpandedTracks.AppendElement(MakePair(i, size_t(0)));
         continue;
       }
       for (auto j : IntegerRange(repeat.count.AsNumber())) {
         Unused << j;
         size_t trackSizesCount = repeat.track_sizes.Length();
         for (auto k : IntegerRange(trackSizesCount)) {
-          mExpandedTracks.AppendElement(std::make_pair(i, k));
+          mExpandedTracks.AppendElement(MakePair(i, k));
         }
       }
     }
     if (MOZ_UNLIKELY(mExpandedTracks.Length() > kMaxLine - 1)) {
       mExpandedTracks.TruncateLength(kMaxLine - 1);
       if (mHasRepeatAuto && mRepeatAutoStart > kMaxLine - 1) {
         // The `repeat(auto-fill/fit)` track is outside the clamped grid.
         mHasRepeatAuto = false;
@@ -1257,17 +1257,17 @@ struct nsGridContainerFrame::TrackSizing
   const Span<const TrackListValue> mTrackListValues;
   const StyleImplicitGridTracks& mAutoSizing;
   // An array from expanded track sizes (without expanding auto-repeat, which is
   // included just once at `mRepeatAutoStart`).
   //
   // Each entry contains two indices, the first into mTrackListValues, and a
   // second one inside mTrackListValues' repeat value, if any, or zero
   // otherwise.
-  nsTArray<std::pair<size_t, size_t>> mExpandedTracks;
+  nsTArray<Pair<size_t, size_t>> mExpandedTracks;
   // Offset from the start of the implicit grid to the first explicit track.
   uint32_t mExplicitGridOffset;
   // The index of the repeat(auto-fill/fit) track, or zero if there is none.
   // Relative to mExplicitGridOffset (repeat tracks are explicit by definition).
   uint32_t mRepeatAutoStart;
   // The (hypothetical) index of the last such repeat() track.
   uint32_t mRepeatAutoEnd;
   // True if there is a specified repeat(auto-fill/fit) track.
--- a/layout/painting/nsCSSRenderingGradients.cpp
+++ b/layout/painting/nsCSSRenderingGradients.cpp
@@ -121,38 +121,37 @@ static Tuple<CSSPoint, CSSPoint> Compute
     default:
       break;
   }
   MOZ_ASSERT_UNREACHABLE("Unknown line direction");
   return MakeTuple(CSSPoint(), CSSPoint());
 }
 
 using EndingShape = StyleGenericEndingShape<Length, LengthPercentage>;
-using RadialGradientRadii =
-    Variant<StyleShapeExtent, std::pair<CSSCoord, CSSCoord>>;
+using RadialGradientRadii = Variant<StyleShapeExtent, Pair<CSSCoord, CSSCoord>>;
 
 static RadialGradientRadii ComputeRadialGradientRadii(const EndingShape& aShape,
                                                       const CSSSize& aSize) {
   if (aShape.IsCircle()) {
     auto& circle = aShape.AsCircle();
     if (circle.IsExtent()) {
       return RadialGradientRadii(circle.AsExtent());
     }
     CSSCoord radius = circle.AsRadius().ToCSSPixels();
-    return RadialGradientRadii(std::make_pair(radius, radius));
+    return RadialGradientRadii(MakePair(radius, radius));
   }
   auto& ellipse = aShape.AsEllipse();
   if (ellipse.IsExtent()) {
     return RadialGradientRadii(ellipse.AsExtent());
   }
 
   auto& radii = ellipse.AsRadii();
   return RadialGradientRadii(
-      std::make_pair(radii._0.ResolveToCSSPixels(aSize.width),
-                     radii._1.ResolveToCSSPixels(aSize.height)));
+      MakePair(radii._0.ResolveToCSSPixels(aSize.width),
+               radii._1.ResolveToCSSPixels(aSize.height)));
 }
 
 // Compute the start and end points of the gradient line for a radial gradient.
 // Also returns the horizontal and vertical radii defining the circle or
 // ellipse to use.
 static Tuple<CSSPoint, CSSPoint, CSSCoord, CSSCoord> ComputeRadialGradientLine(
     const StyleGradient& aGradient, const CSSSize& aBoxSize) {
   const auto& radial = aGradient.AsRadial();
@@ -210,19 +209,19 @@ static Tuple<CSSPoint, CSSPoint, CSSCoor
         }
         break;
       }
       default:
         MOZ_ASSERT_UNREACHABLE("Unknown shape extent keyword?");
         radiusX = radiusY = 0;
     }
   } else {
-    auto pair = radii.as<std::pair<CSSCoord, CSSCoord>>();
-    radiusX = pair.first;
-    radiusY = pair.second;
+    auto pair = radii.as<Pair<CSSCoord, CSSCoord>>();
+    radiusX = pair.first();
+    radiusY = pair.second();
   }
 
   // The gradient line end point is where the gradient line intersects
   // the ellipse.
   CSSPoint end = start + CSSPoint(radiusX, 0);
   return MakeTuple(start, end, radiusX, radiusY);
 }
 
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -10153,64 +10153,64 @@ static Maybe<wr::WrClipId> CreateSimpleC
   return Some(clipId);
 }
 
 enum class HandleOpacity {
   No,
   Yes,
 };
 
-static Maybe<std::pair<wr::WrClipId, HandleOpacity>> CreateWRClipPathAndMasks(
+static Maybe<Pair<wr::WrClipId, HandleOpacity>> CreateWRClipPathAndMasks(
     nsDisplayMasksAndClipPaths* aDisplayItem, const LayoutDeviceRect& aBounds,
     wr::IpcResourceUpdateQueue& aResources, wr::DisplayListBuilder& aBuilder,
     const StackingContextHelper& aSc, layers::RenderRootStateManager* aManager,
     nsDisplayListBuilder* aDisplayListBuilder) {
   if (auto clip = CreateSimpleClipRegion(*aDisplayItem, aBuilder)) {
-    return Some(std::make_pair(*clip, HandleOpacity::Yes));
+    return Some(MakePair(*clip, HandleOpacity::Yes));
   }
 
   Maybe<wr::ImageMask> mask = aManager->CommandBuilder().BuildWrMaskImage(
       aDisplayItem, aBuilder, aResources, aSc, aDisplayListBuilder, aBounds);
   if (!mask) {
     return Nothing();
   }
 
   wr::WrClipId clipId = aBuilder.DefineClip(
       Nothing(), wr::ToLayoutRect(aBounds), nullptr, mask.ptr());
 
-  return Some(std::make_pair(clipId, HandleOpacity::No));
+  return Some(MakePair(clipId, HandleOpacity::No));
 }
 
 bool nsDisplayMasksAndClipPaths::CreateWebRenderCommands(
     mozilla::wr::DisplayListBuilder& aBuilder,
     mozilla::wr::IpcResourceUpdateQueue& aResources,
     const StackingContextHelper& aSc,
     mozilla::layers::RenderRootStateManager* aManager,
     nsDisplayListBuilder* aDisplayListBuilder) {
   bool snap;
   auto appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
   nsRect displayBounds = GetBounds(aDisplayListBuilder, &snap);
   LayoutDeviceRect bounds =
       LayoutDeviceRect::FromAppUnits(displayBounds, appUnitsPerDevPixel);
 
-  Maybe<std::pair<wr::WrClipId, HandleOpacity>> clip = CreateWRClipPathAndMasks(
+  Maybe<Pair<wr::WrClipId, HandleOpacity>> clip = CreateWRClipPathAndMasks(
       this, bounds, aResources, aBuilder, aSc, aManager, aDisplayListBuilder);
 
   Maybe<StackingContextHelper> layer;
   const StackingContextHelper* sc = &aSc;
   if (clip) {
     // Create a new stacking context to attach the mask to, ensuring the mask is
     // applied to the aggregate, and not the individual elements.
 
     // The stacking context shouldn't have any offset.
     bounds.MoveTo(0, 0);
 
-    wr::WrClipId clipId = clip->first;
-
-    Maybe<float> opacity = clip->second == HandleOpacity::Yes
+    wr::WrClipId clipId = clip->first();
+
+    Maybe<float> opacity = clip->second() == HandleOpacity::Yes
                                ? Some(mFrame->StyleEffects()->mOpacity)
                                : Nothing();
 
     wr::StackingContextParams params;
     params.clip = wr::WrStackingContextClip::ClipId(clipId);
     params.opacity = opacity.ptrOr(nullptr);
     layer.emplace(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder, params,
                   bounds);
--- a/layout/style/FontFace.h
+++ b/layout/style/FontFace.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_FontFace_h
 #define mozilla_dom_FontFace_h
 
 #include "mozilla/dom/FontFaceBinding.h"
 #include "mozilla/FontPropertyTypes.h"
 #include "mozilla/Maybe.h"
+#include "mozilla/Pair.h"
 #include "mozilla/ServoStyleConsts.h"
 #include "gfxUserFontSet.h"
 #include "nsCSSPropertyID.h"
 #include "nsCSSValue.h"
 #include "nsWrapperCache.h"
 
 class gfxFontFaceBufferSource;
 struct RawServoFontFaceRule;
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -962,47 +962,47 @@ already_AddRefed<RawServoAnimationValue>
   return Servo_AnimationValue_Compute(aElement, aDeclarations, aStyle,
                                       mRawSet.get())
       .Consume();
 }
 
 bool ServoStyleSet::EnsureUniqueInnerOnCSSSheets() {
   using SheetOwner = Variant<ServoStyleSet*, ShadowRoot*>;
 
-  AutoTArray<std::pair<StyleSheet*, SheetOwner>, 32> queue;
+  AutoTArray<Pair<StyleSheet*, SheetOwner>, 32> queue;
   EnumerateStyleSheets([&](StyleSheet& aSheet) {
-    queue.AppendElement(std::make_pair(&aSheet, SheetOwner{this}));
+    queue.AppendElement(MakePair(&aSheet, SheetOwner{this}));
   });
 
   EnumerateShadowRoots(*mDocument, [&](ShadowRoot& aShadowRoot) {
     for (auto index : IntegerRange(aShadowRoot.SheetCount())) {
       queue.AppendElement(
-          std::make_pair(aShadowRoot.SheetAt(index), SheetOwner{&aShadowRoot}));
+          MakePair(aShadowRoot.SheetAt(index), SheetOwner{&aShadowRoot}));
     }
   });
 
   while (!queue.IsEmpty()) {
     uint32_t idx = queue.Length() - 1;
-    auto* sheet = queue[idx].first;
-    SheetOwner owner = queue[idx].second;
+    auto* sheet = queue[idx].first();
+    SheetOwner owner = queue[idx].second();
     queue.RemoveElementAt(idx);
 
     // Only call EnsureUniqueInner for complete sheets. If we do call it on
     // incomplete sheets, we'll cause problems when the sheet is actually
     // loaded. We don't care about incomplete sheets here anyway, because this
     // method is only invoked by nsPresContext::EnsureSafeToHandOutCSSRules.
     // The CSSRule objects we are handing out won't contain any rules derived
     // from incomplete sheets (because they aren't yet applied in styling).
     if (sheet->IsComplete()) {
       sheet->EnsureUniqueInner();
     }
 
     // Enqueue all the sheet's children.
     for (StyleSheet* child : sheet->ChildSheets()) {
-      queue.AppendElement(std::make_pair(child, owner));
+      queue.AppendElement(MakePair(child, owner));
     }
   }
 
   if (mNeedsRestyleAfterEnsureUniqueInner) {
     // TODO(emilio): We could make this faster if needed tracking the specific
     // origins and sheets that have been cloned. But the only caller of this
     // doesn't seem to really care about perf.
     MarkOriginsDirty(OriginFlags::All);
--- a/layout/style/nsFontFaceUtils.cpp
+++ b/layout/style/nsFontFaceUtils.cpp
@@ -141,24 +141,23 @@ void nsFontFaceUtils::MarkDirtyForFontCh
   NS_ConvertUTF8toUTF16 familyName(aFont->FamilyName());
 
   // check descendants, iterating over subtrees that may include
   // additional subtrees associated with placeholders
   do {
     nsIFrame* subtreeRoot = subtrees.PopLastElement();
 
     // Check all descendants to see if they use the font
-    AutoTArray<std::pair<nsIFrame*, ReflowAlreadyScheduled>, 32> stack;
-    stack.AppendElement(
-        std::make_pair(subtreeRoot, ReflowAlreadyScheduled::No));
+    AutoTArray<Pair<nsIFrame*, ReflowAlreadyScheduled>, 32> stack;
+    stack.AppendElement(MakePair(subtreeRoot, ReflowAlreadyScheduled::No));
 
     do {
       auto pair = stack.PopLastElement();
-      nsIFrame* f = pair.first;
-      ReflowAlreadyScheduled alreadyScheduled = pair.second;
+      nsIFrame* f = pair.first();
+      ReflowAlreadyScheduled alreadyScheduled = pair.second();
 
       // if this frame uses the font, mark its descendants dirty
       // and skip checking its children
       FontUsageKind kind = FrameFontUsage(f, pc, aFont, familyName);
       if (kind != FontUsageKind::None) {
         if (alreadyScheduled == ReflowAlreadyScheduled::No) {
           ScheduleReflow(presShell, f);
           alreadyScheduled = ReflowAlreadyScheduled::Yes;
@@ -182,15 +181,15 @@ void nsFontFaceUtils::MarkDirtyForFontCh
           }
         }
 
         nsIFrame::ChildListIterator lists(f);
         for (; !lists.IsDone(); lists.Next()) {
           nsFrameList::Enumerator childFrames(lists.CurrentList());
           for (; !childFrames.AtEnd(); childFrames.Next()) {
             nsIFrame* kid = childFrames.get();
-            stack.AppendElement(std::make_pair(kid, alreadyScheduled));
+            stack.AppendElement(MakePair(kid, alreadyScheduled));
           }
         }
       }
     } while (!stack.IsEmpty());
   } while (!subtrees.IsEmpty());
 }
rename from mfbt/CompactPair.h
rename to mfbt/Pair.h
--- a/mfbt/CompactPair.h
+++ b/mfbt/Pair.h
@@ -1,192 +1,188 @@
 /* -*- 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/. */
 
 /* A class holding a pair of objects that tries to conserve storage space. */
 
-#ifndef mozilla_CompactPair_h
-#define mozilla_CompactPair_h
+#ifndef mozilla_Pair_h
+#define mozilla_Pair_h
 
 #include <utility>
 
 #include "mozilla/Attributes.h"
 #include "mozilla/TypeTraits.h"
 
 namespace mozilla {
 
 namespace detail {
 
 enum StorageType { AsBase, AsMember };
 
 // Optimize storage using the Empty Base Optimization -- that empty base classes
 // don't take up space -- to optimize size when one or the other class is
 // stateless and can be used as a base class.
 //
-// The extra conditions on storage for B are necessary so that CompactPairHelper
-// won't ambiguously inherit from either A or B, such that one or the other base
-// class would be inaccessible.
+// The extra conditions on storage for B are necessary so that PairHelper won't
+// ambiguously inherit from either A or B, such that one or the other base class
+// would be inaccessible.
 template <
     typename A, typename B,
     detail::StorageType = IsEmpty<A>::value ? detail::AsBase : detail::AsMember,
     detail::StorageType = IsEmpty<B>::value && !std::is_base_of<A, B>::value &&
                                   !std::is_base_of<B, A>::value
                               ? detail::AsBase
                               : detail::AsMember>
-struct CompactPairHelper;
+struct PairHelper;
 
 template <typename A, typename B>
-struct CompactPairHelper<A, B, AsMember, AsMember> {
+struct PairHelper<A, B, AsMember, AsMember> {
  protected:
   template <typename AArg, typename BArg>
-  CompactPairHelper(AArg&& aA, BArg&& aB)
+  PairHelper(AArg&& aA, BArg&& aB)
       : mFirstA(std::forward<AArg>(aA)), mSecondB(std::forward<BArg>(aB)) {}
 
   A& first() { return mFirstA; }
   const A& first() const { return mFirstA; }
   B& second() { return mSecondB; }
   const B& second() const { return mSecondB; }
 
-  void swap(CompactPairHelper& aOther) {
+  void swap(PairHelper& aOther) {
     std::swap(mFirstA, aOther.mFirstA);
     std::swap(mSecondB, aOther.mSecondB);
   }
 
  private:
   A mFirstA;
   B mSecondB;
 };
 
 template <typename A, typename B>
-struct CompactPairHelper<A, B, AsMember, AsBase> : private B {
+struct PairHelper<A, B, AsMember, AsBase> : private B {
  protected:
   template <typename AArg, typename BArg>
-  CompactPairHelper(AArg&& aA, BArg&& aB)
+  PairHelper(AArg&& aA, BArg&& aB)
       : B(std::forward<BArg>(aB)), mFirstA(std::forward<AArg>(aA)) {}
 
   A& first() { return mFirstA; }
   const A& first() const { return mFirstA; }
   B& second() { return *this; }
   const B& second() const { return *this; }
 
-  void swap(CompactPairHelper& aOther) {
+  void swap(PairHelper& aOther) {
     std::swap(mFirstA, aOther.mFirstA);
     std::swap(static_cast<B&>(*this), static_cast<B&>(aOther));
   }
 
  private:
   A mFirstA;
 };
 
 template <typename A, typename B>
-struct CompactPairHelper<A, B, AsBase, AsMember> : private A {
+struct PairHelper<A, B, AsBase, AsMember> : private A {
  protected:
   template <typename AArg, typename BArg>
-  CompactPairHelper(AArg&& aA, BArg&& aB)
+  PairHelper(AArg&& aA, BArg&& aB)
       : A(std::forward<AArg>(aA)), mSecondB(std::forward<BArg>(aB)) {}
 
   A& first() { return *this; }
   const A& first() const { return *this; }
   B& second() { return mSecondB; }
   const B& second() const { return mSecondB; }
 
-  void swap(CompactPairHelper& aOther) {
+  void swap(PairHelper& aOther) {
     std::swap(static_cast<A&>(*this), static_cast<A&>(aOther));
     std::swap(mSecondB, aOther.mSecondB);
   }
 
  private:
   B mSecondB;
 };
 
 template <typename A, typename B>
-struct CompactPairHelper<A, B, AsBase, AsBase> : private A, private B {
+struct PairHelper<A, B, AsBase, AsBase> : private A, private B {
  protected:
   template <typename AArg, typename BArg>
-  CompactPairHelper(AArg&& aA, BArg&& aB)
+  PairHelper(AArg&& aA, BArg&& aB)
       : A(std::forward<AArg>(aA)), B(std::forward<BArg>(aB)) {}
 
   A& first() { return static_cast<A&>(*this); }
   const A& first() const { return static_cast<A&>(*this); }
   B& second() { return static_cast<B&>(*this); }
   const B& second() const { return static_cast<B&>(*this); }
 
-  void swap(CompactPairHelper& aOther) {
+  void swap(PairHelper& aOther) {
     std::swap(static_cast<A&>(*this), static_cast<A&>(aOther));
     std::swap(static_cast<B&>(*this), static_cast<B&>(aOther));
   }
 };
 
 }  // namespace detail
 
 /**
- * CompactPair is the logical concatenation of an instance of A with an instance
- * B. Space is conserved when possible.  Neither A nor B may be a final class.
- *
- * In general if space conservation is not critical is preferred to use
- * std::pair.
+ * Pair is the logical concatenation of an instance of A with an instance B.
+ * Space is conserved when possible.  Neither A nor B may be a final class.
  *
  * It's typically clearer to have individual A and B member fields.  Except if
- * you want the space-conserving qualities of CompactPair, you're probably
- * better off not using this!
+ * you want the space-conserving qualities of Pair, you're probably better off
+ * not using this!
  *
  * No guarantees are provided about the memory layout of A and B, the order of
  * initialization or destruction of A and B, and so on.  (This is approximately
  * required to optimize space usage.)  The first/second names are merely
  * conceptual!
  */
 template <typename A, typename B>
-struct CompactPair : private detail::CompactPairHelper<A, B> {
-  typedef typename detail::CompactPairHelper<A, B> Base;
+struct Pair : private detail::PairHelper<A, B> {
+  typedef typename detail::PairHelper<A, B> Base;
 
  public:
   template <typename AArg, typename BArg>
-  CompactPair(AArg&& aA, BArg&& aB)
+  Pair(AArg&& aA, BArg&& aB)
       : Base(std::forward<AArg>(aA), std::forward<BArg>(aB)) {}
 
-  CompactPair(CompactPair&& aOther) = default;
-  CompactPair(const CompactPair& aOther) = default;
+  Pair(Pair&& aOther) = default;
+  Pair(const Pair& aOther) = default;
 
-  CompactPair& operator=(CompactPair&& aOther) = default;
-  CompactPair& operator=(const CompactPair& aOther) = default;
+  Pair& operator=(Pair&& aOther) = default;
+  Pair& operator=(const Pair& aOther) = default;
 
   /** The A instance. */
   using Base::first;
   /** The B instance. */
   using Base::second;
 
   /** Swap this pair with another pair. */
-  void swap(CompactPair& aOther) { Base::swap(aOther); }
+  void swap(Pair& aOther) { Base::swap(aOther); }
 };
 
 /**
- * MakeCompactPair allows you to construct a CompactPair instance using type
- * inference. A call like this:
+ * MakePair allows you to construct a Pair instance using type inference. A call
+ * like this:
  *
- *   MakeCompactPair(Foo(), Bar())
+ *   MakePair(Foo(), Bar())
  *
- * will return a CompactPair<Foo, Bar>.
+ * will return a Pair<Foo, Bar>.
  */
 template <typename A, typename B>
-CompactPair<typename RemoveCV<typename RemoveReference<A>::Type>::Type,
-            typename RemoveCV<typename RemoveReference<B>::Type>::Type>
-MakeCompactPair(A&& aA, B&& aB) {
-  return CompactPair<
-      typename RemoveCV<typename RemoveReference<A>::Type>::Type,
-      typename RemoveCV<typename RemoveReference<B>::Type>::Type>(
+Pair<typename RemoveCV<typename RemoveReference<A>::Type>::Type,
+     typename RemoveCV<typename RemoveReference<B>::Type>::Type>
+MakePair(A&& aA, B&& aB) {
+  return Pair<typename RemoveCV<typename RemoveReference<A>::Type>::Type,
+              typename RemoveCV<typename RemoveReference<B>::Type>::Type>(
       std::forward<A>(aA), std::forward<B>(aB));
 }
 
 }  // namespace mozilla
 
 namespace std {
 
 template <typename A, class B>
-void swap(mozilla::CompactPair<A, B>& aX, mozilla::CompactPair<A, B>& aY) {
+void swap(mozilla::Pair<A, B>& aX, mozilla::Pair<A, B>& aY) {
   aX.swap(aY);
 }
 
 }  // namespace std
 
-#endif /* mozilla_CompactPair_h */
+#endif /* mozilla_Pair_h */
--- a/mfbt/Tuple.h
+++ b/mfbt/Tuple.h
@@ -8,17 +8,17 @@
 
 #ifndef mozilla_Tuple_h
 #define mozilla_Tuple_h
 
 #include <stddef.h>
 
 #include <utility>
 
-#include "mozilla/CompactPair.h"
+#include "mozilla/Pair.h"
 #include "mozilla/TemplateLib.h"
 #include "mozilla/TypeTraits.h"
 
 namespace mozilla {
 
 namespace detail {
 
 /*
@@ -209,18 +209,18 @@ struct TupleImpl<Index, HeadT, TailT...>
  private:
   HeadT mHead;  // The element stored at this index in the tuple.
 };
 
 }  // namespace detail
 
 /**
  * Tuple is a class that stores zero or more objects, whose types are specified
- * as template parameters. It can be thought of as a generalization of
- * std::pair, (which can be thought of as a 2-tuple).
+ * as template parameters. It can be thought of as a generalization of Pair,
+ * (which can be thought of as a 2-tuple).
  *
  * Tuple allows index-based access to its elements (with the index having to be
  * known at compile time) via the non-member function 'Get<N>(tuple)'.
  */
 template <typename... Elements>
 class Tuple : public detail::TupleImpl<0, Elements...> {
   typedef detail::TupleImpl<0, Elements...> Impl;
 
@@ -268,17 +268,17 @@ class Tuple : public detail::TupleImpl<0
   }
   bool operator==(const Tuple& aOther) const {
     return static_cast<const Impl&>(*this) == static_cast<const Impl&>(aOther);
   }
 };
 
 /**
  * Specialization of Tuple for two elements.
- * This is created to support construction and assignment from a CompactPair or
+ * This is created to support construction and assignment from a Pair or
  * std::pair.
  */
 template <typename A, typename B>
 class Tuple<A, B> : public detail::TupleImpl<0, A, B> {
   typedef detail::TupleImpl<0, A, B> Impl;
 
  public:
   // The constructors and assignment operators here are simple wrappers
@@ -288,19 +288,19 @@ class Tuple<A, B> : public detail::Tuple
   explicit Tuple(const A& aA, const B& aB) : Impl(aA, aB) {}
   template <typename AArg, typename BArg,
             typename = typename EnableIf<detail::CheckConvertibility<
                 detail::Group<AArg, BArg>, detail::Group<A, B>>::value>::Type>
   explicit Tuple(AArg&& aA, BArg&& aB)
       : Impl(std::forward<AArg>(aA), std::forward<BArg>(aB)) {}
   Tuple(const Tuple& aOther) : Impl(aOther) {}
   Tuple(Tuple&& aOther) : Impl(std::move(aOther)) {}
-  explicit Tuple(const CompactPair<A, B>& aOther)
+  explicit Tuple(const Pair<A, B>& aOther)
       : Impl(aOther.first(), aOther.second()) {}
-  explicit Tuple(CompactPair<A, B>&& aOther)
+  explicit Tuple(Pair<A, B>&& aOther)
       : Impl(std::forward<A>(aOther.first()),
              std::forward<B>(aOther.second())) {}
   explicit Tuple(const std::pair<A, B>& aOther)
       : Impl(aOther.first, aOther.second) {}
   explicit Tuple(std::pair<A, B>&& aOther)
       : Impl(std::forward<A>(aOther.first), std::forward<B>(aOther.second)) {}
 
   template <typename AArg, typename BArg>
@@ -317,23 +317,23 @@ class Tuple<A, B> : public detail::Tuple
     static_cast<Impl&>(*this) = aOther;
     return *this;
   }
   Tuple& operator=(Tuple&& aOther) {
     static_cast<Impl&>(*this) = std::move(aOther);
     return *this;
   }
   template <typename AArg, typename BArg>
-  Tuple& operator=(const CompactPair<AArg, BArg>& aOther) {
+  Tuple& operator=(const Pair<AArg, BArg>& aOther) {
     Impl::Head(*this) = aOther.first();
     Impl::Tail(*this).Head(*this) = aOther.second();
     return *this;
   }
   template <typename AArg, typename BArg>
-  Tuple& operator=(CompactPair<AArg, BArg>&& aOther) {
+  Tuple& operator=(Pair<AArg, BArg>&& aOther) {
     Impl::Head(*this) = std::forward<AArg>(aOther.first());
     Impl::Tail(*this).Head(*this) = std::forward<BArg>(aOther.second());
     return *this;
   }
   template <typename AArg, typename BArg>
   Tuple& operator=(const std::pair<AArg, BArg>& aOther) {
     Impl::Head(*this) = aOther.first;
     Impl::Tail(*this).Head(*this) = aOther.second;
--- a/mfbt/UniquePtr.h
+++ b/mfbt/UniquePtr.h
@@ -8,18 +8,18 @@
 
 #ifndef mozilla_UniquePtr_h
 #define mozilla_UniquePtr_h
 
 #include <utility>
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/CompactPair.h"
 #include "mozilla/Compiler.h"
+#include "mozilla/Pair.h"
 #include "mozilla/TypeTraits.h"
 
 namespace mozilla {
 
 template <typename T>
 class DefaultDelete;
 template <typename T, class D = DefaultDelete<T>>
 class UniquePtr;
@@ -189,17 +189,17 @@ struct PointerType {
 template <typename T, class D>
 class UniquePtr {
  public:
   typedef T ElementType;
   typedef D DeleterType;
   typedef typename detail::PointerType<T, DeleterType>::Type Pointer;
 
  private:
-  mozilla::CompactPair<Pointer, DeleterType> mTuple;
+  Pair<Pointer, DeleterType> mTuple;
 
   Pointer& ptr() { return mTuple.first(); }
   const Pointer& ptr() const { return mTuple.first(); }
 
   DeleterType& del() { return mTuple.second(); }
   const DeleterType& del() const { return mTuple.second(); }
 
  public:
@@ -339,17 +339,17 @@ class UniquePtr {
 template <typename T, class D>
 class UniquePtr<T[], D> {
  public:
   typedef T* Pointer;
   typedef T ElementType;
   typedef D DeleterType;
 
  private:
-  mozilla::CompactPair<Pointer, DeleterType> mTuple;
+  Pair<Pointer, DeleterType> mTuple;
 
  public:
   /**
    * Construct a UniquePtr containing nullptr.
    */
   constexpr UniquePtr() : mTuple(static_cast<Pointer>(nullptr), DeleterType()) {
     static_assert(!IsPointer<D>::value, "must provide a deleter instance");
     static_assert(!std::is_reference_v<D>, "must provide a deleter instance");
--- a/mfbt/moz.build
+++ b/mfbt/moz.build
@@ -26,17 +26,16 @@ EXPORTS.mozilla = [
     'BinarySearch.h',
     'BloomFilter.h',
     'Buffer.h',
     'BufferList.h',
     'Casting.h',
     'ChaosMode.h',
     'Char16.h',
     'CheckedInt.h',
-    'CompactPair.h',
     'Compiler.h',
     'Compression.h',
     'DbgMacro.h',
     'DebugOnly.h',
     'DefineEnum.h',
     'DoublyLinkedList.h',
     'EndianUtils.h',
     'EnumeratedArray.h',
@@ -67,16 +66,17 @@ EXPORTS.mozilla = [
     'Maybe.h',
     'MaybeOneOf.h',
     'MemoryChecking.h',
     'MemoryReporting.h',
     'NonDereferenceable.h',
     'NotNull.h',
     'Opaque.h',
     'OperatorNewExtensions.h',
+    'Pair.h',
     'Path.h',
     'PodOperations.h',
     'Poison.h',
     'RandomNum.h',
     'Range.h',
     'RangedArray.h',
     'RangedPtr.h',
     'ReentrancyGuard.h',
deleted file mode 100644
--- a/mfbt/tests/TestCompactPair.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- 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 "mozilla/CompactPair.h"
-#include "mozilla/TypeTraits.h"
-
-using mozilla::CompactPair;
-using mozilla::IsSame;
-using mozilla::MakeCompactPair;
-
-// Sizes aren't part of the guaranteed CompactPair interface, but we want to
-// verify our attempts at compactness through EBO are moderately functional,
-// *somewhere*.
-#define INSTANTIATE(T1, T2, name, size)                                        \
-  CompactPair<T1, T2> name##_1(T1(0), T2(0));                                  \
-  static_assert(sizeof(name##_1.first()) > 0,                                  \
-                "first method should work on CompactPair<" #T1 ", " #T2 ">");  \
-  static_assert(sizeof(name##_1.second()) > 0,                                 \
-                "second method should work on CompactPair<" #T1 ", " #T2 ">"); \
-  static_assert(sizeof(name##_1) == (size),                                    \
-                "CompactPair<" #T1 ", " #T2 "> has an unexpected size");       \
-  CompactPair<T2, T1> name##_2(T2(0), T1(0));                                  \
-  static_assert(sizeof(name##_2.first()) > 0,                                  \
-                "first method should work on CompactPair<" #T2 ", " #T1 ">");  \
-  static_assert(sizeof(name##_2.second()) > 0,                                 \
-                "second method should work on CompactPair<" #T2 ", " #T1 ">"); \
-  static_assert(sizeof(name##_2) == (size),                                    \
-                "CompactPair<" #T2 ", " #T1 "> has an unexpected size");
-
-INSTANTIATE(int, int, prim1, 2 * sizeof(int));
-INSTANTIATE(int, long, prim2, 2 * sizeof(long));
-
-struct EmptyClass {
-  explicit EmptyClass(int) {}
-};
-struct NonEmpty {
-  char mC;
-  explicit NonEmpty(int) : mC('\0') {}
-};
-
-INSTANTIATE(int, EmptyClass, both1, sizeof(int));
-INSTANTIATE(int, NonEmpty, both2, 2 * sizeof(int));
-INSTANTIATE(EmptyClass, NonEmpty, both3, 1);
-
-struct A {
-  char dummy;
-  explicit A(int) : dummy('\0') {}
-};
-struct B : A {
-  explicit B(int aI) : A(aI) {}
-};
-
-INSTANTIATE(A, A, class1, 2);
-INSTANTIATE(A, B, class2, 2);
-INSTANTIATE(A, EmptyClass, class3, 1);
-
-struct OtherEmpty : EmptyClass {
-  explicit OtherEmpty(int aI) : EmptyClass(aI) {}
-};
-
-// C++11 requires distinct objects of the same type, within the same "most
-// derived object", to have different addresses.  CompactPair allocates its
-// elements as two bases, a base and a member, or two members.  If the two
-// elements have non-zero size or are unrelated, no big deal.  But if they're
-// both empty and related, something -- possibly both -- must be inflated.
-// Exactly which are inflated depends which CompactPairHelper specialization is
-// used.  We could potentially assert something about size for this case, but
-// whatever we could assert would be very finicky.  Plus it's two empty classes
-// -- hardly likely. So don't bother trying to assert anything about this case.
-// INSTANTIATE(EmptyClass, OtherEmpty, class4, ...something finicky...);
-
-int main() {
-  A a(0);
-  B b(0);
-  const A constA(0);
-  const B constB(0);
-
-  // Check that MakeCompactPair generates CompactPair objects of the correct
-  // types.
-  static_assert(
-      IsSame<decltype(MakeCompactPair(A(0), B(0))), CompactPair<A, B>>::value,
-      "MakeCompactPair should strip rvalue references");
-  static_assert(
-      IsSame<decltype(MakeCompactPair(a, b)), CompactPair<A, B>>::value,
-      "MakeCompactPair should strip lvalue references");
-  static_assert(IsSame<decltype(MakeCompactPair(constA, constB)),
-                       CompactPair<A, B>>::value,
-                "MakeCompactPair should strip CV-qualifiers");
-
-  // Check that copy assignment and move assignment work.
-  a = constA;
-  a = A(0);
-
-  return 0;
-}
new file mode 100644
--- /dev/null
+++ b/mfbt/tests/TestPair.cpp
@@ -0,0 +1,93 @@
+/* -*- 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 "mozilla/Pair.h"
+#include "mozilla/TypeTraits.h"
+
+using mozilla::IsSame;
+using mozilla::MakePair;
+using mozilla::Pair;
+
+// Sizes aren't part of the guaranteed Pair interface, but we want to verify our
+// attempts at compactness through EBO are moderately functional, *somewhere*.
+#define INSTANTIATE(T1, T2, name, size)                                 \
+  Pair<T1, T2> name##_1(T1(0), T2(0));                                  \
+  static_assert(sizeof(name##_1.first()) > 0,                           \
+                "first method should work on Pair<" #T1 ", " #T2 ">");  \
+  static_assert(sizeof(name##_1.second()) > 0,                          \
+                "second method should work on Pair<" #T1 ", " #T2 ">"); \
+  static_assert(sizeof(name##_1) == (size),                             \
+                "Pair<" #T1 ", " #T2 "> has an unexpected size");       \
+  Pair<T2, T1> name##_2(T2(0), T1(0));                                  \
+  static_assert(sizeof(name##_2.first()) > 0,                           \
+                "first method should work on Pair<" #T2 ", " #T1 ">");  \
+  static_assert(sizeof(name##_2.second()) > 0,                          \
+                "second method should work on Pair<" #T2 ", " #T1 ">"); \
+  static_assert(sizeof(name##_2) == (size),                             \
+                "Pair<" #T2 ", " #T1 "> has an unexpected size");
+
+INSTANTIATE(int, int, prim1, 2 * sizeof(int));
+INSTANTIATE(int, long, prim2, 2 * sizeof(long));
+
+struct EmptyClass {
+  explicit EmptyClass(int) {}
+};
+struct NonEmpty {
+  char mC;
+  explicit NonEmpty(int) : mC('\0') {}
+};
+
+INSTANTIATE(int, EmptyClass, both1, sizeof(int));
+INSTANTIATE(int, NonEmpty, both2, 2 * sizeof(int));
+INSTANTIATE(EmptyClass, NonEmpty, both3, 1);
+
+struct A {
+  char dummy;
+  explicit A(int) : dummy('\0') {}
+};
+struct B : A {
+  explicit B(int aI) : A(aI) {}
+};
+
+INSTANTIATE(A, A, class1, 2);
+INSTANTIATE(A, B, class2, 2);
+INSTANTIATE(A, EmptyClass, class3, 1);
+
+struct OtherEmpty : EmptyClass {
+  explicit OtherEmpty(int aI) : EmptyClass(aI) {}
+};
+
+// C++11 requires distinct objects of the same type, within the same "most
+// derived object", to have different addresses.  Pair allocates its elements as
+// two bases, a base and a member, or two members.  If the two elements have
+// non-zero size or are unrelated, no big deal.  But if they're both empty and
+// related, something -- possibly both -- must be inflated.  Exactly which are
+// inflated depends which PairHelper specialization is used.  We could
+// potentially assert something about size for this case, but whatever we could
+// assert would be very finicky.  Plus it's two empty classes -- hardly likely.
+// So don't bother trying to assert anything about this case.
+// INSTANTIATE(EmptyClass, OtherEmpty, class4, ...something finicky...);
+
+int main() {
+  A a(0);
+  B b(0);
+  const A constA(0);
+  const B constB(0);
+
+  // Check that MakePair generates Pair objects of the correct types.
+  static_assert(IsSame<decltype(MakePair(A(0), B(0))), Pair<A, B>>::value,
+                "MakePair should strip rvalue references");
+  static_assert(IsSame<decltype(MakePair(a, b)), Pair<A, B>>::value,
+                "MakePair should strip lvalue references");
+  static_assert(IsSame<decltype(MakePair(constA, constB)), Pair<A, B>>::value,
+                "MakePair should strip CV-qualifiers");
+
+  // Check that copy assignment and move assignment work.
+  a = constA;
+  a = A(0);
+
+  return 0;
+}
--- a/mfbt/tests/TestTuple.cpp
+++ b/mfbt/tests/TestTuple.cpp
@@ -4,27 +4,27 @@
  * 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 <stddef.h>
 
 #include <utility>
 
 #include "mozilla/Assertions.h"
-#include "mozilla/CompactPair.h"
+#include "mozilla/Pair.h"
 #include "mozilla/Tuple.h"
 #include "mozilla/TypeTraits.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Unused.h"
 
-using mozilla::CompactPair;
 using mozilla::Get;
 using mozilla::IsSame;
 using mozilla::MakeTuple;
 using mozilla::MakeUnique;
+using mozilla::Pair;
 using mozilla::Tie;
 using mozilla::Tuple;
 using mozilla::UniquePtr;
 using mozilla::Unused;
 using std::pair;
 
 #define CHECK(c)                                       \
   do {                                                 \
@@ -76,18 +76,18 @@ static void TestConstruction() {
   Tuple<UniquePtr<int>> h{std::move(g)};
   CHECK(Get<0>(g) == nullptr);
   CHECK(*Get<0>(h) == 42);
 }
 
 static void TestConstructionFromMozPair() {
   // Construction from elements
   int x = 1, y = 1;
-  CompactPair<int, int> a{x, y};
-  CompactPair<int&, const int&> b{x, y};
+  Pair<int, int> a{x, y};
+  Pair<int&, const int&> b{x, y};
   Tuple<int, int> c(a);
   Tuple<int&, const int&> d(b);
   x = 42;
   y = 42;
   CHECK(Get<0>(c) == 1);
   CHECK(Get<1>(c) == 1);
   CHECK(Get<0>(d) == 42);
   CHECK(Get<1>(d) == 42);
@@ -129,36 +129,36 @@ static void TestAssignment() {
   e = std::move(f);
   CHECK(*Get<0>(e) == 42);
   CHECK(Get<0>(f) == nullptr);
 }
 
 static void TestAssignmentFromMozPair() {
   // Copy assignment
   Tuple<int, int> a{0, 0};
-  CompactPair<int, int> b{42, 42};
+  Pair<int, int> b{42, 42};
   a = b;
   CHECK(Get<0>(a) == 42);
   CHECK(Get<1>(a) == 42);
 
   // Assignment to reference member
   int i = 0;
   int j = 0;
   int k = 42;
   Tuple<int&, int&> c{i, j};
-  CompactPair<int&, int&> d{k, k};
+  Pair<int&, int&> d{k, k};
   c = d;
   CHECK(i == 42);
   CHECK(j == 42);
 
   // Move assignment
   Tuple<UniquePtr<int>, UniquePtr<int>> e{MakeUnique<int>(0),
                                           MakeUnique<int>(0)};
-  CompactPair<UniquePtr<int>, UniquePtr<int>> f{MakeUnique<int>(42),
-                                                MakeUnique<int>(42)};
+  Pair<UniquePtr<int>, UniquePtr<int>> f{MakeUnique<int>(42),
+                                         MakeUnique<int>(42)};
   e = std::move(f);
   CHECK(*Get<0>(e) == 42);
   CHECK(*Get<1>(e) == 42);
   CHECK(f.first() == nullptr);
   CHECK(f.second() == nullptr);
 }
 
 static void TestAssignmentFromStdPair() {
@@ -225,42 +225,16 @@ static void TestMakeTuple() {
   // Make sure we don't infer the type to be Tuple<int&>.
   int x = 1;
   auto tuple2 = MakeTuple(x);
   CHECK_TYPE(tuple2, Tuple<int>);
   x = 2;
   CHECK(Get<0>(tuple2) == 1);
 }
 
-static bool TestTieMozPair() {
-  int i;
-  float f;
-  char c;
-  Tuple<int, float, char> rhs1(42, 0.5f, 'c');
-  Tie(i, f, c) = rhs1;
-  CHECK(i == Get<0>(rhs1));
-  CHECK(f == Get<1>(rhs1));
-  CHECK(c == Get<2>(rhs1));
-  // Test conversions
-  Tuple<ConvertibleToInt, double, unsigned char> rhs2(ConvertibleToInt(), 0.7f,
-                                                      'd');
-  Tie(i, f, c) = rhs2;
-  CHECK(i == Get<0>(rhs2));
-  CHECK(f == Get<1>(rhs2));
-  CHECK(c == Get<2>(rhs2));
-
-  // Test Pair
-  CompactPair<int, float> rhs3(42, 1.5f);
-  Tie(i, f) = rhs3;
-  CHECK(i == rhs3.first());
-  CHECK(f == rhs3.second());
-
-  return true;
-}
-
 static bool TestTie() {
   int i;
   float f;
   char c;
   Tuple<int, float, char> rhs1(42, 0.5f, 'c');
   Tie(i, f, c) = rhs1;
   CHECK(i == Get<0>(rhs1));
   CHECK(f == Get<1>(rhs1));
@@ -269,29 +243,33 @@ static bool TestTie() {
   Tuple<ConvertibleToInt, double, unsigned char> rhs2(ConvertibleToInt(), 0.7f,
                                                       'd');
   Tie(i, f, c) = rhs2;
   CHECK(i == Get<0>(rhs2));
   CHECK(f == Get<1>(rhs2));
   CHECK(c == Get<2>(rhs2));
 
   // Test Pair
-  pair<int, float> rhs3(42, 1.5f);
+  Pair<int, float> rhs3(-1, 1.2f);
   Tie(i, f) = rhs3;
-  CHECK(i == rhs3.first);
-  CHECK(f == rhs3.second);
+  CHECK(i == rhs3.first());
+  CHECK(f == rhs3.second());
+
+  pair<int, float> rhs4(42, 1.5f);
+  Tie(i, f) = rhs4;
+  CHECK(i == rhs4.first);
+  CHECK(f == rhs4.second);
 
   return true;
 }
 
 int main() {
   TestConstruction();
   TestConstructionFromMozPair();
   TestConstructionFromStdPair();
   TestAssignment();
   TestAssignmentFromMozPair();
   TestAssignmentFromStdPair();
   TestGet();
   TestMakeTuple();
   TestTie();
-  TestTieMozPair();
   return 0;
 }
--- a/mfbt/tests/moz.build
+++ b/mfbt/tests/moz.build
@@ -17,17 +17,16 @@ CppUnitTests([
     'TestArrayUtils',
     'TestAtomics',
     'TestBinarySearch',
     'TestBloomFilter',
     'TestBufferList',
     'TestCasting',
     'TestCeilingFloor',
     'TestCheckedInt',
-    'TestCompactPair',
     'TestCountPopulation',
     'TestCountZeroes',
     'TestDefineEnum',
     'TestDoublyLinkedList',
     'TestEndian',
     'TestEnumeratedArray',
     'TestEnumSet',
     'TestEnumTypeTraits',
@@ -40,16 +39,17 @@ CppUnitTests([
     'TestJSONWriter',
     'TestLinkedList',
     'TestMacroArgs',
     'TestMacroForEach',
     'TestMathAlgorithms',
     'TestMaybe',
     'TestNonDereferenceable',
     'TestNotNull',
+    'TestPair',
     'TestRandomNum',
     'TestRange',
     'TestRefPtr',
     'TestResult',
     'TestRollingMean',
     'TestSaturate',
     'TestScopeExit',
     'TestSegmentedVector',
--- a/mozglue/baseprofiler/core/platform.cpp
+++ b/mozglue/baseprofiler/core/platform.cpp
@@ -675,37 +675,37 @@ class ActivePS {
   // for all threads that should be included in a profile, both for threads
   // that are still registered, and for threads that have been unregistered but
   // still have data in the buffer.
   // For threads that have already been unregistered, the RegisteredThread
   // pointer will be null.
   // The returned array is sorted by thread register time.
   // Do not hold on to the return value across thread registration or profiler
   // restarts.
-  static Vector<std::pair<RegisteredThread*, ProfiledThreadData*>>
-  ProfiledThreads(PSLockRef) {
+  static Vector<Pair<RegisteredThread*, ProfiledThreadData*>> ProfiledThreads(
+      PSLockRef) {
     MOZ_ASSERT(sInstance);
-    Vector<std::pair<RegisteredThread*, ProfiledThreadData*>> array;
+    Vector<Pair<RegisteredThread*, ProfiledThreadData*>> array;
     MOZ_RELEASE_ASSERT(
         array.initCapacity(sInstance->mLiveProfiledThreads.length() +
                            sInstance->mDeadProfiledThreads.length()));
     for (auto& t : sInstance->mLiveProfiledThreads) {
       MOZ_RELEASE_ASSERT(array.append(
-          std::make_pair(t.mRegisteredThread, t.mProfiledThreadData.get())));
+          MakePair(t.mRegisteredThread, t.mProfiledThreadData.get())));
     }
     for (auto& t : sInstance->mDeadProfiledThreads) {
       MOZ_RELEASE_ASSERT(
-          array.append(std::make_pair((RegisteredThread*)nullptr, t.get())));
+          array.append(MakePair((RegisteredThread*)nullptr, t.get())));
     }
 
     std::sort(array.begin(), array.end(),
-              [](const std::pair<RegisteredThread*, ProfiledThreadData*>& a,
-                 const std::pair<RegisteredThread*, ProfiledThreadData*>& b) {
-                return a.second->Info()->RegisterTime() <
-                       b.second->Info()->RegisterTime();
+              [](const Pair<RegisteredThread*, ProfiledThreadData*>& a,
+                 const Pair<RegisteredThread*, ProfiledThreadData*>& b) {
+                return a.second()->Info()->RegisterTime() <
+                       b.second()->Info()->RegisterTime();
               });
     return array;
   }
 
   static Vector<RefPtr<PageInformation>> ProfiledPages(PSLockRef aLock) {
     MOZ_ASSERT(sInstance);
     Vector<RefPtr<PageInformation>> array;
     for (auto& d : CorePS::RegisteredPages(aLock)) {
@@ -1723,20 +1723,20 @@ static void locked_profiler_stream_json_
 
     // Lists the samples for each thread profile
     aWriter.StartArrayProperty("threads");
   }
 
   // if aOnlyThreads is true, the only output will be the threads array items.
   {
     ActivePS::DiscardExpiredDeadProfiledThreads(aLock);
-    Vector<std::pair<RegisteredThread*, ProfiledThreadData*>> threads =
+    Vector<Pair<RegisteredThread*, ProfiledThreadData*>> threads =
         ActivePS::ProfiledThreads(aLock);
     for (auto& thread : threads) {
-      ProfiledThreadData* profiledThreadData = thread.second;
+      ProfiledThreadData* profiledThreadData = thread.second();
       profiledThreadData->StreamJSON(buffer, aWriter,
                                      CorePS::ProcessName(aLock),
                                      CorePS::ProcessStartTime(), aSinceTime);
     }
   }
 
   if (!aOnlyThreads) {
     aWriter.EndArray();
--- a/mozglue/baseprofiler/public/BlocksRingBuffer.h
+++ b/mozglue/baseprofiler/public/BlocksRingBuffer.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef BlocksRingBuffer_h
 #define BlocksRingBuffer_h
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/BaseProfilerDetail.h"
 #include "mozilla/ModuloBuffer.h"
+#include "mozilla/Pair.h"
 #include "mozilla/ProfileBufferIndex.h"
 #include "mozilla/Unused.h"
 
 #include "mozilla/Maybe.h"
 #include "mozilla/Span.h"
 #include "mozilla/Tuple.h"
 #include "mozilla/UniquePtrExtensions.h"
 #include "mozilla/Variant.h"
--- a/mozglue/tests/TestBaseProfiler.cpp
+++ b/mozglue/tests/TestBaseProfiler.cpp
@@ -27,17 +27,16 @@
 #  include <time.h>
 #  include <unistd.h>
 #endif
 
 #include <algorithm>
 #include <atomic>
 #include <thread>
 #include <type_traits>
-#include <utility>
 
 using namespace mozilla;
 
 MOZ_MAYBE_UNUSED static void SleepMilli(unsigned aMilliseconds) {
 #if defined(_MSC_VER) || defined(__MINGW32__)
   Sleep(aMilliseconds);
 #else
   struct timespec ts = {/* .tv_sec */ static_cast<time_t>(aMilliseconds / 1000),
@@ -895,20 +894,20 @@ void TestBlocksRingBufferAPI() {
     auto bi5_6 =
         rb.Put(sizeof(uint32_t), [&](BlocksRingBuffer::EntryWriter* aEW) {
           MOZ_RELEASE_ASSERT(!!aEW);
           aEW->WriteObject(uint32_t(5));
           MOZ_RELEASE_ASSERT(aEW->GetEntryAt(bi2).isNothing());
           MOZ_RELEASE_ASSERT(aEW->GetEntryAt(bi4).isSome());
           MOZ_RELEASE_ASSERT(aEW->GetEntryAt(bi4)->CurrentBlockIndex() == bi4);
           MOZ_RELEASE_ASSERT(aEW->GetEntryAt(bi4)->ReadObject<uint32_t>() == 4);
-          return std::make_pair(aEW->CurrentBlockIndex(), aEW->BlockEndIndex());
+          return MakePair(aEW->CurrentBlockIndex(), aEW->BlockEndIndex());
         });
-    auto& bi5 = bi5_6.first;
-    auto& bi6 = bi5_6.second;
+    auto& bi5 = bi5_6.first();
+    auto& bi6 = bi5_6.second();
     //  16  17  18  19  20  21  22  23  24  25  26  11  12  13  14  15 (16)
     //  [4 |    int(4)    ] [4 |    int(5)    ]E ? S[4 |    int(3)    ]
     VERIFY_START_END_PUSHED_CLEARED(11, 26, 5, 2);
 
     // Read single entry at bi2, should now gracefully fail.
     rb.ReadAt(bi2, [](Maybe<BlocksRingBuffer::EntryReader>&& aMaybeReader) {
       MOZ_RELEASE_ASSERT(aMaybeReader.isNothing());
     });
--- a/netwerk/dns/IDNBlocklistUtils.cpp
+++ b/netwerk/dns/IDNBlocklistUtils.cpp
@@ -16,48 +16,48 @@ void RemoveCharFromBlocklist(char16_t aC
   auto pos = aBlocklist.BinaryIndexOf(aChar, BlocklistPairToCharComparator());
   if (pos == nsTArray<BlocklistRange>::NoIndex) {
     return;
   }
 
   auto& pair = aBlocklist[pos];
 
   // If the matched range has a length of one, we can just remove it
-  if (pair.second == pair.first) {
+  if (pair.second() == pair.first()) {
     aBlocklist.RemoveElementAt(pos);
     return;
   }
 
   // If the character matches the first element in the range, just update
   // the range.
-  if (aChar == pair.first) {
-    pair.first = pair.first + 1;
+  if (aChar == pair.first()) {
+    pair.first() = pair.first() + 1;
     return;
   }
 
   // Also if it matches the last character in the range, we just update it.
-  if (aChar == pair.second) {
-    pair.second = pair.second - 1;
+  if (aChar == pair.second()) {
+    pair.second() = pair.second() - 1;
     return;
   }
 
   // Our character is in the middle of the range, splitting it in two.
   // We update the matched range to reflect the values before the character,
   // and insert a new range that represents the values after.
-  char16_t lastElement = pair.second;
-  pair.second = aChar - 1;
-  aBlocklist.InsertElementAt(pos + 1,
-                             std::make_pair(char16_t(aChar + 1), lastElement));
+  char16_t lastElement = pair.second();
+  pair.second() = aChar - 1;
+  aBlocklist.InsertElementAt(
+      pos + 1, mozilla::MakePair(char16_t(aChar + 1), lastElement));
 }
 
 void InitializeBlocklist(nsTArray<BlocklistRange>& aBlocklist) {
   aBlocklist.Clear();
   for (auto const& arr : sBlocklistPairs) {
     // The hardcoded pairs are already sorted.
-    aBlocklist.AppendElement(std::make_pair(arr[0], arr[1]));
+    aBlocklist.AppendElement(mozilla::MakePair(arr[0], arr[1]));
   }
 
   nsAutoString extraAllowed;
   nsresult rv =
       Preferences::GetString("network.IDN.extra_allowed_chars", extraAllowed);
   if (NS_SUCCEEDED(rv) && !extraAllowed.IsEmpty()) {
     const char16_t* cur = extraAllowed.BeginReading();
     const char16_t* end = extraAllowed.EndReading();
@@ -68,16 +68,16 @@ void InitializeBlocklist(nsTArray<Blockl
   }
 
   nsAutoString extraBlocked;
   rv = Preferences::GetString("network.IDN.extra_blocked_chars", extraBlocked);
   // We add each extra blocked character to the blocklist as a separate range.
   if (NS_SUCCEEDED(rv) && !extraBlocked.IsEmpty()) {
     for (size_t i = 0; i < extraBlocked.Length(); ++i) {
       aBlocklist.AppendElement(
-          std::make_pair(extraBlocked[i], extraBlocked[i]));
+          mozilla::MakePair(extraBlocked[i], extraBlocked[i]));
     }
     aBlocklist.Sort(BlocklistEntryComparator());
   }
 }
 
 }  // namespace net
 }  // namespace mozilla
--- a/netwerk/dns/IDNBlocklistUtils.h
+++ b/netwerk/dns/IDNBlocklistUtils.h
@@ -1,51 +1,51 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 IDNBlocklistUtils_h__
 #define IDNBlocklistUtils_h__
 
-#include <utility>
+#include "mozilla/Pair.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 namespace net {
 
 // A blocklist range is defined as all of the characters between:
 // { firstCharacterInRange, lastCharacterInRange }
-typedef std::pair<char16_t, char16_t> BlocklistRange;
+typedef mozilla::Pair<char16_t, char16_t> BlocklistRange;
 
 // Used to perform a binary search of the needle in the sorted array of pairs
 class BlocklistPairToCharComparator {
  public:
   bool Equals(const BlocklistRange& pair, char16_t needle) const {
-    // If the needle is between pair.first and pair.second it
+    // If the needle is between pair.first() and pair.second() it
     // is part of the range.
-    return pair.first <= needle && needle <= pair.second;
+    return pair.first() <= needle && needle <= pair.second();
   }
 
   bool LessThan(const BlocklistRange& pair, char16_t needle) const {
     // The needle has to be larger than the second value,
     // otherwise it may be equal.
-    return pair.second < needle;
+    return pair.second() < needle;
   }
 };
 
 // Used to sort the array of pairs
 class BlocklistEntryComparator {
  public:
   bool Equals(const BlocklistRange& a, const BlocklistRange& b) const {
-    return a.first == b.first && a.second == b.second;
+    return a.first() == b.first() && a.second() == b.second();
   }
 
   bool LessThan(const BlocklistRange& a, const BlocklistRange& b) const {
-    return a.first < b.first;
+    return a.first() < b.first();
   }
 };
 
 // Returns true if the char can be found in the blocklist
 inline bool CharInBlocklist(char16_t aChar,
                             const nsTArray<BlocklistRange>& aBlocklist) {
   return aBlocklist.ContainsSorted(aChar, BlocklistPairToCharComparator());
 }
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -2231,18 +2231,18 @@ HttpBaseChannel::TakeAllSecurityMessages
 
   aMessages.Clear();
   for (auto pair : mSecurityConsoleMessages) {
     nsresult rv;
     nsCOMPtr<nsISecurityConsoleMessage> message =
         do_CreateInstance(NS_SECURITY_CONSOLE_MESSAGE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    message->SetTag(pair.first);
-    message->SetCategory(pair.second);
+    message->SetTag(pair.first());
+    message->SetCategory(pair.second());
     aMessages.AppendElement(message);
   }
 
   MOZ_ASSERT(mSecurityConsoleMessages.Length() == aMessages.Length());
   mSecurityConsoleMessages.Clear();
 
   return NS_OK;
 }
@@ -2260,17 +2260,17 @@ nsresult HttpBaseChannel::AddSecurityMes
     const nsAString& aMessageTag, const nsAString& aMessageCategory) {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsresult rv;
 
   // nsSecurityConsoleMessage is not thread-safe refcounted.
   // Delay the object construction until requested.
   // See TakeAllSecurityMessages()
-  std::pair<nsString, nsString> pair(aMessageTag, aMessageCategory);
+  Pair<nsString, nsString> pair(aMessageTag, aMessageCategory);
   mSecurityConsoleMessages.AppendElement(std::move(pair));
 
   nsCOMPtr<nsIConsoleService> console(
       do_GetService(NS_CONSOLESERVICE_CONTRACTID));
   if (!console) {
     return NS_ERROR_FAILURE;
   }
 
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -681,17 +681,17 @@ class HttpBaseChannel : public nsHashPro
 
   RefPtr<nsHttpHandler> mHttpHandler;  // keep gHttpHandler alive
   UniquePtr<nsTArray<nsCString>> mRedirectedCachekeys;
   nsCOMPtr<nsIRequestContext> mRequestContext;
 
   NetAddr mSelfAddr;
   NetAddr mPeerAddr;
 
-  nsTArray<std::pair<nsString, nsString>> mSecurityConsoleMessages;
+  nsTArray<Pair<nsString, nsString>> mSecurityConsoleMessages;
   nsTArray<nsCString> mUnsafeHeaders;
 
   // A time value equal to the starting time of the fetch that initiates the
   // redirect.
   mozilla::TimeStamp mRedirectStartTimeStamp;
   // A time value equal to the time immediately after receiving the last byte of
   // the response of the last redirect.
   mozilla::TimeStamp mRedirectEndTimeStamp;
--- a/other-licenses/nsis/Contrib/CityHash/cityhash/city.h
+++ b/other-licenses/nsis/Contrib/CityHash/cityhash/city.h
@@ -46,21 +46,30 @@
 #include <stdlib.h>  // for size_t.
 #include <stdint.h>
 
 typedef uint8_t uint8;
 typedef uint32_t uint32;
 typedef uint64_t uint64;
 
 #ifdef __cplusplus
-
+// The standard <utility> header doesn't compile, apparently it conflicts
+// with... some Mozilla something or other. But all that's used from it
+// is std::pair, so we can just replace that with mozilla::Pair.
+#ifndef MOZILLA_CLIENT
 #include <utility>
 typedef std::pair<uint64, uint64> uint128;
 inline uint64 Uint128Low64(const uint128& x) { return x.first; }
 inline uint64 Uint128High64(const uint128& x) { return x.second; }
+#else
+#include "mozilla/Pair.h"
+typedef mozilla::Pair<uint64, uint64> uint128;
+inline uint64 Uint128Low64(const uint128& x) { return x.first(); }
+inline uint64 Uint128High64(const uint128& x) { return x.second(); }
+#endif
 
 extern "C" {
 #endif
 
 // Hash function for a byte array.
 uint64 CityHash64(const char *buf, size_t len);
 
 // Hash function for a byte array.  For convenience, a 64-bit seed is also
--- a/startupcache/StartupCache.cpp
+++ b/startupcache/StartupCache.cpp
@@ -468,33 +468,32 @@ Result<Ok, nsresult> StartupCache::Write
   if (!mFile) {
     return Err(NS_ERROR_UNEXPECTED);
   }
 
   AutoFDClose fd;
   MOZ_TRY(mFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
                                   0644, &fd.rwget()));
 
-  nsTArray<std::pair<const nsCString*, StartupCacheEntry*>> entries;
+  nsTArray<Pair<const nsCString*, StartupCacheEntry*>> entries;
   for (auto iter = mTable.iter(); !iter.done(); iter.next()) {
     if (iter.get().value().mRequested) {
-      entries.AppendElement(
-          std::make_pair(&iter.get().key(), &iter.get().value()));
+      entries.AppendElement(MakePair(&iter.get().key(), &iter.get().value()));
     }
   }
 
   if (entries.IsEmpty()) {
     return Ok();
   }
 
   entries.Sort(StartupCacheEntry::Comparator());
   loader::OutputBuffer buf;
   for (auto& e : entries) {
-    auto key = e.first;
-    auto value = e.second;
+    auto key = e.first();
+    auto value = e.second();
     auto uncompressedSize = value->mUncompressedSize;
     // Set the mHeaderOffsetInFile so we can go back and edit the offset.
     value->mHeaderOffsetInFile = buf.cursor();
     // Write a 0 offset/compressed size as a placeholder until we get the real
     // offset after compressing.
     buf.codeUint32(0);
     buf.codeUint32(0);
     buf.codeUint32(uncompressedSize);
@@ -517,17 +516,17 @@ Result<Ok, nsresult> StartupCache::Write
                                  chunkSize, /* aReadBufLen */
                                  true,      /* aChecksum */
                                  true);     /* aStableSrc */
   size_t writeBufLen = ctx.GetRequiredWriteBufferLength();
   auto writeBuffer = MakeUnique<char[]>(writeBufLen);
   auto writeSpan = MakeSpan(writeBuffer.get(), writeBufLen);
 
   for (auto& e : entries) {
-    auto value = e.second;
+    auto value = e.second();
     value->mOffset = offset;
     Span<const char> result;
     MOZ_TRY_VAR(result,
                 ctx.BeginCompressing(writeSpan).mapErr(MapLZ4ErrorToNsresult));
     MOZ_TRY(Write(fd, result.Elements(), result.Length()));
     offset += result.Length();
 
     for (size_t i = 0; i < value->mUncompressedSize; i += chunkSize) {
@@ -542,17 +541,17 @@ Result<Ok, nsresult> StartupCache::Write
     MOZ_TRY_VAR(result, ctx.EndCompressing().mapErr(MapLZ4ErrorToNsresult));
     MOZ_TRY(Write(fd, result.Elements(), result.Length()));
     offset += result.Length();
     value->mCompressedSize = offset - value->mOffset;
     MOZ_TRY(Seek(fd, dataStart + offset));
   }
 
   for (auto& e : entries) {
-    auto value = e.second;
+    auto value = e.second();
     uint8_t* headerEntry = buf.Get() + value->mHeaderOffsetInFile;
     LittleEndian::writeUint32(headerEntry, value->mOffset);
     LittleEndian::writeUint32(headerEntry + sizeof(value->mOffset),
                               value->mCompressedSize);
   }
   MOZ_TRY(Seek(fd, headerStart));
   MOZ_TRY(Write(fd, buf.Get(), buf.cursor()));
 
--- a/startupcache/StartupCache.h
+++ b/startupcache/StartupCache.h
@@ -1,32 +1,31 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 StartupCache_h_
 #define StartupCache_h_
 
-#include <utility>
-
 #include "nsClassHashtable.h"
 #include "nsComponentManagerUtils.h"
 #include "nsTArray.h"
 #include "nsZipArchive.h"
 #include "nsITimer.h"
 #include "nsIMemoryReporter.h"
 #include "nsIObserverService.h"
 #include "nsIObserver.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIFile.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/AutoMemMap.h"
 #include "mozilla/Compression.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/Pair.h"
 #include "mozilla/Result.h"
 #include "mozilla/UniquePtr.h"
 
 /**
  * The StartupCache is a persistent cache of simple key-value pairs,
  * where the keys are null-terminated c-strings and the values are
  * arbitrary data, passed as a (char*, size) tuple.
  *
@@ -104,24 +103,24 @@ struct StartupCacheEntry {
         mOffset(0),
         mCompressedSize(0),
         mUncompressedSize(aLength),
         mHeaderOffsetInFile(0),
         mRequestedOrder(0),
         mRequested(true) {}
 
   struct Comparator {
-    using Value = std::pair<const nsCString*, StartupCacheEntry*>;
+    using Value = Pair<const nsCString*, StartupCacheEntry*>;
 
     bool Equals(const Value& a, const Value& b) const {
-      return a.second->mRequestedOrder == b.second->mRequestedOrder;
+      return a.second()->mRequestedOrder == b.second()->mRequestedOrder;
     }
 
     bool LessThan(const Value& a, const Value& b) const {
-      return a.second->mRequestedOrder < b.second->mRequestedOrder;
+      return a.second()->mRequestedOrder < b.second()->mRequestedOrder;
     }
   };
 };
 
 struct nsCStringHasher {
   using Key = nsCString;
   using Lookup = nsCString;
 
--- a/testing/cppunittest.ini
+++ b/testing/cppunittest.ini
@@ -6,17 +6,16 @@
 [TestArrayUtils]
 [TestAtomics]
 [TestBinarySearch]
 [TestBloomFilter]
 [TestBufferList]
 [TestCasting]
 [TestCeilingFloor]
 [TestCheckedInt]
-[TestCompactPair]
 [TestCountPopulation]
 [TestCountZeroes]
 [TestDefineEnum]
 [TestDoublyLinkedList]
 [TestDllInterceptor]
 skip-if = os != 'win'
 [TestEndian]
 [TestEnumeratedArray]
@@ -49,16 +48,17 @@ skip-if = os != 'win'
 skip-if = os != 'win'
 [TestBaseProfiler]
 [TestNonDereferenceable]
 [TestNotNull]
 [TestParseFTPList]
 [TestPEExportSection]
 skip-if = os != 'win'
 [TestPLDHash]
+[TestPair]
 [TestPoisonArea]
 skip-if = os == 'android' # Bug 1147630
 [TestRange]
 [TestRandomNum]
 [TestRefPtr]
 [TestResult]
 [TestRollingMean]
 [TestScopeExit]
--- a/toolkit/components/antitracking/ContentBlockingAllowList.cpp
+++ b/toolkit/components/antitracking/ContentBlockingAllowList.cpp
@@ -124,33 +124,33 @@ nsresult ContentBlockingAllowList::Check
             _spec),
            aContentBlockingAllowListPrincipal);
 
   nsPermissionManager* permManager = nsPermissionManager::GetInstance();
   NS_ENSURE_TRUE(permManager, NS_ERROR_FAILURE);
 
   // Check both the normal mode and private browsing mode user override
   // permissions.
-  std::pair<const nsLiteralCString, bool> types[] = {
+  Pair<const nsLiteralCString, bool> types[] = {
       {NS_LITERAL_CSTRING("trackingprotection"), false},
       {NS_LITERAL_CSTRING("trackingprotection-pb"), true}};
 
   for (const auto& type : types) {
-    if (aIsPrivateBrowsing != type.second) {
+    if (aIsPrivateBrowsing != type.second()) {
       continue;
     }
 
     uint32_t permissions = nsIPermissionManager::UNKNOWN_ACTION;
     nsresult rv = permManager->TestPermissionFromPrincipal(
-        aContentBlockingAllowListPrincipal, type.first, &permissions);
+        aContentBlockingAllowListPrincipal, type.first(), &permissions);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (permissions == nsIPermissionManager::ALLOW_ACTION) {
       aIsAllowListed = true;
-      LOG(("Found user override type %s", type.first.get()));
+      LOG(("Found user override type %s", type.first().get()));
       // Stop checking the next permisson type if we decided to override.
       break;
     }
   }
 
   if (!aIsAllowListed) {
     LOG(("No user override found"));
   }
--- a/toolkit/components/antitracking/TemporaryAccessGrantObserver.cpp
+++ b/toolkit/components/antitracking/TemporaryAccessGrantObserver.cpp
@@ -31,18 +31,18 @@ void TemporaryAccessGrantObserver::Creat
                                           nsIPrincipal* aPrincipal,
                                           const nsACString& aType) {
   MOZ_ASSERT(XRE_IsParentProcess());
 
   if (!sObservers) {
     sObservers = MakeUnique<ObserversTable>();
   }
   Unused << sObservers
-                ->LookupForAdd(std::make_pair(
-                    nsCOMPtr<nsIPrincipal>(aPrincipal), nsCString(aType)))
+                ->LookupForAdd(MakePair(nsCOMPtr<nsIPrincipal>(aPrincipal),
+                                        nsCString(aType)))
                 .OrInsert([&]() -> nsITimer* {
                   // Only create a new observer if we don't have a matching
                   // entry in our hashtable.
                   nsCOMPtr<nsITimer> timer;
                   RefPtr<TemporaryAccessGrantObserver> observer =
                       new TemporaryAccessGrantObserver(aPM, aPrincipal, aType);
                   nsresult rv =
                       NS_NewTimerWithObserver(getter_AddRefs(timer), observer,
@@ -69,17 +69,17 @@ void TemporaryAccessGrantObserver::SetTi
 
 NS_IMETHODIMP
 TemporaryAccessGrantObserver::Observe(nsISupports* aSubject, const char* aTopic,
                                       const char16_t* aData) {
   if (strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC) == 0) {
     Unused << mPM->RemoveFromPrincipal(mPrincipal, mType);
 
     MOZ_ASSERT(sObservers);
-    sObservers->Remove(std::make_pair(mPrincipal, mType));
+    sObservers->Remove(MakePair(mPrincipal, mType));
   } else if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
     nsCOMPtr<nsIObserverService> observerService =
         mozilla::services::GetObserverService();
     if (observerService) {
       observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
     }
     if (mTimer) {
       mTimer->Cancel();
--- a/toolkit/components/antitracking/TemporaryAccessGrantObserver.h
+++ b/toolkit/components/antitracking/TemporaryAccessGrantObserver.h
@@ -19,40 +19,40 @@ class nsDataHashtable;
 class nsITimer;
 class nsPermissionManager;
 class TemporaryAccessGrantCacheKey;
 
 namespace mozilla {
 
 class TemporaryAccessGrantCacheKey : public PLDHashEntryHdr {
  public:
-  typedef std::pair<nsCOMPtr<nsIPrincipal>, nsCString> KeyType;
+  typedef Pair<nsCOMPtr<nsIPrincipal>, nsCString> KeyType;
   typedef const KeyType* KeyTypePointer;
 
   explicit TemporaryAccessGrantCacheKey(KeyTypePointer aKey)
-      : mPrincipal(aKey->first), mType(aKey->second) {}
+      : mPrincipal(aKey->first()), mType(aKey->second()) {}
   TemporaryAccessGrantCacheKey(TemporaryAccessGrantCacheKey&& aOther) = default;
 
   ~TemporaryAccessGrantCacheKey() = default;
 
-  KeyType GetKey() const { return std::make_pair(mPrincipal, mType); }
+  KeyType GetKey() const { return MakePair(mPrincipal, mType); }
   bool KeyEquals(KeyTypePointer aKey) const {
-    return !!mPrincipal == !!aKey->first && mType == aKey->second &&
-           (mPrincipal ? (mPrincipal->Equals(aKey->first)) : true);
+    return !!mPrincipal == !!aKey->first() && mType == aKey->second() &&
+           (mPrincipal ? (mPrincipal->Equals(aKey->first())) : true);
   }
 
   static KeyTypePointer KeyToPointer(KeyType& aKey) { return &aKey; }
   static PLDHashNumber HashKey(KeyTypePointer aKey) {
     if (!aKey) {
       return 0;
     }
 
-    BasePrincipal* bp = BasePrincipal::Cast(aKey->first);
+    BasePrincipal* bp = BasePrincipal::Cast(aKey->first());
     return HashGeneric(bp->GetOriginNoSuffixHash(), bp->GetOriginSuffixHash(),
-                       HashString(aKey->second));
+                       HashString(aKey->second()));
   }
 
   enum { ALLOW_MEMMOVE = true };
 
  private:
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCString mType;
 };
--- a/toolkit/components/places/Database.cpp
+++ b/toolkit/components/places/Database.cpp
@@ -2148,40 +2148,40 @@ nsresult Database::MigrateV50Up() {
       NS_LITERAL_CSTRING(
           "SELECT id, url FROM moz_places "
           "WHERE url_hash BETWEEN hash('place', 'prefix_lo') AND "
           "hash('place', 'prefix_hi') "
           "AND url LIKE '%folder=%' "),
       getter_AddRefs(stmt));
   if (NS_FAILED(rv)) return rv;
 
-  AutoTArray<std::pair<int64_t, nsCString>, 32> placeURLs;
+  AutoTArray<Pair<int64_t, nsCString>, 32> placeURLs;
 
   bool hasMore = false;
   nsCString url;
   while (NS_SUCCEEDED(stmt->ExecuteStep(&hasMore)) && hasMore) {
     int64_t placeId;
     rv = stmt->GetInt64(0, &placeId);
     if (NS_FAILED(rv)) return rv;
     rv = stmt->GetUTF8String(1, url);
     if (NS_FAILED(rv)) return rv;
 
-    if (!placeURLs.AppendElement(std::make_pair(placeId, url))) {
+    if (!placeURLs.AppendElement(MakePair(placeId, url))) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   if (placeURLs.IsEmpty()) {
     return NS_OK;
   }
 
   int64_t placeId;
   for (uint32_t i = 0; i < placeURLs.Length(); ++i) {
-    placeId = placeURLs[i].first;
-    url = placeURLs[i].second;
+    placeId = placeURLs[i].first();
+    url = placeURLs[i].second();
 
     rv = ConvertOldStyleQuery(url);
     // Something bad happened, and we can't convert it, so just continue.
     if (NS_WARN_IF(NS_FAILED(rv))) {
       continue;
     }
 
     nsCOMPtr<mozIStorageStatement> updateStmt;
--- a/toolkit/components/telemetry/core/TelemetryEvent.cpp
+++ b/toolkit/components/telemetry/core/TelemetryEvent.cpp
@@ -7,16 +7,17 @@
 #include "Telemetry.h"
 #include "TelemetryEvent.h"
 #include <prtime.h>
 #include <limits>
 #include "ipc/TelemetryIPCAccumulator.h"
 #include "jsapi.h"
 #include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject, JS::NewArrayObject
 #include "mozilla/Maybe.h"
+#include "mozilla/Pair.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticMutex.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Unused.h"
 #include "nsClassHashtable.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
@@ -1236,18 +1237,18 @@ nsresult TelemetryEvent::CreateSnapshots
 
   // Creating a JS snapshot of the events is a two-step process:
   // (1) Lock the storage and copy the events into function-local storage.
   // (2) Serialize the events into JS.
   // We can't hold a lock for (2) because we will run into deadlocks otherwise
   // from JS recording Telemetry.
 
   // (1) Extract the events from storage with a lock held.
-  nsTArray<std::pair<const char*, EventRecordArray>> processEvents;
-  nsTArray<std::pair<uint32_t, EventRecordArray>> leftovers;
+  nsTArray<mozilla::Pair<const char*, EventRecordArray>> processEvents;
+  nsTArray<mozilla::Pair<uint32_t, EventRecordArray>> leftovers;
   {
     StaticMutexAutoLock locker(gTelemetryEventsMutex);
 
     if (!gInitDone) {
       return NS_ERROR_FAILURE;
     }
 
     // The snapshotting function is the same for both static and dynamic builtin
@@ -1273,52 +1274,52 @@ nsresult TelemetryEvent::CreateSnapshots
               leftoverEvents.AppendElement(record);
             }
           }
         }
 
         if (events.Length()) {
           const char* processName = GetNameForProcessID(ProcessID(iter.Key()));
           processEvents.AppendElement(
-              std::make_pair(processName, std::move(events)));
+              mozilla::MakePair(processName, std::move(events)));
           if (leftoverEvents.Length()) {
             leftovers.AppendElement(
-                std::make_pair(iter.Key(), std::move(leftoverEvents)));
+                mozilla::MakePair(iter.Key(), std::move(leftoverEvents)));
           }
         }
       }
     };
 
     // Take a snapshot of the plain and dynamic builtin events.
     snapshotter(gEventRecords);
     if (aClear) {
       gEventRecords.Clear();
       for (auto& pair : leftovers) {
-        gEventRecords.Put(pair.first,
-                          new EventRecordArray(std::move(pair.second)));
+        gEventRecords.Put(pair.first(),
+                          new EventRecordArray(std::move(pair.second())));
       }
       leftovers.Clear();
     }
   }
 
   // (2) Serialize the events to a JS object.
   JS::RootedObject rootObj(cx, JS_NewPlainObject(cx));
   if (!rootObj) {
     return NS_ERROR_FAILURE;
   }
 
   const uint32_t processLength = processEvents.Length();
   for (uint32_t i = 0; i < processLength; ++i) {
     JS::RootedObject eventsArray(cx);
-    if (NS_FAILED(SerializeEventsArray(processEvents[i].second, cx,
+    if (NS_FAILED(SerializeEventsArray(processEvents[i].second(), cx,
                                        &eventsArray, aDataset))) {
       return NS_ERROR_FAILURE;
     }
 
-    if (!JS_DefineProperty(cx, rootObj, processEvents[i].first, eventsArray,
+    if (!JS_DefineProperty(cx, rootObj, processEvents[i].first(), eventsArray,
                            JSPROP_ENUMERATE)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   aResult.setObject(*rootObj);
   return NS_OK;
 }
--- a/toolkit/components/telemetry/core/TelemetryOrigin.cpp
+++ b/toolkit/components/telemetry/core/TelemetryOrigin.cpp
@@ -14,29 +14,32 @@
 #include "TelemetryCommon.h"
 #include "TelemetryOriginEnums.h"
 
 #include "js/Array.h"  // JS::NewArrayObject
 #include "mozilla/Atomics.h"
 #include "mozilla/Base64.h"
 #include "mozilla/dom/PrioEncoder.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/Pair.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticMutex.h"
 #include "mozilla/Tuple.h"
 #include "mozilla/UniquePtr.h"
 
 #include <cmath>
 #include <type_traits>
 
 using mozilla::ErrorResult;
 using mozilla::Get;
+using mozilla::MakePair;
 using mozilla::MakeTuple;
 using mozilla::MakeUnique;
 using mozilla::MallocSizeOf;
+using mozilla::Pair;
 using mozilla::StaticMutex;
 using mozilla::StaticMutexAutoLock;
 using mozilla::Tuple;
 using mozilla::UniquePtr;
 using mozilla::dom::PrioEncoder;
 using mozilla::Telemetry::OriginMetricID;
 using mozilla::Telemetry::Common::ToJSString;
 
@@ -122,17 +125,17 @@ UniquePtr<HashToIndexMap> gHashToIndexMa
 typedef nsDataHashtable<nsCStringHashKey, uint32_t> OriginBag;
 typedef nsDataHashtable<OriginMetricIDHashKey, OriginBag> IdToOriginBag;
 
 UniquePtr<IdToOriginBag> gMetricToOriginBag;
 
 mozilla::Atomic<bool, mozilla::Relaxed> gInitDone(false);
 
 // Useful for app-encoded data
-typedef nsTArray<std::pair<OriginMetricID, nsTArray<nsTArray<bool>>>>
+typedef nsTArray<Pair<OriginMetricID, nsTArray<nsTArray<bool>>>>
     IdBoolsPairArray;
 
 // Prio has a maximum supported number of bools it can encode at a time.
 // This means a single metric may result in several encoded payloads if the
 // number of origins exceeds the number of bools.
 // Each encoded payload corresponds to an element in the `prioData` array in the
 // "prio" ping.
 // This number is the number of encoded payloads needed per metric, and is
@@ -226,17 +229,17 @@ nsresult AppEncodeTo(const StaticMutexAu
           MOZ_ASSERT(index < (gOriginHashesList->Length() + kNumMetaOrigins));
           size_t shardIndex = index / PrioEncoder::gNumBooleans;
           MOZ_ASSERT(shardIndex < metricData.Length());
           MOZ_ASSERT(index % PrioEncoder::gNumBooleans <
                      metricData[shardIndex].Length());
           metricData[shardIndex][index % PrioEncoder::gNumBooleans] = true;
         }
       }
-      aResult.AppendElement(std::make_pair(id, metricData));
+      aResult.AppendElement(MakePair(id, metricData));
     } while (generation++ < maxGeneration);
   }
   return NS_OK;
 }
 
 }  // anonymous namespace
 
 ////////////////////////////////////////////////////////////////////////
@@ -493,23 +496,23 @@ nsresult TelemetryOrigin::GetEncodedOrig
       // APIs. And replaying any interleaving recording sounds like too much
       // squeeze for not enough juice.
 
       gMetricToOriginBag->Clear();
     }
   }
 
   // Step 2: Don't need the lock to prio-encode and base64-encode
-  nsTArray<std::pair<nsCString, std::pair<nsCString, nsCString>>> prioData;
+  nsTArray<Pair<nsCString, Pair<nsCString, nsCString>>> prioData;
   for (auto& metricData : appEncodedMetricData) {
-    auto& boolVectors = metricData.second;
+    auto& boolVectors = metricData.second();
     for (uint32_t i = 0; i < boolVectors.Length(); ++i) {
       // "encoding" is of the form `metricName-X` where X is the shard index.
       nsCString encodingName =
-          nsPrintfCString("%s-%u", GetNameForMetricID(metricData.first), i);
+          nsPrintfCString("%s-%u", GetNameForMetricID(metricData.first()), i);
       nsCString aResult;
       nsCString bResult;
       rv = PrioEncoder::EncodeNative(encodingName, boolVectors[i], aResult,
                                      bResult);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       nsCString aBase64;
@@ -519,17 +522,17 @@ nsresult TelemetryOrigin::GetEncodedOrig
       }
       nsCString bBase64;
       rv = mozilla::Base64Encode(bResult, bBase64);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       prioData.AppendElement(
-          std::make_pair(encodingName, std::make_pair(aBase64, bBase64)));
+          MakePair(encodingName, MakePair(aBase64, bBase64)));
     }
   }
 
   // Step 3: Still don't need the lock to translate to JS
   // The resulting data structure is:
   // [{
   //   encoding: <encoding name>,
   //   prio: {
@@ -544,38 +547,39 @@ nsresult TelemetryOrigin::GetEncodedOrig
     return NS_ERROR_FAILURE;
   }
   uint32_t i = 0;
   for (auto& prioDatum : prioData) {
     JS::RootedObject prioDatumObj(aCx, JS_NewPlainObject(aCx));
     if (NS_WARN_IF(!prioDatumObj)) {
       return NS_ERROR_FAILURE;
     }
-    JSString* encoding = ToJSString(aCx, prioDatum.first);
+    JSString* encoding = ToJSString(aCx, prioDatum.first());
     JS::RootedString rootedEncoding(aCx, encoding);
     if (NS_WARN_IF(!JS_DefineProperty(aCx, prioDatumObj, "encoding",
                                       rootedEncoding, JSPROP_ENUMERATE))) {
       return NS_ERROR_FAILURE;
     }
 
     JS::RootedObject prioObj(aCx, JS_NewPlainObject(aCx));
     if (NS_WARN_IF(!prioObj)) {
       return NS_ERROR_FAILURE;
     }
     if (NS_WARN_IF(!JS_DefineProperty(aCx, prioDatumObj, "prio", prioObj,
                                       JSPROP_ENUMERATE))) {
       return NS_ERROR_FAILURE;
     }
 
-    JS::RootedString aRootStr(aCx, ToJSString(aCx, prioDatum.second.first));
+    JS::RootedString aRootStr(aCx, ToJSString(aCx, prioDatum.second().first()));
     if (NS_WARN_IF(!JS_DefineProperty(aCx, prioObj, "a", aRootStr,
                                       JSPROP_ENUMERATE))) {
       return NS_ERROR_FAILURE;
     }
-    JS::RootedString bRootStr(aCx, ToJSString(aCx, prioDatum.second.second));
+    JS::RootedString bRootStr(aCx,
+                              ToJSString(aCx, prioDatum.second().second()));
     if (NS_WARN_IF(!JS_DefineProperty(aCx, prioObj, "b", bRootStr,
                                       JSPROP_ENUMERATE))) {
       return NS_ERROR_FAILURE;
     }
 
     if (NS_WARN_IF(!JS_DefineElement(aCx, prioDataArray, i++, prioDatumObj,
                                      JSPROP_ENUMERATE))) {
       return NS_ERROR_FAILURE;
--- a/toolkit/components/telemetry/core/TelemetryScalar.cpp
+++ b/toolkit/components/telemetry/core/TelemetryScalar.cpp
@@ -842,17 +842,17 @@ ScalarBase* internal_ScalarAllocate(cons
   return scalar;
 }
 
 /**
  * The implementation for the keyed scalar type.
  */
 class KeyedScalar {
  public:
-  typedef std::pair<nsCString, nsCOMPtr<nsIVariant>> KeyValuePair;
+  typedef mozilla::Pair<nsCString, nsCOMPtr<nsIVariant>> KeyValuePair;
 
   // We store the name instead of a reference to the BaseScalarInfo because
   // the BaseScalarInfo can move if it's from a dynamic scalar.
   explicit KeyedScalar(const BaseScalarInfo& info)
       : mScalarName(info.name()),
         mScalarKeyCount(info.key_count),
         mScalarKeyOffset(info.key_offset),
         mMaximumNumberOfKeys(kMaximumNumberOfKeys){};
@@ -1027,17 +1027,18 @@ nsresult KeyedScalar::GetValue(const nsA
       // No value for this store.
       continue;
     }
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     // Append it to value list.
-    aValues.AppendElement(std::make_pair(nsCString(iter.Key()), scalarValue));
+    aValues.AppendElement(
+        mozilla::MakePair(nsCString(iter.Key()), scalarValue));
   }
 
   return NS_OK;
 }
 
 // Forward declaration
 nsresult internal_GetKeyedScalarByEnum(const StaticMutexAutoLock& lock,
                                        const ScalarKey& aId,
@@ -3286,23 +3287,23 @@ nsresult TelemetryScalar::CreateKeyedSna
       const nsTArray<KeyedScalar::KeyValuePair>& keyProps =
           mozilla::Get<1>(keyedScalarData);
       for (uint32_t i = 0; i < keyProps.Length(); i++) {
         const KeyedScalar::KeyValuePair& keyData = keyProps[i];
 
         // Convert the value for the key to a JSValue.
         JS::Rooted<JS::Value> keyJsValue(aCx);
         nsresult rv = nsContentUtils::XPConnect()->VariantToJS(
-            aCx, keyedScalarObj, keyData.second, &keyJsValue);
+            aCx, keyedScalarObj, keyData.second(), &keyJsValue);
         if (NS_FAILED(rv)) {
           return rv;
         }
 
         // Add the key to the scalar representation.
-        const NS_ConvertUTF8toUTF16 key(keyData.first);
+        const NS_ConvertUTF8toUTF16 key(keyData.first());
         if (!JS_DefineUCProperty(aCx, keyedScalarObj, key.Data(), key.Length(),
                                  keyJsValue, JSPROP_ENUMERATE)) {
           return NS_ERROR_FAILURE;
         }
       }
 
       // Add the scalar to the root object.
       if (!JS_DefineProperty(aCx, processObj, scalarName, keyedScalarObj,
@@ -3861,18 +3862,18 @@ nsresult TelemetryScalar::SerializeKeyed
 
       // Define a property for each scalar key, then add it to the keyed scalar
       // object.
       const nsTArray<KeyedScalar::KeyValuePair>& keyProps =
           mozilla::Get<1>(keyedScalarData);
       for (const KeyedScalar::KeyValuePair& keyData : keyProps) {
         nsresult rv = WriteVariantToJSONWriter(
             mozilla::Get<2>(keyedScalarData) /*aScalarType*/,
-            keyData.second /*aInputValue*/,
-            PromiseFlatCString(keyData.first).get() /*aOutKey*/,
+            keyData.second() /*aInputValue*/,
+            PromiseFlatCString(keyData.first()).get() /*aOutKey*/,
             aWriter /*aWriter*/);
         if (NS_FAILED(rv)) {
           // Skip this scalar if we failed to write it. We don't bail out just
           // yet as we may salvage other scalars. We eventually need to call
           // EndObject.
           continue;
         }
       }
@@ -3894,17 +3895,17 @@ nsresult TelemetryScalar::SerializeKeyed
  */
 nsresult TelemetryScalar::DeserializePersistedScalars(JSContext* aCx,
                                                       JS::HandleValue aData) {
   MOZ_ASSERT(XRE_IsParentProcess(), "Only load scalars in the parent process");
   if (!XRE_IsParentProcess()) {
     return NS_ERROR_FAILURE;
   }
 
-  typedef std::pair<nsCString, nsCOMPtr<nsIVariant>> PersistedScalarPair;
+  typedef mozilla::Pair<nsCString, nsCOMPtr<nsIVariant>> PersistedScalarPair;
   typedef nsTArray<PersistedScalarPair> PersistedScalarArray;
   typedef nsDataHashtable<ProcessIDHashKey, PersistedScalarArray>
       PeristedScalarStorage;
 
   PeristedScalarStorage scalarsToUpdate;
 
   // Before updating the scalars, we need to get the data out of the JS
   // wrappers. We can't hold the scalars mutex while handling JS stuff.
@@ -3997,32 +3998,33 @@ nsresult TelemetryScalar::DeserializePer
       if (NS_FAILED(rv)) {
         JS_ClearPendingException(aCx);
         continue;
       }
 
       // Add the scalar to the map.
       PersistedScalarArray& processScalars =
           scalarsToUpdate.GetOrInsert(static_cast<uint32_t>(processID));
-      processScalars.AppendElement(std::make_pair(
+      processScalars.AppendElement(mozilla::MakePair(
           nsCString(NS_ConvertUTF16toUTF8(scalarName)), unpackedVal));
     }
   }
 
   // Now that all the JS specific operations are finished, update the scalars.
   {
     StaticMutexAutoLock lock(gTelemetryScalarsMutex);
 
     for (auto iter = scalarsToUpdate.ConstIter(); !iter.Done(); iter.Next()) {
       PersistedScalarArray& processScalars = iter.Data();
       for (PersistedScalarArray::size_type i = 0; i < processScalars.Length();
            i++) {
         mozilla::Unused << internal_UpdateScalar(
-            lock, processScalars[i].first, ScalarActionType::eSet,
-            processScalars[i].second, ProcessID(iter.Key()), true /* aForce */);
+            lock, processScalars[i].first(), ScalarActionType::eSet,
+            processScalars[i].second(), ProcessID(iter.Key()),
+            true /* aForce */);
       }
     }
   }
 
   return NS_OK;
 }
 
 /**
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -905,37 +905,37 @@ class ActivePS {
   // for all threads that should be included in a profile, both for threads
   // that are still registered, and for threads that have been unregistered but
   // still have data in the buffer.
   // For threads that have already been unregistered, the RegisteredThread
   // pointer will be null.
   // The returned array is sorted by thread register time.
   // Do not hold on to the return value across thread registration or profiler
   // restarts.
-  static Vector<std::pair<RegisteredThread*, ProfiledThreadData*>>
-  ProfiledThreads(PSLockRef) {
+  static Vector<Pair<RegisteredThread*, ProfiledThreadData*>> ProfiledThreads(
+      PSLockRef) {
     MOZ_ASSERT(sInstance);
-    Vector<std::pair<RegisteredThread*, ProfiledThreadData*>> array;
+    Vector<Pair<RegisteredThread*, ProfiledThreadData*>> array;
     MOZ_RELEASE_ASSERT(
         array.initCapacity(sInstance->mLiveProfiledThreads.length() +
                            sInstance->mDeadProfiledThreads.length()));
     for (auto& t : sInstance->mLiveProfiledThreads) {
       MOZ_RELEASE_ASSERT(array.append(
-          std::make_pair(t.mRegisteredThread, t.mProfiledThreadData.get())));
+          MakePair(t.mRegisteredThread, t.mProfiledThreadData.get())));
     }
     for (auto& t : sInstance->mDeadProfiledThreads) {
       MOZ_RELEASE_ASSERT(
-          array.append(std::make_pair((RegisteredThread*)nullptr, t.get())));
+          array.append(MakePair((RegisteredThread*)nullptr, t.get())));
     }
 
     std::sort(array.begin(), array.end(),
-              [](const std::pair<RegisteredThread*, ProfiledThreadData*>& a,
-                 const std::pair<RegisteredThread*, ProfiledThreadData*>& b) {
-                return a.second->Info()->RegisterTime() <
-                       b.second->Info()->RegisterTime();
+              [](const Pair<RegisteredThread*, ProfiledThreadData*>& a,
+                 const Pair<RegisteredThread*, ProfiledThreadData*>& b) {
+                return a.second()->Info()->RegisterTime() <
+                       b.second()->Info()->RegisterTime();
               });
     return array;
   }
 
   static Vector<RefPtr<PageInformation>> ProfiledPages(PSLockRef aLock) {
     MOZ_ASSERT(sInstance);
     Vector<RefPtr<PageInformation>> array;
     for (auto& d : CorePS::RegisteredPages(aLock)) {
@@ -2099,20 +2099,20 @@ static void StreamTaskTracer(PSLockRef a
       aWriter.StringElement(dataString.get());
     }
   }
   aWriter.EndArray();
 
   aWriter.StartArrayProperty("threads");
   {
     ActivePS::DiscardExpiredDeadProfiledThreads(aLock);
-    Vector<std::pair<RegisteredThread*, ProfiledThreadData*>> threads =
+    Vector<Pair<RegisteredThread*, ProfiledThreadData*>> threads =
         ActivePS::ProfiledThreads(aLock);
     for (auto& thread : threads) {
-      RefPtr<ThreadInfo> info = thread.second->Info();
+      RefPtr<ThreadInfo> info = thread.second()->Info();
       StreamNameAndThreadId(aWriter, info->Name(), info->ThreadId());
     }
   }
   aWriter.EndArray();
 
   aWriter.DoubleProperty("start",
                          static_cast<double>(tasktracer::GetStartTime()));
 #endif
@@ -2432,23 +2432,23 @@ static void locked_profiler_stream_json_
     StreamTaskTracer(aLock, aWriter);
     aWriter.EndObject();
   }
 
   // Lists the samples for each thread profile
   aWriter.StartArrayProperty("threads");
   {
     ActivePS::DiscardExpiredDeadProfiledThreads(aLock);
-    Vector<std::pair<RegisteredThread*, ProfiledThreadData*>> threads =
+    Vector<Pair<RegisteredThread*, ProfiledThreadData*>> threads =
         ActivePS::ProfiledThreads(aLock);
     for (auto& thread : threads) {
-      RegisteredThread* registeredThread = thread.first;
+      RegisteredThread* registeredThread = thread.first();
       JSContext* cx =
           registeredThread ? registeredThread->GetJSContext() : nullptr;
-      ProfiledThreadData* profiledThreadData = thread.second;
+      ProfiledThreadData* profiledThreadData = thread.second();
       profiledThreadData->StreamJSON(
           buffer, cx, aWriter, CorePS::ProcessName(aLock),
           CorePS::ProcessStartTime(), aSinceTime,
           ActivePS::FeatureJSTracer(aLock), aService);
     }
 
 #if defined(GP_OS_android)
     if (ActivePS::FeatureJava(aLock)) {