Bug 1455691 - Make the transaction id a struct instead of a uint64_t. r=mattwoodrow
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 20 Apr 2018 15:13:06 -0400
changeset 471054 1224b46e13922d7fd3cec29a441560439d0166cb
parent 471021 e2b0e792967f878029cb9e2fbb538821cc9b0baa
child 471055 fa90dad2faac2a5b0951167f25f006f2d6309136
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1455691
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1455691 - Make the transaction id a struct instead of a uint64_t. r=mattwoodrow MozReview-Commit-ID: 9yZknygQvFr
dom/base/nsDOMWindowUtils.cpp
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
gfx/layers/Layers.h
gfx/layers/LayersTypes.h
gfx/layers/TransactionIdAllocator.h
gfx/layers/client/ClientLayerManager.cpp
gfx/layers/client/ClientLayerManager.h
gfx/layers/ipc/CompositorBridgeChild.cpp
gfx/layers/ipc/CompositorBridgeChild.h
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/CompositorBridgeParent.h
gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayerTransactionParent.h
gfx/layers/ipc/LayersMessageUtils.h
gfx/layers/ipc/LayersMessages.ipdlh
gfx/layers/ipc/PCompositorBridge.ipdl
gfx/layers/ipc/PLayerTransaction.ipdl
gfx/layers/ipc/PWebRenderBridge.ipdl
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
gfx/layers/wr/WebRenderBridgeChild.cpp
gfx/layers/wr/WebRenderBridgeChild.h
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
gfx/layers/wr/WebRenderLayerManager.cpp
gfx/layers/wr/WebRenderLayerManager.h
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/base/nsRefreshDriver.cpp
layout/base/nsRefreshDriver.h
view/nsView.cpp
view/nsView.h
widget/nsIWidgetListener.cpp
widget/nsIWidgetListener.h
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2469,17 +2469,17 @@ NS_IMETHODIMP
 nsDOMWindowUtils::GetLastTransactionId(uint64_t *aLastTransactionId)
 {
   nsPresContext* presContext = GetPresContext();
   if (!presContext) {
     return NS_ERROR_UNEXPECTED;
   }
 
   nsRefreshDriver* driver = presContext->GetRootPresContext()->RefreshDriver();
-  *aLastTransactionId = driver->LastTransactionId();
+  *aLastTransactionId = uint64_t(driver->LastTransactionId());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::RestoreNormalRefresh()
 {
   // Kick the compositor out of test mode before the refresh driver, so that
   // the refresh driver doesn't send an update that gets ignored by the
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -3119,17 +3119,17 @@ TabChild::GetFrom(layers::LayersId aLaye
   StaticMutexAutoLock lock(sTabChildrenMutex);
   if (!sTabChildren) {
     return nullptr;
   }
   return sTabChildren->Get(uint64_t(aLayersId));
 }
 
 void
-TabChild::DidComposite(uint64_t aTransactionId,
+TabChild::DidComposite(mozilla::layers::TransactionId aTransactionId,
                        const TimeStamp& aCompositeStart,
                        const TimeStamp& aCompositeEnd)
 {
   MOZ_ASSERT(mPuppetWidget);
   RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
   MOZ_ASSERT(lm);
 
   lm->DidComposite(aTransactionId, aCompositeStart, aCompositeEnd);
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -536,17 +536,17 @@ public:
   }
 
   static TabChild* GetFrom(nsIPresShell* aPresShell);
   static TabChild* GetFrom(layers::LayersId aLayersId);
 
   layers::LayersId GetLayersId() { return mLayersId; }
   Maybe<bool> IsLayersConnected() { return mLayersConnected; }
 
-  void DidComposite(uint64_t aTransactionId,
+  void DidComposite(mozilla::layers::TransactionId aTransactionId,
                     const TimeStamp& aCompositeStart,
                     const TimeStamp& aCompositeEnd);
 
   void DidRequestComposite(const TimeStamp& aCompositeReqStart,
                            const TimeStamp& aCompositeReqEnd);
 
   void ClearCachedResources();
   void InvalidateLayers();
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -689,33 +689,33 @@ public:
   uint32_t GetAndClearPaintedPixelCount() {
     uint32_t count = mPaintedPixelCount;
     mPaintedPixelCount = 0;
     return count;
   }
 
   virtual void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch) {}
 
-  virtual void DidComposite(uint64_t aTransactionId,
+  virtual void DidComposite(TransactionId aTransactionId,
                             const mozilla::TimeStamp& aCompositeStart,
                             const mozilla::TimeStamp& aCompositeEnd) {}
 
   virtual void AddDidCompositeObserver(DidCompositeObserver* aObserver) { MOZ_CRASH("GFX: LayerManager"); }
   virtual void RemoveDidCompositeObserver(DidCompositeObserver* aObserver) { MOZ_CRASH("GFX: LayerManager"); }
 
   virtual void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier) {}
 
   virtual TextureFactoryIdentifier GetTextureFactoryIdentifier()
   {
     return TextureFactoryIdentifier();
   }
 
   virtual void SetTransactionIdAllocator(TransactionIdAllocator* aAllocator) {}
 
-  virtual uint64_t GetLastTransactionId() { return 0; }
+  virtual TransactionId GetLastTransactionId() { return TransactionId{0}; }
 
   virtual CompositorBridgeChild* GetCompositorBridgeChild() { return nullptr; }
 
 protected:
   RefPtr<Layer> mRoot;
   gfx::UserData mUserData;
   bool mDestroyed;
   bool mSnapEffectiveTransforms;
--- a/gfx/layers/LayersTypes.h
+++ b/gfx/layers/LayersTypes.h
@@ -83,16 +83,67 @@ struct LayersId {
   struct HashFn {
     std::size_t operator()(const LayersId& aKey) const
     {
       return std::hash<uint64_t>{}(aKey.mId);
     }
   };
 };
 
+struct TransactionId {
+  uint64_t mId;
+
+  bool IsValid() const {
+    return mId != 0;
+  }
+
+  MOZ_MUST_USE TransactionId Next() const {
+    return TransactionId{mId + 1};
+  }
+
+  MOZ_MUST_USE TransactionId Prev() const {
+    return TransactionId{mId - 1};
+  }
+
+  int64_t operator-(const TransactionId& aOther) const {
+    return mId - aOther.mId;
+  }
+
+  // Allow explicit cast to a uint64_t for now
+  explicit operator uint64_t() const
+  {
+    return mId;
+  }
+
+  bool operator<(const TransactionId& aOther) const
+  {
+    return mId < aOther.mId;
+  }
+
+  bool operator<=(const TransactionId& aOther) const
+  {
+    return mId <= aOther.mId;
+  }
+
+  bool operator>(const TransactionId& aOther) const
+  {
+    return mId > aOther.mId;
+  }
+
+  bool operator>=(const TransactionId& aOther) const
+  {
+    return mId >= aOther.mId;
+  }
+
+  bool operator==(const TransactionId& aOther) const
+  {
+    return mId == aOther.mId;
+  }
+};
+
 enum class LayersBackend : int8_t {
   LAYERS_NONE = 0,
   LAYERS_BASIC,
   LAYERS_OPENGL,
   LAYERS_D3D11,
   LAYERS_CLIENT,
   LAYERS_WR,
   LAYERS_LAST
--- a/gfx/layers/TransactionIdAllocator.h
+++ b/gfx/layers/TransactionIdAllocator.h
@@ -3,16 +3,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 GFX_TRANSACTION_ID_ALLOCATOR_H
 #define GFX_TRANSACTION_ID_ALLOCATOR_H
 
 #include "nsISupportsImpl.h"
+#include "mozilla/layers/LayersTypes.h"
 #include "mozilla/TimeStamp.h"
 
 namespace mozilla {
 namespace layers {
 
 class TransactionIdAllocator {
 protected:
   virtual ~TransactionIdAllocator() {}
@@ -24,42 +25,42 @@ public:
    * Allocate a unique id number for the current refresh tick, can
    * only be called while IsInRefresh().
    *
    * If too many id's are allocated without being returned then
    * the refresh driver will suspend until they catch up. This
    * "throttling" behaviour can be skipped by passing aThrottle=false.
    * Otherwise call sites should generally be passing aThrottle=true.
    */
-  virtual uint64_t GetTransactionId(bool aThrottle) = 0;
+  virtual TransactionId GetTransactionId(bool aThrottle) = 0;
 
   /**
    * Return the transaction id that for the last non-revoked transaction.
    * This allows the caller to tell whether a composite was triggered by
    * a paint that occurred after a call to TransactionId().
    */
-  virtual uint64_t LastTransactionId() const = 0;
+  virtual TransactionId LastTransactionId() const = 0;
 
   /**
    * Notify that all work (including asynchronous composites)
    * for a given transaction id has been completed.
    *
    * If the refresh driver has been suspended because
    * of having too many outstanding id's, then this may
    * resume it.
    */
-  virtual void NotifyTransactionCompleted(uint64_t aTransactionId) = 0;
+  virtual void NotifyTransactionCompleted(TransactionId aTransactionId) = 0;
 
   /**
    * Revoke a transaction id that isn't needed to track
    * completion of asynchronous work. This is similar
    * to NotifyTransactionCompleted except avoids
    * return ordering issues.
    */
-  virtual void RevokeTransactionId(uint64_t aTransactionId) = 0;
+  virtual void RevokeTransactionId(TransactionId aTransactionId) = 0;
 
   /**
    * Stop waiting for pending transactions, if any.
    *
    * This is used when ClientLayerManager is assigning to another refresh
    * driver, and the current refresh driver may never receive transaction
    * completed notifications.
    */
@@ -68,17 +69,17 @@ public:
   /**
    * Transaction id is usually initialized as 0, however when ClientLayerManager
    * switches to another refresh driver, completed transactions of the previous
    * refresh driver could be delivered and confuse the newly adopted refresh
    * driver. To prevent this situation, use this function to reset transaction
    * id to the last transaction id from previous refresh driver, so that all
    * completed transactions of previous refresh driver will be ignored.
    */
-  virtual void ResetInitialTransactionId(uint64_t aTransactionId) = 0;
+  virtual void ResetInitialTransactionId(TransactionId aTransactionId) = 0;
 
   /**
    * Get the start time of the current refresh tick.
    */
   virtual mozilla::TimeStamp GetTransactionStart() = 0;
 };
 
 } // namespace layers
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -88,17 +88,17 @@ ClientLayerManager::MemoryPressureObserv
   }
 }
 
 NS_IMPL_ISUPPORTS(ClientLayerManager::MemoryPressureObserver, nsIObserver)
 
 ClientLayerManager::ClientLayerManager(nsIWidget* aWidget)
   : mPhase(PHASE_NONE)
   , mWidget(aWidget)
-  , mLatestTransactionId(0)
+  , mLatestTransactionId{0}
   , mLastPaintTime(TimeDuration::Forever())
   , mTargetRotation(ROTATION_0)
   , mRepeatTransaction(false)
   , mIsRepeatTransaction(false)
   , mTransactionIncomplete(false)
   , mCompositorMightResample(false)
   , mNeedsComposite(false)
   , mQueuedAsyncPaints(false)
@@ -134,17 +134,17 @@ ClientLayerManager::Destroy()
   ClearCachedResources();
   LayerManager::Destroy();
 
   if (mTransactionIdAllocator) {
     // Make sure to notify the refresh driver just in case it's waiting on a
     // pending transaction. Do this at the top of the event loop so we don't
     // cause a paint to occur during compositor shutdown.
     RefPtr<TransactionIdAllocator> allocator = mTransactionIdAllocator;
-    uint64_t id = mLatestTransactionId;
+    TransactionId id = mLatestTransactionId;
 
     RefPtr<Runnable> task = NS_NewRunnableFunction(
       "TransactionIdAllocator::NotifyTransactionCompleted",
       [allocator, id] () -> void {
       allocator->NotifyTransactionCompleted(id);
     });
     NS_DispatchToMainThread(task.forget());
   }
@@ -500,31 +500,31 @@ ClientLayerManager::FlushAsyncPaints()
 
 void
 ClientLayerManager::ScheduleComposite()
 {
   mForwarder->ScheduleComposite();
 }
 
 void
-ClientLayerManager::DidComposite(uint64_t aTransactionId,
+ClientLayerManager::DidComposite(TransactionId aTransactionId,
                                  const TimeStamp& aCompositeStart,
                                  const TimeStamp& aCompositeEnd)
 {
   MOZ_ASSERT(mWidget);
 
   // Notifying the observers may tick the refresh driver which can cause
   // a lot of different things to happen that may affect the lifetime of
   // this layer manager. So let's make sure this object stays alive until
   // the end of the method invocation.
   RefPtr<ClientLayerManager> selfRef = this;
 
   // |aTransactionId| will be > 0 if the compositor is acknowledging a shadow
   // layers transaction.
-  if (aTransactionId) {
+  if (aTransactionId.IsValid()) {
     nsIWidgetListener *listener = mWidget->GetWidgetListener();
     if (listener) {
       listener->DidCompositeWindow(aTransactionId, aCompositeStart, aCompositeEnd);
     }
     listener = mWidget->GetAttachedWidgetListener();
     if (listener) {
       listener->DidCompositeWindow(aTransactionId, aCompositeStart, aCompositeEnd);
     }
--- a/gfx/layers/client/ClientLayerManager.h
+++ b/gfx/layers/client/ClientLayerManager.h
@@ -187,17 +187,17 @@ public:
   {
     mNeedsComposite = aNeedsComposite;
   }
   virtual bool NeedsComposite() const override { return mNeedsComposite; }
 
   virtual void ScheduleComposite() override;
   virtual void GetFrameUniformity(FrameUniformityData* aFrameUniformityData) override;
 
-  virtual void DidComposite(uint64_t aTransactionId,
+  virtual void DidComposite(TransactionId aTransactionId,
                             const mozilla::TimeStamp& aCompositeStart,
                             const mozilla::TimeStamp& aCompositeEnd) override;
 
   virtual bool AreComponentAlphaLayersEnabled() override;
 
   // Log APZ test data for the current paint. We supply the paint sequence
   // number ourselves, and take care of calling APZTestData::StartNewPaint()
   // when a new paint is started.
@@ -232,17 +232,17 @@ public:
     return mApzTestData;
   }
 
   // Get a copy of the compositor-side APZ test data for our layers ID.
   void GetCompositorSideAPZTestData(APZTestData* aData) const;
 
   virtual void SetTransactionIdAllocator(TransactionIdAllocator* aAllocator) override;
 
-  virtual uint64_t GetLastTransactionId() override { return mLatestTransactionId; }
+  virtual TransactionId GetLastTransactionId() override { return mLatestTransactionId; }
 
   float RequestProperty(const nsAString& aProperty) override;
 
   bool AsyncPanZoomEnabled() const override;
 
   virtual void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch) override;
 
   virtual void AddDidCompositeObserver(DidCompositeObserver* aObserver) override;
@@ -327,17 +327,17 @@ private:
   // mShadowTarget, and then perform the transaction using
   // mDummyTarget as the render target.  After the transaction ends,
   // we send a message to our remote side to capture the actual pixels
   // being drawn to the default target, and then copy those pixels
   // back to mShadowTarget.
   RefPtr<gfxContext> mShadowTarget;
 
   RefPtr<TransactionIdAllocator> mTransactionIdAllocator;
-  uint64_t mLatestTransactionId;
+  TransactionId mLatestTransactionId;
   TimeDuration mLastPaintTime;
 
   // Sometimes we draw to targets that don't natively support
   // landscape/portrait orientation.  When we need to implement that
   // ourselves, |mTargetRotation| describes the induced transform we
   // need to apply when compositing content to our target.
   ScreenRotation mTargetRotation;
 
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -523,17 +523,17 @@ CompositorBridgeChild::RecvHideAllPlugin
   }
   SendRemotePluginsReady();
   return IPC_OK();
 #endif // !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
 }
 
 mozilla::ipc::IPCResult
 CompositorBridgeChild::RecvDidComposite(const LayersId& aId,
-                                        const uint64_t& aTransactionId,
+                                        const TransactionId& aTransactionId,
                                         const TimeStamp& aCompositeStart,
                                         const TimeStamp& aCompositeEnd)
 {
   // Hold a reference to keep texture pools alive.  See bug 1387799
   AutoTArray<RefPtr<TextureClientPool>,2> texturePools = mTexturePools;
 
   if (mLayerManager) {
     MOZ_ASSERT(!aId.IsValid());
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -80,17 +80,18 @@ public:
 
   static bool ChildProcessHasCompositorBridge();
 
   // Returns whether the compositor is in the GPU process (false if in the UI
   // process). This may only be called on the main thread.
   static bool CompositorIsInGPUProcess();
 
   virtual mozilla::ipc::IPCResult
-  RecvDidComposite(const LayersId& aId, const uint64_t& aTransactionId,
+  RecvDidComposite(const LayersId& aId,
+                   const TransactionId& aTransactionId,
                    const TimeStamp& aCompositeStart,
                    const TimeStamp& aCompositeEnd) override;
 
   virtual mozilla::ipc::IPCResult
   RecvInvalidateLayers(const LayersId& aLayersId) override;
 
   virtual mozilla::ipc::IPCResult
   RecvUpdatePluginConfigurations(const LayoutDeviceIntPoint& aContentOffset,
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -324,17 +324,17 @@ CompositorBridgeParent::CompositorBridge
                                                const TimeDuration& aVsyncRate,
                                                const CompositorOptions& aOptions,
                                                bool aUseExternalSurfaceSize,
                                                const gfx::IntSize& aSurfaceSize)
   : CompositorBridgeParentBase(aManager)
   , mWidget(nullptr)
   , mScale(aScale)
   , mVsyncRate(aVsyncRate)
-  , mPendingTransaction(0)
+  , mPendingTransaction{0}
   , mPaused(false)
   , mUseExternalSurfaceSize(aUseExternalSurfaceSize)
   , mEGLSurfaceSize(aSurfaceSize)
   , mOptions(aOptions)
   , mPauseCompositionMonitor("PauseCompositionMonitor")
   , mResumeCompositionMonitor("ResumeCompositionMonitor")
   , mRootLayerTreeID{0}
   , mOverrideComposeReadiness(false)
@@ -1260,17 +1260,17 @@ CompositorBridgeParent::ShadowLayersUpda
         mRootLayerTreeID, root, aInfo.isFirstPaint(),
         mRootLayerTreeID, aInfo.paintSequenceNumber());
     }
   }
 
   // The transaction ID might get reset to 1 if the page gets reloaded, see
   // https://bugzilla.mozilla.org/show_bug.cgi?id=1145295#c41
   // Otherwise, it should be continually increasing.
-  MOZ_ASSERT(aInfo.id() == 1 || aInfo.id() > mPendingTransaction);
+  MOZ_ASSERT(aInfo.id() == TransactionId{1} || aInfo.id() > mPendingTransaction);
   mPendingTransaction = aInfo.id();
   mTxnStartTime = aInfo.transactionStart();
   mFwdTime = aInfo.fwdTime();
 
   if (root) {
     SetShadowProperties(root);
   }
   if (aInfo.scheduleComposite()) {
@@ -2040,30 +2040,30 @@ void
 CompositorBridgeParent::DidComposite(TimeStamp& aCompositeStart,
                                      TimeStamp& aCompositeEnd)
 {
   if (mWrBridge) {
     NotifyDidComposite(mWrBridge->FlushPendingTransactionIds(), aCompositeStart, aCompositeEnd);
   } else {
     NotifyDidComposite(mPendingTransaction, aCompositeStart, aCompositeEnd);
 #if defined(ENABLE_FRAME_LATENCY_LOG)
-    if (mPendingTransaction) {
+    if (mPendingTransaction.IsValid()) {
       if (mTxnStartTime) {
         uint32_t latencyMs = round((aCompositeEnd - mTxnStartTime).ToMilliseconds());
         printf_stderr("From transaction start to end of generate frame latencyMs %d this %p\n", latencyMs, this);
       }
       if (mFwdTime) {
         uint32_t latencyMs = round((aCompositeEnd - mFwdTime).ToMilliseconds());
         printf_stderr("From forwarding transaction to end of generate frame latencyMs %d this %p\n", latencyMs, this);
       }
     }
     mTxnStartTime = TimeStamp();
     mFwdTime = TimeStamp();
 #endif
-    mPendingTransaction = 0;
+    mPendingTransaction = TransactionId{0};
   }
 }
 
 void
 CompositorBridgeParent::NotifyPipelineRemoved(const wr::PipelineId& aPipelineId)
 {
   if (mAsyncImageManager) {
     mAsyncImageManager->PipelineRemoved(aPipelineId);
@@ -2078,41 +2078,41 @@ CompositorBridgeParent::NotifyDidComposi
   }
   mAsyncImageManager->PipelineRendered(aPipelineId, aEpoch);
 
   if (mPaused) {
     return;
   }
 
   if (mWrBridge->PipelineId() == aPipelineId) {
-    uint64_t transactionId = mWrBridge->FlushTransactionIdsForEpoch(aEpoch, aCompositeEnd);
+    TransactionId transactionId = mWrBridge->FlushTransactionIdsForEpoch(aEpoch, aCompositeEnd);
     Unused << SendDidComposite(LayersId{0}, transactionId, aCompositeStart, aCompositeEnd);
 
     nsTArray<ImageCompositeNotificationInfo> notifications;
     mWrBridge->ExtractImageCompositeNotifications(&notifications);
     if (!notifications.IsEmpty()) {
       Unused << ImageBridgeParent::NotifyImageComposites(notifications);
     }
     return;
   }
 
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   ForEachIndirectLayerTree([&] (LayerTreeState* lts, const LayersId& aLayersId) -> void {
     if (lts->mCrossProcessParent &&
         lts->mWrBridge &&
         lts->mWrBridge->PipelineId() == aPipelineId) {
       CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
-      uint64_t transactionId = lts->mWrBridge->FlushTransactionIdsForEpoch(aEpoch, aCompositeEnd);
+      TransactionId transactionId = lts->mWrBridge->FlushTransactionIdsForEpoch(aEpoch, aCompositeEnd);
       Unused << cpcp->SendDidComposite(aLayersId, transactionId, aCompositeStart, aCompositeEnd);
     }
   });
 }
 
 void
-CompositorBridgeParent::NotifyDidComposite(uint64_t aTransactionId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd)
+CompositorBridgeParent::NotifyDidComposite(TransactionId aTransactionId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd)
 {
   Unused << SendDidComposite(LayersId{0}, aTransactionId, aCompositeStart, aCompositeEnd);
 
   if (mLayerManager) {
     nsTArray<ImageCompositeNotificationInfo> notifications;
     mLayerManager->ExtractImageCompositeNotifications(&notifications);
     if (!notifications.IsEmpty()) {
       Unused << ImageBridgeParent::NotifyImageComposites(notifications);
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -581,34 +581,34 @@ protected:
   void DidComposite(TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
 
   void NotifyDidCompositeToPipeline(const wr::PipelineId& aPipelineId,
                                     const wr::Epoch& aEpoch,
                                     TimeStamp& aCompositeStart,
                                     TimeStamp& aCompositeEnd) override;
   void NotifyPipelineRemoved(const wr::PipelineId& aPipelineId) override;
 
-  void NotifyDidComposite(uint64_t aTransactionId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
+  void NotifyDidComposite(TransactionId aTransactionId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
 
   // The indirect layer tree lock must be held before calling this function.
   // Callback should take (LayerTreeState* aState, const LayersId& aLayersId)
   template <typename Lambda>
   inline void ForEachIndirectLayerTree(const Lambda& aCallback);
 
   RefPtr<HostLayerManager> mLayerManager;
   RefPtr<Compositor> mCompositor;
   RefPtr<AsyncCompositionManager> mCompositionManager;
   RefPtr<AsyncImagePipelineManager> mAsyncImageManager;
   RefPtr<WebRenderBridgeParent> mWrBridge;
   widget::CompositorWidget* mWidget;
   Maybe<TimeStamp> mTestTime;
   CSSToLayoutDeviceScale mScale;
   TimeDuration mVsyncRate;
 
-  uint64_t mPendingTransaction;
+  TransactionId mPendingTransaction;
   TimeStamp mTxnStartTime;
   TimeStamp mFwdTime;
 
   bool mPaused;
 
   bool mUseExternalSurfaceSize;
   gfx::IntSize mEGLSurfaceSize;
 
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
@@ -381,23 +381,23 @@ CrossProcessCompositorBridgeParent::DidC
 void
 CrossProcessCompositorBridgeParent::DidCompositeLocked(
   LayersId aId,
   TimeStamp& aCompositeStart,
   TimeStamp& aCompositeEnd)
 {
   sIndirectLayerTreesLock->AssertCurrentThreadOwns();
   if (LayerTransactionParent *layerTree = sIndirectLayerTrees[aId].mLayerTree) {
-    uint64_t transactionId = layerTree->FlushTransactionId(aCompositeEnd);
-    if (transactionId) {
+    TransactionId transactionId = layerTree->FlushTransactionId(aCompositeEnd);
+    if (transactionId.IsValid()) {
       Unused << SendDidComposite(aId, transactionId, aCompositeStart, aCompositeEnd);
     }
   } else if (WebRenderBridgeParent* wrbridge = sIndirectLayerTrees[aId].mWrBridge) {
-    uint64_t transactionId = wrbridge->FlushPendingTransactionIds();
-    if (transactionId) {
+    TransactionId transactionId = wrbridge->FlushPendingTransactionIds();
+    if (transactionId.IsValid()) {
       Unused << SendDidComposite(aId, transactionId, aCompositeStart, aCompositeEnd);
     }
   }
 }
 
 void
 CrossProcessCompositorBridgeParent::ScheduleComposite(LayerTransactionParent* aLayerTree)
 {
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -50,17 +50,17 @@ LayerTransactionParent::LayerTransaction
                                                CompositorAnimationStorage* aAnimStorage,
                                                LayersId aId)
   : mLayerManager(aManager)
   , mCompositorBridge(aBridge)
   , mAnimStorage(aAnimStorage)
   , mId(aId)
   , mChildEpoch(0)
   , mParentEpoch(0)
-  , mPendingTransaction(0)
+  , mPendingTransaction{0}
   , mDestroyed(false)
   , mIPCOpen(false)
 {
   MOZ_ASSERT(mId.IsValid());
 }
 
 LayerTransactionParent::~LayerTransactionParent()
 {
@@ -144,17 +144,17 @@ public:
     }
   }
 private:
   LayerTransactionParent* mLayerTransaction;
   const InfallibleTArray<OpDestroy>* mActorsToDestroy;
 };
 
 mozilla::ipc::IPCResult
-LayerTransactionParent::RecvPaintTime(const uint64_t& aTransactionId,
+LayerTransactionParent::RecvPaintTime(const TransactionId& aTransactionId,
                                       const TimeDuration& aPaintTime)
 {
   mCompositorBridge->UpdatePaintTime(this, aPaintTime);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
@@ -886,35 +886,35 @@ LayerTransactionParent::DeallocShmem(ipc
   PLayerTransactionParent::DeallocShmem(aShmem);
 }
 
 bool LayerTransactionParent::IsSameProcess() const
 {
   return OtherPid() == base::GetCurrentProcId();
 }
 
-uint64_t
+TransactionId
 LayerTransactionParent::FlushTransactionId(TimeStamp& aCompositeEnd)
 {
 #if defined(ENABLE_FRAME_LATENCY_LOG)
-  if (mPendingTransaction) {
+  if (mPendingTransaction.IsValid()) {
     if (mTxnStartTime) {
       uint32_t latencyMs = round((aCompositeEnd - mTxnStartTime).ToMilliseconds());
       printf_stderr("From transaction start to end of generate frame latencyMs %d this %p\n", latencyMs, this);
     }
     if (mFwdTime) {
       uint32_t latencyMs = round((aCompositeEnd - mFwdTime).ToMilliseconds());
       printf_stderr("From forwarding transaction to end of generate frame latencyMs %d this %p\n", latencyMs, this);
     }
   }
   mTxnStartTime = TimeStamp();
   mFwdTime = TimeStamp();
 #endif
-  uint64_t id = mPendingTransaction;
-  mPendingTransaction = 0;
+  TransactionId id = mPendingTransaction;
+  mPendingTransaction = TransactionId{0};
   return id;
 }
 
 void
 LayerTransactionParent::SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage)
 {
   MOZ_ASSERT_UNREACHABLE("unexpected to be called");
 }
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -73,24 +73,24 @@ public:
   bool AllocUnsafeShmem(size_t aSize,
                         ipc::SharedMemory::SharedMemoryType aType,
                         ipc::Shmem* aShmem) override;
 
   void DeallocShmem(ipc::Shmem& aShmem) override;
 
   bool IsSameProcess() const override;
 
-  const uint64_t& GetPendingTransactionId() { return mPendingTransaction; }
-  void SetPendingTransactionId(uint64_t aId, const TimeStamp& aTxnStartTime, const TimeStamp& aFwdTime)
+  const TransactionId& GetPendingTransactionId() { return mPendingTransaction; }
+  void SetPendingTransactionId(TransactionId aId, const TimeStamp& aTxnStartTime, const TimeStamp& aFwdTime)
   {
     mPendingTransaction = aId;
     mTxnStartTime = aTxnStartTime;
     mFwdTime = aFwdTime;
   }
-  uint64_t FlushTransactionId(TimeStamp& aCompositeEnd);
+  TransactionId FlushTransactionId(TimeStamp& aCompositeEnd);
 
   // CompositableParentManager
   void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
 
   void SendPendingAsyncMessages() override;
 
   void SetAboutToSendAsyncMessages() override;
 
@@ -100,17 +100,17 @@ public:
   {
     return OtherPid();
   }
 
 protected:
   mozilla::ipc::IPCResult RecvShutdown() override;
   mozilla::ipc::IPCResult RecvShutdownSync() override;
 
-  mozilla::ipc::IPCResult RecvPaintTime(const uint64_t& aTransactionId,
+  mozilla::ipc::IPCResult RecvPaintTime(const TransactionId& aTransactionId,
                                         const TimeDuration& aPaintTime) override;
 
   mozilla::ipc::IPCResult RecvUpdate(const TransactionInfo& aInfo) override;
 
   mozilla::ipc::IPCResult RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch) override;
   mozilla::ipc::IPCResult RecvNewCompositable(const CompositableHandle& aHandle,
                                               const TextureInfo& aInfo) override;
   mozilla::ipc::IPCResult RecvReleaseLayer(const LayerHandle& aHandle) override;
@@ -189,17 +189,17 @@ private:
 
   // These fields keep track of the latest epoch values in the child and the
   // parent. mChildEpoch is the latest epoch value received from the child.
   // mParentEpoch is the latest epoch value that we have told TabParent about
   // (via ObserveLayerUpdate).
   uint64_t mChildEpoch;
   uint64_t mParentEpoch;
 
-  uint64_t mPendingTransaction;
+  TransactionId mPendingTransaction;
   TimeStamp mTxnStartTime;
   TimeStamp mFwdTime;
 
   // When the widget/frame/browser stuff in this process begins its
   // destruction process, we need to Disconnect() all the currently
   // live shadow layers, because some of them might be orphaned from
   // the layer tree.  This happens in Destroy() above.  After we
   // Destroy() ourself, there's a window in which that information
--- a/gfx/layers/ipc/LayersMessageUtils.h
+++ b/gfx/layers/ipc/LayersMessageUtils.h
@@ -34,16 +34,21 @@
 namespace IPC {
 
 template <>
 struct ParamTraits<mozilla::layers::LayersId>
   : public PlainOldDataSerializer<mozilla::layers::LayersId>
 {};
 
 template <>
+struct ParamTraits<mozilla::layers::TransactionId>
+  : public PlainOldDataSerializer<mozilla::layers::TransactionId>
+{};
+
+template <>
 struct ParamTraits<mozilla::layers::LayersBackend>
   : public ContiguousEnumSerializer<
              mozilla::layers::LayersBackend,
              mozilla::layers::LayersBackend::LAYERS_NONE,
              mozilla::layers::LayersBackend::LAYERS_LAST>
 {};
 
 template <>
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -50,16 +50,17 @@ using mozilla::layers::BorderColors from
 using mozilla::layers::BorderCorners from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::BorderWidths from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::LayerHandle from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::SimpleLayerAttributes from "mozilla/layers/LayerAttributes.h";
 using mozilla::CrossProcessSemaphoreHandle from "mozilla/ipc/CrossProcessSemaphore.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
+using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
 
 namespace mozilla {
 namespace layers {
 
 struct TargetConfig {
   IntRect naturalBounds;
   ScreenRotation rotation;
   ScreenOrientationInternal orientation;
@@ -558,17 +559,17 @@ struct PaintTiming {
 struct TransactionInfo
 {
   Edit[] cset;
   OpSetSimpleLayerAttributes[] setSimpleAttrs;
   OpSetLayerAttributes[] setAttrs;
   CompositableOperation[] paints;
   OpDestroy[] toDestroy;
   uint64_t fwdTransactionId;
-  uint64_t id;
+  TransactionId id;
   TargetConfig targetConfig;
   PluginWindowData[] plugins;
   bool isFirstPaint;
   FocusTarget focusTarget;
   bool scheduleComposite;
   uint32_t paintSequenceNumber;
   bool isRepeatTransaction;
   TimeStamp transactionStart;
--- a/gfx/layers/ipc/PCompositorBridge.ipdl
+++ b/gfx/layers/ipc/PCompositorBridge.ipdl
@@ -38,16 +38,17 @@ using class mozilla::TimeStamp from "moz
 using class mozilla::layers::FrameUniformityData from "mozilla/layers/FrameUniformityData.h";
 using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h";
 using mozilla::layers::CompositorOptions from "mozilla/layers/CompositorOptions.h";
 using mozilla::wr::PipelineId from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::IdNamespace from "mozilla/webrender/WebRenderTypes.h";
 using base::ProcessId from "base/process.h";
 using mozilla::wr::MaybeExternalImageId from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::WebRenderError from "mozilla/webrender/WebRenderTypes.h";
+using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
 
 namespace mozilla {
 namespace layers {
 
 
 /**
  * The PCompositorBridge protocol is a top-level protocol for the compositor.
  * There is an instance of the protocol for each compositor, plus one for each
@@ -91,17 +92,17 @@ child:
   // TextureSources are recreated.
   async InvalidateLayers(LayersId layersId);
 
   // The compositor completed a layers transaction. id is the layers id
   // of the child layer tree that was composited (or 0 when notifying
   // the root layer tree).
   // transactionId is the id of the transaction before this composite, or 0
   // if there was no transaction since the last composite.
-  async DidComposite(LayersId id, uint64_t transactionId,
+  async DidComposite(LayersId id, TransactionId transactionId,
                      TimeStamp compositeStart, TimeStamp compositeEnd);
 
   /**
    * Parent informs the child that the graphics objects are ready for
    * compositing.  This usually means that the graphics objects (textures
    * and the like) are available on the GPU.  This is used for chrome UI.
    * @see RequestNotifyAfterRemotePaint
    * @see PBrowser
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -18,16 +18,17 @@ using struct mozilla::layers::TextureInf
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using class mozilla::layers::APZTestData from "mozilla/layers/APZTestData.h";
 using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
 using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
 using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
 using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::LayerHandle from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
+using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
 
 /**
  * The layers protocol is spoken between thread contexts that manage
  * layer (sub)trees.  The protocol comprises atomically publishing
  * layer subtrees to a "shadow" thread context (which grafts the
  * subtree into its own tree), and atomically updating a published
  * subtree.  ("Atomic" in this sense is wrt painting.)
  */
@@ -46,17 +47,17 @@ namespace layers {
 sync protocol PLayerTransaction {
   manager PCompositorBridge;
 
 parent:
   // The isFirstPaint flag can be used to indicate that this is the first update
   // for a particular document.
   async Update(TransactionInfo txn);
 
-  async PaintTime(uint64_t id, TimeDuration paintTime);
+  async PaintTime(TransactionId id, TimeDuration paintTime);
 
   async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
 
   // Create a new Compositable.
   async NewCompositable(CompositableHandle handle, TextureInfo info);
 
   // Release an object that is no longer in use.
   async ReleaseLayer(LayerHandle layer);
--- a/gfx/layers/ipc/PWebRenderBridge.ipdl
+++ b/gfx/layers/ipc/PWebRenderBridge.ipdl
@@ -17,37 +17,38 @@ include protocol PTexture;
 using mozilla::layers::APZTestData from "mozilla/layers/APZTestData.h";
 using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
 using mozilla::wr::BuiltDisplayListDescriptor from "mozilla/webrender/webrender_ffi.h";
 using mozilla::wr::IdNamespace from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::layers::WebRenderScrollData from "mozilla/layers/WebRenderScrollData.h";
 using mozilla::layers::FocusTarget from "mozilla/layers/FocusTarget.h";
+using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
 
 namespace mozilla {
 namespace layers {
 
 sync protocol PWebRenderBridge
 {
   manager PCompositorBridge;
 
 parent:
   async NewCompositable(CompositableHandle handle, TextureInfo info);
   async ReleaseCompositable(CompositableHandle compositable);
 
   sync Create(IntSize aSize);
   async DeleteCompositorAnimations(uint64_t[] aIds);
-  async SetDisplayList(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
+  async SetDisplayList(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, TransactionId transactionId,
                        LayoutSize aContentSize, ByteBuf aDL, BuiltDisplayListDescriptor aDLDesc,
                        WebRenderScrollData aScrollData,
                        OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems,
                        IdNamespace aIdNamespace, TimeStamp txnStartTime, TimeStamp fwdTime);
   async EmptyTransaction(FocusTarget focusTarget,
-                         WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
+                         WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, TransactionId transactionId,
                          IdNamespace aIdNamespace, TimeStamp txnStartTime, TimeStamp fwdTime);
   async SetFocusTarget(FocusTarget focusTarget);
   async UpdateResources(OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems);
   async ParentCommands(WebRenderParentCommand[] commands);
   sync GetSnapshot(PTexture texture);
   async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
   async ClearCachedResources();
   // Schedule a composite if one isn't already scheduled.
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -585,27 +585,27 @@ ShadowLayerForwarder::StorePluginWidgetC
     mPluginWindowData.AppendElement(PluginWindowData(configuration.mWindowID,
                                                      configuration.mClipRegion,
                                                      configuration.mBounds,
                                                      configuration.mVisible));
   }
 }
 
 void
-ShadowLayerForwarder::SendPaintTime(uint64_t aId, TimeDuration aPaintTime)
+ShadowLayerForwarder::SendPaintTime(TransactionId aId, TimeDuration aPaintTime)
 {
   if (!IPCOpen() ||
       !mShadowManager->SendPaintTime(aId, aPaintTime)) {
     NS_WARNING("Could not send paint times over IPC");
   }
 }
 
 bool
 ShadowLayerForwarder::EndTransaction(const nsIntRegion& aRegionToClear,
-                                     uint64_t aId,
+                                     TransactionId aId,
                                      bool aScheduleComposite,
                                      uint32_t aPaintSequenceNumber,
                                      bool aIsRepeatTransaction,
                                      const mozilla::TimeStamp& aTransactionStart,
                                      bool* aSent)
 {
   *aSent = false;
 
@@ -618,17 +618,17 @@ ShadowLayerForwarder::EndTransaction(con
 
   Maybe<TimeStamp> startTime;
   if (gfxPrefs::LayersDrawFPS()) {
     startTime = Some(TimeStamp::Now());
   }
 
   GetCompositorBridgeChild()->WillEndTransaction();
 
-  MOZ_ASSERT(aId);
+  MOZ_ASSERT(aId.IsValid());
 
   AUTO_PROFILER_LABEL("ShadowLayerForwarder::EndTransaction", GRAPHICS);
 
   RenderTraceScope rendertrace("Foward Transaction", "000091");
   MOZ_ASSERT(!mTxn->Finished(), "forgot BeginTransaction?");
 
   DiagnosticTypes diagnostics = gfxPlatform::GetPlatform()->GetLayerDiagnosticTypes();
   if (mDiagnosticTypes != diagnostics) {
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -241,25 +241,25 @@ public:
                            const nsTArray<TimedTextureClient>& aTextures) override;
   virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
                                          TextureClient* aClientOnBlack,
                                          TextureClient* aClientOnWhite) override;
 
   /**
    * Used for debugging to tell the compositor how long this frame took to paint.
    */
-  void SendPaintTime(uint64_t aId, TimeDuration aPaintTime);
+  void SendPaintTime(TransactionId aId, TimeDuration aPaintTime);
 
   /**
    * End the current transaction and forward it to LayerManagerComposite.
    * |aReplies| are directions from the LayerManagerComposite to the
    * caller of EndTransaction().
    */
   bool EndTransaction(const nsIntRegion& aRegionToClear,
-                      uint64_t aId,
+                      TransactionId aId,
                       bool aScheduleComposite,
                       uint32_t aPaintSequenceNumber,
                       bool aIsRepeatTransaction,
                       const mozilla::TimeStamp& aTransactionStart,
                       bool* aSent);
 
   /**
    * Set an actor through which layer updates will be pushed.
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -122,17 +122,17 @@ WebRenderBridgeChild::UpdateResources(wr
   this->SendUpdateResources(resourceUpdates, Move(smallShmems), largeShmems);
 }
 
 void
 WebRenderBridgeChild::EndTransaction(const wr::LayoutSize& aContentSize,
                                      wr::BuiltDisplayList& aDL,
                                      wr::IpcResourceUpdateQueue& aResources,
                                      const gfx::IntSize& aSize,
-                                     uint64_t aTransactionId,
+                                     TransactionId aTransactionId,
                                      const WebRenderScrollData& aScrollData,
                                      const mozilla::TimeStamp& aTxnStartTime)
 {
   MOZ_ASSERT(!mDestroyed);
   MOZ_ASSERT(mIsInTransaction);
 
   ByteBuf dlData(aDL.dl.inner.data, aDL.dl.inner.length, aDL.dl.inner.capacity);
   aDL.dl.inner.capacity = 0;
@@ -156,17 +156,17 @@ WebRenderBridgeChild::EndTransaction(con
 
   mParentCommands.Clear();
   mDestroyedActors.Clear();
   mIsInTransaction = false;
 }
 
 void
 WebRenderBridgeChild::EndEmptyTransaction(const FocusTarget& aFocusTarget,
-                                          uint64_t aTransactionId,
+                                          TransactionId aTransactionId,
                                           const mozilla::TimeStamp& aTxnStartTime)
 {
   MOZ_ASSERT(!mDestroyed);
   MOZ_ASSERT(mIsInTransaction);
 
   TimeStamp fwdTime;
 #if defined(ENABLE_FRAME_LATENCY_LOG)
   fwdTime = TimeStamp::Now();
--- a/gfx/layers/wr/WebRenderBridgeChild.h
+++ b/gfx/layers/wr/WebRenderBridgeChild.h
@@ -68,21 +68,21 @@ public:
   void AddWebRenderParentCommands(const nsTArray<WebRenderParentCommand>& aCommands);
 
   void UpdateResources(wr::IpcResourceUpdateQueue& aResources);
   void BeginTransaction();
   void EndTransaction(const wr::LayoutSize& aContentSize,
                       wr::BuiltDisplayList& dl,
                       wr::IpcResourceUpdateQueue& aResources,
                       const gfx::IntSize& aSize,
-                      uint64_t aTransactionId,
+                      TransactionId aTransactionId,
                       const WebRenderScrollData& aScrollData,
                       const mozilla::TimeStamp& aTxnStartTime);
   void EndEmptyTransaction(const FocusTarget& aFocusTarget,
-                           uint64_t aTransactionId,
+                           TransactionId aTransactionId,
                            const mozilla::TimeStamp& aTxnStartTime);
   void ProcessWebRenderParentCommands();
 
   CompositorBridgeChild* GetCompositorBridgeChild();
 
   wr::PipelineId GetPipeline() { return mPipelineId; }
 
   // KnowsCompositor
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -552,17 +552,17 @@ WebRenderBridgeParent::SetAPZSampleTime(
   }
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
                                           InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                           InfallibleTArray<OpDestroy>&& aToDestroy,
                                           const uint64_t& aFwdTransactionId,
-                                          const uint64_t& aTransactionId,
+                                          const TransactionId& aTransactionId,
                                           const wr::LayoutSize& aContentSize,
                                           ipc::ByteBuf&& dl,
                                           const wr::BuiltDisplayListDescriptor& dlDesc,
                                           const WebRenderScrollData& aScrollData,
                                           nsTArray<OpUpdateResource>&& aResourceUpdates,
                                           nsTArray<RefCountedShmem>&& aSmallShmems,
                                           nsTArray<ipc::Shmem>&& aLargeShmems,
                                           const wr::IdNamespace& aIdNamespace,
@@ -644,17 +644,17 @@ WebRenderBridgeParent::RecvSetDisplayLis
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvEmptyTransaction(const FocusTarget& aFocusTarget,
                                             InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                             InfallibleTArray<OpDestroy>&& aToDestroy,
                                             const uint64_t& aFwdTransactionId,
-                                            const uint64_t& aTransactionId,
+                                            const TransactionId& aTransactionId,
                                             const wr::IdNamespace& aIdNamespace,
                                             const TimeStamp& aTxnStartTime,
                                             const TimeStamp& aFwdTime)
 {
   if (mDestroyed) {
     for (const auto& op : aToDestroy) {
       DestroyActor(op);
     }
@@ -1270,49 +1270,49 @@ WebRenderBridgeParent::CompositeToTarget
 
   txn.GenerateFrame();
 
   mApi->SendTransaction(txn);
 }
 
 void
 WebRenderBridgeParent::HoldPendingTransactionId(const wr::Epoch& aWrEpoch,
-                                                uint64_t aTransactionId,
+                                                TransactionId aTransactionId,
                                                 const TimeStamp& aTxnStartTime,
                                                 const TimeStamp& aFwdTime)
 {
   MOZ_ASSERT(aTransactionId > LastPendingTransactionId());
   mPendingTransactionIds.push(PendingTransactionId(aWrEpoch, aTransactionId, aTxnStartTime, aFwdTime));
 }
 
-uint64_t
+TransactionId
 WebRenderBridgeParent::LastPendingTransactionId()
 {
-  uint64_t id = 0;
+  TransactionId id{0};
   if (!mPendingTransactionIds.empty()) {
     id = mPendingTransactionIds.back().mId;
   }
   return id;
 }
 
-uint64_t
+TransactionId
 WebRenderBridgeParent::FlushPendingTransactionIds()
 {
-  uint64_t id = 0;
+  TransactionId id{0};
   if (!mPendingTransactionIds.empty()) {
     id = mPendingTransactionIds.back().mId;
     std::queue<PendingTransactionId>().swap(mPendingTransactionIds); // clear queue
   }
   return id;
 }
 
-uint64_t
+TransactionId
 WebRenderBridgeParent::FlushTransactionIdsForEpoch(const wr::Epoch& aEpoch, const TimeStamp& aEndTime)
 {
-  uint64_t id = 0;
+  TransactionId id{0};
   while (!mPendingTransactionIds.empty()) {
     if (aEpoch.mHandle < mPendingTransactionIds.front().mEpoch.mHandle) {
       break;
     }
 #if defined(ENABLE_FRAME_LATENCY_LOG)
     if (mPendingTransactionIds.front().mTxnStartTime) {
       uint32_t latencyMs = round((aEndTime - mPendingTransactionIds.front().mTxnStartTime).ToMilliseconds());
       printf_stderr("From transaction start to end of generate frame latencyMs %d this %p\n", latencyMs, this);
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -73,32 +73,32 @@ public:
   mozilla::ipc::IPCResult RecvDeleteCompositorAnimations(InfallibleTArray<uint64_t>&& aIds) override;
   mozilla::ipc::IPCResult RecvUpdateResources(nsTArray<OpUpdateResource>&& aUpdates,
                                               nsTArray<RefCountedShmem>&& aSmallShmems,
                                               nsTArray<ipc::Shmem>&& aLargeShmems) override;
   mozilla::ipc::IPCResult RecvSetDisplayList(const gfx::IntSize& aSize,
                                              InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                              InfallibleTArray<OpDestroy>&& aToDestroy,
                                              const uint64_t& aFwdTransactionId,
-                                             const uint64_t& aTransactionId,
+                                             const TransactionId& aTransactionId,
                                              const wr::LayoutSize& aContentSize,
                                              ipc::ByteBuf&& dl,
                                              const wr::BuiltDisplayListDescriptor& dlDesc,
                                              const WebRenderScrollData& aScrollData,
                                              nsTArray<OpUpdateResource>&& aResourceUpdates,
                                              nsTArray<RefCountedShmem>&& aSmallShmems,
                                              nsTArray<ipc::Shmem>&& aLargeShmems,
                                              const wr::IdNamespace& aIdNamespace,
                                              const TimeStamp& aTxnStartTime,
                                              const TimeStamp& aFwdTime) override;
   mozilla::ipc::IPCResult RecvEmptyTransaction(const FocusTarget& aFocusTarget,
                                                InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                                InfallibleTArray<OpDestroy>&& aToDestroy,
                                                const uint64_t& aFwdTransactionId,
-                                               const uint64_t& aTransactionId,
+                                               const TransactionId& aTransactionId,
                                                const wr::IdNamespace& aIdNamespace,
                                                const TimeStamp& aTxnStartTime,
                                                const TimeStamp& aFwdTime) override;
   mozilla::ipc::IPCResult RecvSetFocusTarget(const FocusTarget& aFocusTarget) override;
   mozilla::ipc::IPCResult RecvParentCommands(nsTArray<WebRenderParentCommand>&& commands) override;
   mozilla::ipc::IPCResult RecvGetSnapshot(PTextureParent* aTexture) override;
 
   mozilla::ipc::IPCResult RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch) override;
@@ -141,22 +141,22 @@ public:
   bool IsSameProcess() const override;
   base::ProcessId GetChildProcessId() override;
   void NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId) override;
   void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
   void SendPendingAsyncMessages() override;
   void SetAboutToSendAsyncMessages() override;
 
   void HoldPendingTransactionId(const wr::Epoch& aWrEpoch,
-                                uint64_t aTransactionId,
+                                TransactionId aTransactionId,
                                 const TimeStamp& aTxnStartTime,
                                 const TimeStamp& aFwdTime);
-  uint64_t LastPendingTransactionId();
-  uint64_t FlushPendingTransactionIds();
-  uint64_t FlushTransactionIdsForEpoch(const wr::Epoch& aEpoch, const TimeStamp& aEndTime);
+  TransactionId LastPendingTransactionId();
+  TransactionId FlushPendingTransactionIds();
+  TransactionId FlushTransactionIdsForEpoch(const wr::Epoch& aEpoch, const TimeStamp& aEndTime);
 
   TextureFactoryIdentifier GetTextureFactoryIdentifier();
 
   void ExtractImageCompositeNotifications(nsTArray<ImageCompositeNotificationInfo>* aNotifications);
 
   wr::IdNamespace GetIdNamespace()
   {
     return mIdNamespace;
@@ -222,24 +222,24 @@ private:
 
   // Tell APZ what the subsequent sampling's timestamp should be.
   void SetAPZSampleTime();
 
   wr::Epoch GetNextWrEpoch();
 
 private:
   struct PendingTransactionId {
-    PendingTransactionId(const wr::Epoch& aEpoch, uint64_t aId, const TimeStamp& aTxnStartTime, const TimeStamp& aFwdTime)
+    PendingTransactionId(const wr::Epoch& aEpoch, TransactionId aId, const TimeStamp& aTxnStartTime, const TimeStamp& aFwdTime)
       : mEpoch(aEpoch)
       , mId(aId)
       , mTxnStartTime(aTxnStartTime)
       , mFwdTime(aFwdTime)
     {}
     wr::Epoch mEpoch;
-    uint64_t mId;
+    TransactionId mId;
     TimeStamp mTxnStartTime;
     TimeStamp mFwdTime;
   };
 
   CompositorBridgeParentBase* MOZ_NON_OWNING_REF mCompositorBridge;
   wr::PipelineId mPipelineId;
   RefPtr<widget::CompositorWidget> mWidget;
   RefPtr<wr::WebRenderAPI> mApi;
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -33,17 +33,17 @@
 namespace mozilla {
 
 using namespace gfx;
 
 namespace layers {
 
 WebRenderLayerManager::WebRenderLayerManager(nsIWidget* aWidget)
   : mWidget(aWidget)
-  , mLatestTransactionId(0)
+  , mLatestTransactionId{0}
   , mWindowOverlayChanged(false)
   , mNeedsComposite(false)
   , mIsFirstPaint(false)
   , mTarget(nullptr)
   , mPaintSequenceNumber(0)
   , mWebRenderCommandBuilder(this)
   , mLastDisplayListSize(0)
 {
@@ -122,17 +122,17 @@ WebRenderLayerManager::DoDestroy(bool aI
 
   mWebRenderCommandBuilder.Destroy();
 
   if (mTransactionIdAllocator) {
     // Make sure to notify the refresh driver just in case it's waiting on a
     // pending transaction. Do this at the top of the event loop so we don't
     // cause a paint to occur during compositor shutdown.
     RefPtr<TransactionIdAllocator> allocator = mTransactionIdAllocator;
-    uint64_t id = mLatestTransactionId;
+    TransactionId id = mLatestTransactionId;
 
     RefPtr<Runnable> task = NS_NewRunnableFunction(
       "TransactionIdAllocator::NotifyTransactionCompleted",
       [allocator, id] () -> void {
       allocator->NotifyTransactionCompleted(id);
     });
     NS_DispatchToMainThread(task.forget());
   }
@@ -466,31 +466,31 @@ void
 WebRenderLayerManager::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)
 {
   if (WrBridge()->IPCOpen()) {
     WrBridge()->SendSetLayerObserverEpoch(aLayerObserverEpoch);
   }
 }
 
 void
-WebRenderLayerManager::DidComposite(uint64_t aTransactionId,
+WebRenderLayerManager::DidComposite(TransactionId aTransactionId,
                                     const mozilla::TimeStamp& aCompositeStart,
                                     const mozilla::TimeStamp& aCompositeEnd)
 {
   MOZ_ASSERT(mWidget);
 
   // Notifying the observers may tick the refresh driver which can cause
   // a lot of different things to happen that may affect the lifetime of
   // this layer manager. So let's make sure this object stays alive until
   // the end of the method invocation.
   RefPtr<WebRenderLayerManager> selfRef = this;
 
   // |aTransactionId| will be > 0 if the compositor is acknowledging a shadow
   // layers transaction.
-  if (aTransactionId) {
+  if (aTransactionId.IsValid()) {
     nsIWidgetListener *listener = mWidget->GetWidgetListener();
     if (listener) {
       listener->DidCompositeWindow(aTransactionId, aCompositeStart, aCompositeEnd);
     }
     listener = mWidget->GetAttachedWidgetListener();
     if (listener) {
       listener->DidCompositeWindow(aTransactionId, aCompositeStart, aCompositeEnd);
     }
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -88,17 +88,17 @@ public:
   already_AddRefed<ColorLayer> CreateColorLayer() override { return nullptr; }
   already_AddRefed<BorderLayer> CreateBorderLayer() override { return nullptr; }
   already_AddRefed<CanvasLayer> CreateCanvasLayer() override { return nullptr; }
 
   virtual bool NeedsWidgetInvalidation() override { return false; }
 
   virtual void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch) override;
 
-  virtual void DidComposite(uint64_t aTransactionId,
+  virtual void DidComposite(TransactionId aTransactionId,
                             const mozilla::TimeStamp& aCompositeStart,
                             const mozilla::TimeStamp& aCompositeEnd) override;
 
   virtual void ClearCachedResources(Layer* aSubtree = nullptr) override;
   virtual void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier) override;
   virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() override;
 
   virtual void SetTransactionIdAllocator(TransactionIdAllocator* aAllocator) override;
@@ -181,17 +181,17 @@ private:
   std::unordered_set<uint64_t> mActiveCompositorAnimationIds;
   // Compositor animation ids for animations that are done now and that we want
   // the compositor to discard information for.
   nsTArray<uint64_t> mDiscardedCompositorAnimationsIds;
 
   RefPtr<WebRenderBridgeChild> mWrChild;
 
   RefPtr<TransactionIdAllocator> mTransactionIdAllocator;
-  uint64_t mLatestTransactionId;
+  TransactionId mLatestTransactionId;
 
   nsTArray<DidCompositeObserver*> mDidCompositeObservers;
 
   // This holds the scroll data that we need to send to the compositor for
   // APZ to do it's job
   WebRenderScrollData mScrollData;
 
   bool mWindowOverlayChanged;
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -139,17 +139,17 @@ nsPresContext::IsDOMPaintEventPending()
   if (!mTransactions.IsEmpty()) {
     return true;
   }
   nsRootPresContext* drpc = GetRootPresContext();
   if (drpc && drpc->mRefreshDriver->ViewManagerFlushIsPending()) {
     // Since we're promising that there will be a MozAfterPaint event
     // fired, we record an empty invalidation in case display list
     // invalidation doesn't invalidate anything further.
-    NotifyInvalidation(drpc->mRefreshDriver->LastTransactionId() + 1, nsRect(0, 0, 0, 0));
+    NotifyInvalidation(drpc->mRefreshDriver->LastTransactionId().Next(), nsRect(0, 0, 0, 0));
     return true;
   }
   return false;
 }
 
 void
 nsPresContext::PrefChangedCallback(const char* aPrefName, void* instance_data)
 {
@@ -2326,17 +2326,18 @@ nsPresContext::EnsureSafeToHandOutCSSRul
     // Nothing to do.
     return;
   }
 
   RebuildAllStyleData(nsChangeHint(0), eRestyle_Subtree);
 }
 
 void
-nsPresContext::FireDOMPaintEvent(nsTArray<nsRect>* aList, uint64_t aTransactionId,
+nsPresContext::FireDOMPaintEvent(nsTArray<nsRect>* aList,
+                                 TransactionId aTransactionId,
                                  mozilla::TimeStamp aTimeStamp /* = mozilla::TimeStamp() */)
 {
   nsPIDOMWindowInner* ourWindow = mDocument->GetInnerWindow();
   if (!ourWindow)
     return;
 
   nsCOMPtr<EventTarget> dispatchTarget = do_QueryInterface(ourWindow);
   nsCOMPtr<EventTarget> eventTarget = dispatchTarget;
@@ -2365,17 +2366,17 @@ nsPresContext::FireDOMPaintEvent(nsTArra
   // Events sent to the window get propagated to the chrome event handler
   // automatically.
   //
   // This will empty our list in case dispatching the event causes more damage
   // (hopefully it won't, or we're likely to get an infinite loop! At least
   // it won't be blocking app execution though).
   RefPtr<NotifyPaintEvent> event =
     NS_NewDOMNotifyPaintEvent(eventTarget, this, nullptr, eAfterPaint, aList,
-                              aTransactionId, timeStamp);
+                              uint64_t(aTransactionId), timeStamp);
 
   // Even if we're not telling the window about the event (so eventTarget is
   // the chrome event handler, not the window), the window is still
   // logically the event target.
   event->SetTarget(eventTarget);
   event->SetTrusted(true);
   EventDispatcher::DispatchDOMEvent(dispatchTarget, nullptr,
                                     static_cast<Event*>(event), this, nullptr);
@@ -2455,17 +2456,17 @@ nsPresContext::MayHavePaintEventListener
   }
 
   bool result = false;
   mDocument->EnumerateSubDocuments(MayHavePaintEventListenerSubdocumentCallback, &result);
   return result;
 }
 
 void
-nsPresContext::NotifyInvalidation(uint64_t aTransactionId, const nsIntRect& aRect)
+nsPresContext::NotifyInvalidation(TransactionId aTransactionId, const nsIntRect& aRect)
 {
   // Prevent values from overflow after DevPixelsToAppUnits().
   //
   // DevPixelsTopAppUnits() will multiple a factor (60) to the value,
   // it may make the result value over the edge (overflow) of max or
   // min value of int32_t. Compute the max sized dev pixel rect that
   // we can support and intersect with it.
   nsIntRect clampedRect = nsIntRect::MaxIntRect();
@@ -2476,28 +2477,28 @@ nsPresContext::NotifyInvalidation(uint64
   nsRect rect(DevPixelsToAppUnits(clampedRect.x),
               DevPixelsToAppUnits(clampedRect.y),
               DevPixelsToAppUnits(clampedRect.width),
               DevPixelsToAppUnits(clampedRect.height));
   NotifyInvalidation(aTransactionId, rect);
 }
 
 nsPresContext::TransactionInvalidations*
-nsPresContext::GetInvalidations(uint64_t aTransactionId)
+nsPresContext::GetInvalidations(TransactionId aTransactionId)
 {
   for (TransactionInvalidations& t : mTransactions) {
     if (t.mTransactionId == aTransactionId) {
       return &t;
     }
   }
   return nullptr;
 }
 
 void
-nsPresContext::NotifyInvalidation(uint64_t aTransactionId, const nsRect& aRect)
+nsPresContext::NotifyInvalidation(TransactionId aTransactionId, const nsRect& aRect)
 {
   MOZ_ASSERT(GetContainerWeak(), "Invalidation in detached pres context");
 
   // If there is no paint event listener, then we don't need to fire
   // the asynchronous event. We don't even need to record invalidation.
   // MayHavePaintEventListener is pretty cheap and we could make it
   // even cheaper by providing a more efficient
   // nsPIDOMWindow::GetListenerManager.
@@ -2530,17 +2531,17 @@ nsPresContext::NotifySubDocInvalidation(
 {
   ContainerLayerPresContext *data =
     static_cast<ContainerLayerPresContext*>(
       aContainer->GetUserData(&gNotifySubDocInvalidationData));
   if (!data) {
     return;
   }
 
-  uint64_t transactionId = aContainer->Manager()->GetLastTransactionId();
+  TransactionId transactionId = aContainer->Manager()->GetLastTransactionId();
   IntRect visibleBounds = aContainer->GetVisibleRegion().GetBounds().ToUnknownRect();
 
   if (!aRegion) {
     IntRect rect(IntPoint(0, 0), visibleBounds.Size());
     data->mPresContext->NotifyInvalidation(transactionId, rect);
     return;
   }
 
@@ -2565,17 +2566,17 @@ nsPresContext::SetNotifySubDocInvalidati
 
 /* static */ void
 nsPresContext::ClearNotifySubDocInvalidationData(ContainerLayer* aContainer)
 {
   aContainer->SetUserData(&gNotifySubDocInvalidationData, nullptr);
 }
 
 struct NotifyDidPaintSubdocumentCallbackClosure {
-  uint64_t mTransactionId;
+  TransactionId mTransactionId;
   const mozilla::TimeStamp& mTimeStamp;
 };
 /* static */ bool
 nsPresContext::NotifyDidPaintSubdocumentCallback(nsIDocument* aDocument, void* aData)
 {
   NotifyDidPaintSubdocumentCallbackClosure* closure =
     static_cast<NotifyDidPaintSubdocumentCallbackClosure*>(aData);
   nsPresContext* pc = aDocument->GetPresContext();
@@ -2586,17 +2587,17 @@ nsPresContext::NotifyDidPaintSubdocument
   return true;
 }
 
 class DelayedFireDOMPaintEvent : public Runnable {
 public:
   DelayedFireDOMPaintEvent(
     nsPresContext* aPresContext,
     nsTArray<nsRect>* aList,
-    uint64_t aTransactionId,
+    TransactionId aTransactionId,
     const mozilla::TimeStamp& aTimeStamp = mozilla::TimeStamp())
     : mozilla::Runnable("DelayedFireDOMPaintEvent")
     , mPresContext(aPresContext)
     , mTransactionId(aTransactionId)
     , mTimeStamp(aTimeStamp)
   {
     MOZ_ASSERT(mPresContext->GetContainerWeak(),
                "DOMPaintEvent requested for a detached pres context");
@@ -2608,23 +2609,23 @@ public:
     // that's fine, just don't fire the event.
     if (mPresContext->GetContainerWeak()) {
       mPresContext->FireDOMPaintEvent(&mList, mTransactionId, mTimeStamp);
     }
     return NS_OK;
   }
 
   RefPtr<nsPresContext> mPresContext;
-  uint64_t mTransactionId;
+  TransactionId mTransactionId;
   const mozilla::TimeStamp mTimeStamp;
   nsTArray<nsRect> mList;
 };
 
 void
-nsPresContext::NotifyDidPaintForSubtree(uint64_t aTransactionId,
+nsPresContext::NotifyDidPaintForSubtree(TransactionId aTransactionId,
                                         const mozilla::TimeStamp& aTimeStamp)
 {
   if (IsRoot()) {
     static_cast<nsRootPresContext*>(this)->CancelDidPaintTimers(aTransactionId);
 
     if (mTransactions.IsEmpty()) {
       return;
     }
@@ -3280,17 +3281,17 @@ nsRootPresContext::CollectPluginGeometry
   if (clm) {
     clm->StorePluginWidgetConfigurations(configurations);
   }
   PluginDidSetGeometry(mRegisteredPlugins);
 #endif  // #ifndef XP_MACOSX
 }
 
 void
-nsRootPresContext::EnsureEventualDidPaintEvent(uint64_t aTransactionId)
+nsRootPresContext::EnsureEventualDidPaintEvent(TransactionId aTransactionId)
 {
   for (NotifyDidPaintTimer& t : mNotifyDidPaintTimers) {
     if (t.mTransactionId == aTransactionId) {
       return;
     }
   }
 
   nsCOMPtr<nsITimer> timer;
@@ -3306,17 +3307,17 @@ nsRootPresContext::EnsureEventualDidPain
   if (NS_SUCCEEDED(rv)) {
     NotifyDidPaintTimer* t = mNotifyDidPaintTimers.AppendElement();
     t->mTransactionId = aTransactionId;
     t->mTimer = timer;
   }
 }
 
 void
-nsRootPresContext::CancelDidPaintTimers(uint64_t aTransactionId)
+nsRootPresContext::CancelDidPaintTimers(TransactionId aTransactionId)
 {
   uint32_t i = 0;
   while (i < mNotifyDidPaintTimers.Length()) {
     if (mNotifyDidPaintTimers[i].mTransactionId <= aTransactionId) {
       mNotifyDidPaintTimers[i].mTimer->Cancel();
       mNotifyDidPaintTimers.RemoveElementAt(i);
     } else {
       i++;
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -130,16 +130,17 @@ class nsRootPresContext;
 class nsPresContext : public nsISupports,
                       public mozilla::SupportsWeakPtr<nsPresContext> {
 public:
   using Encoding = mozilla::Encoding;
   template <typename T> using NotNull = mozilla::NotNull<T>;
   typedef mozilla::LangGroupFontPrefs LangGroupFontPrefs;
   typedef mozilla::ScrollbarStyles ScrollbarStyles;
   typedef mozilla::StaticPresData StaticPresData;
+  using TransactionId = mozilla::layers::TransactionId;
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsPresContext)
   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsPresContext)
 
   enum nsPresContextType {
     eContext_Galley,       // unpaginated screen presentation
     eContext_PrintPreview, // paginated screen presentation
@@ -1031,22 +1032,23 @@ public:
   // engine by ensuring that all CSS style sheets have unique inners
   // and, if necessary, synchronously rebuilding all style data.
   void EnsureSafeToHandOutCSSRules();
 
   // Mark an area as invalidated, associated with a given transaction id (allocated
   // by nsRefreshDriver::GetTransactionId).
   // Invalidated regions will be dispatched to MozAfterPaint events when
   // NotifyDidPaintForSubtree is called for the transaction id (or any higher id).
-  void NotifyInvalidation(uint64_t aTransactionId, const nsRect& aRect);
+  void NotifyInvalidation(TransactionId aTransactionId, const nsRect& aRect);
   // aRect is in device pixels
-  void NotifyInvalidation(uint64_t aTransactionId, const nsIntRect& aRect);
-  void NotifyDidPaintForSubtree(uint64_t aTransactionId = 0,
+  void NotifyInvalidation(TransactionId aTransactionId, const nsIntRect& aRect);
+  void NotifyDidPaintForSubtree(TransactionId aTransactionId = TransactionId{0},
                                 const mozilla::TimeStamp& aTimeStamp = mozilla::TimeStamp());
-  void FireDOMPaintEvent(nsTArray<nsRect>* aList, uint64_t aTransactionId,
+  void FireDOMPaintEvent(nsTArray<nsRect>* aList,
+                         TransactionId aTransactionId,
                          mozilla::TimeStamp aTimeStamp = mozilla::TimeStamp());
 
   // Callback for catching invalidations in ContainerLayers
   // Passed to LayerProperties::ComputeDifference
   static void NotifySubDocInvalidation(mozilla::layers::ContainerLayer* aContainer,
                                        const nsIntRegion* aRegion);
   void SetNotifySubDocInvalidationData(mozilla::layers::ContainerLayer* aContainer);
   static void ClearNotifySubDocInvalidationData(mozilla::layers::ContainerLayer* aContainer);
@@ -1270,20 +1272,20 @@ protected:
 
   // Creates a one-shot timer with the given aCallback & aDelay.
   // Returns a refcounted pointer to the timer (or nullptr on failure).
   already_AddRefed<nsITimer> CreateTimer(nsTimerCallbackFunc aCallback,
                                          const char* aName,
                                          uint32_t aDelay);
 
   struct TransactionInvalidations {
-    uint64_t mTransactionId;
+    TransactionId mTransactionId;
     nsTArray<nsRect> mInvalidations;
   };
-  TransactionInvalidations* GetInvalidations(uint64_t aTransactionId);
+  TransactionInvalidations* GetInvalidations(TransactionId aTransactionId);
 
   // IMPORTANT: The ownership implicit in the following member variables
   // has been explicitly checked.  If you add any members to this class,
   // please make the ownership explicit (pinkerton, scc).
 
   nsPresContextType     mType;
   // the nsPresShell owns a strong reference to the nsPresContext, and is responsible
   // for nulling this pointer before it is destroyed
@@ -1526,23 +1528,23 @@ public:
   nsRootPresContext(nsIDocument* aDocument, nsPresContextType aType);
   virtual ~nsRootPresContext();
   virtual void Detach() override;
 
   /**
    * Ensure that NotifyDidPaintForSubtree is eventually called on this
    * object after a timeout.
    */
-  void EnsureEventualDidPaintEvent(uint64_t aTransactionId);
+  void EnsureEventualDidPaintEvent(TransactionId aTransactionId);
 
   /**
    * Cancels any pending eventual did paint timer for transaction
    * ids up to and including aTransactionId.
    */
-  void CancelDidPaintTimers(uint64_t aTransactionId);
+  void CancelDidPaintTimers(TransactionId aTransactionId);
 
   /**
    * Cancel all pending eventual did paint timers.
    */
   void CancelAllDidPaintTimers();
 
   /**
    * Registers a plugin to receive geometry updates (position and clip
@@ -1631,17 +1633,17 @@ protected:
     }
     // The lifetime of this reference is handled by an nsRevocableEventPtr
     nsRootPresContext* MOZ_NON_OWNING_REF mPresContext;
   };
 
   friend class nsPresContext;
 
   struct NotifyDidPaintTimer {
-    uint64_t mTransactionId;
+    TransactionId mTransactionId;
     nsCOMPtr<nsITimer> mTimer;
   };
   AutoTArray<NotifyDidPaintTimer, 4> mNotifyDidPaintTimers;
 
   nsCOMPtr<nsITimer> mApplyPluginGeometryTimer;
   nsTHashtable<nsRefPtrHashKey<nsIContent> > mRegisteredPlugins;
   nsTArray<nsCOMPtr<nsIRunnable> > mWillPaintObservers;
   nsRevocableEventPtr<RunWillPaintObservers> mWillPaintFallbackEvent;
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1143,18 +1143,18 @@ nsRefreshDriver::ChooseTimer() const
   }
   return sRegularRateTimer;
 }
 
 nsRefreshDriver::nsRefreshDriver(nsPresContext* aPresContext)
   : mActiveTimer(nullptr),
     mPresContext(aPresContext),
     mRootRefresh(nullptr),
-    mPendingTransaction(0),
-    mCompletedTransaction(0),
+    mPendingTransaction{0},
+    mCompletedTransaction{0},
     mFreezeCount(0),
     mThrottledFrameRequestInterval(TimeDuration::FromMilliseconds(
                                      GetThrottledTimerInterval())),
     mMinRecomputeVisibilityInterval(GetMinRecomputeVisibilityInterval()),
     mThrottled(false),
     mNeedToRecomputeVisibility(false),
     mTestControllingRefreshes(false),
     mViewManagerFlushIsPending(false),
@@ -2159,75 +2159,75 @@ nsRefreshDriver::FinishedWaitingForTrans
       (HasObservers() || HasImageRequests())) {
     AUTO_PROFILER_TRACING("Paint", "RefreshDriverTick");
     DoRefresh();
   }
   mSkippedPaints = false;
   mWarningThreshold = 1;
 }
 
-uint64_t
+mozilla::layers::TransactionId
 nsRefreshDriver::GetTransactionId(bool aThrottle)
 {
-  ++mPendingTransaction;
+  mPendingTransaction = mPendingTransaction.Next();
 
   if (aThrottle &&
-      mPendingTransaction >= mCompletedTransaction + 2 &&
+      mPendingTransaction - mCompletedTransaction >= 2 &&
       !mWaitingForTransaction &&
       !mTestControllingRefreshes) {
     mWaitingForTransaction = true;
     mSkippedPaints = false;
     mWarningThreshold = 1;
   }
 
   return mPendingTransaction;
 }
 
-uint64_t
+mozilla::layers::TransactionId
 nsRefreshDriver::LastTransactionId() const
 {
   return mPendingTransaction;
 }
 
 void
-nsRefreshDriver::RevokeTransactionId(uint64_t aTransactionId)
+nsRefreshDriver::RevokeTransactionId(mozilla::layers::TransactionId aTransactionId)
 {
   MOZ_ASSERT(aTransactionId == mPendingTransaction);
-  if (mPendingTransaction == mCompletedTransaction + 2 &&
+  if (mPendingTransaction - mCompletedTransaction == 2 &&
       mWaitingForTransaction) {
     MOZ_ASSERT(!mSkippedPaints, "How did we skip a paint when we're in the middle of one?");
     FinishedWaitingForTransaction();
   }
-  mPendingTransaction--;
+  mPendingTransaction = mPendingTransaction.Prev();
 }
 
 void
 nsRefreshDriver::ClearPendingTransactions()
 {
   mCompletedTransaction = mPendingTransaction;
   mWaitingForTransaction = false;
 }
 
 void
-nsRefreshDriver::ResetInitialTransactionId(uint64_t aTransactionId)
+nsRefreshDriver::ResetInitialTransactionId(mozilla::layers::TransactionId aTransactionId)
 {
   mCompletedTransaction = mPendingTransaction = aTransactionId;
 }
 
 mozilla::TimeStamp
 nsRefreshDriver::GetTransactionStart()
 {
   return mTickStart;
 }
 
 void
-nsRefreshDriver::NotifyTransactionCompleted(uint64_t aTransactionId)
+nsRefreshDriver::NotifyTransactionCompleted(mozilla::layers::TransactionId aTransactionId)
 {
   if (aTransactionId > mCompletedTransaction) {
-    if (mPendingTransaction > mCompletedTransaction + 1 &&
+    if (mPendingTransaction - mCompletedTransaction > 1 &&
         mWaitingForTransaction) {
       mCompletedTransaction = aTransactionId;
       FinishedWaitingForTransaction();
     } else {
       mCompletedTransaction = aTransactionId;
     }
   }
 }
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -74,16 +74,18 @@ public:
 class nsAPostRefreshObserver {
 public:
   virtual void DidRefresh() = 0;
 };
 
 class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
                               public nsARefreshObserver
 {
+  using TransactionId = mozilla::layers::TransactionId;
+
 public:
   explicit nsRefreshDriver(nsPresContext *aPresContext);
   ~nsRefreshDriver();
 
   /**
    * Methods for testing, exposed via nsIDOMWindowUtils.  See
    * nsIDOMWindowUtils.advanceTimeAndRefresh for description.
    */
@@ -348,22 +350,22 @@ public:
    * time.
    *
    * Return `false` if `aJank` needs to be grown to accomodate the
    * data but we didn't have enough memory.
    */
   static bool GetJankLevels(mozilla::Vector<uint64_t>& aJank);
 
   // mozilla::layers::TransactionIdAllocator
-  uint64_t GetTransactionId(bool aThrottle) override;
-  uint64_t LastTransactionId() const override;
-  void NotifyTransactionCompleted(uint64_t aTransactionId) override;
-  void RevokeTransactionId(uint64_t aTransactionId) override;
+  TransactionId GetTransactionId(bool aThrottle) override;
+  TransactionId LastTransactionId() const override;
+  void NotifyTransactionCompleted(TransactionId aTransactionId) override;
+  void RevokeTransactionId(TransactionId aTransactionId) override;
   void ClearPendingTransactions() override;
-  void ResetInitialTransactionId(uint64_t aTransactionId) override;
+  void ResetInitialTransactionId(TransactionId aTransactionId) override;
   mozilla::TimeStamp GetTransactionStart() override;
 
   bool IsWaitingForPaint(mozilla::TimeStamp aTime);
 
   // nsARefreshObserver
   NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override { return TransactionIdAllocator::AddRef(); }
   NS_IMETHOD_(MozExternalRefCountType) Release(void) override { return TransactionIdAllocator::Release(); }
   virtual void WillRefresh(mozilla::TimeStamp aTime) override;
@@ -448,19 +450,19 @@ private:
   mozilla::RefreshDriverTimer* mActiveTimer;
 
   // nsPresContext passed in constructor and unset in Disconnect.
   mozilla::WeakPtr<nsPresContext> mPresContext;
 
   RefPtr<nsRefreshDriver> mRootRefresh;
 
   // The most recently allocated transaction id.
-  uint64_t mPendingTransaction;
+  TransactionId mPendingTransaction;
   // The most recently completed transaction id.
-  uint64_t mCompletedTransaction;
+  TransactionId mCompletedTransaction;
 
   uint32_t mFreezeCount;
 
   // How long we wait between ticks for throttled (which generally means
   // non-visible) documents registered with a non-throttled refresh driver.
   const mozilla::TimeDuration mThrottledFrameRequestInterval;
 
   // How long we wait, at a minimum, before recomputing approximate frame
--- a/view/nsView.cpp
+++ b/view/nsView.cpp
@@ -1073,17 +1073,17 @@ nsView::PaintWindow(nsIWidget* aWidget, 
 void
 nsView::DidPaintWindow()
 {
   RefPtr<nsViewManager> vm = mViewManager;
   vm->DidPaintWindow();
 }
 
 void
-nsView::DidCompositeWindow(uint64_t aTransactionId,
+nsView::DidCompositeWindow(mozilla::layers::TransactionId aTransactionId,
                            const TimeStamp& aCompositeStart,
                            const TimeStamp& aCompositeEnd)
 {
   nsIPresShell* presShell = mViewManager->GetPresShell();
   if (presShell) {
     nsAutoScriptBlocker scriptBlocker;
 
     nsPresContext* context = presShell->GetPresContext();
--- a/view/nsView.h
+++ b/view/nsView.h
@@ -383,17 +383,17 @@ public:
   virtual nsView* GetView() override { return this; }
   virtual bool WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y) override;
   virtual bool WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight) override;
   virtual bool RequestWindowClose(nsIWidget* aWidget) override;
   virtual void WillPaintWindow(nsIWidget* aWidget) override;
   virtual bool PaintWindow(nsIWidget* aWidget,
                            LayoutDeviceIntRegion aRegion) override;
   virtual void DidPaintWindow() override;
-  virtual void DidCompositeWindow(uint64_t aTransactionId,
+  virtual void DidCompositeWindow(mozilla::layers::TransactionId aTransactionId,
                                   const mozilla::TimeStamp& aCompositeStart,
                                   const mozilla::TimeStamp& aCompositeEnd) override;
   virtual void RequestRepaint() override;
   virtual nsEventStatus HandleEvent(mozilla::WidgetGUIEvent* aEvent,
                                     bool aUseAttachedEvents) override;
 
   virtual ~nsView();
 
--- a/widget/nsIWidgetListener.cpp
+++ b/widget/nsIWidgetListener.cpp
@@ -117,17 +117,17 @@ nsIWidgetListener::PaintWindow(nsIWidget
 }
 
 void
 nsIWidgetListener::DidPaintWindow()
 {
 }
 
 void
-nsIWidgetListener::DidCompositeWindow(uint64_t aTransactionId,
+nsIWidgetListener::DidCompositeWindow(mozilla::layers::TransactionId aTransactionId,
                                       const TimeStamp& aCompositeStart,
                                       const TimeStamp& aCompositeEnd)
 {
 }
 
 void
 nsIWidgetListener::RequestRepaint()
 {
--- a/widget/nsIWidgetListener.h
+++ b/widget/nsIWidgetListener.h
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsIWidgetListener_h__
 #define nsIWidgetListener_h__
 
 #include <stdint.h>
 
 #include "mozilla/EventForwards.h"
+#include "mozilla/layers/LayersTypes.h"
 #include "mozilla/TimeStamp.h"
 
 #include "nsRegionFwd.h"
 #include "Units.h"
 
 class nsView;
 class nsIPresShell;
 class nsIWidget;
@@ -151,17 +152,17 @@ public:
   /**
    * Indicates that a paint occurred.
    * This is called at a time when it is OK to change the geometry of
    * this widget or of other widgets.
    * Must be called after every call to PaintWindow.
    */
   virtual void DidPaintWindow();
 
-  virtual void DidCompositeWindow(uint64_t aTransactionId,
+  virtual void DidCompositeWindow(mozilla::layers::TransactionId aTransactionId,
                                   const mozilla::TimeStamp& aCompositeStart,
                                   const mozilla::TimeStamp& aCompositeEnd);
 
   /**
    * Request that layout schedules a repaint on the next refresh driver tick.
    */
   virtual void RequestRepaint();