Bug 1360241: Devirtualize nsIFrame::GetType. r=heycam
authorEmilio Cobos Álvarez <emilio@crisal.io>
Sun, 30 Apr 2017 17:30:08 +0200
changeset 355815 662df8ef329fd7a38fb2ceb24e305cd31e7bcaa7
parent 355809 a8322bcff72e90e836000866635081f0f095828c
child 355816 5638ca797d82f0a89d8f1658a21afdbeeca73ad3
push id31744
push userarchaeopteryx@coole-files.de
push dateMon, 01 May 2017 09:20:17 +0000
treeherdermozilla-central@de63010ad9d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1360241
milestone55.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 1360241: Devirtualize nsIFrame::GetType. r=heycam MozReview-Commit-ID: 5Nzhyta5Hle
accessible/base/nsAccessibilityService.cpp
accessible/generic/Accessible.cpp
accessible/generic/HyperTextAccessible.cpp
dom/base/DOMIntersectionObserver.cpp
dom/base/Element.cpp
dom/base/nsFocusManager.cpp
dom/base/nsGkAtomList.h
dom/base/nsGlobalWindow.cpp
dom/base/nsRange.cpp
dom/events/ContentEventHandler.cpp
dom/events/EventStateManager.cpp
dom/html/nsGenericHTMLElement.cpp
dom/svg/SVGTextContentElement.cpp
layout/base/AccessibleCaretManager.cpp
layout/base/GeckoRestyleManager.cpp
layout/base/GeometryUtils.cpp
layout/base/PresShell.cpp
layout/base/RestyleManager.cpp
layout/base/ServoRestyleManager.cpp
layout/base/nsBidiPresUtils.cpp
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/base/nsCaret.cpp
layout/base/nsDocumentViewer.cpp
layout/base/nsFrameManager.cpp
layout/base/nsFrameTraversal.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/forms/nsColorControlFrame.cpp
layout/forms/nsColorControlFrame.h
layout/forms/nsComboboxControlFrame.cpp
layout/forms/nsComboboxControlFrame.h
layout/forms/nsDateTimeControlFrame.cpp
layout/forms/nsDateTimeControlFrame.h
layout/forms/nsFieldSetFrame.cpp
layout/forms/nsFieldSetFrame.h
layout/forms/nsFormControlFrame.cpp
layout/forms/nsFormControlFrame.h
layout/forms/nsGfxButtonControlFrame.cpp
layout/forms/nsGfxButtonControlFrame.h
layout/forms/nsHTMLButtonControlFrame.cpp
layout/forms/nsHTMLButtonControlFrame.h
layout/forms/nsImageControlFrame.cpp
layout/forms/nsLegendFrame.cpp
layout/forms/nsLegendFrame.h
layout/forms/nsListControlFrame.cpp
layout/forms/nsListControlFrame.h
layout/forms/nsMeterFrame.cpp
layout/forms/nsMeterFrame.h
layout/forms/nsNumberControlFrame.cpp
layout/forms/nsNumberControlFrame.h
layout/forms/nsProgressFrame.cpp
layout/forms/nsProgressFrame.h
layout/forms/nsRangeFrame.cpp
layout/forms/nsRangeFrame.h
layout/forms/nsSelectsAreaFrame.cpp
layout/forms/nsTextControlFrame.cpp
layout/forms/nsTextControlFrame.h
layout/generic/BRFrame.cpp
layout/generic/BlockReflowInput.cpp
layout/generic/CSSOrderAwareFrameIterator.h
layout/generic/DetailsFrame.cpp
layout/generic/DetailsFrame.h
layout/generic/FrameTypeList.h
layout/generic/ReflowInput.cpp
layout/generic/ReflowInput.h
layout/generic/RubyUtils.cpp
layout/generic/RubyUtils.h
layout/generic/TextOverflow.cpp
layout/generic/TextOverflow.h
layout/generic/ViewportFrame.cpp
layout/generic/ViewportFrame.h
layout/generic/moz.build
layout/generic/nsAbsoluteContainingBlock.cpp
layout/generic/nsAtomicContainerFrame.h
layout/generic/nsBackdropFrame.cpp
layout/generic/nsBackdropFrame.h
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsBlockReflowContext.cpp
layout/generic/nsBulletFrame.cpp
layout/generic/nsBulletFrame.h
layout/generic/nsCanvasFrame.cpp
layout/generic/nsCanvasFrame.h
layout/generic/nsColumnSetFrame.cpp
layout/generic/nsColumnSetFrame.h
layout/generic/nsContainerFrame.cpp
layout/generic/nsContainerFrame.h
layout/generic/nsFirstLetterFrame.cpp
layout/generic/nsFirstLetterFrame.h
layout/generic/nsFlexContainerFrame.cpp
layout/generic/nsFlexContainerFrame.h
layout/generic/nsFontInflationData.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/generic/nsFrameList.cpp
layout/generic/nsFrameSetFrame.cpp
layout/generic/nsFrameSetFrame.h
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsGridContainerFrame.cpp
layout/generic/nsGridContainerFrame.h
layout/generic/nsHTMLCanvasFrame.cpp
layout/generic/nsHTMLCanvasFrame.h
layout/generic/nsIFrame.h
layout/generic/nsIFrameInlines.h
layout/generic/nsImageFrame.cpp
layout/generic/nsImageFrame.h
layout/generic/nsInlineFrame.cpp
layout/generic/nsInlineFrame.h
layout/generic/nsLeafFrame.h
layout/generic/nsLineLayout.cpp
layout/generic/nsPageContentFrame.cpp
layout/generic/nsPageContentFrame.h
layout/generic/nsPageFrame.cpp
layout/generic/nsPageFrame.h
layout/generic/nsPlaceholderFrame.cpp
layout/generic/nsPlaceholderFrame.h
layout/generic/nsPluginFrame.cpp
layout/generic/nsPluginFrame.h
layout/generic/nsRubyBaseContainerFrame.cpp
layout/generic/nsRubyBaseContainerFrame.h
layout/generic/nsRubyBaseFrame.cpp
layout/generic/nsRubyBaseFrame.h
layout/generic/nsRubyContentFrame.h
layout/generic/nsRubyFrame.cpp
layout/generic/nsRubyFrame.h
layout/generic/nsRubyTextContainerFrame.cpp
layout/generic/nsRubyTextContainerFrame.h
layout/generic/nsRubyTextFrame.cpp
layout/generic/nsRubyTextFrame.h
layout/generic/nsSelection.cpp
layout/generic/nsSimplePageSequenceFrame.cpp
layout/generic/nsSimplePageSequenceFrame.h
layout/generic/nsSplittableFrame.cpp
layout/generic/nsSplittableFrame.h
layout/generic/nsSubDocumentFrame.cpp
layout/generic/nsSubDocumentFrame.h
layout/generic/nsTextFrame.cpp
layout/generic/nsTextFrame.h
layout/generic/nsVideoFrame.cpp
layout/generic/nsVideoFrame.h
layout/mathml/nsMathMLContainerFrame.cpp
layout/mathml/nsMathMLContainerFrame.h
layout/mathml/nsMathMLTokenFrame.cpp
layout/mathml/nsMathMLmrowFrame.cpp
layout/mathml/nsMathMLmtableFrame.cpp
layout/mathml/nsMathMLmtableFrame.h
layout/painting/nsCSSRendering.cpp
layout/painting/nsDisplayList.cpp
layout/printing/nsPrintEngine.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsFontFaceUtils.cpp
layout/style/nsStyleStructInlines.h
layout/svg/SVGFEContainerFrame.cpp
layout/svg/SVGFEImageFrame.cpp
layout/svg/SVGFELeafFrame.cpp
layout/svg/SVGFEUnstyledLeafFrame.cpp
layout/svg/SVGGeometryFrame.cpp
layout/svg/SVGGeometryFrame.h
layout/svg/SVGTextFrame.cpp
layout/svg/SVGTextFrame.h
layout/svg/SVGViewFrame.cpp
layout/svg/nsSVGAFrame.cpp
layout/svg/nsSVGClipPathFrame.cpp
layout/svg/nsSVGClipPathFrame.h
layout/svg/nsSVGContainerFrame.cpp
layout/svg/nsSVGContainerFrame.h
layout/svg/nsSVGEffects.cpp
layout/svg/nsSVGEffects.h
layout/svg/nsSVGFilterFrame.cpp
layout/svg/nsSVGFilterFrame.h
layout/svg/nsSVGFilterInstance.cpp
layout/svg/nsSVGForeignObjectFrame.cpp
layout/svg/nsSVGForeignObjectFrame.h
layout/svg/nsSVGGFrame.cpp
layout/svg/nsSVGGFrame.h
layout/svg/nsSVGGenericContainerFrame.cpp
layout/svg/nsSVGGenericContainerFrame.h
layout/svg/nsSVGGradientFrame.cpp
layout/svg/nsSVGGradientFrame.h
layout/svg/nsSVGImageFrame.cpp
layout/svg/nsSVGInnerSVGFrame.cpp
layout/svg/nsSVGInnerSVGFrame.h
layout/svg/nsSVGIntegrationUtils.cpp
layout/svg/nsSVGMarkerFrame.cpp
layout/svg/nsSVGMarkerFrame.h
layout/svg/nsSVGMaskFrame.cpp
layout/svg/nsSVGMaskFrame.h
layout/svg/nsSVGOuterSVGFrame.cpp
layout/svg/nsSVGOuterSVGFrame.h
layout/svg/nsSVGPaintServerFrame.h
layout/svg/nsSVGPatternFrame.cpp
layout/svg/nsSVGPatternFrame.h
layout/svg/nsSVGStopFrame.cpp
layout/svg/nsSVGSwitchFrame.cpp
layout/svg/nsSVGUseFrame.cpp
layout/svg/nsSVGUtils.cpp
layout/tables/BasicTableLayoutStrategy.cpp
layout/tables/nsTableCellFrame.cpp
layout/tables/nsTableCellFrame.h
layout/tables/nsTableColFrame.cpp
layout/tables/nsTableColFrame.h
layout/tables/nsTableColGroupFrame.cpp
layout/tables/nsTableColGroupFrame.h
layout/tables/nsTableFrame.cpp
layout/tables/nsTableFrame.h
layout/tables/nsTablePainter.cpp
layout/tables/nsTableRowFrame.cpp
layout/tables/nsTableRowFrame.h
layout/tables/nsTableRowGroupFrame.cpp
layout/tables/nsTableRowGroupFrame.h
layout/tables/nsTableWrapperFrame.cpp
layout/tables/nsTableWrapperFrame.h
layout/xul/nsBox.cpp
layout/xul/nsBox.h
layout/xul/nsBoxFrame.cpp
layout/xul/nsBoxFrame.h
layout/xul/nsDeckFrame.cpp
layout/xul/nsDeckFrame.h
layout/xul/nsImageBoxFrame.cpp
layout/xul/nsImageBoxFrame.h
layout/xul/nsLeafBoxFrame.cpp
layout/xul/nsLeafBoxFrame.h
layout/xul/nsMenuFrame.cpp
layout/xul/nsMenuFrame.h
layout/xul/nsMenuPopupFrame.cpp
layout/xul/nsMenuPopupFrame.h
layout/xul/nsPopupSetFrame.cpp
layout/xul/nsPopupSetFrame.h
layout/xul/nsProgressMeterFrame.h
layout/xul/nsRootBoxFrame.cpp
layout/xul/nsScrollbarFrame.cpp
layout/xul/nsScrollbarFrame.h
layout/xul/nsSliderFrame.cpp
layout/xul/nsSliderFrame.h
layout/xul/nsXULLabelFrame.cpp
layout/xul/nsXULLabelFrame.h
view/nsView.cpp
widget/cocoa/nsNativeThemeCocoa.mm
widget/nsBaseDragService.cpp
widget/nsNativeTheme.cpp
widget/windows/nsNativeThemeWin.cpp
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -1137,19 +1137,18 @@ nsAccessibilityService::CreateAccessible
     // XBL bindings may use @role attribute to point the accessible type
     // they belong to.
     newAcc = CreateAccessibleByType(content, document);
 
     // Any XUL box can be used as tabpanel, make sure we create a proper
     // accessible for it.
     if (!newAcc && aContext->IsXULTabpanels() &&
         content->GetParent() == aContext->GetContent()) {
-      nsIAtom* frameType = frame->GetType();
-      if (frameType == nsGkAtoms::boxFrame ||
-          frameType == nsGkAtoms::scrollFrame) {
+      FrameType frameType = frame->Type();
+      if (frameType == FrameType::Box || frameType == FrameType::Scroll) {
         newAcc = new XULTabpanelAccessible(content, document);
       }
     }
   }
 
   if (!newAcc) {
     if (content->IsSVGElement()) {
       SVGGeometryFrame* geometryFrame = do_QueryFrame(frame);
@@ -1610,22 +1609,22 @@ nsAccessibilityService::CreateAccessible
       // accessible HTML table or a direct child of accessible of HTML table.
       Accessible* table = aContext->IsTable() ? aContext : nullptr;
       if (!table && aContext->Parent() && aContext->Parent()->IsTable())
         table = aContext->Parent();
 
       if (table) {
         nsIContent* parentContent = aContent->GetParent();
         nsIFrame* parentFrame = parentContent->GetPrimaryFrame();
-        if (parentFrame->GetType() != nsGkAtoms::tableWrapperFrame) {
+        if (!parentFrame->IsTableWrapperFrame()) {
           parentContent = parentContent->GetParent();
           parentFrame = parentContent->GetPrimaryFrame();
         }
 
-        if (parentFrame->GetType() == nsGkAtoms::tableWrapperFrame &&
+        if (parentFrame->IsTableWrapperFrame() &&
             table->GetContent() == parentContent) {
           newAcc = new HTMLTableRowAccessible(aContent, document);
         }
       }
       break;
     }
     case eHTMLTextFieldType:
       newAcc = new HTMLTextFieldAccessible(aContent, document);
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -380,17 +380,17 @@ Accessible::VisibilityState()
     curFrame = parentFrame;
   } while (curFrame);
 
   // Zero area rects can occur in the first frame of a multi-frame text flow,
   // in which case the rendered text is not empty and the frame should not be
   // marked invisible.
   // XXX Can we just remove this check? Why do we need to mark empty
   // text invisible?
-  if (frame->GetType() == nsGkAtoms::textFrame &&
+  if (frame->IsTextFrame() &&
       !(frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
       frame->GetRect().IsEmpty()) {
     nsIFrame::RenderedText text = frame->GetRenderedText(0,
         UINT32_MAX, nsIFrame::TextOffsetType::OFFSETS_IN_CONTENT_TEXT,
         nsIFrame::TrailingWhitespace::DONT_TRIM_TRAILING_WHITESPACE);
     if (text.mString.IsEmpty()) {
       return states::INVISIBLE;
     }
@@ -631,17 +631,18 @@ Accessible::RelativeBounds(nsIFrame** aB
   if (frame && mContent) {
     bool* hasHitRegionRect = static_cast<bool*>(mContent->GetProperty(nsGkAtoms::hitregion));
 
     if (hasHitRegionRect && mContent->IsElement()) {
       // This is for canvas fallback content
       // Find a canvas frame the found hit region is relative to.
       nsIFrame* canvasFrame = frame->GetParent();
       if (canvasFrame) {
-        canvasFrame = nsLayoutUtils::GetClosestFrameOfType(canvasFrame, nsGkAtoms::HTMLCanvasFrame);
+        canvasFrame = nsLayoutUtils::GetClosestFrameOfType(
+          canvasFrame, FrameType::HTMLCanvas);
       }
 
       // make the canvas the bounding frame
       if (canvasFrame) {
         *aBoundingFrame = canvasFrame;
         dom::HTMLCanvasElement *canvas =
           dom::HTMLCanvasElement::FromContent(canvasFrame->GetContent());
 
@@ -1883,17 +1884,17 @@ Accessible::AppendTextTo(nsAString& aTex
 
   nsIFrame *frame = GetFrame();
   if (!frame)
     return;
 
   NS_ASSERTION(mParent,
                "Called on accessible unbound from tree. Result can be wrong.");
 
-  if (frame->GetType() == nsGkAtoms::brFrame) {
+  if (frame->IsBrFrame()) {
     aText += kForcedNewLineChar;
   } else if (mParent && nsAccUtils::MustPrune(mParent)) {
     // Expose the embedded object accessible as imaginary embedded object
     // character if its parent hypertext accessible doesn't expose children to
     // AT.
     aText += kImaginaryEmbeddedObjectChar;
   } else {
     aText += kEmbeddedObjectChar;
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -60,17 +60,17 @@ NS_IMPL_ISUPPORTS_INHERITED0(HyperTextAc
 role
 HyperTextAccessible::NativeRole()
 {
   a11y::role r = GetAccService()->MarkupRole(mContent);
   if (r != roles::NOTHING)
     return r;
 
   nsIFrame* frame = GetFrame();
-  if (frame && frame->GetType() == nsGkAtoms::inlineFrame)
+  if (frame && frame->IsInlineFrame())
     return roles::TEXT;
 
   return roles::TEXT_CONTAINER;
 }
 
 uint64_t
 HyperTextAccessible::NativeState()
 {
@@ -91,17 +91,17 @@ HyperTextAccessible::NativeState()
 }
 
 nsIntRect
 HyperTextAccessible::GetBoundsInFrame(nsIFrame* aFrame,
                                       uint32_t aStartRenderedOffset,
                                       uint32_t aEndRenderedOffset)
 {
   nsPresContext* presContext = mDoc->PresContext();
-  if (aFrame->GetType() != nsGkAtoms::textFrame) {
+  if (!aFrame->IsTextFrame()) {
     return aFrame->GetScreenRectInAppUnits().
       ToNearestPixels(presContext->AppUnitsPerDevPixel());
   }
 
   // Substring must be entirely within the same text node.
   int32_t startContentOffset, endContentOffset;
   nsresult rv = RenderedToContentOffset(aFrame, aStartRenderedOffset, &startContentOffset);
   NS_ENSURE_SUCCESS(rv, nsIntRect());
@@ -534,17 +534,17 @@ HyperTextAccessible::FindOffset(uint32_t
   nsIFrame* childFrame = child->GetFrame();
   if (!childFrame) {
     NS_ERROR("No child frame");
     return 0;
   }
 
   int32_t innerContentOffset = innerOffset;
   if (child->IsTextLeaf()) {
-    NS_ASSERTION(childFrame->GetType() == nsGkAtoms::textFrame, "Wrong frame!");
+    NS_ASSERTION(childFrame->IsTextFrame(), "Wrong frame!");
     RenderedToContentOffset(childFrame, innerOffset, &innerContentOffset);
   }
 
   nsIFrame* frameAtOffset = childFrame;
   int32_t unusedOffsetInFrame = 0;
   childFrame->GetChildFrameContainingOffset(innerContentOffset, true,
                                             &unusedOffsetInFrame,
                                             &frameAtOffset);
@@ -912,17 +912,17 @@ HyperTextAccessible::TextAttributes(bool
   int32_t offsetInAcc = offset - startOffset;
 
   TextAttrsMgr textAttrsMgr(this, aIncludeDefAttrs, accAtOffset,
                             accAtOffsetIdx);
   textAttrsMgr.GetAttributes(attributes, &startOffset, &endOffset);
 
   // Compute spelling attributes on text accessible only.
   nsIFrame *offsetFrame = accAtOffset->GetFrame();
-  if (offsetFrame && offsetFrame->GetType() == nsGkAtoms::textFrame) {
+  if (offsetFrame && offsetFrame->IsTextFrame()) {
     int32_t nodeOffset = 0;
     RenderedToContentOffset(offsetFrame, offsetInAcc, &nodeOffset);
 
     // Set 'misspelled' text attribute.
     GetSpellTextAttr(accAtOffset->GetNode(), nodeOffset,
                      &startOffset, &endOffset, attributes);
   }
 
@@ -1104,17 +1104,17 @@ already_AddRefed<nsIPersistentProperties
 HyperTextAccessible::NativeAttributes()
 {
   nsCOMPtr<nsIPersistentProperties> attributes =
     AccessibleWrap::NativeAttributes();
 
   // 'formatting' attribute is deprecated, 'display' attribute should be
   // instead.
   nsIFrame *frame = GetFrame();
-  if (frame && frame->GetType() == nsGkAtoms::blockFrame) {
+  if (frame && frame->IsBlockFrame()) {
     nsAutoString unused;
     attributes->SetStringProperty(NS_LITERAL_CSTRING("formatting"),
                                   NS_LITERAL_STRING("block"), unused);
   }
 
   if (FocusMgr()->IsFocused(this)) {
     int32_t lineNumber = CaretLineNumber();
     if (lineNumber >= 1) {
@@ -1218,17 +1218,17 @@ HyperTextAccessible::OffsetAtPoint(int32
     nsIFrame *frame = primaryFrame;
     while (frame) {
       nsIContent *content = frame->GetContent();
       NS_ENSURE_TRUE(content, -1);
       nsPoint pointInFrame = pointInHyperText - frame->GetOffsetTo(hyperFrame);
       nsSize frameSize = frame->GetSize();
       if (pointInFrame.x < frameSize.width && pointInFrame.y < frameSize.height) {
         // Finished
-        if (frame->GetType() == nsGkAtoms::textFrame) {
+        if (frame->IsTextFrame()) {
           nsIFrame::ContentOffsets contentOffsets =
             frame->GetContentOffsetsFromPointExternal(pointInFrame, nsIFrame::IGNORE_SELECTION_STYLE);
           if (contentOffsets.IsNull() || contentOffsets.content != content) {
             return -1; // Not found
           }
           uint32_t addToOffset;
           nsresult rv = ContentToRenderedOffset(primaryFrame,
                                                 contentOffsets.offset,
@@ -1966,18 +1966,17 @@ HyperTextAccessible::ContentToRenderedOf
     return NS_OK;
   }
 
   if (IsTextField()) {
     *aRenderedOffset = aContentOffset;
     return NS_OK;
   }
 
-  NS_ASSERTION(aFrame->GetType() == nsGkAtoms::textFrame,
-               "Need text frame for offset conversion");
+  NS_ASSERTION(aFrame->IsTextFrame(), "Need text frame for offset conversion");
   NS_ASSERTION(aFrame->GetPrevContinuation() == nullptr,
                "Call on primary frame only");
 
   nsIFrame::RenderedText text = aFrame->GetRenderedText(aContentOffset,
       aContentOffset + 1, nsIFrame::TextOffsetType::OFFSETS_IN_CONTENT_TEXT,
       nsIFrame::TrailingWhitespace::DONT_TRIM_TRAILING_WHITESPACE);
   *aRenderedOffset = text.mOffsetWithinNodeRenderedText;
 
@@ -1991,18 +1990,17 @@ HyperTextAccessible::RenderedToContentOf
   if (IsTextField()) {
     *aContentOffset = aRenderedOffset;
     return NS_OK;
   }
 
   *aContentOffset = 0;
   NS_ENSURE_TRUE(aFrame, NS_ERROR_FAILURE);
 
-  NS_ASSERTION(aFrame->GetType() == nsGkAtoms::textFrame,
-               "Need text frame for offset conversion");
+  NS_ASSERTION(aFrame->IsTextFrame(), "Need text frame for offset conversion");
   NS_ASSERTION(aFrame->GetPrevContinuation() == nullptr,
                "Call on primary frame only");
 
   nsIFrame::RenderedText text = aFrame->GetRenderedText(aRenderedOffset,
       aRenderedOffset + 1, nsIFrame::TextOffsetType::OFFSETS_IN_RENDERED_TEXT,
       nsIFrame::TrailingWhitespace::DONT_TRIM_TRAILING_WHITESPACE);
   *aContentOffset = text.mOffsetWithinNodeText;
 
@@ -2095,17 +2093,17 @@ HyperTextAccessible::GetDOMPointByFrameO
     nsIContent* content = aAccessible->GetContent();
     NS_ASSERTION(content, "Shouldn't operate on defunct accessible!");
 
     nsIContent* parent = content->GetParent();
 
     aPoint->idx = parent->IndexOf(content) + 1;
     aPoint->node = parent;
 
-  } else if (aFrame->GetType() == nsGkAtoms::textFrame) {
+  } else if (aFrame->IsTextFrame()) {
     nsIContent* content = aFrame->GetContent();
     NS_ENSURE_STATE(content);
 
     nsIFrame *primaryFrame = content->GetPrimaryFrame();
     nsresult rv = RenderedToContentOffset(primaryFrame, aOffset, &(aPoint->idx));
     NS_ENSURE_SUCCESS(rv, rv);
 
     aPoint->node = content;
--- a/dom/base/DOMIntersectionObserver.cpp
+++ b/dom/base/DOMIntersectionObserver.cpp
@@ -261,17 +261,17 @@ DOMIntersectionObserver::Update(nsIDocum
   Element* root = nullptr;
   nsIFrame* rootFrame = nullptr;
   nsRect rootRect;
 
   if (mRoot) {
     root = mRoot;
     rootFrame = root->GetPrimaryFrame();
     if (rootFrame) {
-      if (rootFrame->GetType() == nsGkAtoms::scrollFrame) {
+      if (rootFrame->IsScrollFrame()) {
         nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
         rootRect = nsLayoutUtils::TransformFrameRectToAncestor(
           rootFrame,
           rootFrame->GetContentRectRelativeToSelf(),
           scrollFrame->GetScrolledFrame());
       } else {
         rootRect = nsLayoutUtils::GetAllInFlowRectsUnion(rootFrame,
           nsLayoutUtils::GetContainingBlockForClientRect(rootFrame),
@@ -348,17 +348,17 @@ DOMIntersectionObserver::Update(nsIDocum
         targetFrame,
         nsLayoutUtils::GetContainingBlockForClientRect(targetFrame),
         nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS
       );
       intersectionRect = Some(targetFrame->GetVisualOverflowRect());
 
       nsIFrame* containerFrame = nsLayoutUtils::GetCrossDocParentFrame(targetFrame);
       while (containerFrame && containerFrame != rootFrame) {
-        if (containerFrame->GetType() == nsGkAtoms::scrollFrame) {
+        if (containerFrame->IsScrollFrame()) {
           nsIScrollableFrame* scrollFrame = do_QueryFrame(containerFrame);
           nsRect subFrameRect = scrollFrame->GetScrollPortRect();
           nsRect intersectionRectRelativeToContainer =
             nsLayoutUtils::TransformFrameRectToAncestor(targetFrame,
                                                         intersectionRect.value(),
                                                         containerFrame);
           intersectionRect = EdgeInclusiveIntersection(intersectionRectRelativeToContainer,
                                                        subFrameRect);
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -643,18 +643,18 @@ Element::GetScrollFrame(nsIFrame **aStyl
     *aStyledFrame = frame;
   }
   if (!frame) {
     return nullptr;
   }
 
   // menu frames implement GetScrollTargetFrame but we don't want
   // to use it here.  Similar for comboboxes.
-  nsIAtom* type = frame->GetType();
-  if (type != nsGkAtoms::menuFrame && type != nsGkAtoms::comboboxControlFrame) {
+  FrameType type = frame->Type();
+  if (type != FrameType::Menu && type != FrameType::ComboboxControl) {
     nsIScrollableFrame *scrollFrame = frame->GetScrollTargetFrame();
     if (scrollFrame)
       return scrollFrame;
   }
 
   nsIDocument* doc = OwnerDoc();
   bool quirksMode = doc->GetCompatibilityMode() == eCompatibility_NavQuirks;
   Element* elementWithRootScrollInfo =
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -2685,18 +2685,18 @@ nsFocusManager::DetermineElementToMoveFo
       if (startContent != rootContent)
         ignoreTabIndex = true;
     }
 
     // check if the focus is currently inside a popup. Elements such as the
     // autocomplete widget use the noautofocus attribute to allow the focus to
     // remain outside the popup when it is opened.
     if (frame) {
-      popupFrame = nsLayoutUtils::GetClosestFrameOfType(frame,
-                                                        nsGkAtoms::menuPopupFrame);
+      popupFrame =
+        nsLayoutUtils::GetClosestFrameOfType(frame, FrameType::MenuPopup);
     }
 
     if (popupFrame && !forDocumentNavigation) {
       // Don't navigate outside of a popup, so pretend that the
       // root content is the popup itself
       rootContent = popupFrame->GetContent();
       NS_ASSERTION(rootContent, "Popup frame doesn't have a content node");
     }
@@ -2912,18 +2912,18 @@ nsFocusManager::DetermineElementToMoveFo
       }
 
       // if the frame is inside a popup, make sure to scan only within the
       // popup. This handles the situation of tabbing amongst elements
       // inside an iframe which is itself inside a popup. Otherwise,
       // navigation would move outside the popup when tabbing outside the
       // iframe.
       if (!forDocumentNavigation) {
-        popupFrame = nsLayoutUtils::GetClosestFrameOfType(frame,
-                                                          nsGkAtoms::menuPopupFrame);
+        popupFrame =
+          nsLayoutUtils::GetClosestFrameOfType(frame, FrameType::MenuPopup);
         if (popupFrame) {
           rootContent = popupFrame->GetContent();
           NS_ASSERTION(rootContent, "Popup frame doesn't have a content node");
         }
       }
     }
     else {
       // There is no parent, so call the tree owner. This will tell the
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -121,17 +121,16 @@ GK_ATOM(aural, "aural")
 GK_ATOM(_auto, "auto")
 GK_ATOM(autocheck, "autocheck")
 GK_ATOM(autocomplete, "autocomplete")
 GK_ATOM(autofocus, "autofocus")
 GK_ATOM(autoplay, "autoplay")
 GK_ATOM(autorepeatbutton, "autorepeatbutton")
 GK_ATOM(axis, "axis")
 GK_ATOM(b, "b")
-GK_ATOM(backdropFrame, "BackdropFrame")
 GK_ATOM(background, "background")
 GK_ATOM(base, "base")
 GK_ATOM(basefont, "basefont")
 GK_ATOM(baseline, "baseline")
 GK_ATOM(bdi, "bdi")
 GK_ATOM(bdo, "bdo")
 GK_ATOM(before, "before")
 GK_ATOM(before_end, "before_end")
@@ -1973,111 +1972,21 @@ GK_ATOM(cdataTagName, "#cdata-section")
 GK_ATOM(commentTagName, "#comment")
 GK_ATOM(documentNodeName, "#document")
 GK_ATOM(documentFragmentNodeName, "#document-fragment")
 GK_ATOM(documentTypeNodeName, "#document-type")
 GK_ATOM(processingInstructionTagName, "#processing-instruction")
 GK_ATOM(textTagName, "#text")
 
 // Frame types
-GK_ATOM(bcTableCellFrame, "BCTableCellFrame") // table cell in border collapsing model
-GK_ATOM(blockFrame, "BlockFrame")
-GK_ATOM(boxFrame, "BoxFrame")
-GK_ATOM(brFrame, "BRFrame")
-GK_ATOM(bulletFrame, "BulletFrame")
-GK_ATOM(colorControlFrame, "colorControlFrame")
-GK_ATOM(columnSetFrame, "ColumnSetFrame")
-GK_ATOM(comboboxControlFrame, "ComboboxControlFrame")
-GK_ATOM(comboboxDisplayFrame, "ComboboxDisplayFrame")
-GK_ATOM(dateTimeControlFrame, "DateTimeControlFrame")
-GK_ATOM(deckFrame, "DeckFrame")
-GK_ATOM(detailsFrame, "DetailsFrame")
-GK_ATOM(fieldSetFrame, "FieldSetFrame")
-GK_ATOM(flexContainerFrame, "FlexContainerFrame")
-GK_ATOM(formControlFrame, "FormControlFrame") // radio or checkbox
-GK_ATOM(frameSetFrame, "FrameSetFrame")
-GK_ATOM(gfxButtonControlFrame, "gfxButtonControlFrame")
-GK_ATOM(gridContainerFrame, "GridContainerFrame")
-GK_ATOM(HTMLButtonControlFrame, "HTMLButtonControlFrame")
-GK_ATOM(HTMLCanvasFrame, "HTMLCanvasFrame")
-GK_ATOM(subDocumentFrame, "subDocumentFrame")
-GK_ATOM(imageBoxFrame, "ImageBoxFrame")
-GK_ATOM(imageFrame, "ImageFrame")
-GK_ATOM(imageControlFrame, "ImageControlFrame")
-GK_ATOM(inlineFrame, "InlineFrame")
-GK_ATOM(leafBoxFrame, "LeafBoxFrame")
-GK_ATOM(legendFrame, "LegendFrame")
-GK_ATOM(letterFrame, "LetterFrame")
-GK_ATOM(lineFrame, "LineFrame")
-GK_ATOM(listControlFrame,"ListControlFrame")
-GK_ATOM(menuFrame,"MenuFrame")
-GK_ATOM(meterFrame, "MeterFrame")
-GK_ATOM(menuPopupFrame,"MenuPopupFrame")
-GK_ATOM(numberControlFrame, "NumberControlFrame")
-GK_ATOM(objectFrame, "ObjectFrame")
-GK_ATOM(pageFrame, "PageFrame")
-GK_ATOM(pageBreakFrame, "PageBreakFrame")
-GK_ATOM(pageContentFrame, "PageContentFrame")
+//
+// TODO(emilio): Rename this? This is only used now to mark the style context of
+// the placeholder with a dummy pseudo.
 GK_ATOM(placeholderFrame, "PlaceholderFrame")
-GK_ATOM(popupSetFrame, "PopupSetFrame")
-GK_ATOM(progressFrame, "ProgressFrame")
-GK_ATOM(canvasFrame, "CanvasFrame")
-GK_ATOM(rangeFrame, "RangeFrame")
-GK_ATOM(rootFrame, "RootFrame")
-GK_ATOM(rubyBaseContainerFrame, "RubyBaseContainerFrame")
-GK_ATOM(rubyBaseFrame, "RubyBaseFrame")
-GK_ATOM(rubyFrame, "RubyFrame")
-GK_ATOM(rubyTextContainerFrame, "RubyTextContainerFrame")
-GK_ATOM(rubyTextFrame, "RubyTextFrame")
-GK_ATOM(scrollFrame, "ScrollFrame")
-GK_ATOM(scrollbarFrame, "ScrollbarFrame")
-GK_ATOM(sequenceFrame, "SequenceFrame")
-GK_ATOM(sliderFrame, "sliderFrame")
-GK_ATOM(tableCellFrame, "TableCellFrame")
-GK_ATOM(tableColFrame, "TableColFrame")
-GK_ATOM(tableColGroupFrame, "TableColGroupFrame")
-GK_ATOM(tableFrame, "TableFrame")
-GK_ATOM(tableWrapperFrame, "TableWrapperFrame")
-GK_ATOM(tableRowGroupFrame, "TableRowGroupFrame")
-GK_ATOM(tableRowFrame, "TableRowFrame")
-GK_ATOM(textInputFrame,"TextInputFrame")
-GK_ATOM(textFrame, "TextFrame")
-GK_ATOM(viewportFrame, "ViewportFrame")
-#ifdef MOZ_XUL
-GK_ATOM(XULLabelFrame, "XULLabelFrame")
-#endif
-GK_ATOM(svgAFrame, "SVGAFrame")
-GK_ATOM(svgClipPathFrame, "SVGClipPathFrame")
-GK_ATOM(svgDefsFrame, "SVGDefsFrame")
-GK_ATOM(svgFEContainerFrame, "SVGFEContainerFrame")
-GK_ATOM(svgFEImageFrame, "SVGFEImageFrame")
-GK_ATOM(svgFELeafFrame, "SVGFELeafFrame")
-GK_ATOM(svgFEUnstyledLeafFrame, "SVGFEUnstyledLeafFrame")
-GK_ATOM(svgFilterFrame, "SVGFilterFrame")
-GK_ATOM(svgForeignObjectFrame, "SVGForeignObjectFrame")
-GK_ATOM(svgGenericContainerFrame, "SVGGenericContainerFrame")
-GK_ATOM(svgGeometryFrame, "SVGGeometryFrame")
-GK_ATOM(svgGFrame, "SVGGFrame")
-GK_ATOM(svgGradientFrame, "SVGGradientFrame")
-GK_ATOM(svgImageFrame, "SVGImageFrame")
-GK_ATOM(svgInnerSVGFrame, "SVGInnerSVGFrame")
-GK_ATOM(svgLinearGradientFrame, "SVGLinearGradientFrame")
-GK_ATOM(svgMarkerFrame, "SVGMarkerFrame")
-GK_ATOM(svgMarkerAnonChildFrame, "SVGMarkerAnonChildFrame")
-GK_ATOM(svgMaskFrame, "SVGMaskFrame")
-GK_ATOM(svgOuterSVGFrame, "SVGOuterSVGFrame")
-GK_ATOM(svgOuterSVGAnonChildFrame, "SVGOuterSVGAnonChildFrame")
-GK_ATOM(svgPatternFrame, "SVGPatternFrame")
-GK_ATOM(svgRadialGradientFrame, "SVGRadialGradientFrame")
-GK_ATOM(svgStopFrame, "SVGStopFrame")
-GK_ATOM(svgSwitchFrame, "SVGSwitchFrame")
-GK_ATOM(svgTextFrame, "SVGTextFrame")
-GK_ATOM(svgUseFrame, "SVGUseFrame")
-GK_ATOM(svgViewFrame, "SVGViewFrame")
-GK_ATOM(HTMLVideoFrame, "VideoFrame")
+
 GK_ATOM(onloadend, "onloadend")
 GK_ATOM(onloadstart, "onloadstart")
 GK_ATOM(onprogress, "onprogress")
 GK_ATOM(onsuspend, "onsuspend")
 GK_ATOM(onemptied, "onemptied")
 GK_ATOM(onstalled, "onstalled")
 GK_ATOM(onplay, "onplay")
 GK_ATOM(onpause, "onpause")
@@ -2362,17 +2271,16 @@ GK_ATOM(aria_rowcount, "aria-rowcount")
 GK_ATOM(aria_rowindex, "aria-rowindex")
 GK_ATOM(aria_selected, "aria-selected")
 GK_ATOM(aria_setsize, "aria-setsize")
 GK_ATOM(aria_sort, "aria-sort")
 GK_ATOM(aria_valuenow, "aria-valuenow")
 GK_ATOM(aria_valuemin, "aria-valuemin")
 GK_ATOM(aria_valuemax, "aria-valuemax")
 GK_ATOM(aria_valuetext, "aria-valuetext")
-GK_ATOM(AreaFrame, "AreaFrame")
 GK_ATOM(auto_generated, "auto-generated")
 GK_ATOM(banner, "banner")
 GK_ATOM(checkable, "checkable")
 GK_ATOM(choices, "choices")
 GK_ATOM(columnheader, "columnheader")
 GK_ATOM(complementary, "complementary")
 GK_ATOM(containerAtomic, "container-atomic")
 GK_ATOM(containerBusy, "container-busy")
@@ -2383,17 +2291,16 @@ GK_ATOM(contentinfo, "contentinfo")
 GK_ATOM(cycles, "cycles")
 GK_ATOM(datatable, "datatable")
 GK_ATOM(eventFromInput, "event-from-input")
 GK_ATOM(feed, "feed")
 GK_ATOM(grammar, "grammar")
 GK_ATOM(gridcell, "gridcell")
 GK_ATOM(heading, "heading")
 GK_ATOM(hitregion, "hitregion")
-GK_ATOM(InlineBlockFrame, "InlineBlockFrame")
 GK_ATOM(inlinevalue, "inline")
 GK_ATOM(invalid, "invalid")
 GK_ATOM(item, "item")
 GK_ATOM(itemset, "itemset")
 GK_ATOM(lineNumber, "line-number")
 GK_ATOM(linkedPanel, "linkedpanel")
 GK_ATOM(live, "live")
 GK_ATOM(menuitemcheckbox, "menuitemcheckbox")
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -14023,17 +14023,17 @@ nsGlobalWindow::BeginWindowMove(Event& a
   MOZ_ASSERT(IsInnerWindow());
 
   nsCOMPtr<nsIWidget> widget;
 
   // if a panel was supplied, use its widget instead.
 #ifdef MOZ_XUL
   if (aPanel) {
     nsIFrame* frame = aPanel->GetPrimaryFrame();
-    if (!frame || frame->GetType() != nsGkAtoms::menuPopupFrame) {
+    if (!frame || !frame->IsMenuPopupFrame()) {
       return;
     }
 
     widget = (static_cast<nsMenuPopupFrame*>(frame))->GetWidget();
   }
   else {
 #endif
     widget = GetMainWidget();
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -2968,17 +2968,17 @@ GetTextFrameForContent(nsIContent* aCont
     presShell->FrameConstructor()->EnsureFrameForTextNode(
         static_cast<nsGenericDOMDataNode*>(aContent));
 
     if (aFlushLayout) {
       aContent->OwnerDoc()->FlushPendingNotifications(FlushType::Layout);
     }
 
     nsIFrame* frame = aContent->GetPrimaryFrame();
-    if (frame && frame->GetType() == nsGkAtoms::textFrame) {
+    if (frame && frame->IsTextFrame()) {
       return static_cast<nsTextFrame*>(frame);
     }
   }
   return nullptr;
 }
 
 static nsresult GetPartialTextRect(nsLayoutUtils::RectCallback* aCallback,
                                    Sequence<nsString>* aTextList,
@@ -3508,47 +3508,46 @@ GetRequiredInnerTextLineBreakCount(nsIFr
     return 1;
   }
   return 0;
 }
 
 static bool
 IsLastCellOfRow(nsIFrame* aFrame)
 {
-  nsIAtom* type = aFrame->GetType();
-  if (type != nsGkAtoms::tableCellFrame &&
-      type != nsGkAtoms::bcTableCellFrame) {
+  FrameType type = aFrame->Type();
+  if (type != FrameType::TableCell && type != FrameType::BCTableCell) {
     return true;
   }
   for (nsIFrame* c = aFrame; c; c = c->GetNextContinuation()) {
     if (c->GetNextSibling()) {
       return false;
     }
   }
   return true;
 }
 
 static bool
 IsLastRowOfRowGroup(nsIFrame* aFrame)
 {
-  if (aFrame->GetType() != nsGkAtoms::tableRowFrame) {
+  if (!aFrame->IsTableRowFrame()) {
     return true;
   }
   for (nsIFrame* c = aFrame; c; c = c->GetNextContinuation()) {
     if (c->GetNextSibling()) {
       return false;
     }
   }
   return true;
 }
 
 static bool
 IsLastNonemptyRowGroupOfTable(nsIFrame* aFrame)
 {
-  if (aFrame->GetType() != nsGkAtoms::tableRowGroupFrame) {
+  if (!aFrame->IsTableRowGroupFrame()) {
     return true;
   }
   for (nsIFrame* c = aFrame; c; c = c->GetNextContinuation()) {
     for (nsIFrame* next = c->GetNextSibling(); next; next = next->GetNextSibling()) {
       if (next->PrincipalChildList().FirstChild()) {
         return false;
       }
     }
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -951,17 +951,17 @@ ContentEventHandler::ExpandToClusterBoun
   }
   int32_t startOffset, endOffset;
   nsresult rv = frame->GetOffsets(startOffset, endOffset);
   NS_ENSURE_SUCCESS(rv, rv);
   if (*aXPOffset == static_cast<uint32_t>(startOffset) ||
       *aXPOffset == static_cast<uint32_t>(endOffset)) {
     return NS_OK;
   }
-  if (frame->GetType() != nsGkAtoms::textFrame) {
+  if (!frame->IsTextFrame()) {
     return NS_ERROR_FAILURE;
   }
   nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
   int32_t newOffsetInFrame = *aXPOffset - startOffset;
   newOffsetInFrame += aForward ? -1 : 1;
   textFrame->PeekOffsetCharacter(aForward, &newOffsetInFrame);
   *aXPOffset = startOffset + newOffsetInFrame;
   return NS_OK;
@@ -1612,17 +1612,17 @@ ContentEventHandler::GetLastFrameInRange
                       true, &lastFrame);
   if (!lastFrame) {
     return FrameAndNodeOffset();
   }
 
   // If the last frame is a text frame, we need to check if the range actually
   // includes at least one character in the range.  Therefore, if it's not a
   // text frame, we need to do nothing anymore.
-  if (lastFrame->GetType() != nsGkAtoms::textFrame) {
+  if (!lastFrame->IsTextFrame()) {
     return FrameAndNodeOffset(lastFrame, nodePosition.mOffset);
   }
 
   int32_t start, end;
   if (NS_WARN_IF(NS_FAILED(lastFrame->GetOffsets(start, end)))) {
     return FrameAndNodeOffset();
   }
 
@@ -1650,17 +1650,17 @@ ContentEventHandler::GetLineBreakerRectB
   MOZ_ASSERT(ShouldBreakLineBefore(aFrame->GetContent(), mRootContent) ||
              IsMozBR(aFrame->GetContent()));
 
   nsIFrame* frameForFontMetrics = aFrame;
 
   // If it's not a <br> frame, this method computes the line breaker's rect
   // outside the frame.  Therefore, we need to compute with parent frame's
   // font metrics in such case.
-  if (aFrame->GetType() != nsGkAtoms::brFrame && aFrame->GetParent()) {
+  if (!aFrame->IsBrFrame() && aFrame->GetParent()) {
     frameForFontMetrics = aFrame->GetParent();
   }
 
   // Note that <br> element's rect is decided with line-height but we need
   // a rect only with font height.  Additionally, <br> frame's width and
   // height are 0 in quirks mode if it's not an empty line.  So, we cannot
   // use frame rect information even if it's a <br> frame.
 
@@ -1695,17 +1695,17 @@ ContentEventHandler::GetLineBreakerRectB
   // | I +-<p>-----------------  <p>'s border box
   // | I |
   // | I |
   // |   |
   //   ^- caret
   //
   // However, this is a hack for unusual scenario.  This hack shouldn't be
   // used as far as possible.
-  if (aFrame->GetType() != nsGkAtoms::brFrame) {
+  if (!aFrame->IsBrFrame()) {
     if (kWritingMode.IsVertical()) {
       if (kWritingMode.IsLineInverted()) {
         // above of top-left corner of aFrame.
         result.mRect.x = 0;
       } else {
         // above of top-right corner of aFrame.
         result.mRect.x = aFrame->GetRect().XMost() - result.mRect.width;
       }
@@ -1868,17 +1868,17 @@ ContentEventHandler::OnQueryTextRectArra
 
     nsIFrame* baseFrame = firstFrame;
     // charRect should have each character rect or line breaker rect relative
     // to the base frame.
     AutoTArray<nsRect, 16> charRects;
 
     // If the first frame is a text frame, the result should be computed with
     // the frame's API.
-    if (firstFrame->GetType() == nsGkAtoms::textFrame) {
+    if (firstFrame->IsTextFrame()) {
       rv = firstFrame->GetCharacterRectsInRange(firstFrame.mOffsetInNode,
                                                 kEndOffset - offset, charRects);
       if (NS_WARN_IF(NS_FAILED(rv)) || NS_WARN_IF(charRects.IsEmpty())) {
         return rv;
       }
       // Assign the characters whose rects are computed by the call of
       // nsTextFrame::GetCharacterRectsInRange().
       AppendSubString(chars, firstContent, firstFrame.mOffsetInNode,
@@ -1934,18 +1934,17 @@ ContentEventHandler::OnQueryTextRectArra
       //  +------------------------------------+
       // Therefore, if the first frame isn't a <br> frame and there is a text
       // node before the first node in the queried range, we should compute the
       // first rect with the previous character's rect.
       // If we already compute a character's rect in the queried range, we can
       // compute it with the cached last character's rect.  (However, don't
       // use this path if it's a <br> frame because trusting <br> frame's rect
       // is better than guessing the rect from the previous character.)
-      if (firstFrame->GetType() != nsGkAtoms::brFrame &&
-          aEvent->mInput.mOffset != offset) {
+      if (!firstFrame->IsBrFrame() && aEvent->mInput.mOffset != offset) {
         baseFrame = lastFrame;
         brRect = lastCharRect;
         if (!wasLineBreaker) {
           if (isVertical) {
             // Right of the last character.
             brRect.y = brRect.YMost() + 1;
             brRect.height = 1;
           } else {
@@ -1953,17 +1952,17 @@ ContentEventHandler::OnQueryTextRectArra
             brRect.x = brRect.XMost() + 1;
             brRect.width = 1;
           }
         }
       }
       // If it's not a <br> frame and it's the first character rect at the
       // queried range, we need to the previous character of the start of
       // the queried range if there is a text node.
-      else if (firstFrame->GetType() != nsGkAtoms::brFrame && lastTextContent) {
+      else if (!firstFrame->IsBrFrame() && lastTextContent) {
         FrameRelativeRect brRectRelativeToLastTextFrame =
           GuessLineBreakerRectAfter(lastTextContent);
         if (NS_WARN_IF(!brRectRelativeToLastTextFrame.IsValid())) {
           return NS_ERROR_FAILURE;
         }
         // Look for the last text frame for lastTextContent.
         nsIFrame* primaryFrame = lastTextContent->GetPrimaryFrame();
         if (NS_WARN_IF(!primaryFrame)) {
@@ -2176,21 +2175,21 @@ ContentEventHandler::OnQueryTextRect(Wid
     // caret rect at the end of the contents.
     if (lastFrame) {
       if (NS_WARN_IF(!lastFrame->GetContent())) {
         return NS_ERROR_FAILURE;
       }
       FrameRelativeRect relativeRect;
       // If there is a <br> frame at the end, it represents an empty line at
       // the end with moz-<br> or content <br> in a block level element.
-      if (lastFrame->GetType() == nsGkAtoms::brFrame) {
+      if (lastFrame->IsBrFrame()) {
         relativeRect = GetLineBreakerRectBefore(lastFrame);
       }
       // If there is a text frame at the end, use its information.
-      else if (lastFrame->GetType() == nsGkAtoms::textFrame) {
+      else if (lastFrame->IsTextFrame()) {
         relativeRect = GuessLineBreakerRectAfter(lastFrame->GetContent());
       }
       // If there is an empty frame which is neither a text frame nor a <br>
       // frame at the end, guess caret rect in it.
       else {
         relativeRect = GuessFirstCaretRectIn(lastFrame);
       }
       if (NS_WARN_IF(!relativeRect.IsValid())) {
@@ -2229,17 +2228,17 @@ ContentEventHandler::OnQueryTextRect(Wid
   }
 
   nsRect rect, frameRect;
   nsPoint ptOffset;
 
   // If the first frame is a text frame, the result should be computed with
   // the frame's rect but not including the rect before start point of the
   // queried range.
-  if (firstFrame->GetType() == nsGkAtoms::textFrame) {
+  if (firstFrame->IsTextFrame()) {
     rect.SetRect(nsPoint(0, 0), firstFrame->GetRect().Size());
     rv = ConvertToRootRelativeOffset(firstFrame, rect);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     frameRect = rect;
     // Exclude the rect before start point of the queried range.
     firstFrame->GetPointFromOffset(firstFrame.mOffsetInNode, &ptOffset);
@@ -2271,17 +2270,17 @@ ContentEventHandler::OnQueryTextRect(Wid
   //  +------------------------------------+
   //
   //  +-<p>--------------------------------+
   //  |def                                 |
   //  +------------------------------------+
   // Therefore, if the first frame isn't a <br> frame and there is a text
   // node before the first node in the queried range, we should compute the
   // first rect with the previous character's rect.
-  else if (firstFrame->GetType() != nsGkAtoms::brFrame && lastTextContent) {
+  else if (!firstFrame->IsBrFrame() && lastTextContent) {
     FrameRelativeRect brRectAfterLastChar =
       GuessLineBreakerRectAfter(lastTextContent);
     if (NS_WARN_IF(!brRectAfterLastChar.IsValid())) {
       return NS_ERROR_FAILURE;
     }
     rect = brRectAfterLastChar.mRect;
     rv = ConvertToRootRelativeOffset(brRectAfterLastChar.mBaseFrame, rect);
     if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -2337,29 +2336,28 @@ ContentEventHandler::OnQueryTextRect(Wid
         if (!primaryFrame) {
           continue;
         }
         // We should take only text frame's rect and br frame's rect.  We can
         // always use frame rect of text frame and GetLineBreakerRectBefore()
         // can return exactly correct rect only for <br> frame for now.  On the
         // other hand, GetLineBreakRectBefore() returns guessed caret rect for
         // the other frames.  We shouldn't include such odd rect to the result.
-        if (primaryFrame->GetType() == nsGkAtoms::textFrame ||
-            primaryFrame->GetType() == nsGkAtoms::brFrame) {
+        if (primaryFrame->IsTextFrame() || primaryFrame->IsBrFrame()) {
           frame = primaryFrame;
         }
       } while (!frame && !iter->IsDone());
       if (!frame) {
         break;
       }
     }
-    if (frame->GetType() == nsGkAtoms::textFrame) {
+    if (frame->IsTextFrame()) {
       frameRect.SetRect(nsPoint(0, 0), frame->GetRect().Size());
     } else {
-      MOZ_ASSERT(frame->GetType() == nsGkAtoms::brFrame);
+      MOZ_ASSERT(frame->IsBrFrame());
       FrameRelativeRect relativeRect = GetLineBreakerRectBefore(frame);
       if (NS_WARN_IF(!relativeRect.IsValid())) {
         return NS_ERROR_FAILURE;
       }
       frameRect = relativeRect.RectRelativeTo(frame);
     }
     rv = ConvertToRootRelativeOffset(frame, frameRect);
     if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -2381,17 +2379,17 @@ ContentEventHandler::OnQueryTextRect(Wid
     frameRect.SetRect(nsPoint(0, 0), lastFrame->GetRect().Size());
     rv = ConvertToRootRelativeOffset(lastFrame, frameRect);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   // Shrink the last frame for cutting off the text after the query range.
-  if (lastFrame->GetType() == nsGkAtoms::textFrame) {
+  if (lastFrame->IsTextFrame()) {
     lastFrame->GetPointFromOffset(lastFrame.mOffsetInNode, &ptOffset);
     if (lastFrame->GetWritingMode().IsVertical()) {
       frameRect.height -= lastFrame->GetRect().height - ptOffset.y;
     } else {
       frameRect.width -= lastFrame->GetRect().width - ptOffset.x;
     }
     // UnionRect() requires non-empty rect.  So, let's make sure to get
     // non-empty rect from the last frame.
@@ -2589,17 +2587,17 @@ ContentEventHandler::OnQueryCharacterAtP
                                 NodePosition(tentativeCaretOffsets),
                                 mRootContent,
                                 &aEvent->mReply.mTentativeCaretOffset,
                                 GetLineBreakType(aEvent));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  if (targetFrame->GetType() != nsGkAtoms::textFrame) {
+  if (!targetFrame->IsTextFrame()) {
     // There is no character at the point but there is tentative caret point.
     aEvent->mSucceeded = true;
     return NS_OK;
   }
 
   MOZ_ASSERT(
     aEvent->mReply.mTentativeCaretOffset != WidgetQueryContentEvent::NOT_FOUND,
     "The point is inside a character bounding box.  Why tentative caret point "
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -2734,20 +2734,20 @@ EventStateManager::DecideGestureEvent(Wi
     // assist is solving this.
     if (current && IsRemoteTarget(current->GetContent())) {
       panDirection = WidgetGestureNotifyEvent::ePanBoth;
       // We don't know when we reach bounds, so just disable feedback for now.
       displayPanFeedback = false;
       break;
     }
 
-    nsIAtom* currentFrameType = current->GetType();
+    FrameType currentFrameType = current->Type();
 
     // Scrollbars should always be draggable
-    if (currentFrameType == nsGkAtoms::scrollbarFrame) {
+    if (currentFrameType == FrameType::Scrollbar) {
       panDirection = WidgetGestureNotifyEvent::ePanNone;
       break;
     }
 
 #ifdef MOZ_XUL
     // Special check for trees
     nsTreeBodyFrame* treeFrame = do_QueryFrame(current);
     if (treeFrame) {
@@ -2764,17 +2764,17 @@ EventStateManager::DecideGestureEvent(Wi
     nsIScrollableFrame* scrollableFrame = do_QueryFrame(current);
     if (scrollableFrame) {
       if (current->IsFrameOfType(nsIFrame::eXULBox)) {
         displayPanFeedback = true;
 
         nsRect scrollRange = scrollableFrame->GetScrollRange();
         bool canScrollHorizontally = scrollRange.width > 0;
 
-        if (targetFrame->GetType() == nsGkAtoms::menuFrame) {
+        if (targetFrame->IsMenuFrame()) {
           // menu frames report horizontal scroll when they have submenus
           // and we don't want that
           canScrollHorizontally = false;
           displayPanFeedback = false;
         }
 
         // Vertical panning has priority over horizontal panning, so
         // when vertical movement is possible we can just finish the loop.
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -233,27 +233,29 @@ nsGenericHTMLElement::GetAccessKeyLabel(
   nsAutoString suffix;
   GetAccessKey(suffix);
   if (!suffix.IsEmpty()) {
     EventStateManager::GetAccessKeyLabelPrefix(this, aLabel);
     aLabel.Append(suffix);
   }
 }
 
-static bool IS_TABLE_CELL(nsIAtom* frameType) {
-  return nsGkAtoms::tableCellFrame == frameType ||
-    nsGkAtoms::bcTableCellFrame == frameType;
+static bool
+IS_TABLE_CELL(FrameType frameType)
+{
+  return FrameType::TableCell == frameType ||
+         FrameType::BCTableCell == frameType;
 }
 
 static bool
 IsOffsetParent(nsIFrame* aFrame)
 {
-  nsIAtom* frameType = aFrame->GetType();
-  
-  if (IS_TABLE_CELL(frameType) || frameType == nsGkAtoms::tableFrame) {
+  FrameType frameType = aFrame->Type();
+
+  if (IS_TABLE_CELL(frameType) || frameType == FrameType::Table) {
     // Per the IDL for Element, only td, th, and table are acceptable offsetParents
     // apart from body or positioned elements; we need to check the content type as
     // well as the frame type so we ignore anonymous tables created by an element
     // with display: table-cell with no actual table
     nsIContent* content = aFrame->GetContent();
 
     return content->IsAnyOfHTMLElements(nsGkAtoms::table,
                                         nsGkAtoms::td,
@@ -270,18 +272,17 @@ nsGenericHTMLElement::GetOffsetRect(CSSI
   nsIFrame* frame = GetStyledFrame();
   if (!frame) {
     return nullptr;
   }
 
   nsIFrame* parent = frame->GetParent();
   nsPoint origin(0, 0);
 
-  if (parent && parent->GetType() == nsGkAtoms::tableWrapperFrame &&
-      frame->GetType() == nsGkAtoms::tableFrame) {
+  if (parent && parent->IsTableWrapperFrame() && frame->IsTableFrame()) {
     origin = parent->GetPositionIgnoringScrolling();
     parent = parent->GetParent();
   }
 
   nsIContent* offsetParent = nullptr;
   Element* docElement = GetComposedDoc()->GetRootElement();
   nsIContent* content = frame->GetContent();
 
--- a/dom/svg/SVGTextContentElement.cpp
+++ b/dom/svg/SVGTextContentElement.cpp
@@ -33,26 +33,26 @@ nsSVGElement::LengthInfo SVGTextContentE
   { &nsGkAtoms::textLength, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::XY }
 };
 
 SVGTextFrame*
 SVGTextContentElement::GetSVGTextFrame()
 {
   nsIFrame* frame = GetPrimaryFrame(FlushType::Layout);
   nsIFrame* textFrame =
-    nsLayoutUtils::GetClosestFrameOfType(frame, nsGkAtoms::svgTextFrame);
+    nsLayoutUtils::GetClosestFrameOfType(frame, FrameType::SVGText);
   return static_cast<SVGTextFrame*>(textFrame);
 }
 
 SVGTextFrame*
 SVGTextContentElement::GetSVGTextFrameForNonLayoutDependentQuery()
 {
   nsIFrame* frame = GetPrimaryFrame(FlushType::Frames);
   nsIFrame* textFrame =
-    nsLayoutUtils::GetClosestFrameOfType(frame, nsGkAtoms::svgTextFrame);
+    nsLayoutUtils::GetClosestFrameOfType(frame, FrameType::SVGText);
   return static_cast<SVGTextFrame*>(textFrame);
 }
 
 already_AddRefed<SVGAnimatedLength>
 SVGTextContentElement::TextLength()
 {
   return LengthAttributes()[TEXTLENGTH].ToDOMAnimatedLength(this);
 }
--- a/layout/base/AccessibleCaretManager.cpp
+++ b/layout/base/AccessibleCaretManager.cpp
@@ -1260,17 +1260,17 @@ AccessibleCaretManager::DragCaretInterna
   }
 
   ClearMaintainedSelection();
 
   nsIFrame* anchorFrame = nullptr;
   selection->GetPrimaryFrameForAnchorNode(&anchorFrame);
 
   nsIFrame* scrollable =
-    nsLayoutUtils::GetClosestFrameOfType(anchorFrame, nsGkAtoms::scrollFrame);
+    nsLayoutUtils::GetClosestFrameOfType(anchorFrame, FrameType::Scroll);
   AutoWeakFrame weakScrollable = scrollable;
   fs->HandleClick(offsets.content, offsets.StartOffset(), offsets.EndOffset(),
                   GetCaretMode() == CaretMode::Selection, false,
                   offsets.associate);
   if (!weakScrollable.IsAlive()) {
     return NS_OK;
   }
 
--- a/layout/base/GeckoRestyleManager.cpp
+++ b/layout/base/GeckoRestyleManager.cpp
@@ -702,43 +702,43 @@ ElementForStyleContext(nsIContent* aPare
   }
 
   if (aPseudoType == CSSPseudoElementType::InheritingAnonBox ||
       aPseudoType == CSSPseudoElementType::NonInheritingAnonBox) {
     return nullptr;
   }
 
   if (aPseudoType == CSSPseudoElementType::firstLetter) {
-    NS_ASSERTION(aFrame->GetType() == nsGkAtoms::letterFrame,
+    NS_ASSERTION(aFrame->IsLetterFrame(),
                  "firstLetter pseudoTag without a nsFirstLetterFrame");
     nsBlockFrame* block = nsBlockFrame::GetNearestAncestorBlock(aFrame);
     return block->GetContent()->AsElement();
   }
 
   if (aPseudoType == CSSPseudoElementType::mozColorSwatch) {
     MOZ_ASSERT(aFrame->GetParent() &&
                aFrame->GetParent()->GetParent(),
                "Color swatch frame should have a parent & grandparent");
 
     nsIFrame* grandparentFrame = aFrame->GetParent()->GetParent();
-    MOZ_ASSERT(grandparentFrame->GetType() == nsGkAtoms::colorControlFrame,
+    MOZ_ASSERT(grandparentFrame->IsColorControlFrame(),
                "Color swatch's grandparent should be nsColorControlFrame");
 
     return grandparentFrame->GetContent()->AsElement();
   }
 
   if (aPseudoType == CSSPseudoElementType::mozNumberText ||
       aPseudoType == CSSPseudoElementType::mozNumberWrapper ||
       aPseudoType == CSSPseudoElementType::mozNumberSpinBox ||
       aPseudoType == CSSPseudoElementType::mozNumberSpinUp ||
       aPseudoType == CSSPseudoElementType::mozNumberSpinDown) {
     // Get content for nearest nsNumberControlFrame:
     nsIFrame* f = aFrame->GetParent();
     MOZ_ASSERT(f);
-    while (f->GetType() != nsGkAtoms::numberControlFrame) {
+    while (!f->IsNumberControlFrame()) {
       f = f->GetParent();
       MOZ_ASSERT(f);
     }
     return f->GetContent()->AsElement();
   }
 
   Element* frameElement = aFrame->GetContent()->AsElement();
   if (frameElement->IsNativeAnonymous() &&
@@ -856,26 +856,26 @@ GetPrevContinuationWithSameStyle(nsIFram
     prevContinuation = nullptr;
   }
   return prevContinuation;
 }
 
 nsresult
 GeckoRestyleManager::ReparentStyleContext(nsIFrame* aFrame)
 {
-  nsIAtom* frameType = aFrame->GetType();
-  if (frameType == nsGkAtoms::placeholderFrame) {
+  FrameType frameType = aFrame->Type();
+  if (frameType == FrameType::Placeholder) {
     // Also reparent the out-of-flow and all its continuations.
     nsIFrame* outOfFlow =
       nsPlaceholderFrame::GetRealFrameForPlaceholder(aFrame);
     NS_ASSERTION(outOfFlow, "no out-of-flow frame");
     do {
       ReparentStyleContext(outOfFlow);
     } while ((outOfFlow = outOfFlow->GetNextContinuation()));
-  } else if (frameType == nsGkAtoms::backdropFrame) {
+  } else if (frameType == FrameType::Backdrop) {
     // Style context of backdrop frame has no parent style context, and
     // thus we do not need to reparent it.
     return NS_OK;
   }
 
   // DO NOT verify the style tree before reparenting.  The frame
   // tree has already been changed, so this check would just fail.
   nsStyleContext* oldContext = aFrame->StyleContext();
@@ -987,17 +987,17 @@ GeckoRestyleManager::ReparentStyleContex
 
       nsIFrame::ChildListIterator lists(aFrame);
       for (; !lists.IsDone(); lists.Next()) {
         for (nsIFrame* child : lists.CurrentList()) {
           // only do frames that are in flow
           if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
               child != providerChild) {
 #ifdef DEBUG
-            if (nsGkAtoms::placeholderFrame == child->GetType()) {
+            if (child->IsPlaceholderFrame()) {
               nsIFrame* outOfFlowFrame =
                 nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
               NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
 
               NS_ASSERTION(outOfFlowFrame != providerChild,
                            "Out of flow provider?");
             }
 #endif
@@ -1435,17 +1435,17 @@ ElementRestyler::ConditionallyRestyleCon
     nsIFrame::ChildListIterator lists(f);
     for (; !lists.IsDone(); lists.Next()) {
       for (nsIFrame* child : lists.CurrentList()) {
         // Out-of-flows are reached through their placeholders.  Continuations
         // and block-in-inline splits are reached through those chains.
         if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
             !GetPrevContinuationWithSameStyle(child)) {
           // only do frames that are in flow
-          if (child->GetType() == nsGkAtoms::placeholderFrame) { // placeholder
+          if (child->IsPlaceholderFrame()) { // placeholder
             // get out of flow frame and recur there
             nsIFrame* outOfFlowFrame =
               nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
 
             // |nsFrame::GetParentStyleContext| checks being out
             // of flow so that this works correctly.
             do {
               if (GetPrevContinuationWithSameStyle(outOfFlowFrame)) {
@@ -1648,26 +1648,25 @@ ElementRestyler::MoveStyleContextsForCon
       if (child->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
         return false;
       }
       if (GetPrevContinuationWithSameStyle(child)) {
         continue;
       }
       // Bail out if we have placeholder frames.
       // FIXME: It is probably safe to just continue here instead of bailing out.
-      if (nsGkAtoms::placeholderFrame == child->GetType()) {
+      if (child->IsPlaceholderFrame()) {
         return false;
       }
       nsStyleContext* sc = child->StyleContext();
       if (sc->GetParent() != aOldContext) {
         return false;
       }
-      nsIAtom* type = child->GetType();
-      if (type == nsGkAtoms::letterFrame ||
-          type == nsGkAtoms::lineFrame) {
+      FrameType type = child->Type();
+      if (type == FrameType::Letter || type == FrameType::Line) {
         return false;
       }
       if (sc->HasChildThatUsesGrandancestorStyle()) {
         // XXX Not sure if we need this?
         return false;
       }
       nsIAtom* pseudoTag = sc->GetPseudo();
       if (pseudoTag && !nsCSSAnonBoxes::IsNonElement(pseudoTag)) {
@@ -2064,26 +2063,26 @@ ElementRestyler::ComputeRestyleResultFro
     return;
   }
 
   // Style changes might have moved children between the two nsLetterFrames
   // (the one matching ::first-letter and the one containing the rest of the
   // content).  Continue restyling to the children of the nsLetterFrame so
   // that they get the correct style context parent.  Similarly for
   // nsLineFrames.
-  nsIAtom* type = aSelf->GetType();
-
-  if (type == nsGkAtoms::letterFrame) {
+  FrameType type = aSelf->Type();
+
+  if (type == FrameType::Letter) {
     LOG_RESTYLE_CONTINUE("frame is a letter frame");
     aRestyleResult = RestyleResult::eContinue;
     aCanStopWithStyleChange = false;
     return;
   }
 
-  if (type == nsGkAtoms::lineFrame) {
+  if (type == FrameType::Line) {
     LOG_RESTYLE_CONTINUE("frame is a line frame");
     aRestyleResult = RestyleResult::eContinue;
     aCanStopWithStyleChange = false;
     return;
   }
 
   // Some style computations depend not on the parent's style, but a grandparent
   // or one the grandparent's ancestors.  An example is an explicit 'inherit'
@@ -2495,17 +2494,17 @@ ElementRestyler::RestyleSelf(nsIFrame* a
       ->GetPseudo() == oldContext->GetPseudo() &&
      prevContinuationContext->GetParent() == parentContext;
   if (copyFromContinuation) {
     // Just use the style context from the frame's previous
     // continuation.
     LOG_RESTYLE("using previous continuation's context");
     newContext = prevContinuationContext;
   } else if (pseudoTag == nsCSSAnonBoxes::mozText) {
-    MOZ_ASSERT(aSelf->GetType() == nsGkAtoms::textFrame);
+    MOZ_ASSERT(aSelf->IsTextFrame());
     newContext =
       styleSet->ResolveStyleForText(aSelf->GetContent(), parentContext);
   } else if (pseudoTag == nsCSSAnonBoxes::firstLetterContinuation) {
     newContext = styleSet->ResolveStyleForFirstLetterContinuation(parentContext);
   } else if (pseudoTag == nsCSSAnonBoxes::oofPlaceholder) {
     // We still need to ResolveStyleForPlaceholder() here, because we may be
     // doing a ruletree reconstruct and hence actually changing our style
     // context.
@@ -3416,17 +3415,17 @@ ElementRestyler::RestyleContentChildren(
         // nsPageFrame that does not have a content.
         nsIContent* parent = child->GetContent() ? child->GetContent()->GetParent() : nullptr;
         TreeMatchContext::AutoAncestorPusher insertionPointPusher(mTreeMatchContext);
         if (parent && nsContentUtils::IsContentInsertionPoint(parent)) {
           insertionPointPusher.PushAncestorAndStyleScope(parent);
         }
 
         // only do frames that are in flow
-        if (nsGkAtoms::placeholderFrame == child->GetType()) { // placeholder
+        if (child->IsPlaceholderFrame()) { // placeholder
           // get out of flow frame and recur there
           nsIFrame* outOfFlowFrame =
             nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
           NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
           NS_ASSERTION(outOfFlowFrame != mResolvedChild,
                        "out-of-flow frame not a true descendant");
 
           // |nsFrame::GetParentStyleContext| checks being out
--- a/layout/base/GeometryUtils.cpp
+++ b/layout/base/GeometryUtils.cpp
@@ -180,18 +180,17 @@ public:
       // table
       mIncludeCaptionBoxForTable = false;
     }
   }
 
   virtual void AddBox(nsIFrame* aFrame) override
   {
     nsIFrame* f = aFrame;
-    if (mBoxType == CSSBoxType::Margin &&
-        f->GetType() == nsGkAtoms::tableFrame) {
+    if (mBoxType == CSSBoxType::Margin && f->IsTableFrame()) {
       // Margin boxes for table frames should be taken from the table wrapper
       // frame, since that has the margin.
       f = f->GetParent();
     }
     nsRect box = GetBoxRectForFrame(&f, mBoxType);
     nsPoint appUnits[4] =
       { box.TopLeft(), box.TopRight(), box.BottomRight(), box.BottomLeft() };
     CSSPoint points[4];
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -1765,18 +1765,19 @@ PresShell::Initialize(nscoord aWidth, ns
 
   nsIFrame* invalidateFrame = nullptr;
   for (nsIFrame* f = rootFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
     if (f->GetStateBits() & NS_FRAME_NO_COMPONENT_ALPHA) {
       invalidateFrame = f;
       f->RemoveStateBits(NS_FRAME_NO_COMPONENT_ALPHA);
     }
     nsCOMPtr<nsIPresShell> shell;
-    if (f->GetType() == nsGkAtoms::subDocumentFrame &&
-        (shell = static_cast<nsSubDocumentFrame*>(f)->GetSubdocumentPresShellForPainting(0)) &&
+    if (f->IsSubDocumentFrame() &&
+        (shell = static_cast<nsSubDocumentFrame*>(f)
+                   ->GetSubdocumentPresShellForPainting(0)) &&
         shell->GetPresContext()->IsRootContentDocument()) {
       // Root content documents build a 'force active' layer, and component alpha flattening
       // can't be propagated across that so no need to invalidate above this frame.
       break;
     }
 
 
   }
@@ -2468,20 +2469,20 @@ nsIPresShell::GetRootFrameExternal() con
   return mFrameConstructor->GetRootFrame();
 }
 
 nsIFrame*
 nsIPresShell::GetRootScrollFrame() const
 {
   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
   // Ensure root frame is a viewport frame
-  if (!rootFrame || nsGkAtoms::viewportFrame != rootFrame->GetType())
+  if (!rootFrame || !rootFrame->IsViewportFrame())
     return nullptr;
   nsIFrame* theFrame = rootFrame->PrincipalChildList().FirstChild();
-  if (!theFrame || nsGkAtoms::scrollFrame != theFrame->GetType())
+  if (!theFrame || !theFrame->IsScrollFrame())
     return nullptr;
   return theFrame;
 }
 
 nsIScrollableFrame*
 nsIPresShell::GetRootScrollFrameAsScrollable() const
 {
   nsIFrame* frame = GetRootScrollFrame();
@@ -2752,17 +2753,17 @@ PresShell::FrameNeedsReflow(nsIFrame *aF
       // code; see comments there for how and why it differs.
       AutoTArray<nsIFrame*, 32> stack;
       stack.AppendElement(subtreeRoot);
 
       do {
         nsIFrame *f = stack.ElementAt(stack.Length() - 1);
         stack.RemoveElementAt(stack.Length() - 1);
 
-        if (f->GetType() == nsGkAtoms::placeholderFrame) {
+        if (f->IsPlaceholderFrame()) {
           nsIFrame *oof = nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
           if (!nsLayoutUtils::IsProperAncestorFrame(subtreeRoot, oof)) {
             // We have another distinct subtree we need to mark.
             subtrees.AppendElement(oof);
           }
         }
 
         nsIFrame::ChildListIterator lists(f);
@@ -3261,19 +3262,17 @@ AccumulateFrameBounds(nsIFrame* aContain
     nsIFrame *f = aFrame;
 
     while (f && f->IsFrameOfType(nsIFrame::eLineParticipant) &&
            !f->IsTransformed() && !f->IsAbsPosContainingBlock()) {
       prevFrame = f;
       f = prevFrame->GetParent();
     }
 
-    if (f != aFrame &&
-        f &&
-        f->GetType() == nsGkAtoms::blockFrame) {
+    if (f != aFrame && f && f->IsBlockFrame()) {
       // find the line containing aFrame and increase the top of |offset|.
       if (f != aPrevBlock) {
         aLines = f->GetLineIterator();
         aPrevBlock = f;
         aCurLine = 0;
       }
       if (aLines) {
         int32_t index = aLines->FindLineContaining(prevFrame, aCurLine);
@@ -3529,17 +3528,17 @@ PresShell::DoScrollContentIntoView()
     // coords and size are all zero, and it has no content showing anyway.
     // Don't bother scrolling to it.  We'll try again when we finish up layout.
     return;
   }
 
   // Make sure we skip 'frame' ... if it's scrollable, we should use its
   // scrollable ancestor as the container.
   nsIFrame* container =
-    nsLayoutUtils::GetClosestFrameOfType(frame->GetParent(), nsGkAtoms::scrollFrame);
+    nsLayoutUtils::GetClosestFrameOfType(frame->GetParent(), FrameType::Scroll);
   if (!container) {
     // nothing can be scrolled
     return;
   }
 
   ScrollIntoViewData* data = static_cast<ScrollIntoViewData*>(
     mContentToScrollTo->GetProperty(nsGkAtoms::scrolling));
   if (MOZ_UNLIKELY(!data)) {
@@ -4815,17 +4814,17 @@ PresShell::ClipListToRange(nsDisplayList
     // itemToInsert indiciates the item that should be inserted into the
     // temporary list. If null, no item should be inserted.
     nsDisplayItem* itemToInsert = nullptr;
     nsIFrame* frame = i->Frame();
     nsIContent* content = frame->GetContent();
     if (content) {
       bool atStart = (content == aRange->GetStartParent());
       bool atEnd = (content == aRange->GetEndParent());
-      if ((atStart || atEnd) && frame->GetType() == nsGkAtoms::textFrame) {
+      if ((atStart || atEnd) && frame->IsTextFrame()) {
         int32_t frameStartOffset, frameEndOffset;
         frame->GetOffsets(frameStartOffset, frameEndOffset);
 
         int32_t hilightStart =
           atStart ? std::max(aRange->StartOffset(), frameStartOffset) : frameStartOffset;
         int32_t hilightEnd =
           atEnd ? std::min(aRange->EndOffset(), frameEndOffset) : frameEndOffset;
         if (hilightStart < hilightEnd) {
@@ -9561,17 +9560,17 @@ ReResolveMenusAndTrees(nsIFrame *aFrame,
     menu->CloseMenu(true);
   return true;
 }
 
 static bool
 ReframeImageBoxes(nsIFrame *aFrame, void *aClosure)
 {
   nsStyleChangeList *list = static_cast<nsStyleChangeList*>(aClosure);
-  if (aFrame->GetType() == nsGkAtoms::imageBoxFrame) {
+  if (aFrame->IsImageBoxFrame()) {
     list->AppendChange(aFrame, aFrame->GetContent(),
                        nsChangeHint_ReconstructFrame);
     return false; // don't walk descendants
   }
   return true; // walk descendants
 }
 
 static void
@@ -9868,17 +9867,17 @@ LogVerifyMessage(nsIFrame* k1, nsIFrame*
 static bool
 CompareTrees(nsPresContext* aFirstPresContext, nsIFrame* aFirstFrame,
              nsPresContext* aSecondPresContext, nsIFrame* aSecondFrame)
 {
   if (!aFirstPresContext || !aFirstFrame || !aSecondPresContext || !aSecondFrame)
     return true;
   // XXX Evil hack to reduce false positives; I can't seem to figure
   // out how to flush scrollbar changes correctly
-  //if (aFirstFrame->GetType() == nsGkAtoms::scrollbarFrame)
+  //if (aFirstFrame->IsScrollbarFrame())
   //  return true;
   bool ok = true;
   nsIFrame::ChildListIterator lists1(aFirstFrame);
   nsIFrame::ChildListIterator lists2(aSecondFrame);
   do {
     const nsFrameList& kids1 = !lists1.IsDone() ? lists1.CurrentList() : nsFrameList();
     const nsFrameList& kids2 = !lists2.IsDone() ? lists2.CurrentList() : nsFrameList();
     int32_t l1 = kids1.GetLength();
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -614,17 +614,17 @@ VerifyStyleTree(nsIFrame* aFrame)
   nsStyleContext* context = aFrame->StyleContext();
   VerifyContextParent(aFrame, context, nullptr);
 
   nsIFrame::ChildListIterator lists(aFrame);
   for (; !lists.IsDone(); lists.Next()) {
     for (nsIFrame* child : lists.CurrentList()) {
       if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
         // only do frames that are in flow
-        if (nsGkAtoms::placeholderFrame == child->GetType()) {
+        if (child->IsPlaceholderFrame()) {
           // placeholder: first recurse and verify the out of flow frame,
           // then verify the placeholder's context
           nsIFrame* outOfFlowFrame =
             nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
 
           // recurse to out of flow frame, letting the parent context get resolved
           do {
             VerifyStyleTree(outOfFlowFrame);
@@ -697,28 +697,28 @@ static void StyleChangeReflow(nsIFrame* 
  * may have been propagated up to an ancestor frame. Processing hints using an
  * ancestor frame is fine in general, but nsChangeHint_ChildrenOnlyTransform is
  * a special case since it is intended to update the children of a specific
  * frame.
  */
 static nsIFrame*
 GetFrameForChildrenOnlyTransformHint(nsIFrame* aFrame)
 {
-  if (aFrame->GetType() == nsGkAtoms::viewportFrame) {
+  if (aFrame->IsViewportFrame()) {
     // This happens if the root-<svg> is fixed positioned, in which case we
     // can't use aFrame->GetContent() to find the primary frame, since
     // GetContent() returns nullptr for ViewportFrame.
     aFrame = aFrame->PrincipalChildList().FirstChild();
   }
   // For an nsHTMLScrollFrame, this will get the SVG frame that has the
   // children-only transforms:
   aFrame = aFrame->GetContent()->GetPrimaryFrame();
-  if (aFrame->GetType() == nsGkAtoms::svgOuterSVGFrame) {
+  if (aFrame->IsSVGOuterSVGFrame()) {
     aFrame = aFrame->PrincipalChildList().FirstChild();
-    MOZ_ASSERT(aFrame->GetType() == nsGkAtoms::svgOuterSVGAnonChildFrame,
+    MOZ_ASSERT(aFrame->IsSVGOuterSVGAnonChildFrame(),
                "Where is the nsSVGOuterSVGFrame's anon child??");
   }
   MOZ_ASSERT(aFrame->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer),
              "Children-only transforms only expected on SVG frames");
   return aFrame;
 }
 
 // Returns true if this function managed to successfully move a frame, and
@@ -726,17 +726,17 @@ GetFrameForChildrenOnlyTransformHint(nsI
 // be performed instead.
 bool
 RecomputePosition(nsIFrame* aFrame)
 {
   // Don't process position changes on table frames, since we already handle
   // the dynamic position change on the table wrapper frame, and the
   // reflow-based fallback code path also ignores positions on inner table
   // frames.
-  if (aFrame->GetType() == nsGkAtoms::tableFrame) {
+  if (aFrame->IsTableFrame()) {
     return true;
   }
 
   const nsStyleDisplay* display = aFrame->StyleDisplay();
   // Changes to the offsets of a non-positioned element can safely be ignored.
   if (display->mPosition == NS_STYLE_POSITION_STATIC) {
     return true;
   }
@@ -836,17 +836,17 @@ RecomputePosition(nsIFrame* aFrame)
 
   // The bogus parent state here was created with no parent state of its own,
   // and therefore it won't have an mCBReflowInput set up.
   // But we may need one (for InitCBReflowInput in a child state), so let's
   // try to create one here for the cases where it will be needed.
   Maybe<ReflowInput> cbReflowInput;
   nsIFrame* cbFrame = parentFrame->GetContainingBlock();
   if (cbFrame && (aFrame->GetContainingBlock() != parentFrame ||
-                  parentFrame->GetType() == nsGkAtoms::tableFrame)) {
+                  parentFrame->IsTableFrame())) {
     LogicalSize cbSize = cbFrame->GetLogicalSize();
     cbReflowInput.emplace(cbFrame->PresContext(), cbFrame, &rc, cbSize);
     cbReflowInput->ComputedPhysicalMargin() = cbFrame->GetUsedMargin();
     cbReflowInput->ComputedPhysicalPadding() = cbFrame->GetUsedPadding();
     cbReflowInput->ComputedPhysicalBorderPadding() =
       cbFrame->GetUsedBorderAndPadding();
     parentReflowInput.mCBReflowInput = cbReflowInput.ptr();
   }
@@ -941,17 +941,17 @@ HasBoxAncestor(nsIFrame* aFrame)
 static bool
 FrameHasPositionedPlaceholderDescendants(nsIFrame* aFrame,
                                          uint32_t aPositionMask)
 {
   MOZ_ASSERT(aPositionMask & (1 << NS_STYLE_POSITION_FIXED));
 
   for (nsIFrame::ChildListIterator lists(aFrame); !lists.IsDone(); lists.Next()) {
     for (nsIFrame* f : lists.CurrentList()) {
-      if (f->GetType() == nsGkAtoms::placeholderFrame) {
+      if (f->IsPlaceholderFrame()) {
         nsIFrame* outOfFlow =
           nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
         // If SVG text frames could appear here, they could confuse us since
         // they ignore their position style ... but they can't.
         NS_ASSERTION(!nsSVGUtils::IsInSVGTextSubtree(outOfFlow),
                      "SVG text frames can't be out of flow");
         if (aPositionMask & (1 << outOfFlow->StyleDisplay()->mPosition)) {
           return true;
@@ -1074,17 +1074,17 @@ DoApplyRenderingChangeToTree(nsIFrame* a
       }
     }
     if (aChange & nsChangeHint_UpdateTextPath) {
       if (nsSVGUtils::IsInSVGTextSubtree(aFrame)) {
         // Invalidate and reflow the entire SVGTextFrame:
         NS_ASSERTION(aFrame->GetContent()->IsSVGElement(nsGkAtoms::textPath),
                      "expected frame for a <textPath> element");
         nsIFrame* text =
-          nsLayoutUtils::GetClosestFrameOfType(aFrame, nsGkAtoms::svgTextFrame);
+          nsLayoutUtils::GetClosestFrameOfType(aFrame, FrameType::SVGText);
         NS_ASSERTION(text, "expected to find an ancestor SVGTextFrame");
         static_cast<SVGTextFrame*>(text)->NotifyGlyphMetricsChange();
       } else {
         MOZ_ASSERT(false, "unexpected frame got nsChangeHint_UpdateTextPath");
       }
     }
     if (aChange & nsChangeHint_UpdateOpacityLayer) {
       // FIXME/bug 796697: we can get away with empty transactions for
@@ -1151,17 +1151,17 @@ SyncViewsAndInvalidateDescendants(nsIFra
     aFrame->SyncFrameViewProperties();
   }
 
   nsIFrame::ChildListIterator lists(aFrame);
   for (; !lists.IsDone(); lists.Next()) {
     for (nsIFrame* child : lists.CurrentList()) {
       if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
         // only do frames that don't have placeholders
-        if (nsGkAtoms::placeholderFrame == child->GetType()) {
+        if (child->IsPlaceholderFrame()) {
           // do the out-of-flow frame and its continuations
           nsIFrame* outOfFlowFrame =
             nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
           DoApplyRenderingChangeToTree(outOfFlowFrame, aChange);
         } else if (lists.CurrentID() == nsIFrame::kPopupList) {
           DoApplyRenderingChangeToTree(child, aChange);
         } else { // regular frame
           SyncViewsAndInvalidateDescendants(child, aChange);
@@ -1424,17 +1424,17 @@ RestyleManager::ProcessRestyledFrames(ns
       if (!(hint & nsChangeHint_ReconstructFrame)) {
         continue;
       }
     }
 
     if ((hint & nsChangeHint_UpdateContainingBlock) && frame &&
         !(hint & nsChangeHint_ReconstructFrame)) {
       if (NeedToReframeForAddingOrRemovingTransform(frame) ||
-          frame->GetType() == nsGkAtoms::fieldSetFrame ||
+          frame->IsFieldSetFrame() ||
           frame->GetContentInsertionFrame() != frame) {
         // The frame has positioned children that need to be reparented, or
         // it can't easily be converted to/from being an abs-pos container correctly.
         hint |= nsChangeHint_ReconstructFrame;
       } else {
         for (nsIFrame* cont = frame; cont;
              cont = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) {
           // Normally frame construction would set state bits as needed,
@@ -1680,18 +1680,17 @@ RestyleManager::ProcessRestyledFrames(ns
 
 #ifdef DEBUG
     // reget frame from content since it may have been regenerated...
     if (data.mContent) {
       nsIFrame* frame = data.mContent->GetPrimaryFrame();
       if (frame) {
         DebugVerifyStyleTree(frame);
       }
-    } else if (!data.mFrame ||
-               data.mFrame->GetType() != nsGkAtoms::viewportFrame) {
+    } else if (!data.mFrame || !data.mFrame->IsViewportFrame()) {
       NS_WARNING("Unable to test style tree integrity -- no content node "
                  "(and not a viewport frame)");
     }
 #endif
   }
 
   aChangeList.Clear();
 }
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -146,17 +146,17 @@ ServoRestyleManager::ProcessPostTraversa
   nsChangeHint changeHint = Servo_TakeChangeHint(aElement);
 
   // Handle lazy frame construction by posting a reconstruct for any lazily-
   // constructed roots.
   if (aElement->HasFlag(NODE_NEEDS_FRAME)) {
     changeHint |= nsChangeHint_ReconstructFrame;
     // The only time the primary frame is non-null is when image maps do hacky
     // SetPrimaryFrame calls.
-    MOZ_ASSERT_IF(styleFrame, styleFrame->GetType() == nsGkAtoms::imageFrame);
+    MOZ_ASSERT_IF(styleFrame, styleFrame->IsImageFrame());
     styleFrame = nullptr;
   }
 
   // Although we shouldn't generate non-ReconstructFrame hints for elements with
   // no frames, we can still get them here if they were explicitly posted by
   // PostRestyleEvent, such as a RepaintFrame hint when a :link changes to be
   // :visited.  Skip processing these hints if there is no frame.
   if ((styleFrame || (changeHint & nsChangeHint_ReconstructFrame)) && changeHint) {
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -500,20 +500,20 @@ DumpBidiLine(BidiLineData* aData, bool a
 
 /* Some helper methods for Resolve() */
 
 // Should this frame be split between text runs?
 static bool
 IsBidiSplittable(nsIFrame* aFrame)
 {
   // Bidi inline containers should be split, unless they're line frames.
-  nsIAtom* frameType = aFrame->GetType();
+  FrameType frameType = aFrame->Type();
   return (aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer) &&
-          frameType != nsGkAtoms::lineFrame) ||
-         frameType == nsGkAtoms::textFrame;
+          frameType != FrameType::Line) ||
+         frameType == FrameType::Text;
 }
 
 // Should this frame be treated as a leaf (e.g. when building mLogicalFrames)?
 static bool
 IsBidiLeaf(nsIFrame* aFrame)
 {
   nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
   return !kid || !aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer);
@@ -637,18 +637,17 @@ CreateContinuation(nsIFrame*  aFrame,
   nsContainerFrame* parent = aFrame->GetParent();
   NS_ASSERTION(parent, "Couldn't get frame parent in nsBidiPresUtils::CreateContinuation");
 
   nsresult rv = NS_OK;
   
   // Have to special case floating first letter frames because the continuation
   // doesn't go in the first letter frame. The continuation goes with the rest
   // of the text that the first letter frame was made out of.
-  if (parent->GetType() == nsGkAtoms::letterFrame &&
-      parent->IsFloating()) {
+  if (parent->IsLetterFrame() && parent->IsFloating()) {
     nsFirstLetterFrame* letterFrame = do_QueryFrame(parent);
     rv = letterFrame->CreateContinuationForFloatingParent(presContext, aFrame,
                                                           aNewFrame, aIsFluid);
     return rv;
   }
 
   *aNewFrame = presShell->FrameConstructor()->
     CreateContinuingFrame(presContext, aFrame, parent, aIsFluid);
@@ -856,18 +855,17 @@ nsBidiPresUtils::ResolveParagraph(BidiPa
 
   for (; ;) {
     if (fragmentLength <= 0) {
       // Get the next frame from mLogicalFrames
       if (++frameIndex >= frameCount) {
         break;
       }
       frame = aBpd->FrameAt(frameIndex);
-      if (frame == NS_BIDI_CONTROL_FRAME ||
-          nsGkAtoms::textFrame != frame->GetType()) {
+      if (frame == NS_BIDI_CONTROL_FRAME || !frame->IsTextFrame()) {
         /*
          * Any non-text frame corresponds to a single character in the text buffer
          * (a bidi control character, LINE SEPARATOR, or OBJECT SUBSTITUTE)
          */
         isTextFrame = false;
         fragmentLength = 1;
       } else {
         currentLine = aBpd->GetLineForFrameAt(frameIndex);
@@ -1064,20 +1062,20 @@ nsBidiPresUtils::TraverseFrames(nsBlockI
      * twice.
      */
     nsIFrame* nextSibling = childFrame->GetNextSibling();
 
     // If the real frame for a placeholder is a first letter frame, we need to
     // drill down into it and include its contents in Bidi resolution.
     // If not, we just use the placeholder.
     nsIFrame* frame = childFrame;
-    if (nsGkAtoms::placeholderFrame == childFrame->GetType()) {
+    if (childFrame->IsPlaceholderFrame()) {
       nsIFrame* realFrame =
         nsPlaceholderFrame::GetRealFrameForPlaceholder(childFrame);
-      if (realFrame->GetType() == nsGkAtoms::letterFrame) {
+      if (realFrame->IsLetterFrame()) {
         frame = realFrame;
       }
     }
 
     auto DifferentBidiValues = [](nsStyleContext* aSC1, nsIFrame* aFrame2) {
       nsStyleContext* sc2 = aFrame2->StyleContext();
       return GetBidiControl(aSC1) != GetBidiControl(sc2) ||
              GetBidiOverride(aSC1) != GetBidiOverride(sc2);
@@ -1122,18 +1120,18 @@ nsBidiPresUtils::TraverseFrames(nsBlockI
        * and add its index to the mContentToFrameIndex hashtable. This
        * will be used in RemoveBidiContinuation() to identify the last
        * frame in the array with a given content.
        */
       nsIContent* content = frame->GetContent();
       aBpd->AppendFrame(frame, aLineIter, content);
 
       // Append the content of the frame to the paragraph buffer
-      nsIAtom* frameType = frame->GetType();
-      if (nsGkAtoms::textFrame == frameType) {
+      FrameType frameType = frame->Type();
+      if (FrameType::Text == frameType) {
         if (content != aBpd->mPrevContent) {
           aBpd->mPrevContent = content;
           if (!frame->StyleText()->NewlineIsSignificant(
                 static_cast<nsTextFrame*>(frame))) {
             content->AppendTextTo(aBpd->mBuffer);
           } else {
             /*
              * For preformatted text we have to do bidi resolution on each line
@@ -1238,17 +1236,17 @@ nsBidiPresUtils::TraverseFrames(nsBlockI
                */
               if (frame && frame == nextSibling) {
                 nextSibling = frame->GetNextSibling();
               }
 
             } while (next);
           }
         }
-      } else if (nsGkAtoms::brFrame == frameType) {
+      } else if (FrameType::Br == frameType) {
         // break frame -- append line separator
         aBpd->AppendUnichar(kLineSeparator);
         ResolveParagraphWithinBlock(aBpd);
       } else { 
         // other frame type -- see the Unicode Bidi Algorithm:
         // "...inline objects (such as graphics) are treated as if they are ...
         // U+FFFC"
         // <wbr>, however, is treated as U+200B ZERO WIDTH SPACE. See
@@ -1296,32 +1294,32 @@ nsBidiPresUtils::ChildListMayRequireBidi
 
   for (nsIFrame* childFrame = aFirstChild; childFrame;
        childFrame = childFrame->GetNextSibling()) {
 
     nsIFrame* frame = childFrame;
 
     // If the real frame for a placeholder is a first-letter frame, we need to
     // consider its contents for potential Bidi resolution.
-    if (childFrame->GetType() == nsGkAtoms::placeholderFrame) {
+    if (childFrame->IsPlaceholderFrame()) {
       nsIFrame* realFrame =
         nsPlaceholderFrame::GetRealFrameForPlaceholder(childFrame);
-      if (realFrame->GetType() == nsGkAtoms::letterFrame) {
+      if (realFrame->IsLetterFrame()) {
         frame = realFrame;
       }
     }
 
     // If unicode-bidi properties are present, we should do bidi resolution.
     nsStyleContext* sc = frame->StyleContext();
     if (GetBidiControl(sc) || GetBidiOverride(sc)) {
       return true;
     }
 
     if (IsBidiLeaf(frame)) {
-      if (frame->GetType() == nsGkAtoms::textFrame) {
+      if (frame->IsTextFrame()) {
         // Check whether the text frame has any RTL characters; if so, bidi
         // resolution will be needed.
         nsIContent* content = frame->GetContent();
         if (content != *aCurrContent) {
           *aCurrContent = content;
           const nsTextFragment* txt = content->GetText();
           if (txt->Is2b() && HasRTLChars(txt->Get2b(), txt->GetLength())) {
             return true;
@@ -1350,17 +1348,17 @@ nsBidiPresUtils::ReorderFrames(nsIFrame*
                                int32_t aNumFramesOnLine,
                                WritingMode aLineWM,
                                const nsSize& aContainerSize,
                                nscoord aStart)
 {
   nsSize containerSize(aContainerSize);
 
   // If this line consists of a line frame, reorder the line frame's children.
-  if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) {
+  if (aFirstFrameOnLine->IsLineFrame()) {
     // The line frame is positioned at the start-edge, so use its size
     // as the container size.
     containerSize = aFirstFrameOnLine->GetSize();
 
     aFirstFrameOnLine = aFirstFrameOnLine->PrincipalChildList().FirstChild();
     if (!aFirstFrameOnLine) {
       return 0;
     }
@@ -1375,18 +1373,17 @@ nsBidiPresUtils::ReorderFrames(nsIFrame*
 
 nsIFrame*
 nsBidiPresUtils::GetFirstLeaf(nsIFrame* aFrame)
 {
   nsIFrame* firstLeaf = aFrame;
   while (!IsBidiLeaf(firstLeaf)) {
     nsIFrame* firstChild = firstLeaf->PrincipalChildList().FirstChild();
     nsIFrame* realFrame = nsPlaceholderFrame::GetRealFrameFor(firstChild);
-    firstLeaf = (realFrame->GetType() == nsGkAtoms::letterFrame) ?
-                 realFrame : firstChild;
+    firstLeaf = (realFrame->IsLetterFrame()) ? realFrame : firstChild;
   }
   return firstLeaf;
 }
 
 FrameBidiData
 nsBidiPresUtils::GetFrameBidiData(nsIFrame* aFrame)
 {
   return GetFirstLeaf(aFrame)->GetBidiData();
@@ -1562,24 +1559,24 @@ nsBidiPresUtils::RepositionRubyContentFr
 
 /* static */ nscoord
 nsBidiPresUtils::RepositionRubyFrame(
   nsIFrame* aFrame,
   const nsContinuationStates* aContinuationStates,
   const WritingMode aContainerWM,
   const LogicalMargin& aBorderPadding)
 {
-  nsIAtom* frameType = aFrame->GetType();
+  FrameType frameType = aFrame->Type();
   MOZ_ASSERT(RubyUtils::IsRubyBox(frameType));
 
   nscoord icoord = 0;
   WritingMode frameWM = aFrame->GetWritingMode();
   bool isLTR = frameWM.IsBidiLTR();
   nsSize frameSize = aFrame->GetSize();
-  if (frameType == nsGkAtoms::rubyFrame) {
+  if (frameType == FrameType::Ruby) {
     icoord += aBorderPadding.IStart(frameWM);
     // Reposition ruby segments in a ruby container
     for (RubySegmentEnumerator e(static_cast<nsRubyFrame*>(aFrame));
           !e.AtEnd(); e.Next()) {
       nsRubyBaseContainerFrame* rbc = e.GetBaseContainer();
       AutoRubyTextContainerArray textContainers(rbc);
 
       nscoord segmentISize = RepositionFrame(rbc, isLTR, icoord,
@@ -1588,17 +1585,17 @@ nsBidiPresUtils::RepositionRubyFrame(
       for (nsRubyTextContainerFrame* rtc : textContainers) {
         nscoord isize = RepositionFrame(rtc, isLTR, icoord, aContinuationStates,
                                         frameWM, false, frameSize);
         segmentISize = std::max(segmentISize, isize);
       }
       icoord += segmentISize;
     }
     icoord += aBorderPadding.IEnd(frameWM);
-  } else if (frameType == nsGkAtoms::rubyBaseContainerFrame) {
+  } else if (frameType == FrameType::RubyBaseContainer) {
     // Reposition ruby columns in a ruby segment
     auto rbc = static_cast<nsRubyBaseContainerFrame*>(aFrame);
     AutoRubyTextContainerArray textContainers(rbc);
 
     for (RubyColumnEnumerator e(rbc, textContainers); !e.AtEnd(); e.Next()) {
       RubyColumn column;
       e.GetColumn(column);
 
@@ -1608,18 +1605,17 @@ nsBidiPresUtils::RepositionRubyFrame(
       for (nsRubyTextFrame* rt : column.mTextFrames) {
         nscoord isize = RepositionFrame(rt, isLTR, icoord, aContinuationStates,
                                         frameWM, false, frameSize);
         columnISize = std::max(columnISize, isize);
       }
       icoord += columnISize;
     }
   } else {
-    if (frameType == nsGkAtoms::rubyBaseFrame ||
-        frameType == nsGkAtoms::rubyTextFrame) {
+    if (frameType == FrameType::RubyBase || frameType == FrameType::RubyText) {
       RepositionRubyContentFrame(aFrame, frameWM, aBorderPadding);
     }
     // Note that, ruby text container is not present in all conditions
     // above. It is intended, because the children of rtc are reordered
     // with the children of ruby base container simultaneously. We only
     // need to return its isize here, as it should not be changed.
     icoord += aFrame->ISize(aContainerWM);
   }
@@ -1702,17 +1698,17 @@ nsBidiPresUtils::RepositionFrame(nsIFram
     for (nsFrameList::Enumerator e(aFrame->PrincipalChildList());
          !e.AtEnd(); e.Next()) {
       icoord += RepositionFrame(e.get(), aIsEvenLevel, icoord,
                                 aContinuationStates,
                                 frameWM, reverseDir, frameSize);
     }
     icoord += reverseDir ?
       borderPadding.IStart(frameWM) : borderPadding.IEnd(frameWM);
-  } else if (RubyUtils::IsRubyBox(aFrame->GetType())) {
+  } else if (RubyUtils::IsRubyBox(aFrame->Type())) {
     icoord += RepositionRubyFrame(aFrame, aContinuationStates,
                                   aContainerWM, borderPadding);
   } else {
     icoord +=
       frameWM.IsOrthogonalTo(aContainerWM) ? aFrame->BSize() : frameISize;
   }
 
   // In the following variables, if aContainerReverseDir is true, i.e.
@@ -1739,17 +1735,17 @@ nsBidiPresUtils::RepositionFrame(nsIFram
 void
 nsBidiPresUtils::InitContinuationStates(nsIFrame*              aFrame,
                                         nsContinuationStates*  aContinuationStates)
 {
   nsFrameContinuationState* state = aContinuationStates->PutEntry(aFrame);
   state->mFirstVisualFrame = nullptr;
   state->mFrameCount = 0;
 
-  if (!IsBidiLeaf(aFrame) || RubyUtils::IsRubyBox(aFrame->GetType())) {
+  if (!IsBidiLeaf(aFrame) || RubyUtils::IsRubyBox(aFrame->Type())) {
     // Continue for child frames
     for (nsIFrame* frame : aFrame->PrincipalChildList()) {
       InitContinuationStates(frame,
                              aContinuationStates);
     }
   }
 }
 
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -338,50 +338,44 @@ IsAnonymousFlexOrGridItem(const nsIFrame
   return pseudoType == nsCSSAnonBoxes::anonymousFlexItem ||
          pseudoType == nsCSSAnonBoxes::anonymousGridItem;
 }
 
 // Returns true if aFrame is a flex/grid container.
 static inline bool
 IsFlexOrGridContainer(const nsIFrame* aFrame)
 {
-  const nsIAtom* t = aFrame->GetType();
-  return t == nsGkAtoms::flexContainerFrame ||
-         t == nsGkAtoms::gridContainerFrame;
+  const FrameType t = aFrame->Type();
+  return t == FrameType::FlexContainer || t == FrameType::GridContainer;
 }
 
 // Returns true IFF the given nsIFrame is a nsFlexContainerFrame and
-// represents a -webkit-{inline-}box container. The frame's GetType() result is
-// passed as a separate argument, since in most cases, the caller will have
-// looked it up already, and we'd rather not make redundant calls to the
-// virtual GetType() method.
+// represents a -webkit-{inline-}box container.
 static inline bool
-IsFlexContainerForLegacyBox(const nsIFrame* aFrame,
-                            const nsIAtom* aFrameType)
-{
-  MOZ_ASSERT(aFrame->GetType() == aFrameType, "wrong aFrameType was passed");
-  return aFrameType == nsGkAtoms::flexContainerFrame &&
-    aFrame->HasAnyStateBits(NS_STATE_FLEX_IS_LEGACY_WEBKIT_BOX);
+IsFlexContainerForLegacyBox(const nsIFrame* aFrame)
+{
+  return aFrame->IsFlexContainerFrame() &&
+         aFrame->HasAnyStateBits(NS_STATE_FLEX_IS_LEGACY_WEBKIT_BOX);
 }
 
 #if DEBUG
 static void
 AssertAnonymousFlexOrGridItemParent(const nsIFrame* aChild,
                                     const nsIFrame* aParent)
 {
   MOZ_ASSERT(IsAnonymousFlexOrGridItem(aChild),
              "expected an anonymous flex or grid item child frame");
   MOZ_ASSERT(aParent, "expected a parent frame");
   const nsIAtom* pseudoType = aChild->StyleContext()->GetPseudo();
   if (pseudoType == nsCSSAnonBoxes::anonymousFlexItem) {
-    MOZ_ASSERT(aParent->GetType() == nsGkAtoms::flexContainerFrame,
+    MOZ_ASSERT(aParent->IsFlexContainerFrame(),
                "anonymous flex items should only exist as children "
                "of flex container frames");
   } else {
-    MOZ_ASSERT(aParent->GetType() == nsGkAtoms::gridContainerFrame,
+    MOZ_ASSERT(aParent->IsGridContainerFrame(),
                "anonymous grid items should only exist as children "
                "of grid container frames");
   }
 }
 #else
 #define AssertAnonymousFlexOrGridItemParent(x, y) do { /* nothing */ } while(0)
 #endif
 
@@ -1972,47 +1966,47 @@ IsRubyPseudo(nsIFrame* aFrame)
 static bool
 IsTableOrRubyPseudo(nsIFrame* aFrame)
 {
   return IsTablePseudo(aFrame) || IsRubyPseudo(aFrame);
 }
 
 /* static */
 nsCSSFrameConstructor::ParentType
-nsCSSFrameConstructor::GetParentType(nsIAtom* aFrameType)
-{
-  if (aFrameType == nsGkAtoms::tableFrame) {
+nsCSSFrameConstructor::GetParentType(FrameType aFrameType)
+{
+  if (aFrameType == FrameType::Table) {
     return eTypeTable;
   }
-  if (aFrameType == nsGkAtoms::tableRowGroupFrame) {
+  if (aFrameType == FrameType::TableRowGroup) {
     return eTypeRowGroup;
   }
-  if (aFrameType == nsGkAtoms::tableRowFrame) {
+  if (aFrameType == FrameType::TableRow) {
     return eTypeRow;
   }
-  if (aFrameType == nsGkAtoms::tableColGroupFrame) {
+  if (aFrameType == FrameType::TableColGroup) {
     return eTypeColGroup;
   }
-  if (aFrameType == nsGkAtoms::rubyBaseContainerFrame) {
+  if (aFrameType == FrameType::RubyBaseContainer) {
     return eTypeRubyBaseContainer;
   }
-  if (aFrameType == nsGkAtoms::rubyTextContainerFrame) {
+  if (aFrameType == FrameType::RubyTextContainer) {
     return eTypeRubyTextContainer;
   }
-  if (aFrameType == nsGkAtoms::rubyFrame) {
+  if (aFrameType == FrameType::Ruby) {
     return eTypeRuby;
   }
 
   return eTypeBlock;
 }
 
 static nsContainerFrame*
 AdjustCaptionParentFrame(nsContainerFrame* aParentFrame)
 {
-  if (nsGkAtoms::tableFrame == aParentFrame->GetType()) {
+  if (aParentFrame->IsTableFrame()) {
     return aParentFrame->GetParent();
   }
   return aParentFrame;
 }
 
 /**
  * If the parent frame is a |tableFrame| and the child is a
  * |captionFrame|, then we want to insert the frames beneath the
@@ -2693,17 +2687,17 @@ nsCSSFrameConstructor::ConstructDocEleme
   }
 
   // set the primary frame
   aDocElement->SetPrimaryFrame(contentFrame);
 
   SetInitialSingleChild(mDocElementContainingBlock, newFrame);
 
   // Create frames for anonymous contents if there is a canvas frame.
-  if (mDocElementContainingBlock->GetType() == nsGkAtoms::canvasFrame) {
+  if (mDocElementContainingBlock->IsCanvasFrame()) {
     ConstructAnonymousContentForCanvas(state, mDocElementContainingBlock,
                                        aDocElement);
   }
 
   return newFrame;
 }
 
 
@@ -2960,17 +2954,17 @@ nsCSSFrameConstructor::SetUpDocElementCo
   }
 }
 
 void
 nsCSSFrameConstructor::ConstructAnonymousContentForCanvas(nsFrameConstructorState& aState,
                                                           nsIFrame* aFrame,
                                                           nsIContent* aDocElement)
 {
-  NS_ASSERTION(aFrame->GetType() == nsGkAtoms::canvasFrame, "aFrame should be canvas frame!");
+  NS_ASSERTION(aFrame->IsCanvasFrame(), "aFrame should be canvas frame!");
 
   AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
   GetAnonymousContent(aDocElement, aFrame, anonymousItems);
   if (anonymousItems.IsEmpty()) {
     return;
   }
 
   FrameConstructionItemList itemsToConstruct;
@@ -3369,17 +3363,17 @@ nsCSSFrameConstructor::ConstructFieldSet
                   childItems, true, aItem.mPendingBinding);
 
   nsFrameItems fieldsetKids;
   fieldsetKids.AddChild(scrollFrame ? scrollFrame : contentFrameTop);
 
   for (nsFrameList::Enumerator e(childItems); !e.AtEnd(); e.Next()) {
     nsIFrame* child = e.get();
     nsContainerFrame* cif = child->GetContentInsertionFrame();
-    if (cif && cif->GetType() == nsGkAtoms::legendFrame) {
+    if (cif && cif->IsLegendFrame()) {
       // We want the legend to be the first frame in the fieldset child list.
       // That way the EventStateManager will do the right thing when tabbing
       // from a selection point within the legend (bug 236071), which is
       // used for implementing legend access keys (bug 81481).
       // GetAdjustedParentFrame() below depends on this frame order.
       childItems.RemoveFrame(child);
       // Make sure to reparent the legend so it has the fieldset as the parent.
       fieldsetKids.InsertFrame(fieldsetFrame, nullptr, child);
@@ -3564,25 +3558,25 @@ nsCSSFrameConstructor::FindDataByTag(nsI
 #define SIMPLE_TAG_CREATE(_tag, _func)          \
   { &nsGkAtoms::_tag, SIMPLE_FCDATA(_func) }
 #define SIMPLE_TAG_CHAIN(_tag, _func)                                   \
   { &nsGkAtoms::_tag, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER,  _func) }
 #define COMPLEX_TAG_CREATE(_tag, _func)             \
   { &nsGkAtoms::_tag, FULL_CTOR_FCDATA(0, _func) }
 
 static bool
-IsFrameForFieldSet(nsIFrame* aFrame, nsIAtom* aFrameType)
+IsFrameForFieldSet(nsIFrame* aFrame)
 {
   nsIAtom* pseudo = aFrame->StyleContext()->GetPseudo();
   if (pseudo == nsCSSAnonBoxes::fieldsetContent ||
       pseudo == nsCSSAnonBoxes::scrolledContent ||
       pseudo == nsCSSAnonBoxes::columnContent) {
-    return IsFrameForFieldSet(aFrame->GetParent(), aFrame->GetParent()->GetType());
-  }
-  return aFrameType == nsGkAtoms::fieldSetFrame;
+    return IsFrameForFieldSet(aFrame->GetParent());
+  }
+  return aFrame->IsFieldSetFrame();
 }
 
 /* static */
 const nsCSSFrameConstructor::FrameConstructionData*
 nsCSSFrameConstructor::FindHTMLData(Element* aElement,
                                     nsIAtom* aTag,
                                     int32_t aNameSpaceID,
                                     nsIFrame* aParentFrame,
@@ -3593,21 +3587,20 @@ nsCSSFrameConstructor::FindHTMLData(Elem
   // ShouldHaveFirstLineStyle.
   if (aNameSpaceID != kNameSpaceID_XHTML) {
     return nullptr;
   }
 
   NS_ASSERTION(!aParentFrame ||
                aParentFrame->StyleContext()->GetPseudo() !=
                  nsCSSAnonBoxes::fieldsetContent ||
-               aParentFrame->GetParent()->GetType() == nsGkAtoms::fieldSetFrame,
+               aParentFrame->GetParent()->IsFieldSetFrame(),
                "Unexpected parent for fieldset content anon box");
   if (aTag == nsGkAtoms::legend &&
-      (!aParentFrame ||
-       !IsFrameForFieldSet(aParentFrame, aParentFrame->GetType()) ||
+      (!aParentFrame || !IsFrameForFieldSet(aParentFrame) ||
        aStyleContext->StyleDisplay()->IsFloatingStyle() ||
        aStyleContext->StyleDisplay()->IsAbsolutelyPositionedStyle())) {
     // <legend> is only special inside fieldset, we only check the frame tree
     // parent because the content tree parent may not be a <fieldset> due to
     // display:contents, Shadow DOM, or XBL. For floated or absolutely
     // positioned legends we want to construct by display type and
     // not do special legend stuff.
     return nullptr;
@@ -3908,18 +3901,17 @@ nsCSSFrameConstructor::ConstructFrameFro
   } else {
     newFrame =
       (*data->mFunc.mCreationFunc)(mPresShell, styleContext);
 
     bool allowOutOfFlow = !(bits & FCDATA_DISALLOW_OUT_OF_FLOW);
     bool isPopup = aItem.mIsPopup;
     NS_ASSERTION(!isPopup ||
                  (aState.mPopupItems.containingBlock &&
-                  aState.mPopupItems.containingBlock->GetType() ==
-                    nsGkAtoms::popupSetFrame),
+                  aState.mPopupItems.containingBlock->IsPopupSetFrame()),
                  "Should have a containing block here!");
 
     nsContainerFrame* geometricParent =
       isPopup ? aState.mPopupItems.containingBlock :
       (allowOutOfFlow ? aState.GetGeometricParent(display, aParentFrame)
                       : aParentFrame);
 
     // Must init frameToAddToList to null, since it's inout
@@ -4238,36 +4230,36 @@ nsCSSFrameConstructor::GetAnonymousConte
   uint32_t count = aContent.Length();
   for (uint32_t i=0; i < count; i++) {
     // get our child's content and set its parent to our content
     nsIContent* content = aContent[i].mContent;
     NS_ASSERTION(content, "null anonymous content?");
 
     ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
 
-    nsIAtom* parentFrameType = aParentFrame->GetType();
-    if (parentFrameType == nsGkAtoms::svgUseFrame) {
+    FrameType parentFrameType = aParentFrame->Type();
+    if (parentFrameType == FrameType::SVGUse) {
       // least-surprise CSS binding until we do the SVG specified
       // cascading rules for <svg:use> - bug 265894
       content->SetFlags(NODE_IS_ANONYMOUS_ROOT);
     } else {
       content->SetIsNativeAnonymousRoot();
       // Don't mark descendants of the custom content container
       // as native anonymous.  When canvas custom content is initially
       // created and appended to the custom content container, in
       // nsIDocument::InsertAnonymousContent, it is not considered native
       // anonymous content.  But if we end up reframing the root element,
       // we will re-create the nsCanvasFrame, and we would end up in here,
       // marking it as NAC.  Existing uses of canvas custom content would
       // break if it becomes NAC (since each element starts inheriting
       // styles from its closest non-NAC ancestor, rather than from its
       // parent).
-      if (!(parentFrameType == nsGkAtoms::canvasFrame &&
-              content == static_cast<nsCanvasFrame*>(aParentFrame)
-                           ->GetCustomContentContainer())) {
+      if (!(parentFrameType == FrameType::Canvas &&
+            content == static_cast<nsCanvasFrame*>(aParentFrame)
+                         ->GetCustomContentContainer())) {
         SetNativeAnonymousBitOnDescendants(content);
       }
     }
 
     bool anonContentIsEditable = content->HasFlag(NODE_IS_EDITABLE);
 
     // If the parent is in a shadow tree, make sure we don't
     // bind with a document because shadow roots and its descendants
@@ -4275,17 +4267,17 @@ nsCSSFrameConstructor::GetAnonymousConte
     nsIDocument* bindDocument =
       aParent->HasFlag(NODE_IS_IN_SHADOW_TREE) ? nullptr : mDocument;
     rv = content->BindToTree(bindDocument, aParent, aParent, true);
     // If the anonymous content creator requested that the content should be
     // editable, honor its request.
     // We need to set the flag on the whole subtree, because existing
     // children's flags have already been set as part of the BindToTree operation.
     if (anonContentIsEditable) {
-      NS_ASSERTION(aParentFrame->GetType() == nsGkAtoms::textInputFrame,
+      NS_ASSERTION(aParentFrame->IsTextInputFrame(),
                    "We only expect this for anonymous content under a text control frame");
       SetFlagsOnSubtree(content, NODE_IS_EDITABLE);
     }
     if (NS_FAILED(rv)) {
       content->UnbindFromTree();
       return rv;
     }
   }
@@ -5474,42 +5466,41 @@ nsCSSFrameConstructor::FindSVGData(Eleme
     // frame that doesn't render) so that paint servers can still be referenced,
     // even if they live inside an element with failing conditional processing
     // attributes.
     return &sContainerData;
   }
 
   // Ensure that a stop frame is a child of a gradient and that gradients
   // can only have stop children.
-  bool parentIsGradient = aParentFrame &&
-    (aParentFrame->GetType() == nsGkAtoms::svgLinearGradientFrame ||
-     aParentFrame->GetType() == nsGkAtoms::svgRadialGradientFrame);
+  bool parentIsGradient =
+    aParentFrame && (aParentFrame->IsSVGLinearGradientFrame() ||
+                     aParentFrame->IsSVGRadialGradientFrame());
   bool stop = (aTag == nsGkAtoms::stop);
   if ((parentIsGradient && !stop) ||
       (!parentIsGradient && stop)) {
     return &sSuppressData;
   }
 
   // Prevent bad frame types being children of filters or parents of filter
   // primitives.  If aParentFrame is null, we know that the frame that will
   // be created will be an nsInlineFrame, so it can never be a filter.
-  bool parentIsFilter = aParentFrame &&
-    aParentFrame->GetType() == nsGkAtoms::svgFilterFrame;
+  bool parentIsFilter = aParentFrame && aParentFrame->IsSVGFilterFrame();
   bool filterPrimitive = aElement->IsNodeOfType(nsINode::eFILTER);
   if ((parentIsFilter && !filterPrimitive) ||
       (!parentIsFilter && filterPrimitive)) {
     return &sSuppressData;
   }
 
   // Prevent bad frame types being children of filter primitives or parents of
   // filter primitive children.  If aParentFrame is null, we know that the frame
   // that will be created will be an nsInlineFrame, so it can never be a filter
   // primitive.
-  bool parentIsFEContainerFrame = aParentFrame &&
-    aParentFrame->GetType() == nsGkAtoms::svgFEContainerFrame;
+  bool parentIsFEContainerFrame =
+    aParentFrame && aParentFrame->IsSVGFEContainerFrame();
   if ((parentIsFEContainerFrame && !IsFilterPrimitiveChildTag(aTag)) ||
       (!parentIsFEContainerFrame && IsFilterPrimitiveChildTag(aTag))) {
     return &sSuppressData;
   }
 
   // Special cases for text/tspan/textPath, because the kind of frame
   // they get depends on the parent frame.  We ignore 'a' elements when
   // determining the parent, however.
@@ -5685,19 +5676,18 @@ nsCSSFrameConstructor::DoAddFrameConstru
                                                    nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren,
                                                    FrameConstructionItemList& aItems)
 {
   uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK;
   if (aParentFrame) {
     if (nsSVGUtils::IsInSVGTextSubtree(aParentFrame)) {
       flags |= ITEM_IS_WITHIN_SVG_TEXT;
     }
-    if (aParentFrame->GetType() == nsGkAtoms::blockFrame &&
-        aParentFrame->GetParent() &&
-        aParentFrame->GetParent()->GetType() == nsGkAtoms::svgTextFrame) {
+    if (aParentFrame->IsBlockFrame() && aParentFrame->GetParent() &&
+        aParentFrame->GetParent()->IsSVGTextFrame()) {
       flags |= ITEM_ALLOWS_TEXT_PATH_CHILD;
     }
   }
   AddFrameConstructionItemsInternal(aState, aContent, aParentFrame,
                                     aContent->NodeInfo()->NameAtom(),
                                     aContent->GetNameSpaceID(),
                                     aSuppressWhiteSpaceOptimizations,
                                     aStyleContext,
@@ -5926,48 +5916,44 @@ nsCSSFrameConstructor::AddFrameConstruct
     if (data->mBits & FCDATA_SUPPRESS_FRAME) {
       SetAsUndisplayedContent(aState, aItems, element, styleContext, isGeneratedContent);
       return;
     }
 
 #ifdef MOZ_XUL
     if ((data->mBits & FCDATA_IS_POPUP) &&
         (!aParentFrame || // Parent is inline
-         aParentFrame->GetType() != nsGkAtoms::menuFrame)) {
+         !aParentFrame->IsMenuFrame())) {
       if (!aState.mPopupItems.containingBlock &&
           !aState.mHavePendingPopupgroup) {
         SetAsUndisplayedContent(aState, aItems, element, styleContext,
                                 isGeneratedContent);
         return;
       }
 
       isPopup = true;
     }
 #endif /* MOZ_XUL */
   }
 
   uint32_t bits = data->mBits;
 
   // Inside colgroups, suppress everything except columns.
-  if (aParentFrame &&
-      aParentFrame->GetType() == nsGkAtoms::tableColGroupFrame &&
+  if (aParentFrame && aParentFrame->IsTableColGroupFrame() &&
       (!(bits & FCDATA_IS_TABLE_PART) ||
        display->mDisplay != StyleDisplay::TableColumn)) {
     SetAsUndisplayedContent(aState, aItems, aContent, styleContext, isGeneratedContent);
     return;
   }
 
   bool canHavePageBreak =
-    (aFlags & ITEM_ALLOW_PAGE_BREAK) &&
-    aState.mPresContext->IsPaginated() &&
+    (aFlags & ITEM_ALLOW_PAGE_BREAK) && aState.mPresContext->IsPaginated() &&
     !display->IsAbsolutelyPositionedStyle() &&
-    !(aParentFrame &&
-      aParentFrame->GetType() == nsGkAtoms::gridContainerFrame) &&
-    !(bits & FCDATA_IS_TABLE_PART) &&
-    !(bits & FCDATA_IS_SVG_TEXT);
+    !(aParentFrame && aParentFrame->IsGridContainerFrame()) &&
+    !(bits & FCDATA_IS_TABLE_PART) && !(bits & FCDATA_IS_SVG_TEXT);
 
   if (canHavePageBreak && display->mBreakBefore) {
     AddPageBreakItem(aContent, aItems);
   }
 
   if (MOZ_UNLIKELY(bits & FCDATA_IS_CONTENTS)) {
     if (!GetDisplayContentsStyleFor(aContent)) {
       MOZ_ASSERT(styleContext->GetPseudo() || !isGeneratedContent,
@@ -6270,17 +6256,17 @@ nsCSSFrameConstructor::ConstructFramesFr
 
   aState.mAdditionalStateBits = savedStateBits;
 }
 
 
 inline bool
 IsRootBoxFrame(nsIFrame *aFrame)
 {
-  return (aFrame->GetType() == nsGkAtoms::rootFrame);
+  return (aFrame->IsRootFrame());
 }
 
 void
 nsCSSFrameConstructor::ReconstructDocElementHierarchy()
 {
   Element* rootElement = mDocument->GetRootElement();
   if (!rootElement) {
     /* nothing to do */
@@ -6301,19 +6287,18 @@ nsCSSFrameConstructor::GetAbsoluteContai
       // If it's mathml, bail out -- no absolute positioning out from inside
       // mathml frames.  Note that we don't make this part of the loop
       // condition because of the stuff at the end of this method...
       return nullptr;
     }
 
     // Look for the ICB.
     if (aType == FIXED_POS) {
-      nsIAtom* t = frame->GetType();
-      if (t == nsGkAtoms::viewportFrame ||
-          t == nsGkAtoms::pageContentFrame) {
+      FrameType t = frame->Type();
+      if (t == FrameType::Viewport || t == FrameType::PageContent) {
         return static_cast<nsContainerFrame*>(frame);
       }
     }
 
     // If the frame is positioned, we will probably return it as the containing
     // block (see the exceptions below).  Otherwise, we'll start looking at the
     // parent frame, unless we're dealing with a scrollframe.
     // Scrollframes are special since they're not positioned, but their
@@ -6322,41 +6307,41 @@ nsCSSFrameConstructor::GetAbsoluteContai
     // If we're looking for a fixed-pos containing block and the frame is
     // not transformed, skip it.
     if (!frame->IsAbsPosContainingBlock() ||
         (aType == FIXED_POS &&
          !frame->IsFixedPosContainingBlock())) {
       continue;
     }
     nsIFrame* absPosCBCandidate = frame;
-    nsIAtom* type = absPosCBCandidate->GetType();
-    if (type == nsGkAtoms::fieldSetFrame) {
+    FrameType type = absPosCBCandidate->Type();
+    if (type == FrameType::FieldSet) {
       absPosCBCandidate = static_cast<nsFieldSetFrame*>(absPosCBCandidate)->GetInner();
       if (!absPosCBCandidate) {
         continue;
       }
-      type = absPosCBCandidate->GetType();
-    }
-    if (type == nsGkAtoms::scrollFrame) {
+      type = absPosCBCandidate->Type();
+    }
+    if (type == FrameType::Scroll) {
       nsIScrollableFrame* scrollFrame = do_QueryFrame(absPosCBCandidate);
       absPosCBCandidate = scrollFrame->GetScrolledFrame();
       if (!absPosCBCandidate) {
         continue;
       }
-      type = absPosCBCandidate->GetType();
+      type = absPosCBCandidate->Type();
     }
     // Only first continuations can be containing blocks.
     absPosCBCandidate = absPosCBCandidate->FirstContinuation();
     // Is the frame really an absolute container?
     if (!absPosCBCandidate->IsAbsoluteContainer()) {
       continue;
     }
 
     // For tables, skip the inner frame and consider the table wrapper frame.
-    if (type == nsGkAtoms::tableFrame) {
+    if (type == FrameType::Table) {
       continue;
     }
     // For table wrapper frames, we can just return absPosCBCandidate.
     MOZ_ASSERT((nsContainerFrame*)do_QueryFrame(absPosCBCandidate),
                "abs.pos. containing block must be nsContainerFrame sub-class");
     return static_cast<nsContainerFrame*>(absPosCBCandidate);
   }
 
@@ -6637,26 +6622,26 @@ nsCSSFrameConstructor::AppendFramesToPar
 // inside fieldsets, (5) popups and other kids of the menu are siblings from a
 // content perspective, they are not considered siblings in the frame tree.
 bool
 nsCSSFrameConstructor::IsValidSibling(nsIFrame*              aSibling,
                                       nsIContent*            aContent,
                                       StyleDisplay&          aDisplay)
 {
   nsIFrame* parentFrame = aSibling->GetParent();
-  nsIAtom* parentType = parentFrame->GetType();
+  FrameType parentType = parentFrame->Type();
 
   StyleDisplay siblingDisplay = aSibling->GetDisplay();
   if (StyleDisplay::TableColumnGroup == siblingDisplay ||
       StyleDisplay::TableColumn      == siblingDisplay ||
       StyleDisplay::TableCaption     == siblingDisplay ||
       StyleDisplay::TableHeaderGroup == siblingDisplay ||
       StyleDisplay::TableRowGroup    == siblingDisplay ||
       StyleDisplay::TableFooterGroup == siblingDisplay ||
-      nsGkAtoms::menuFrame == parentType) {
+      FrameType::Menu == parentType) {
     // if we haven't already, construct a style context to find the display type of aContent
     if (UNSET_DISPLAY == aDisplay) {
       nsIFrame* styleParent;
       aSibling->GetParentStyleContext(&styleParent);
       if (!styleParent) {
         styleParent = aSibling->GetParent();
       }
       if (!styleParent) {
@@ -6671,17 +6656,17 @@ nsCSSFrameConstructor::IsValidSibling(ns
       }
       // XXXbz when this code is killed, the state argument to
       // ResolveStyleContext can be made non-optional.
       RefPtr<nsStyleContext> styleContext =
         ResolveStyleContext(styleParent, aContent, nullptr);
       const nsStyleDisplay* display = styleContext->StyleDisplay();
       aDisplay = display->mDisplay;
     }
-    if (nsGkAtoms::menuFrame == parentType) {
+    if (FrameType::Menu == parentType) {
       return
         (StyleDisplay::MozPopup == aDisplay) ==
         (StyleDisplay::MozPopup == siblingDisplay);
     }
     // To have decent performance we want to return false in cases in which
     // reordering the two siblings has no effect on display.  To ensure
     // correctness, we MUST return false in cases where the two siblings have
     // the same desired parent type and live on different display lists.
@@ -6707,26 +6692,26 @@ nsCSSFrameConstructor::IsValidSibling(ns
       // siblings.
       return false;
     }
     // Fall through; it's possible that the display type was overridden and
     // a different sort of frame was constructed, so we may need to return false
     // below.
   }
 
-  if (IsFrameForFieldSet(parentFrame, parentType)) {
+  if (IsFrameForFieldSet(parentFrame)) {
     // Legends can be sibling of legends but not of other content in the fieldset
     if (nsContainerFrame* cif = aSibling->GetContentInsertionFrame()) {
       aSibling = cif;
     }
-    nsIAtom* sibType = aSibling->GetType();
+    FrameType sibType = aSibling->Type();
     bool legendContent = aContent->IsHTMLElement(nsGkAtoms::legend);
 
-    if ((legendContent  && (nsGkAtoms::legendFrame != sibType)) ||
-        (!legendContent && (nsGkAtoms::legendFrame == sibType)))
+    if ((legendContent && (FrameType::Legend != sibType)) ||
+        (!legendContent && (FrameType::Legend == sibType)))
       return false;
   }
 
   return true;
 }
 
 nsIFrame*
 nsCSSFrameConstructor::FindFrameForContentSibling(nsIContent* aContent,
@@ -6834,25 +6819,24 @@ nsCSSFrameConstructor::FindNextSibling(F
   }
 
   return nullptr;
 }
 
 // For fieldsets, returns the area frame, if the child is not a legend.
 static nsContainerFrame*
 GetAdjustedParentFrame(nsContainerFrame* aParentFrame,
-                       nsIAtom*          aParentFrameType,
-                       nsIContent*       aChildContent)
-{
-  NS_PRECONDITION(nsGkAtoms::tableWrapperFrame != aParentFrameType,
+                       nsIContent* aChildContent)
+{
+  NS_PRECONDITION(!aParentFrame->IsTableWrapperFrame(),
                   "Shouldn't be happening!");
 
   nsContainerFrame* newParent = nullptr;
 
-  if (nsGkAtoms::fieldSetFrame == aParentFrameType) {
+  if (aParentFrame->IsFieldSetFrame()) {
     // If the parent is a fieldSet, use the fieldSet's area frame as the
     // parent unless the new content is a legend.
     if (!aChildContent->IsHTMLElement(nsGkAtoms::legend)) {
       newParent = GetFieldSetBlockFrame(aParentFrame);
     }
   }
   return newParent ? newParent : aParentFrame;
 }
@@ -6916,19 +6900,17 @@ nsCSSFrameConstructor::GetInsertionPrevS
       if (!nextSibling) {
         // Our siblings (if any) does not have a frame to guide us.
         // The frame for aChild should be inserted whereever a frame for
         // the container would be inserted.  This is needed when inserting
         // into nested display:contents nodes.
         nsIContent* child = aInsertion->mContainer;
         nsIContent* parent = child->GetParent();
         aInsertion->mParentFrame =
-          ::GetAdjustedParentFrame(aInsertion->mParentFrame,
-                                   aInsertion->mParentFrame->GetType(),
-                                   parent);
+          ::GetAdjustedParentFrame(aInsertion->mParentFrame, parent);
         InsertionPoint fakeInsertion(aInsertion->mParentFrame, parent);
         nsIFrame* result = GetInsertionPrevSibling(&fakeInsertion, child, aIsAppend,
                                                    aIsRangeInsertSafe, nullptr, nullptr);
         MOZ_ASSERT(aInsertion->mParentFrame->GetContent() ==
                    fakeInsertion.mParentFrame->GetContent());
         // fakeInsertion.mParentFrame may now be a continuation of the frame
         // we started with in the ctor above.
         aInsertion->mParentFrame = fakeInsertion.mParentFrame;
@@ -6951,19 +6933,17 @@ nsCSSFrameConstructor::GetInsertionPrevS
           GetLastIBSplitSibling(aInsertion->mParentFrame, false);
       }
       // Get continuation that parents the last child.  This MUST be done
       // before the AdjustAppendParentForAfterContent call.
       aInsertion->mParentFrame =
         nsLayoutUtils::LastContinuationWithChild(aInsertion->mParentFrame);
       // Deal with fieldsets
       aInsertion->mParentFrame =
-        ::GetAdjustedParentFrame(aInsertion->mParentFrame,
-                                 aInsertion->mParentFrame->GetType(),
-                                 aChild);
+        ::GetAdjustedParentFrame(aInsertion->mParentFrame, aChild);
       nsIFrame* appendAfterFrame;
       aInsertion->mParentFrame =
         ::AdjustAppendParentForAfterContent(this, aInsertion->mContainer,
                                             aInsertion->mParentFrame,
                                             aChild, &appendAfterFrame);
       prevSibling = ::FindAppendPrevSibling(aInsertion->mParentFrame, appendAfterFrame);
     }
   }
@@ -7383,17 +7363,17 @@ nsCSSFrameConstructor::GetRangeInsertion
   return insertionPoint;
 }
 
 bool
 nsCSSFrameConstructor::MaybeRecreateForFrameset(nsIFrame* aParentFrame,
                                                 nsIContent* aStartChild,
                                                 nsIContent* aEndChild)
 {
-  if (aParentFrame->GetType() == nsGkAtoms::frameSetFrame) {
+  if (aParentFrame->IsFrameSetFrame()) {
     // Check whether we have any kids we care about.
     for (nsIContent* cur = aStartChild;
          cur != aEndChild;
          cur = cur->GetNextSibling()) {
       if (IsSpecialFramesetChild(cur)) {
         // Just reframe the parent, since framesets are weird like that.
         RecreateFramesForContent(aParentFrame->GetContent(), false,
                                  REMOVE_FOR_RECONSTRUCTION, nullptr);
@@ -7622,18 +7602,17 @@ nsCSSFrameConstructor::ContentAppended(n
   }
 
   // Get continuation that parents the last child.  This MUST be done
   // before the AdjustAppendParentForAfterContent call.
   parentFrame = nsLayoutUtils::LastContinuationWithChild(parentFrame);
 
   // We should never get here with fieldsets or details, since they have
   // multiple insertion points.
-  MOZ_ASSERT(parentFrame->GetType() != nsGkAtoms::fieldSetFrame &&
-             parentFrame->GetType() != nsGkAtoms::detailsFrame,
+  MOZ_ASSERT(!parentFrame->IsFieldSetFrame() && !parentFrame->IsDetailsFrame(),
              "Parent frame should not be fieldset or details!");
 
   // Deal with possible :after generated content on the parent
   nsIFrame* parentAfterFrame;
   parentFrame =
     ::AdjustAppendParentForAfterContent(this, insertion.mContainer, parentFrame,
                                         aFirstNewContent, &parentAfterFrame);
 
@@ -7663,17 +7642,17 @@ nsCSSFrameConstructor::ContentAppended(n
                                containingBlock->StyleContext());
   }
 
   if (haveFirstLetterStyle) {
     // Before we get going, remove the current letter frames
     RemoveLetterFrames(state.mPresShell, containingBlock);
   }
 
-  nsIAtom* frameType = parentFrame->GetType();
+  FrameType frameType = parentFrame->Type();
 
   FlattenedChildIterator iter(aContainer);
   bool haveNoXBLChildren = (!iter.XBLInvolved() || !iter.GetNextChild());
   FrameConstructionItemList items;
   if (aFirstNewContent->GetPreviousSibling() &&
       GetParentType(frameType) == eTypeBlock &&
       haveNoXBLChildren) {
     // If there's a text node in the normal content list just before the new
@@ -7711,18 +7690,18 @@ nsCSSFrameConstructor::ContentAppended(n
   LAYOUT_PHASE_TEMP_REENTER();
 
   // If the parent is a block frame, and we're not in a special case
   // where frames can be moved around, determine if the list is for the
   // start or end of the block.
   if (nsLayoutUtils::GetAsBlock(parentFrame) && !haveFirstLetterStyle &&
       !haveFirstLineStyle && !parentIBSplit) {
     items.SetLineBoundaryAtStart(!prevSibling ||
-        !prevSibling->IsInlineOutside() ||
-        prevSibling->GetType() == nsGkAtoms::brFrame);
+                                 !prevSibling->IsInlineOutside() ||
+                                 prevSibling->IsBrFrame());
     // :after content can't be <br> so no need to check it
     items.SetLineBoundaryAtEnd(!parentAfterFrame ||
         !parentAfterFrame->IsInlineOutside());
   }
   // To suppress whitespace-only text frames, we have to verify that
   // our container's DOM child list matches its flattened tree child list.
   items.SetParentHasNoXBLChildren(haveNoXBLChildren);
 
@@ -7738,17 +7717,17 @@ nsCSSFrameConstructor::ContentAppended(n
     // GetChildAt calls instead and do this during construction of our
     // FrameConstructionItemList?
     InvalidateCanvasIfNeeded(mPresShell, child);
   }
 
   // If the container is a table and a caption was appended, it needs to be put
   // in the table wrapper frame's additional child list.
   nsFrameItems captionItems;
-  if (nsGkAtoms::tableFrame == frameType) {
+  if (FrameType::Table == frameType) {
     // Pull out the captions.  Note that we don't want to do that as we go,
     // because processing a single caption can add a whole bunch of things to
     // the frame items due to pseudoframe processing.  So we'd have to pull
     // captions from a list anyway; might as well do that here.
     // XXXbz this is no longer true; we could pull captions directly out of the
     // FrameConstructionItemList now.
     PullOutCaptionFrames(frameItems, captionItems);
   }
@@ -7759,17 +7738,17 @@ nsCSSFrameConstructor::ContentAppended(n
     AppendFirstLineFrames(state, containingBlock->GetContent(),
                           containingBlock, frameItems);
   }
 
   // Notify the parent frame passing it the list of new frames
   // Append the flowed frames to the principal child list; captions
   // need special treatment
   if (captionItems.NotEmpty()) { // append the caption to the table wrapper
-    NS_ASSERTION(nsGkAtoms::tableFrame == frameType, "how did that happen?");
+    NS_ASSERTION(FrameType::Table == frameType, "how did that happen?");
     nsContainerFrame* outerTable = parentFrame->GetParent();
     AppendFrames(outerTable, nsIFrame::kCaptionList, captionItems);
   }
 
   if (frameItems.NotEmpty()) { // append the in-flow kids
     AppendFramesToParent(state, parentFrame, frameItems, prevSibling);
   }
 
@@ -8086,47 +8065,47 @@ nsCSSFrameConstructor::ContentRangeInser
     IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
                                  aAllowLazyConstruction, aForReconstruction);
     LAYOUT_PHASE_TEMP_REENTER();
     return;
   }
 
   nsIContent* container = insertion.mParentFrame->GetContent();
 
-  nsIAtom* frameType = insertion.mParentFrame->GetType();
+  FrameType frameType = insertion.mParentFrame->Type();
   LAYOUT_PHASE_TEMP_EXIT();
   if (MaybeRecreateForFrameset(insertion.mParentFrame, aStartChild, aEndChild)) {
     LAYOUT_PHASE_TEMP_REENTER();
     return;
   }
   LAYOUT_PHASE_TEMP_REENTER();
 
   // We should only get here with fieldsets when doing a single insert, because
   // fieldsets have multiple insertion points.
-  NS_ASSERTION(isSingleInsert || frameType != nsGkAtoms::fieldSetFrame,
+  NS_ASSERTION(isSingleInsert || frameType != FrameType::FieldSet,
                "Unexpected parent");
-  if (IsFrameForFieldSet(insertion.mParentFrame, frameType) &&
+  if (IsFrameForFieldSet(insertion.mParentFrame) &&
       aStartChild->NodeInfo()->NameAtom() == nsGkAtoms::legend) {
     // Just reframe the parent, since figuring out whether this
     // should be the new legend and then handling it is too complex.
     // We could do a little better here --- check if the fieldset already
     // has a legend which occurs earlier in its child list than this node,
     // and if so, proceed. But we'd have to extend nsFieldSetFrame
     // to locate this legend in the inserted frames and extract it.
     LAYOUT_PHASE_TEMP_EXIT();
     RecreateFramesForContent(insertion.mParentFrame->GetContent(), false,
                              REMOVE_FOR_RECONSTRUCTION, nullptr);
     LAYOUT_PHASE_TEMP_REENTER();
     return;
   }
 
   // We should only get here with details when doing a single insertion because
   // we treat details frame as if it has multiple insertion points.
-  MOZ_ASSERT(isSingleInsert || frameType != nsGkAtoms::detailsFrame);
-  if (frameType == nsGkAtoms::detailsFrame) {
+  MOZ_ASSERT(isSingleInsert || frameType != FrameType::Details);
+  if (frameType == FrameType::Details) {
     // When inserting an element into <details>, just reframe the details frame
     // and let it figure out where the element should be laid out. It might seem
     // expensive to recreate the entire details frame, but it's the simplest way
     // to handle the insertion.
     LAYOUT_PHASE_TEMP_EXIT();
     RecreateFramesForContent(insertion.mParentFrame->GetContent(), false,
                              REMOVE_FOR_RECONSTRUCTION, nullptr);
     LAYOUT_PHASE_TEMP_REENTER();
@@ -8189,17 +8168,17 @@ nsCSSFrameConstructor::ContentRangeInser
       haveFirstLineStyle =
         ShouldHaveFirstLineStyle(containingBlock->GetContent(),
                                  containingBlock->StyleContext());
     }
 
     if (haveFirstLetterStyle) {
       // If our current insertion.mParentFrame is a Letter frame, use its parent as our
       // new parent hint
-      if (insertion.mParentFrame->GetType() == nsGkAtoms::letterFrame) {
+      if (insertion.mParentFrame->IsLetterFrame()) {
         // If insertion.mParentFrame is out of flow, then we actually want the parent of
         // the placeholder frame.
         if (insertion.mParentFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
           nsPlaceholderFrame* placeholderFrame =
             GetPlaceholderFrameFor(insertion.mParentFrame);
           NS_ASSERTION(placeholderFrame, "No placeholder for out-of-flow?");
           insertion.mParentFrame = placeholderFrame->GetParent();
         } else {
@@ -8225,17 +8204,17 @@ nsCSSFrameConstructor::ContentRangeInser
         LAYOUT_PHASE_TEMP_EXIT();
         IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
                                      aAllowLazyConstruction, aForReconstruction);
         LAYOUT_PHASE_TEMP_REENTER();
         return;
       }
 
       container = insertion.mParentFrame->GetContent();
-      frameType = insertion.mParentFrame->GetType();
+      frameType = insertion.mParentFrame->Type();
     }
   }
 
   if (!prevSibling) {
     // We're inserting the new frames as the first child. See if the
     // parent has a :before pseudo-element
     nsIFrame* firstChild = insertion.mParentFrame->PrincipalChildList().FirstChild();
 
@@ -8307,18 +8286,17 @@ nsCSSFrameConstructor::ContentRangeInser
 
   if (frameItems.NotEmpty()) {
     for (nsIContent* child = aStartChild;
          child != aEndChild;
          child = child->GetNextSibling()){
       InvalidateCanvasIfNeeded(mPresShell, child);
     }
 
-    if (nsGkAtoms::tableFrame == frameType ||
-        nsGkAtoms::tableWrapperFrame == frameType) {
+    if (FrameType::Table == frameType || FrameType::TableWrapper == frameType) {
       PullOutCaptionFrames(frameItems, captionItems);
     }
   }
 
   // If the parent of our current prevSibling is different from the frame we'll
   // actually use as the parent, then the calculated insertion point is now
   // invalid and as it is unknown where to insert correctly we append instead
   // (bug 341858).
@@ -8338,23 +8316,23 @@ nsCSSFrameConstructor::ContentRangeInser
   if (prevSibling && frameItems.NotEmpty() &&
       frameItems.FirstChild()->GetParent() != prevSibling->GetParent()) {
 #ifdef DEBUG
     nsIFrame* frame1 = frameItems.FirstChild()->GetParent();
     nsIFrame* frame2 = prevSibling->GetParent();
     NS_ASSERTION(!IsFramePartOfIBSplit(frame1) &&
                  !IsFramePartOfIBSplit(frame2),
                  "Neither should be ib-split");
-    NS_ASSERTION((frame1->GetType() == nsGkAtoms::tableFrame &&
-                  frame2->GetType() == nsGkAtoms::tableWrapperFrame) ||
-                 (frame1->GetType() == nsGkAtoms::tableWrapperFrame &&
-                  frame2->GetType() == nsGkAtoms::tableFrame) ||
-                 frame1->GetType() == nsGkAtoms::fieldSetFrame ||
+    NS_ASSERTION((frame1->IsTableFrame() &&
+                  frame2->IsTableWrapperFrame()) ||
+                 (frame1->IsTableWrapperFrame() &&
+                  frame2->IsTableFrame()) ||
+                 frame1->IsFieldSetFrame() ||
                  (frame1->GetParent() &&
-                  frame1->GetParent()->GetType() == nsGkAtoms::fieldSetFrame),
+                  frame1->GetParent()->IsFieldSetFrame()),
                  "Unexpected frame types");
 #endif
     isAppend = true;
     nsIFrame* appendAfterFrame;
     insertion.mParentFrame =
       ::AdjustAppendParentForAfterContent(this, container,
                                           frameItems.FirstChild()->GetParent(),
                                           aStartChild, &appendAfterFrame);
@@ -8377,18 +8355,18 @@ nsCSSFrameConstructor::ContentRangeInser
       InsertFirstLineFrames(state, container, containingBlock, &insertion.mParentFrame,
                             prevSibling, frameItems);
     }
   }
 
   // We might have captions; put them into the caption list of the
   // table wrapper frame.
   if (captionItems.NotEmpty()) {
-    NS_ASSERTION(nsGkAtoms::tableFrame == frameType ||
-                 nsGkAtoms::tableWrapperFrame == frameType,
+    NS_ASSERTION(FrameType::Table == frameType ||
+                 FrameType::TableWrapper == frameType,
                  "parent for caption is not table?");
     // We need to determine where to put the caption items; start with the
     // the parent frame that has already been determined and get the insertion
     // prevsibling of the first caption item.
     bool captionIsAppend;
     nsIFrame* captionPrevSibling = nullptr;
 
     // aIsRangeInsertSafe is ignored on purpose because it is irrelevant here.
@@ -8411,17 +8389,17 @@ nsCSSFrameConstructor::ContentRangeInser
 
     nsContainerFrame* outerTable = nullptr;
     if (GetCaptionAdjustedParent(captionInsertion.mParentFrame,
                                  captionItems.FirstChild(),
                                  &outerTable)) {
       // If the parent is not a table wrapper frame we will try to add frames
       // to a named child list that the parent does not honor and the frames
       // will get lost.
-      NS_ASSERTION(nsGkAtoms::tableWrapperFrame == outerTable->GetType(),
+      NS_ASSERTION(outerTable->IsTableWrapperFrame(),
                    "Pseudo frame construction failure; "
                    "a caption can be only a child of a table wrapper frame");
 
       // If the parent of our current prevSibling is different from the frame
       // we'll actually use as the parent, then the calculated insertion
       // point is now invalid (bug 341382).
       if (captionPrevSibling &&
           captionPrevSibling->GetParent() != outerTable) {
@@ -8642,34 +8620,33 @@ nsCSSFrameConstructor::ContentRemoved(ns
         *aDestroyedFramesFor = container;
       }
       return;
     }
     LAYOUT_PHASE_TEMP_REENTER();
 
     // Get the childFrame's parent frame
     nsIFrame* parentFrame = childFrame->GetParent();
-    nsIAtom* parentType = parentFrame->GetType();
-
-    if (parentType == nsGkAtoms::frameSetFrame &&
-        IsSpecialFramesetChild(aChild)) {
+    FrameType parentType = parentFrame->Type();
+
+    if (parentType == FrameType::FrameSet && IsSpecialFramesetChild(aChild)) {
       // Just reframe the parent, since framesets are weird like that.
       *aDidReconstruct = true;
       LAYOUT_PHASE_TEMP_EXIT();
       RecreateFramesForContent(parentFrame->GetContent(), false,
                                aFlags, aDestroyedFramesFor);
       LAYOUT_PHASE_TEMP_REENTER();
       return;
     }
 
     // If we're a child of MathML, then we should reframe the MathML content.
     // If we're non-MathML, then we would be wrapped in a block so we need to
     // check our grandparent in that case.
-    nsIFrame* possibleMathMLAncestor = parentType == nsGkAtoms::blockFrame ?
-         parentFrame->GetParent() : parentFrame;
+    nsIFrame* possibleMathMLAncestor =
+      parentType == FrameType::Block ? parentFrame->GetParent() : parentFrame;
     if (possibleMathMLAncestor->IsFrameOfType(nsIFrame::eMathML)) {
       *aDidReconstruct = true;
       LAYOUT_PHASE_TEMP_EXIT();
       RecreateFramesForContent(possibleMathMLAncestor->GetContent(),
                                false, aFlags, aDestroyedFramesFor);
       LAYOUT_PHASE_TEMP_REENTER();
       return;
     }
@@ -8730,17 +8707,17 @@ nsCSSFrameConstructor::ContentRemoved(ns
       childFrame = aChild->GetPrimaryFrame();
       if (!childFrame || childFrame->GetContent() != aChild) {
         // XXXbz the GetContent() != aChild check is needed due to bug 135040.
         // Remove it once that's fixed.
         ClearUndisplayedContentIn(aChild, aContainer);
         return;
       }
       parentFrame = childFrame->GetParent();
-      parentType = parentFrame->GetType();
+      parentType = parentFrame->Type();
 
 #ifdef NOISY_FIRST_LETTER
       printf("  ==> revised parentFrame=");
       nsFrame::ListTag(stdout, parentFrame);
       printf(" childFrame=");
       nsFrame::ListTag(stdout, childFrame);
       printf("\n");
 #endif
@@ -9155,76 +9132,76 @@ nsCSSFrameConstructor::CreateContinuingF
 {
   nsIPresShell*              shell = aPresContext->PresShell();
   nsStyleContext*            styleContext = aFrame->StyleContext();
   nsIFrame*                  newFrame = nullptr;
   nsIFrame*                  nextContinuation = aFrame->GetNextContinuation();
   nsIFrame*                  nextInFlow = aFrame->GetNextInFlow();
 
   // Use the frame type to determine what type of frame to create
-  nsIAtom* frameType = aFrame->GetType();
+  FrameType frameType = aFrame->Type();
   nsIContent* content = aFrame->GetContent();
 
   NS_ASSERTION(aFrame->GetSplittableType() != NS_FRAME_NOT_SPLITTABLE,
                "why CreateContinuingFrame for a non-splittable frame?");
 
-  if (nsGkAtoms::textFrame == frameType) {
+  if (FrameType::Text == frameType) {
     newFrame = NS_NewContinuingTextFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
-  } else if (nsGkAtoms::inlineFrame == frameType) {
+  } else if (FrameType::Inline == frameType) {
     newFrame = NS_NewInlineFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
-  } else if (nsGkAtoms::blockFrame == frameType) {
+  } else if (FrameType::Block == frameType) {
     MOZ_ASSERT(!aFrame->IsTableCaption(),
                "no support for fragmenting table captions yet");
     newFrame = NS_NewBlockFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
 #ifdef MOZ_XUL
-  } else if (nsGkAtoms::XULLabelFrame == frameType) {
+  } else if (FrameType::XULLabel == frameType) {
     newFrame = NS_NewXULLabelFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
 #endif
-  } else if (nsGkAtoms::columnSetFrame == frameType) {
+  } else if (FrameType::ColumnSet == frameType) {
     MOZ_ASSERT(!aFrame->IsTableCaption(),
                "no support for fragmenting table captions yet");
     newFrame = NS_NewColumnSetFrame(shell, styleContext, nsFrameState(0));
     newFrame->Init(content, aParentFrame, aFrame);
-  } else if (nsGkAtoms::pageFrame == frameType) {
+  } else if (FrameType::Page == frameType) {
     nsContainerFrame* canvasFrame;
     newFrame = ConstructPageFrame(shell, aParentFrame, aFrame, canvasFrame);
-  } else if (nsGkAtoms::tableWrapperFrame == frameType) {
+  } else if (FrameType::TableWrapper == frameType) {
     newFrame =
       CreateContinuingOuterTableFrame(shell, aPresContext, aFrame, aParentFrame,
                                       content, styleContext);
 
-  } else if (nsGkAtoms::tableFrame == frameType) {
+  } else if (FrameType::Table == frameType) {
     newFrame =
       CreateContinuingTableFrame(shell, aFrame, aParentFrame,
                                  content, styleContext);
 
-  } else if (nsGkAtoms::tableRowGroupFrame == frameType) {
+  } else if (FrameType::TableRowGroup == frameType) {
     newFrame = NS_NewTableRowGroupFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
     if (newFrame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN) {
       nsTableFrame::RegisterPositionedTablePart(newFrame);
     }
-  } else if (nsGkAtoms::tableRowFrame == frameType) {
+  } else if (FrameType::TableRow == frameType) {
     nsTableRowFrame* rowFrame = NS_NewTableRowFrame(shell, styleContext);
 
     rowFrame->Init(content, aParentFrame, aFrame);
     if (rowFrame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN) {
       nsTableFrame::RegisterPositionedTablePart(rowFrame);
     }
 
     // Create a continuing frame for each table cell frame
     nsFrameItems  newChildList;
     nsIFrame* cellFrame = aFrame->PrincipalChildList().FirstChild();
     while (cellFrame) {
       // See if it's a table cell frame
-      if (IS_TABLE_CELL(cellFrame->GetType())) {
+      if (IS_TABLE_CELL(cellFrame->Type())) {
         nsIFrame* continuingCellFrame =
           CreateContinuingFrame(aPresContext, cellFrame, rowFrame);
         newChildList.AddChild(continuingCellFrame);
       }
       cellFrame = cellFrame->GetNextSibling();
     }
 
     rowFrame->SetInitialChildList(kPrincipalList, newChildList);
@@ -9247,38 +9224,38 @@ nsCSSFrameConstructor::CreateContinuingF
     // Create a continuing area frame
     nsIFrame* blockFrame = aFrame->PrincipalChildList().FirstChild();
     nsIFrame* continuingBlockFrame =
       CreateContinuingFrame(aPresContext, blockFrame,
                             static_cast<nsContainerFrame*>(cellFrame));
 
     SetInitialSingleChild(cellFrame, continuingBlockFrame);
     newFrame = cellFrame;
-  } else if (nsGkAtoms::lineFrame == frameType) {
+  } else if (FrameType::Line == frameType) {
     newFrame = NS_NewFirstLineFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
-  } else if (nsGkAtoms::letterFrame == frameType) {
+  } else if (FrameType::Letter == frameType) {
     newFrame = NS_NewFirstLetterFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
-  } else if (nsGkAtoms::imageFrame == frameType) {
+  } else if (FrameType::Image == frameType) {
     newFrame = NS_NewImageFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
-  } else if (nsGkAtoms::imageControlFrame == frameType) {
+  } else if (FrameType::ImageControl == frameType) {
     newFrame = NS_NewImageControlFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
-  } else if (nsGkAtoms::placeholderFrame == frameType) {
+  } else if (FrameType::Placeholder == frameType) {
     // create a continuing out of flow frame
     nsIFrame* oofFrame = nsPlaceholderFrame::GetRealFrameForPlaceholder(aFrame);
     nsIFrame* oofContFrame =
       CreateContinuingFrame(aPresContext, oofFrame, aParentFrame);
     newFrame =
       CreatePlaceholderFrameFor(shell, content, oofContFrame,
                                 aParentFrame, aFrame,
                                 aFrame->GetStateBits() & PLACEHOLDER_TYPE_MASK);
-  } else if (nsGkAtoms::fieldSetFrame == frameType) {
+  } else if (FrameType::FieldSet == frameType) {
     nsContainerFrame* fieldset = NS_NewFieldSetFrame(shell, styleContext);
 
     fieldset->Init(content, aParentFrame, aFrame);
 
     // Create a continuing area frame
     // XXXbz we really shouldn't have to do this by hand!
     nsContainerFrame* blockFrame = GetFieldSetBlockFrame(aFrame);
     if (blockFrame) {
@@ -9286,35 +9263,35 @@ nsCSSFrameConstructor::CreateContinuingF
         CreateContinuingFrame(aPresContext, blockFrame, fieldset);
       // Set the fieldset's initial child list
       SetInitialSingleChild(fieldset, continuingBlockFrame);
     } else {
       MOZ_ASSERT(aFrame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER,
                  "FieldSet block may only be null for overflow containers");
     }
     newFrame = fieldset;
-  } else if (nsGkAtoms::legendFrame == frameType) {
+  } else if (FrameType::Legend == frameType) {
     newFrame = NS_NewLegendFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
-  } else if (nsGkAtoms::flexContainerFrame == frameType) {
+  } else if (FrameType::FlexContainer == frameType) {
     newFrame = NS_NewFlexContainerFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
-  } else if (nsGkAtoms::gridContainerFrame == frameType) {
+  } else if (FrameType::GridContainer == frameType) {
     newFrame = NS_NewGridContainerFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
-  } else if (nsGkAtoms::rubyFrame == frameType) {
+  } else if (FrameType::Ruby == frameType) {
     newFrame = NS_NewRubyFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
-  } else if (nsGkAtoms::rubyBaseContainerFrame == frameType) {
+  } else if (FrameType::RubyBaseContainer == frameType) {
     newFrame = NS_NewRubyBaseContainerFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
-  } else if (nsGkAtoms::rubyTextContainerFrame == frameType) {
+  } else if (FrameType::RubyTextContainer == frameType) {
     newFrame = NS_NewRubyTextContainerFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
-  } else if (nsGkAtoms::detailsFrame == frameType) {
+  } else if (FrameType::Details == frameType) {
     newFrame = NS_NewDetailsFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
   } else {
     MOZ_CRASH("unexpected frame type");
   }
 
   // Init() set newFrame to be a fluid continuation of aFrame.
   // If we want a non-fluid continuation, we need to call SetPrevContinuation()
@@ -9480,25 +9457,23 @@ nsCSSFrameConstructor::GetInsertionPoint
     return InsertionPoint();
   }
 
   InsertionPoint insertion(GetContentInsertionFrameFor(insertionElement),
                            insertionElement);
 
   // Fieldset frames have multiple normal flow child frame lists so handle it
   // the same as if it had multiple content insertion points.
-  if (insertion.mParentFrame &&
-      insertion.mParentFrame->GetType() == nsGkAtoms::fieldSetFrame) {
+  if (insertion.mParentFrame && insertion.mParentFrame->IsFieldSetFrame()) {
     insertion.mMultiple = true;
   }
 
   // A details frame moves the first summary frame to be its first child, so we
   // treat it as if it has multiple content insertion points.
-  if (insertion.mParentFrame &&
-      insertion.mParentFrame->GetType() == nsGkAtoms::detailsFrame) {
+  if (insertion.mParentFrame && insertion.mParentFrame->IsDetailsFrame()) {
     insertion.mMultiple = true;
   }
 
   return insertion;
 }
 
 // Capture state for the frame tree rooted at the frame associated with the
 // content object, aContent
@@ -9572,18 +9547,17 @@ nsCSSFrameConstructor::MaybeRecreateFram
   RecreateFramesForContent(aElement, false, REMOVE_FOR_RECONSTRUCTION, nullptr);
   return nullptr;
 }
 
 static bool
 IsWhitespaceFrame(nsIFrame* aFrame)
 {
   MOZ_ASSERT(aFrame, "invalid argument");
-  return aFrame->GetType() == nsGkAtoms::textFrame &&
-    aFrame->GetContent()->TextIsOnlyWhitespace();
+  return aFrame->IsTextFrame() && aFrame->GetContent()->TextIsOnlyWhitespace();
 }
 
 static nsIFrame*
 FindFirstNonWhitespaceChild(nsIFrame* aParentFrame)
 {
   nsIFrame* f = aParentFrame->PrincipalChildList().FirstChild();
   while (f && IsWhitespaceFrame(f)) {
     f = f->GetNextSibling();
@@ -9635,27 +9609,26 @@ nsCSSFrameConstructor::MaybeRecreateCont
     }
 #endif
 
     ReframeContainingBlock(aFrame, aFlags, aDestroyedFramesFor);
     return true;
   }
 
   nsContainerFrame* insertionFrame = aFrame->GetContentInsertionFrame();
-  if (insertionFrame && insertionFrame->GetType() == nsGkAtoms::legendFrame &&
-      aFrame->GetParent()->GetType() == nsGkAtoms::fieldSetFrame) {
+  if (insertionFrame && insertionFrame->IsLegendFrame() &&
+      aFrame->GetParent()->IsFieldSetFrame()) {
     // When we remove the legend for a fieldset, we should reframe
     // the fieldset to ensure another legend is used, if there is one
     RecreateFramesForContent(aFrame->GetParent()->GetContent(), false,
                              aFlags, aDestroyedFramesFor);
     return true;
   }
 
-  if (insertionFrame &&
-      aFrame->GetParent()->GetType() == nsGkAtoms::detailsFrame) {
+  if (insertionFrame && aFrame->GetParent()->IsDetailsFrame()) {
     HTMLSummaryElement* summary =
       HTMLSummaryElement::FromContent(insertionFrame->GetContent());
 
     if (summary && summary->IsMainSummary()) {
       // When removing a summary, we should reframe the parent details frame to
       // ensure that another summary is used or the default summary is
       // generated.
       RecreateFramesForContent(aFrame->GetParent()->GetContent(),
@@ -9680,17 +9653,17 @@ nsCSSFrameConstructor::MaybeRecreateCont
     if (FindFirstNonWhitespaceChild(parent) == inFlowFrame ||
         !FindNextNonWhitespaceSibling(inFlowFrame->LastContinuation()) ||
         // If it is a whitespace, and is the only child of the parent, the
         // pseudo parent was created for the space, and should now be removed.
         (IsWhitespaceFrame(aFrame) &&
          parent->PrincipalChildList().OnlyChild()) ||
         // If we're a table-column-group, then the OnlyChild check above is
         // not going to catch cases when we're the first child.
-        (inFlowFrame->GetType() == nsGkAtoms::tableColGroupFrame &&
+        (inFlowFrame->IsTableColGroupFrame() &&
          parent->GetChildList(nsIFrame::kColGroupList).FirstChild() == inFlowFrame) ||
         // Similar if we're a table-caption.
         (inFlowFrame->IsTableCaption() &&
          parent->GetChildList(nsIFrame::kCaptionList).FirstChild() == inFlowFrame)) {
       // We're the first or last frame in the pseudo.  Need to reframe.
       // Good enough to recreate frames for |parent|'s content
       RecreateFramesForContent(parent->GetContent(), true, aFlags,
                                aDestroyedFramesFor);
@@ -9724,18 +9697,18 @@ nsCSSFrameConstructor::MaybeRecreateCont
       // aFrame's parent is a pseudo, that'll be the right content node.
       RecreateFramesForContent(parent->GetContent(), true, aFlags,
                                aDestroyedFramesFor);
       return true;
     }
   }
 
   // Check ruby containers
-  nsIAtom* parentType = parent->GetType();
-  if (parentType == nsGkAtoms::rubyFrame ||
+  FrameType parentType = parent->Type();
+  if (parentType == FrameType::Ruby ||
       RubyUtils::IsRubyContainerBox(parentType)) {
     // In ruby containers, pseudo frames may be created from
     // whitespaces or even nothing. There are two cases we actually
     // need to handle here, but hard to check exactly:
     // 1. Status of spaces beside the frame may vary, and related
     //    frames may be constructed or destroyed accordingly.
     // 2. The type of the first child of a ruby frame determines
     //    whether a pseudo ruby base container should exist.
@@ -9783,17 +9756,17 @@ nsCSSFrameConstructor::MaybeRecreateCont
 #endif // DEBUG
     // Recreate frames for the flex container (the removed frame's grandparent)
     RecreateFramesForContent(parent->GetParent()->GetContent(), true,
                              aFlags, aDestroyedFramesFor);
     return true;
   }
 
 #ifdef MOZ_XUL
-  if (aFrame->GetType() == nsGkAtoms::popupSetFrame) {
+  if (aFrame->IsPopupSetFrame()) {
     nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
     if (rootBox && rootBox->GetPopupSetFrame() == aFrame) {
       ReconstructDocElementHierarchy();
       return true;
     }
   }
 #endif
 
@@ -9898,17 +9871,17 @@ nsCSSFrameConstructor::RecreateFramesFor
       nsIAnonymousContentCreator* acc = nullptr;
       nsIFrame* ancestor = nsLayoutUtils::GetParentOrPlaceholderFor(frame);
       while (!(acc = do_QueryFrame(ancestor))) {
         ancestor = nsLayoutUtils::GetParentOrPlaceholderFor(ancestor);
       }
       NS_ASSERTION(acc, "Where is the nsIAnonymousContentCreator? We may fail "
                         "to recreate its content correctly");
       // nsSVGUseFrame is special, and we know this is unnecessary for it.
-      if (ancestor->GetType() != nsGkAtoms::svgUseFrame) {
+      if (!ancestor->IsSVGUseFrame()) {
         NS_ASSERTION(aContent->IsInNativeAnonymousSubtree(),
                      "Why is NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT set?");
         return RecreateFramesForContent(ancestor->GetContent(), aAsyncInsert,
                                         aFlags, aDestroyedFramesFor);
       }
     }
 
     nsIFrame* parent = frame->GetParent();
@@ -10151,24 +10124,23 @@ void
 nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
   nsFrameConstructorState& aState,
   FrameConstructionItemList& aItems,
   nsIFrame* aParentFrame)
 {
   if (aItems.IsEmpty()) {
     return;
   }
-  const nsIAtom* parentType = aParentFrame->GetType();
-  if (parentType != nsGkAtoms::flexContainerFrame &&
-      parentType != nsGkAtoms::gridContainerFrame) {
+  const FrameType parentType = aParentFrame->Type();
+  if (parentType != FrameType::FlexContainer &&
+      parentType != FrameType::GridContainer) {
     return;
   }
 
-  const bool isWebkitBox = IsFlexContainerForLegacyBox(aParentFrame,
-                                                       parentType);
+  const bool isWebkitBox = IsFlexContainerForLegacyBox(aParentFrame);
   FCItemIterator iter(aItems);
   do {
     // Advance iter past children that don't want to be wrapped
     if (iter.SkipItemsThatDontNeedAnonFlexOrGridItem(aState, isWebkitBox)) {
       // Hit the end of the items without finding any remaining children that
       // need to be wrapped. We're finished!
       return;
     }
@@ -10216,18 +10188,19 @@ nsCSSFrameConstructor::CreateNeededAnonF
     FCItemIterator endIter(iter); // iterator to find the end of the group
     endIter.SkipItemsThatNeedAnonFlexOrGridItem(aState, isWebkitBox);
 
     NS_ASSERTION(iter != endIter,
                  "Should've had at least one wrappable child to seek past");
 
     // Now, we create the anonymous flex or grid item to contain the children
     // between |iter| and |endIter|.
-    nsIAtom* pseudoType = (aParentFrame->GetType() == nsGkAtoms::flexContainerFrame) ?
-      nsCSSAnonBoxes::anonymousFlexItem : nsCSSAnonBoxes::anonymousGridItem;
+    nsIAtom* pseudoType = (aParentFrame->IsFlexContainerFrame())
+                            ? nsCSSAnonBoxes::anonymousFlexItem
+                            : nsCSSAnonBoxes::anonymousGridItem;
     nsStyleContext* parentStyle = aParentFrame->StyleContext();
     nsIContent* parentContent = aParentFrame->GetContent();
     already_AddRefed<nsStyleContext> wrapperStyle =
       mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(pseudoType,
                                                                  parentStyle);
 
     static const FrameConstructionData sBlockFormattingContextFCData =
       FCDATA_DECL(FCDATA_SKIP_FRAMESET | FCDATA_USE_CHILD_ITEMS,
@@ -10827,46 +10800,46 @@ void nsCSSFrameConstructor::CreateNeeded
  * purely for sanity-checking the children of these container types.
  * NOTE: See also NeedsAnonFlexOrGridItem(), for the non-debug version of this
  * logic (which operates a bit earlier, on FCData instead of frames).
  */
 static bool
 FrameWantsToBeInAnonymousItem(const nsIFrame* aContainerFrame,
                               const nsIFrame* aFrame)
 {
-  nsIAtom* containerType = aContainerFrame->GetType();
-  MOZ_ASSERT(containerType == nsGkAtoms::flexContainerFrame ||
-             containerType == nsGkAtoms::gridContainerFrame);
+  FrameType containerType = aContainerFrame->Type();
+  MOZ_ASSERT(containerType == FrameType::FlexContainer ||
+             containerType == FrameType::GridContainer);
 
   // Any line-participant frames (e.g. text) definitely want to be wrapped in
   // an anonymous flex/grid item.
   if (aFrame->IsFrameOfType(nsIFrame::eLineParticipant)) {
     return true;
   }
 
   // If the container is a -webkit-box/-webkit-inline-box, then placeholders
   // also need to be wrapped, for compatibility.
-  if (containerType == nsGkAtoms::flexContainerFrame &&
+  if (containerType == FrameType::FlexContainer &&
       aContainerFrame->HasAnyStateBits(NS_STATE_FLEX_IS_LEGACY_WEBKIT_BOX) &&
-      aFrame->GetType() == nsGkAtoms::placeholderFrame) {
+      aFrame->IsPlaceholderFrame()) {
     return true;
   }
 
   return false;
 }
 #endif
 
 static void
 VerifyGridFlexContainerChildren(nsIFrame* aParentFrame,
                                 const nsFrameList& aChildren)
 {
 #ifdef DEBUG
-  auto parentType = aParentFrame->GetType();
-  if (parentType != nsGkAtoms::flexContainerFrame &&
-      parentType != nsGkAtoms::gridContainerFrame) {
+  auto parentType = aParentFrame->Type();
+  if (parentType != FrameType::FlexContainer &&
+      parentType != FrameType::GridContainer) {
     return;
   }
 
   bool prevChildWasAnonItem = false;
   for (const nsIFrame* child : aChildren) {
     MOZ_ASSERT(!FrameWantsToBeInAnonymousItem(aParentFrame, child),
                "frame wants to be inside an anonymous item, but it isn't");
     if (IsAnonymousFlexOrGridItem(child)) {
@@ -11020,18 +10993,17 @@ nsCSSFrameConstructor::AddFCItemsForAnon
       }
     }
 
     nsIFrame* styleParentFrame =
       nsFrame::CorrectStyleParentFrame(inheritFrame, pseudo);
     // The only way we can not have a style parent now is if inheritFrame is the
     // canvas frame and we're the NAC parent for all the things added via
     // nsIDocument::InsertAnonymousContent.
-    MOZ_ASSERT_IF(!styleParentFrame,
-                  inheritFrame->GetType() == nsGkAtoms::canvasFrame);
+    MOZ_ASSERT_IF(!styleParentFrame, inheritFrame->IsCanvasFrame());
     // And that anonymous div has no pseudo.
     MOZ_ASSERT_IF(!styleParentFrame, !pseudo);
 
     Element* originating =
       pseudo ? styleParentFrame->GetContent()->AsElement() : nullptr;
     nsStyleContext* parentStyle =
       styleParentFrame ? styleParentFrame->StyleContext() : nullptr;
     styleContext =
@@ -11355,17 +11327,17 @@ nsCSSFrameConstructor::AppendFirstLineFr
     WrapFramesInFirstLineFrame(aState, aBlockContent,
                                aBlockFrame, nullptr, aFrameItems);
     return;
   }
 
   // Examine the last block child - if it's a first-line frame then
   // appended frames need special treatment.
   nsIFrame* lastBlockKid = blockKids.LastChild();
-  if (lastBlockKid->GetType() != nsGkAtoms::lineFrame) {
+  if (!lastBlockKid->IsLineFrame()) {
     // No first-line frame at the end of the list, therefore there is
     // an intervening block between any first-line frame the frames
     // we are appending. Therefore, we don't need any special
     // treatment of the appended frames.
     return;
   }
 
   nsFirstLineFrame* lineFrame = static_cast<nsFirstLineFrame*>(lastBlockKid);
@@ -11393,17 +11365,17 @@ nsCSSFrameConstructor::InsertFirstLineFr
   nsIFrame* parentFrame = *aParentFrame;
   nsIFrame* newFrame = aFrameItems.childList;
   bool isInline = IsInlineOutside(newFrame);
 
   if (!aPrevSibling) {
     // Insertion will become the first frame. Two cases: we either
     // already have a first-line frame or we don't.
     nsIFrame* firstBlockKid = aBlockFrame->PrincipalChildList().FirstChild();
-    if (firstBlockKid->GetType() == nsGkAtoms::lineFrame) {
+    if (firstBlockKid->IsLineFrame()) {
       // We already have a first-line frame
       nsIFrame* lineFrame = firstBlockKid;
 
       if (isInline) {
         // Easy case: the new inline frame will go into the lineFrame.
         ReparentFrame(this, lineFrame, newFrame);
         InsertFrames(lineFrame, kPrincipalList, nullptr, newFrame);
 
@@ -11781,34 +11753,33 @@ nsCSSFrameConstructor::WrapFramesInFirst
   bool*                    aStopLooking)
 {
   nsIFrame* prevFrame = nullptr;
   nsIFrame* frame = aParentFrameList;
 
   while (frame) {
     nsIFrame* nextFrame = frame->GetNextSibling();
 
-    nsIAtom* frameType = frame->GetType();
-    if (nsGkAtoms::textFrame == frameType) {
+    FrameType frameType = frame->Type();
+    if (FrameType::Text == frameType) {
       // Wrap up first-letter content in a letter frame
       nsIContent* textContent = frame->GetContent();
       if (IsFirstLetterContent(textContent)) {
         // Create letter frame to wrap up the text
         CreateLetterFrame(aBlockFrame, aBlockContinuation, textContent,
                           aParentFrame, aLetterFrames);
 
         // Provide adjustment information for parent
         *aModifiedParent = aParentFrame;
         *aTextFrame = frame;
         *aPrevFrame = prevFrame;
         *aStopLooking = true;
         return;
       }
-    }
-    else if (IsInlineFrame(frame) && frameType != nsGkAtoms::brFrame) {
+    } else if (IsInlineFrame(frame) && frameType != FrameType::Br) {
       nsIFrame* kids = frame->PrincipalChildList().FirstChild();
       WrapFramesInFirstLetterFrame(aBlockFrame, aBlockContinuation,
                                    static_cast<nsContainerFrame*>(frame),
                                    kids, aModifiedParent, aTextFrame,
                                    aPrevFrame, aLetterFrames, aStopLooking);
       if (*aStopLooking) {
         return;
       }
@@ -11829,17 +11800,17 @@ nsCSSFrameConstructor::WrapFramesInFirst
   }
 }
 
 static nsIFrame*
 FindFirstLetterFrame(nsIFrame* aFrame, nsIFrame::ChildListID aListID)
 {
   nsFrameList list = aFrame->GetChildList(aListID);
   for (nsFrameList::Enumerator e(list); !e.AtEnd(); e.Next()) {
-    if (nsGkAtoms::letterFrame == e.get()->GetType()) {
+    if (e.get()->IsLetterFrame()) {
       return e.get();
     }
   }
   return nullptr;
 }
 
 void
 nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames(
@@ -11909,18 +11880,17 @@ nsCSSFrameConstructor::RemoveFloatingFir
   // Remove placeholder frame and the float
   RemoveFrame(kPrincipalList, placeholderFrame);
 
   // Now that the old frames are gone, we can start pointing to our
   // new primary frame.
   textContent->SetPrimaryFrame(newTextFrame);
 
   // Wallpaper bug 822910.
-  bool offsetsNeedFixing =
-    prevSibling && prevSibling->GetType() == nsGkAtoms::textFrame;
+  bool offsetsNeedFixing = prevSibling && prevSibling->IsTextFrame();
   if (offsetsNeedFixing) {
     prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
   }
 
   // Insert text frame in its place
   nsFrameList textList(newTextFrame, newTextFrame);
   InsertFrames(parentFrame, kPrincipalList, prevSibling, textList);
 
@@ -11934,17 +11904,17 @@ nsCSSFrameConstructor::RemoveFirstLetter
                                                nsContainerFrame* aFrame,
                                                nsContainerFrame* aBlockFrame,
                                                bool* aStopLooking)
 {
   nsIFrame* prevSibling = nullptr;
   nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
 
   while (kid) {
-    if (nsGkAtoms::letterFrame == kid->GetType()) {
+    if (kid->IsLetterFrame()) {
       // Bingo. Found it. First steal away the text frame.
       nsIFrame* textFrame = kid->PrincipalChildList().FirstChild();
       if (!textFrame) {
         break;
       }
 
       // Create a new textframe
       nsStyleContext* parentSC = aFrame->StyleContext();
@@ -11963,18 +11933,17 @@ nsCSSFrameConstructor::RemoveFirstLetter
       // Next rip out the kid and replace it with the text frame
       RemoveFrame(kPrincipalList, kid);
 
       // Now that the old frames are gone, we can start pointing to our
       // new primary frame.
       textContent->SetPrimaryFrame(textFrame);
 
       // Wallpaper bug 822910.
-      bool offsetsNeedFixing =
-        prevSibling && prevSibling->GetType() == nsGkAtoms::textFrame;
+      bool offsetsNeedFixing = prevSibling && prevSibling->IsTextFrame();
       if (offsetsNeedFixing) {
         prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
       }
 
       // Insert text frame in its place
       nsFrameList textList(textFrame, textFrame);
       InsertFrames(aFrame, kPrincipalList, prevSibling, textList);
 
@@ -12145,18 +12114,17 @@ nsCSSFrameConstructor::ConstructBlock(ns
                                       nsStyleContext*          aStyleContext,
                                       nsContainerFrame**       aNewFrame,
                                       nsFrameItems&            aFrameItems,
                                       nsIFrame*                aPositionedFrameForAbsPosContainer,
                                       PendingBinding*          aPendingBinding)
 {
   // Create column wrapper if necessary
   nsContainerFrame* blockFrame = *aNewFrame;
-  NS_ASSERTION((blockFrame->GetType() == nsGkAtoms::blockFrame ||
-                blockFrame->GetType() == nsGkAtoms::detailsFrame),
+  NS_ASSERTION((blockFrame->IsBlockFrame() || blockFrame->IsDetailsFrame()),
                "not a block frame nor a details frame?");
   nsContainerFrame* parent = aParentFrame;
   RefPtr<nsStyleContext> blockStyle = aStyleContext;
   const nsStyleColumn* columns = aStyleContext->StyleColumn();
 
   if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO
       || columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
     nsContainerFrame* columnSetFrame =
@@ -12559,24 +12527,24 @@ nsCSSFrameConstructor::WipeContainingBlo
     return true;
   }
 
   nsIFrame* nextSibling = ::GetInsertNextSibling(aFrame, aPrevSibling);
 
   // Situation #2 is a flex or grid container frame into which we're inserting
   // new inline non-replaced children, adjacent to an existing anonymous
   // flex or grid item.
-  nsIAtom* frameType = aFrame->GetType();
-  if (frameType == nsGkAtoms::flexContainerFrame ||
-      frameType == nsGkAtoms::gridContainerFrame) {
+  FrameType frameType = aFrame->Type();
+  if (frameType == FrameType::FlexContainer ||
+      frameType == FrameType::GridContainer) {
     FCItemIterator iter(aItems);
 
     // Check if we're adding to-be-wrapped content right *after* an existing
     // anonymous flex or grid item (which would need to absorb this content).
-    const bool isWebkitBox = IsFlexContainerForLegacyBox(aFrame, frameType);
+    const bool isWebkitBox = IsFlexContainerForLegacyBox(aFrame);
     if (aPrevSibling && IsAnonymousFlexOrGridItem(aPrevSibling) &&
         iter.item().NeedsAnonFlexOrGridItem(aState, isWebkitBox)) {
       RecreateFramesForContent(aFrame->GetContent(), true,
                                REMOVE_FOR_RECONSTRUCTION, nullptr);
       return true;
     }
 
     // Check if we're adding to-be-wrapped content right *before* an existing
@@ -12606,18 +12574,17 @@ nsCSSFrameConstructor::WipeContainingBlo
     // _flex/grid container_ as its parent in the content tree.
     nsFrameConstructorSaveState floatSaveState;
     aState.PushFloatContainingBlock(nullptr, floatSaveState);
 
     FCItemIterator iter(aItems);
     // Skip over things that _do_ need an anonymous flex item, because
     // they're perfectly happy to go here -- they won't cause a reframe.
     nsIFrame* containerFrame = aFrame->GetParent();
-    const bool isWebkitBox =
-      IsFlexContainerForLegacyBox(containerFrame, containerFrame->GetType());
+    const bool isWebkitBox = IsFlexContainerForLegacyBox(containerFrame);
     if (!iter.SkipItemsThatNeedAnonFlexOrGridItem(aState,
                                                   isWebkitBox)) {
       // We hit something that _doesn't_ need an anonymous flex item!
       // Rebuild the flex container to bust it out.
       RecreateFramesForContent(containerFrame->GetContent(), true,
                                REMOVE_FOR_RECONSTRUCTION, nullptr);
       return true;
     }
@@ -12631,18 +12598,17 @@ nsCSSFrameConstructor::WipeContainingBlo
   // spaces. It containes these two special cases apart from tables:
   // 1) There are effectively three types of white spaces in ruby frames
   //    we handle differently: leading/tailing/inter-level space,
   //    inter-base/inter-annotation space, and inter-segment space.
   //    These three types of spaces can be converted to each other when
   //    their sibling changes.
   // 2) The first effective child of a ruby frame must always be a ruby
   //    base container. It should be created or destroyed accordingly.
-  if (IsRubyPseudo(aFrame) ||
-      frameType == nsGkAtoms::rubyFrame ||
+  if (IsRubyPseudo(aFrame) || frameType == FrameType::Ruby ||
       RubyUtils::IsRubyContainerBox(frameType)) {
     // We want to optimize it better, and avoid reframing as much as
     // possible. But given the cases above, and the fact that a ruby
     // usually won't be very large, it should be fine to reframe it.
     RecreateFramesForContent(aFrame->GetContent(), true,
                              REMOVE_FOR_RECONSTRUCTION, nullptr);
     return true;
   }
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -606,21 +606,21 @@ private:
 #define FCDATA_DESIRED_PARENT_TYPE(_bits)           \
   ParentType((_bits) >> FCDATA_PARENT_TYPE_OFFSET)
   /* Macro to create FrameConstructionData bits out of a desired parent type */
 #define FCDATA_DESIRED_PARENT_TYPE_TO_BITS(_type)     \
   (((uint32_t)(_type)) << FCDATA_PARENT_TYPE_OFFSET)
 
   /* Get the parent type that aParentFrame has. */
   static ParentType GetParentType(nsIFrame* aParentFrame) {
-    return GetParentType(aParentFrame->GetType());
+    return GetParentType(aParentFrame->Type());
   }
 
-  /* Get the parent type for the given nsIFrame type atom */
-  static ParentType GetParentType(nsIAtom* aFrameType);
+  /* Get the parent type for the given FrameType */
+  static ParentType GetParentType(mozilla::FrameType aFrameType);
 
   static bool IsRubyParentType(ParentType aParentType) {
     return (aParentType == eTypeRuby ||
             aParentType == eTypeRubyBase ||
             aParentType == eTypeRubyBaseContainer ||
             aParentType == eTypeRubyText ||
             aParentType == eTypeRubyTextContainer);
   }
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -51,17 +51,17 @@ static const int32_t kMinBidiIndicatorPi
  * at aFrame which is either a text frame logically at the end of a line,
  * or which is aStopAtFrame. Return null if no such frame is found. We don't
  * descend into the children of non-eLineParticipant frames.
  */
 static nsIFrame*
 CheckForTrailingTextFrameRecursive(nsIFrame* aFrame, nsIFrame* aStopAtFrame)
 {
   if (aFrame == aStopAtFrame ||
-      ((aFrame->GetType() == nsGkAtoms::textFrame &&
+      ((aFrame->IsTextFrame() &&
        (static_cast<nsTextFrame*>(aFrame))->IsAtEndOfLine())))
     return aFrame;
   if (!aFrame->IsFrameOfType(nsIFrame::eLineParticipant))
     return nullptr;
 
   for (nsIFrame* f : aFrame->PrincipalChildList())
   {
     nsIFrame* r = CheckForTrailingTextFrameRecursive(f, aStopAtFrame);
@@ -99,17 +99,17 @@ AdjustCaretFrameForLineEnd(nsIFrame** aF
   for (nsIFrame* f = line->mFirstChild; count > 0; --count, f = f->GetNextSibling())
   {
     nsIFrame* r = CheckForTrailingTextFrameRecursive(f, *aFrame);
     if (r == *aFrame)
       return;
     if (r)
     {
       *aFrame = r;
-      NS_ASSERTION(r->GetType() == nsGkAtoms::textFrame, "Expected text frame");
+      NS_ASSERTION(r->IsTextFrame(), "Expected text frame");
       *aOffset = (static_cast<nsTextFrame*>(r))->GetContentEnd();
       return;
     }
   }
 }
 
 static bool
 IsBidiUI()
@@ -369,18 +369,18 @@ nsCaret::GetGeometryForFrame(nsIFrame* a
     }
   }
 
   rect = nsRect(framePos, vertical ? nsSize(height, caretMetrics.mCaretWidth) :
                                      nsSize(caretMetrics.mCaretWidth, height));
 
   // Clamp the inline-position to be within our scroll frame. If we don't, then
   // it clips us, and we don't appear at all. See bug 335560.
-  nsIFrame *scrollFrame =
-    nsLayoutUtils::GetClosestFrameOfType(aFrame, nsGkAtoms::scrollFrame);
+  nsIFrame* scrollFrame =
+    nsLayoutUtils::GetClosestFrameOfType(aFrame, FrameType::Scroll);
   if (scrollFrame) {
     // First, use the scrollFrame to get at the scrollable view that we're in.
     nsIScrollableFrame *sf = do_QueryFrame(scrollFrame);
     nsIFrame *scrolled = sf->GetScrolledFrame();
     nsRect caretInScroll = rect + aFrame->GetOffsetTo(scrolled);
 
     // Now see if the caret extends beyond the view's bounds. If it does,
     // then snap it back, put it as close to the edge as it can.
@@ -545,20 +545,19 @@ nsCaret::GetPaintGeometry(nsRect* aRect)
        userinterface->mUserModify == StyleUserModify::ReadOnly) ||
       userinterface->mUserInput == StyleUserInput::None ||
       userinterface->mUserInput == StyleUserInput::Disabled) {
     return nullptr;
   }
 
   // If the offset falls outside of the frame, then don't paint the caret.
   int32_t startOffset, endOffset;
-  if (frame->GetType() == nsGkAtoms::textFrame &&
+  if (frame->IsTextFrame() &&
       (NS_FAILED(frame->GetOffsets(startOffset, endOffset)) ||
-      startOffset > frameOffset ||
-      endOffset < frameOffset)) {
+       startOffset > frameOffset || endOffset < frameOffset)) {
     return nullptr;
   }
 
   nsRect caretRect;
   nsRect hookRect;
   ComputeCaretRects(frame, frameOffset, &caretRect, &hookRect);
 
   aRect->UnionRect(caretRect, hookRect);
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -2574,18 +2574,18 @@ nsDocumentViewer::FindContainerView()
     LAYOUT_WARNING("Subdocument container has no frame");
     return nullptr;
   }
 
   // subdocFrame might not be a subdocument frame; the frame
   // constructor can treat a <frame> as an inline in some XBL
   // cases. Treat that as display:none, the document is not
   // displayed.
-  if (subdocFrame->GetType() != nsGkAtoms::subDocumentFrame) {
-    NS_WARNING_ASSERTION(!subdocFrame->GetType(),
+  if (!subdocFrame->IsSubDocumentFrame()) {
+    NS_WARNING_ASSERTION(subdocFrame->Type() == FrameType::None,
                          "Subdocument container has non-subdocument frame");
     return nullptr;
   }
 
   NS_ASSERTION(subdocFrame->GetView(), "Subdoc frames must have views");
   return static_cast<nsSubDocumentFrame*>(subdocFrame)->EnsureInnerView();
 }
 
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -174,30 +174,29 @@ nsFrameManager::GetPlaceholderFrameFor(c
 
   return nullptr;
 }
 
 void
 nsFrameManager::RegisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame)
 {
   MOZ_ASSERT(aPlaceholderFrame, "null param unexpected");
-  MOZ_ASSERT(nsGkAtoms::placeholderFrame == aPlaceholderFrame->GetType(),
-             "unexpected frame type");
+  MOZ_ASSERT(aPlaceholderFrame->IsPlaceholderFrame(), "unexpected frame type");
   auto entry = static_cast<PlaceholderMapEntry*>
     (mPlaceholderMap.Add(aPlaceholderFrame->GetOutOfFlowFrame()));
   MOZ_ASSERT(!entry->placeholderFrame,
              "Registering a placeholder for a frame that already has a placeholder!");
   entry->placeholderFrame = aPlaceholderFrame;
 }
 
 void
 nsFrameManager::UnregisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame)
 {
   NS_PRECONDITION(aPlaceholderFrame, "null param unexpected");
-  NS_PRECONDITION(nsGkAtoms::placeholderFrame == aPlaceholderFrame->GetType(),
+  NS_PRECONDITION(aPlaceholderFrame->IsPlaceholderFrame(),
                   "unexpected frame type");
 
   mPlaceholderMap.Remove(aPlaceholderFrame->GetOutOfFlowFrame());
 }
 
 void
 nsFrameManager::ClearPlaceholderFrameMap()
 {
@@ -509,17 +508,17 @@ nsFrameManager::RemoveFrame(ChildListID 
   // reasonably likely to happen when removing a last child in a way
   // that doesn't change the size of the parent.)
   // This has to sure to invalidate the entire overflow rect; this
   // is important in the presence of absolute positioning
   aOldFrame->InvalidateFrameForRemoval();
 
   NS_ASSERTION(!aOldFrame->GetPrevContinuation() ||
                // exception for nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames
-               aOldFrame->GetType() == nsGkAtoms::textFrame,
+               aOldFrame->IsTextFrame(),
                "Must remove first continuation.");
   NS_ASSERTION(!(aOldFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW &&
                  GetPlaceholderFrameFor(aOldFrame)),
                "Must call RemoveFrame on placeholder for out-of-flows.");
   nsContainerFrame* parentFrame = aOldFrame->GetParent();
   if (parentFrame->IsAbsoluteContainer() &&
       aListID == parentFrame->GetAbsoluteListID()) {
     parentFrame->GetAbsoluteContainingBlock()->
--- a/layout/base/nsFrameTraversal.cpp
+++ b/layout/base/nsFrameTraversal.cpp
@@ -197,17 +197,17 @@ nsFrameIterator::nsFrameIterator(nsPresC
   mFollowOOFs(aFollowOOFs),
   mSkipPopupChecks(aSkipPopupChecks),
   mType(aType),
   mStart(aStart),
   mCurrent(aStart),
   mLast(aStart),
   mOffEdge(0)
 {
-  MOZ_ASSERT(!aFollowOOFs || aStart->GetType() != nsGkAtoms::placeholderFrame,
+  MOZ_ASSERT(!aFollowOOFs || !aStart->IsPlaceholderFrame(),
              "Caller should have resolved placeholder frame");
 }
 
 
 
 nsIFrame*
 nsFrameIterator::CurrentItem()
 {
@@ -229,37 +229,35 @@ void
 nsFrameIterator::First()
 {
   mCurrent = mStart;
 }
 
 static bool
 IsRootFrame(nsIFrame* aFrame)
 {
-  nsIAtom* atom = aFrame->GetType();
-  return (atom == nsGkAtoms::canvasFrame) ||
-         (atom == nsGkAtoms::rootFrame);
+  return aFrame->IsCanvasFrame() || aFrame->IsRootFrame();
 }
 
 void
 nsFrameIterator::Last()
 {
   nsIFrame* result;
   nsIFrame* parent = getCurrent();
   // If the current frame is a popup, don't move farther up the tree.
   // Otherwise, get the nearest root frame or popup.
-  if (mSkipPopupChecks || parent->GetType() != nsGkAtoms::menuPopupFrame) {
+  if (mSkipPopupChecks || !parent->IsMenuPopupFrame()) {
     while (!IsRootFrame(parent) && (result = GetParentFrameNotPopup(parent)))
       parent = result;
   }
 
   while ((result = GetLastChild(parent))) {
     parent = result;
   }
-  
+
   setCurrent(parent);
   if (!parent)
     setOffEdge(1);
 }
 
 void
 nsFrameIterator::Next()
 {
@@ -293,17 +291,17 @@ nsFrameIterator::Next()
           }
           result = parent;
         }
         break;
       }
       else {
         result = GetParentFrameNotPopup(parent);
         if (!result || IsRootFrame(result) ||
-            (mLockScroll && result->GetType() == nsGkAtoms::scrollFrame)) {
+            (mLockScroll && result->IsScrollFrame())) {
           result = nullptr;
           break;
         }
         if (mType == ePostOrder)
           break;
         parent = result;
       }
     }
@@ -348,17 +346,17 @@ nsFrameIterator::Prev()
             parent = result;
           }
           result = parent;
         }
         break;
       } else {
         result = GetParentFrameNotPopup(parent);
         if (!result || IsRootFrame(result) ||
-            (mLockScroll && result->GetType() == nsGkAtoms::scrollFrame)) {
+            (mLockScroll && result->IsScrollFrame())) {
           result = nullptr;
           break;
         }
         if (mType == ePreOrder)
           break;
         parent = result;
       }
     }
@@ -395,32 +393,32 @@ nsFrameIterator::GetParentFrameNotPopup(
     
   return nullptr;
 }
 
 nsIFrame*
 nsFrameIterator::GetFirstChild(nsIFrame* aFrame)
 {
   nsIFrame* result = GetFirstChildInner(aFrame);
-  if (mLockScroll && result && result->GetType() == nsGkAtoms::scrollFrame)
+  if (mLockScroll && result && result->IsScrollFrame())
     return nullptr;
   if (result && mFollowOOFs) {
     result = nsPlaceholderFrame::GetRealFrameFor(result);
     
     if (IsPopupFrame(result))
       result = GetNextSibling(result);
   }
   return result;
 }
 
 nsIFrame*
 nsFrameIterator::GetLastChild(nsIFrame* aFrame)
 {
   nsIFrame* result = GetLastChildInner(aFrame);
-  if (mLockScroll && result && result->GetType() == nsGkAtoms::scrollFrame)
+  if (mLockScroll && result && result->IsScrollFrame())
     return nullptr;
   if (result && mFollowOOFs) {
     result = nsPlaceholderFrame::GetRealFrameFor(result);
     
     if (IsPopupFrame(result))
       result = GetPrevSibling(result);
   }
   return result;
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1516,47 +1516,46 @@ nsLayoutUtils::GetChildListNameFor(nsIFr
       } else {
         id = nsIFrame::kAbsoluteList;
       }
 #ifdef MOZ_XUL
     } else if (StyleDisplay::MozPopup == disp->mDisplay) {
       // Out-of-flows that are DISPLAY_POPUP must be kids of the root popup set
 #ifdef DEBUG
       nsIFrame* parent = aChildFrame->GetParent();
-      NS_ASSERTION(parent && parent->GetType() == nsGkAtoms::popupSetFrame,
-                   "Unexpected parent");
+      NS_ASSERTION(parent && parent->IsPopupSetFrame(), "Unexpected parent");
 #endif // DEBUG
 
       id = nsIFrame::kPopupList;
 #endif // MOZ_XUL
     } else {
       NS_ASSERTION(aChildFrame->IsFloating(), "not a floated frame");
       id = nsIFrame::kFloatList;
     }
 
   } else {
-    nsIAtom* childType = aChildFrame->GetType();
-    if (nsGkAtoms::menuPopupFrame == childType) {
+    FrameType childType = aChildFrame->Type();
+    if (FrameType::MenuPopup == childType) {
       nsIFrame* parent = aChildFrame->GetParent();
       MOZ_ASSERT(parent, "nsMenuPopupFrame can't be the root frame");
       if (parent) {
-        if (parent->GetType() == nsGkAtoms::popupSetFrame) {
+        if (parent->IsPopupSetFrame()) {
           id = nsIFrame::kPopupList;
         } else {
           nsIFrame* firstPopup = parent->GetChildList(nsIFrame::kPopupList).FirstChild();
           MOZ_ASSERT(!firstPopup || !firstPopup->GetNextSibling(),
                      "We assume popupList only has one child, but it has more.");
           id = firstPopup == aChildFrame
                  ? nsIFrame::kPopupList
                  : nsIFrame::kPrincipalList;
         }
       } else {
         id = nsIFrame::kPrincipalList;
       }
-    } else if (nsGkAtoms::tableColGroupFrame == childType) {
+    } else if (FrameType::TableColGroup == childType) {
       id = nsIFrame::kColGroupList;
     } else if (aChildFrame->IsTableCaption()) {
       id = nsIFrame::kCaptionList;
     } else {
       id = nsIFrame::kPrincipalList;
     }
   }
 
@@ -1618,35 +1617,41 @@ nsLayoutUtils::GetAfterFrame(const nsICo
 {
   Element* pseudo = GetAfterPseudo(aContent);
   return pseudo ? pseudo->GetPrimaryFrame() : nullptr;
 }
 
 // static
 nsIFrame*
 nsLayoutUtils::GetClosestFrameOfType(nsIFrame* aFrame,
-                                     nsIAtom* aFrameType,
+                                     FrameType aFrameType,
                                      nsIFrame* aStopAt)
 {
   for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
-    if (frame->GetType() == aFrameType) {
+    if (frame->Type() == aFrameType) {
       return frame;
     }
     if (frame == aStopAt) {
       break;
     }
   }
   return nullptr;
 }
 
+/* static */ nsIFrame*
+nsLayoutUtils::GetPageFrame(nsIFrame* aFrame)
+{
+  return GetClosestFrameOfType(aFrame, FrameType::Page);
+}
+
 // static
 nsIFrame*
 nsLayoutUtils::GetStyleFrame(nsIFrame* aFrame)
 {
-  if (aFrame->GetType() == nsGkAtoms::tableWrapperFrame) {
+  if (aFrame->IsTableWrapperFrame()) {
     nsIFrame* inner = aFrame->PrincipalChildList().FirstChild();
     // inner may be null, if aFrame is mid-destruction
     return inner;
   }
 
   return aFrame;
 }
 
@@ -1669,18 +1674,17 @@ nsLayoutUtils::GetRealPrimaryFrameFor(co
     return nullptr;
   }
 
   return nsPlaceholderFrame::GetRealFrameFor(frame);
 }
 
 nsIFrame*
 nsLayoutUtils::GetFloatFromPlaceholder(nsIFrame* aFrame) {
-  NS_ASSERTION(nsGkAtoms::placeholderFrame == aFrame->GetType(),
-               "Must have a placeholder here");
+  NS_ASSERTION(aFrame->IsPlaceholderFrame(), "Must have a placeholder here");
   if (aFrame->GetStateBits() & PLACEHOLDER_FOR_FLOAT) {
     nsIFrame *outOfFlowFrame =
       nsPlaceholderFrame::GetRealFrameForPlaceholder(aFrame);
     NS_ASSERTION(outOfFlowFrame->IsFloating(),
                  "How did that happen?");
     return outOfFlowFrame;
   }
 
@@ -2888,17 +2892,17 @@ nsLayoutUtils::ContainsPoint(const nsRec
   rect.Inflate(aInflateSize);
   return rect.Contains(aPoint);
 }
 
 nsRect
 nsLayoutUtils::ClampRectToScrollFrames(nsIFrame* aFrame, const nsRect& aRect)
 {
   nsIFrame* closestScrollFrame =
-    nsLayoutUtils::GetClosestFrameOfType(aFrame, nsGkAtoms::scrollFrame);
+    nsLayoutUtils::GetClosestFrameOfType(aFrame, FrameType::Scroll);
 
   nsRect resultRect = aRect;
 
   while (closestScrollFrame) {
     nsIScrollableFrame* sf = do_QueryFrame(closestScrollFrame);
 
     nsRect scrollPortRect = sf->GetScrollPortRect();
     nsLayoutUtils::TransformRect(closestScrollFrame, aFrame, scrollPortRect);
@@ -2908,17 +2912,17 @@ nsLayoutUtils::ClampRectToScrollFrames(n
     // Check whether aRect is visible in the scroll frame or not.
     if (resultRect.IsEmpty()) {
       break;
     }
 
     // Get next ancestor scroll frame.
     closestScrollFrame =
       nsLayoutUtils::GetClosestFrameOfType(closestScrollFrame->GetParent(),
-                                           nsGkAtoms::scrollFrame);
+                                           FrameType::Scroll);
   }
 
   return resultRect;
 }
 
 bool
 nsLayoutUtils::GetLayerTransformForFrame(nsIFrame* aFrame,
                                          Matrix4x4* aTransform)
@@ -3006,17 +3010,17 @@ static SVGTextFrame*
 GetContainingSVGTextFrame(nsIFrame* aFrame)
 {
   if (!nsSVGUtils::IsInSVGTextSubtree(aFrame)) {
     return nullptr;
   }
 
   return static_cast<SVGTextFrame*>
     (nsLayoutUtils::GetClosestFrameOfType(aFrame->GetParent(),
-                                          nsGkAtoms::svgTextFrame));
+                                          FrameType::SVGText));
 }
 
 nsPoint
 nsLayoutUtils::TransformAncestorPointToFrame(nsIFrame* aFrame,
                                              const nsPoint& aPoint,
                                              nsIFrame* aAncestor)
 {
     SVGTextFrame* text = GetContainingSVGTextFrame(aFrame);
@@ -3587,28 +3591,28 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
         }
       }
 
       nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(&builder, id);
 
       aFrame->BuildDisplayListForStackingContext(&builder, dirtyRect, &list);
     }
 
-    nsIAtom* frameType = aFrame->GetType();
+    FrameType frameType = aFrame->Type();
 
     // For the viewport frame in print preview/page layout we want to paint
     // the grey background behind the page, not the canvas color.
-    if (frameType == nsGkAtoms::viewportFrame &&
+    if (frameType == FrameType::Viewport &&
         nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) {
       nsRect bounds = nsRect(builder.ToReferenceFrame(aFrame),
                              aFrame->GetSize());
       nsDisplayListBuilder::AutoBuildingDisplayList
         buildingDisplayList(&builder, aFrame, bounds, false);
       presShell->AddPrintPreviewBackgroundItem(builder, list, aFrame, bounds);
-    } else if (frameType != nsGkAtoms::pageFrame) {
+    } else if (frameType != FrameType::Page) {
       // For printing, this function is first called on an nsPageFrame, which
       // creates a display list with a PageContent item. The PageContent item's
       // paint function calls this function on the nsPageFrame's child which is
       // an nsPageContentFrame. We only want to add the canvas background color
       // item once, for the nsPageContentFrame.
 
       // Add the canvas background color to the bottom of the list. This
       // happens after we've built the list so that AddCanvasBackgroundColorItem
@@ -4007,17 +4011,17 @@ struct MOZ_RAII BoxToRectAndText : publi
                    Sequence<nsString>* aTextList, uint32_t aFlags)
     : BoxToRect(aRelativeTo, aCallback, aFlags), mTextList(aTextList) {}
 
   static void AccumulateText(nsIFrame* aFrame, nsAString& aResult) {
     MOZ_ASSERT(aFrame);
 
     // Get all the text in aFrame and child frames, while respecting
     // the content offsets in each of the nsTextFrames.
-    if (aFrame->GetType() == nsGkAtoms::textFrame) {
+    if (aFrame->IsTextFrame()) {
       nsTextFrame* textFrame = static_cast<nsTextFrame*>(aFrame);
 
       nsIFrame::RenderedText renderedText = textFrame->GetRenderedText(
         textFrame->GetContentOffset(),
         textFrame->GetContentOffset() + textFrame->GetContentLength(),
         nsIFrame::TextOffsetType::OFFSETS_IN_CONTENT_TEXT,
         nsIFrame::TrailingWhitespace::DONT_TRIM_TRAILING_WHITESPACE);
 
@@ -4374,17 +4378,17 @@ nsLayoutUtils::ComputeObjectDestRect(con
 }
 
 already_AddRefed<nsFontMetrics>
 nsLayoutUtils::GetFontMetricsForFrame(const nsIFrame* aFrame, float aInflation)
 {
   nsStyleContext* styleContext = aFrame->StyleContext();
   uint8_t variantWidth = NS_FONT_VARIANT_WIDTH_NORMAL;
   if (styleContext->IsTextCombined()) {
-    MOZ_ASSERT(aFrame->GetType() == nsGkAtoms::textFrame);
+    MOZ_ASSERT(aFrame->IsTextFrame());
     auto textFrame = static_cast<const nsTextFrame*>(aFrame);
     auto clusters = textFrame->CountGraphemeClusters();
     if (clusters == 2) {
       variantWidth = NS_FONT_VARIANT_WIDTH_HALF;
     } else if (clusters == 3) {
       variantWidth = NS_FONT_VARIANT_WIDTH_THIRD;
     } else if (clusters == 4) {
       variantWidth = NS_FONT_VARIANT_WIDTH_QUARTER;
@@ -4648,19 +4652,19 @@ GetPercentBSize(const nsStyleCoord& aSty
   const nsStylePosition *pos = f->StylePosition();
   const nsStyleCoord& bSizeCoord = pos->BSize(wm);
   nscoord h;
   if (!GetAbsoluteCoord(bSizeCoord, h) &&
       !GetPercentBSize(bSizeCoord, f, aHorizontalAxis, h)) {
     NS_ASSERTION(bSizeCoord.GetUnit() == eStyleUnit_Auto ||
                  bSizeCoord.HasPercent(),
                  "unknown block-size unit");
-    nsIAtom* fType = f->GetType();
-    if (fType != nsGkAtoms::viewportFrame && fType != nsGkAtoms::canvasFrame &&
-        fType != nsGkAtoms::pageContentFrame) {
+    FrameType fType = f->Type();
+    if (fType != FrameType::Viewport && fType != FrameType::Canvas &&
+        fType != FrameType::PageContent) {
       // There's no basis for the percentage height, so it acts like auto.
       // Should we consider a max-height < min-height pair a basis for
       // percentage heights?  The spec is somewhat unclear, and not doing
       // so is simpler and avoids troubling discontinuities in behavior,
       // so I'll choose not to. -LDB
       return false;
     }
 
@@ -4826,31 +4830,31 @@ static int32_t gNoiseIndent = 0;
 inline static bool
 FormControlShrinksForPercentISize(nsIFrame* aFrame)
 {
   if (!aFrame->IsFrameOfType(nsIFrame::eReplaced)) {
     // Quick test to reject most frames.
     return false;
   }
 
-  nsIAtom* fType = aFrame->GetType();
-  if (fType == nsGkAtoms::meterFrame || fType == nsGkAtoms::progressFrame) {
+  FrameType fType = aFrame->Type();
+  if (fType == FrameType::Meter || fType == FrameType::Progress) {
     // progress and meter do have this shrinking behavior
     // FIXME: Maybe these should be nsIFormControlFrame?
     return true;
   }
 
   if (!static_cast<nsIFormControlFrame*>(do_QueryFrame(aFrame))) {
     // Not a form control.  This includes fieldsets, which do not
     // shrink.
     return false;
   }
 
-  if (fType == nsGkAtoms::gfxButtonControlFrame ||
-      fType == nsGkAtoms::HTMLButtonControlFrame) {
+  if (fType == FrameType::GfxButtonControl ||
+      fType == FrameType::HTMLButtonControl) {
     // Buttons don't have this shrinking behavior.  (Note that color
     // inputs do, even though they inherit from button, so we can't use
     // do_QueryFrame here.)
     return false;
   }
 
   return true;
 }
@@ -5227,17 +5231,17 @@ nsLayoutUtils::IntrinsicForAxis(Physical
           // https://www.w3.org/TR/css-flexbox-1/#min-width-automatic-minimum-size
           // https://drafts.csswg.org/css-grid/#min-size-auto
           result = std::min(result, minContentSize);
         }
       }
     }
   }
 
-  if (aFrame->GetType() == nsGkAtoms::tableFrame) {
+  if (aFrame->IsTableFrame()) {
     // Tables can't shrink smaller than their intrinsic minimum width,
     // no matter what.
     min = aFrame->GetMinISize(aRenderingContext);
   }
 
   nsIFrame::IntrinsicISizeOffsetData offsets =
     MOZ_LIKELY(aAxis == ourInlineAxis) ? aFrame->IntrinsicISizeOffsets()
                                        : aFrame->IntrinsicBSizeOffsets();
@@ -5435,17 +5439,17 @@ nsLayoutUtils::MarkDescendantsDirty(nsIF
     stack.AppendElement(subtreeRoot);
 
     do {
       nsIFrame *f = stack.ElementAt(stack.Length() - 1);
       stack.RemoveElementAt(stack.Length() - 1);
 
       f->MarkIntrinsicISizesDirty();
 
-      if (f->GetType() == nsGkAtoms::placeholderFrame) {
+      if (f->IsPlaceholderFrame()) {
         nsIFrame *oof = nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
         if (!nsLayoutUtils::IsProperAncestorFrame(subtreeRoot, oof)) {
           // We have another distinct subtree we need to mark.
           subtrees.AppendElement(oof);
         }
       }
 
       nsIFrame::ChildListIterator lists(f);
@@ -5958,25 +5962,25 @@ nsLayoutUtils::GetFirstLineBaseline(Writ
 nsLayoutUtils::GetFirstLinePosition(WritingMode aWM,
                                     const nsIFrame* aFrame,
                                     LinePosition* aResult)
 {
   const nsBlockFrame* block = nsLayoutUtils::GetAsBlock(const_cast<nsIFrame*>(aFrame));
   if (!block) {
     // For the first-line baseline we also have to check for a table, and if
     // so, use the baseline of its first row.
-    nsIAtom* fType = aFrame->GetType();
-    if (fType == nsGkAtoms::tableWrapperFrame  ||
-        fType == nsGkAtoms::flexContainerFrame ||
-        fType == nsGkAtoms::gridContainerFrame) {
-      if ((fType == nsGkAtoms::gridContainerFrame &&
+    FrameType fType = aFrame->Type();
+    if (fType == FrameType::TableWrapper  ||
+        fType == FrameType::FlexContainer ||
+        fType == FrameType::GridContainer) {
+      if ((fType == FrameType::GridContainer &&
            aFrame->HasAnyStateBits(NS_STATE_GRID_SYNTHESIZE_BASELINE)) ||
-          (fType == nsGkAtoms::flexContainerFrame &&
+          (fType == FrameType::FlexContainer &&
            aFrame->HasAnyStateBits(NS_STATE_FLEX_SYNTHESIZE_BASELINE)) ||
-          (fType == nsGkAtoms::tableWrapperFrame &&
+          (fType == FrameType::TableWrapper &&
            static_cast<const nsTableWrapperFrame*>(aFrame)->GetRowCount() == 0)) {
         // empty grid/flex/table container
         aResult->mBStart = 0;
         aResult->mBaseline = aFrame->SynthesizeBaselineBOffsetFromBorderBox(aWM,
                                        BaselineSharingGroup::eFirst);
         aResult->mBEnd = aFrame->BSize(aWM);
         return true;
       }
@@ -5984,17 +5988,17 @@ nsLayoutUtils::GetFirstLinePosition(Writ
       aResult->mBaseline = aFrame->GetLogicalBaseline(aWM);
       // This is what we want for the list bullet caller; not sure if
       // other future callers will want the same.
       aResult->mBEnd = aFrame->BSize(aWM);
       return true;
     }
 
     // For first-line baselines, we have to consider scroll frames.
-    if (fType == nsGkAtoms::scrollFrame) {
+    if (fType == FrameType::Scroll) {
       nsIScrollableFrame *sFrame = do_QueryFrame(const_cast<nsIFrame*>(aFrame));
       if (!sFrame) {
         NS_NOTREACHED("not scroll frame");
       }
       LinePosition kidPosition;
       if (GetFirstLinePosition(aWM,
                                sFrame->GetScrolledFrame(), &kidPosition)) {
         // Consider only the border and padding that contributes to the
@@ -6002,17 +6006,17 @@ nsLayoutUtils::GetFirstLinePosition(Writ
         // position.
         *aResult = kidPosition +
           aFrame->GetLogicalUsedBorderAndPadding(aWM).BStart(aWM);
         return true;
       }
       return false;
     }
 
-    if (fType == nsGkAtoms::fieldSetFrame) {
+    if (fType == FrameType::FieldSet) {
       LinePosition kidPosition;
       nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
       // kid might be a legend frame here, but that's ok.
       if (GetFirstLinePosition(aWM, kid, &kidPosition)) {
         *aResult = kidPosition +
           kid->GetLogicalNormalPosition(aWM, aFrame->GetSize()).B(aWM);
         return true;
       }
@@ -6069,17 +6073,17 @@ nsLayoutUtils::GetLastLineBaseline(Writi
       nsIFrame *kid = line->mFirstChild;
       nscoord kidBaseline;
       const nsSize& containerSize = line->mContainerSize;
       if (GetLastLineBaseline(aWM, kid, &kidBaseline)) {
         // Ignore relative positioning for baseline calculations
         *aResult = kidBaseline +
           kid->GetLogicalNormalPosition(aWM, containerSize).B(aWM);
         return true;
-      } else if (kid->GetType() == nsGkAtoms::scrollFrame) {
+      } else if (kid->IsScrollFrame()) {
         // Defer to nsFrame::GetLogicalBaseline (which synthesizes a baseline
         // from the margin-box).
         kidBaseline = kid->GetLogicalBaseline(aWM);
         *aResult = kidBaseline +
           kid->GetLogicalNormalPosition(aWM, containerSize).B(aWM);
         return true;
       }
     } else {
@@ -6159,18 +6163,17 @@ nsLayoutUtils::CalculateContentBEnd(Writ
 }
 
 /* static */ nsIFrame*
 nsLayoutUtils::GetClosestLayer(nsIFrame* aFrame)
 {
   nsIFrame* layer;
   for (layer = aFrame; layer; layer = layer->GetParent()) {
     if (layer->IsAbsPosContainingBlock() ||
-        (layer->GetParent() &&
-          layer->GetParent()->GetType() == nsGkAtoms::scrollFrame))
+        (layer->GetParent() && layer->GetParent()->IsScrollFrame()))
       break;
   }
   if (layer)
     return layer;
   return aFrame->PresContext()->PresShell()->FrameManager()->GetRootFrame();
 }
 
 SamplingFilter
@@ -6914,17 +6917,17 @@ nsLayoutUtils::GetFrameTransparency(nsIF
   if (aCSSRootFrame->IsThemed(&transparency))
     return transparency == nsITheme::eTransparent
          ? eTransparencyTransparent
          : eTransparencyOpaque;
 
   // We need an uninitialized window to be treated as opaque because
   // doing otherwise breaks window display effects on some platforms,
   // specifically Vista. (bug 450322)
-  if (aBackgroundFrame->GetType() == nsGkAtoms::viewportFrame &&
+  if (aBackgroundFrame->IsViewportFrame() &&
       !aBackgroundFrame->PrincipalChildList().FirstChild()) {
     return eTransparencyOpaque;
   }
 
   nsStyleContext* bgSC;
   if (!nsCSSRendering::FindBackground(aBackgroundFrame, &bgSC)) {
     return eTransparencyTransparent;
   }
@@ -6934,24 +6937,24 @@ nsLayoutUtils::GetFrameTransparency(nsIF
       bg->BottomLayer().mClip != StyleGeometryBox::BorderBox)
     return eTransparencyTransparent;
   return eTransparencyOpaque;
 }
 
 static bool IsPopupFrame(nsIFrame* aFrame)
 {
   // aFrame is a popup it's the list control frame dropdown for a combobox.
-  nsIAtom* frameType = aFrame->GetType();
-  if (frameType == nsGkAtoms::listControlFrame) {
+  FrameType frameType = aFrame->Type();
+  if (frameType == FrameType::ListControl) {
     nsListControlFrame* lcf = static_cast<nsListControlFrame*>(aFrame);
     return lcf->IsInDropDownMode();
   }
 
   // ... or if it's a XUL menupopup frame.
-  return frameType == nsGkAtoms::menuPopupFrame;
+  return frameType == FrameType::MenuPopup;
 }
 
 /* static */ bool
 nsLayoutUtils::IsPopup(nsIFrame* aFrame)
 {
   // Optimization: the frame can't possibly be a popup if it has no view.
   if (!aFrame->HasView()) {
     NS_ASSERTION(!IsPopupFrame(aFrame), "popup frame must have a view");
@@ -7118,19 +7121,19 @@ nsLayoutUtils::GetDeviceContextForScreen
 nsLayoutUtils::IsReallyFixedPos(nsIFrame* aFrame)
 {
   NS_PRECONDITION(aFrame->GetParent(),
                   "IsReallyFixedPos called on frame not in tree");
   NS_PRECONDITION(aFrame->StyleDisplay()->mPosition ==
                     NS_STYLE_POSITION_FIXED,
                   "IsReallyFixedPos called on non-'position:fixed' frame");
 
-  nsIAtom *parentType = aFrame->GetParent()->GetType();
-  return parentType == nsGkAtoms::viewportFrame ||
-         parentType == nsGkAtoms::pageContentFrame;
+  FrameType parentType = aFrame->GetParent()->Type();
+  return parentType == FrameType::Viewport ||
+         parentType == FrameType::PageContent;
 }
 
 nsLayoutUtils::SurfaceFromElementResult
 nsLayoutUtils::SurfaceFromOffscreenCanvas(OffscreenCanvas* aOffscreenCanvas,
                                           uint32_t aSurfaceFlags,
                                           RefPtr<DrawTarget>& aTarget)
 {
   SurfaceFromElementResult result;
@@ -7465,17 +7468,17 @@ nsLayoutUtils::AssertNoDuplicateContinua
   }
 }
 
 // Is one of aFrame's ancestors a letter frame?
 static bool
 IsInLetterFrame(nsIFrame *aFrame)
 {
   for (nsIFrame *f = aFrame->GetParent(); f; f = f->GetParent()) {
-    if (f->GetType() == nsGkAtoms::letterFrame) {
+    if (f->IsLetterFrame()) {
       return true;
     }
   }
   return false;
 }
 
 /* static */ void
 nsLayoutUtils::AssertTreeOnlyEmptyNextInFlows(nsIFrame *aSubtreeRoot)
@@ -7507,17 +7510,17 @@ nsLayoutUtils::AssertTreeOnlyEmptyNextIn
 }
 #endif
 
 static void
 GetFontFacesForFramesInner(nsIFrame* aFrame, nsFontFaceList* aFontFaceList)
 {
   NS_PRECONDITION(aFrame, "NULL frame pointer");
 
-  if (aFrame->GetType() == nsGkAtoms::textFrame) {
+  if (aFrame->IsTextFrame()) {
     if (!aFrame->GetPrevContinuation()) {
       nsLayoutUtils::GetFontFacesForText(aFrame, 0, INT32_MAX, true,
                                          aFontFaceList);
     }
     return;
   }
 
   nsIFrame::ChildListID childLists[] = { nsIFrame::kPrincipalList,
@@ -7551,17 +7554,17 @@ nsLayoutUtils::GetFontFacesForFrames(nsI
 nsresult
 nsLayoutUtils::GetFontFacesForText(nsIFrame* aFrame,
                                    int32_t aStartOffset, int32_t aEndOffset,
                                    bool aFollowContinuations,
                                    nsFontFaceList* aFontFaceList)
 {
   NS_PRECONDITION(aFrame, "NULL frame pointer");
 
-  if (aFrame->GetType() != nsGkAtoms::textFrame) {
+  if (!aFrame->IsTextFrame()) {
     return NS_OK;
   }
 
   nsTextFrame* curr = static_cast<nsTextFrame*>(aFrame);
   do {
     int32_t fstart = std::max(curr->GetContentOffset(), aStartOffset);
     int32_t fend = std::min(curr->GetContentEnd(), aEndOffset);
     if (fstart >= fend) {
@@ -7599,17 +7602,17 @@ size_t
 nsLayoutUtils::SizeOfTextRunsForFrames(nsIFrame* aFrame,
                                        MallocSizeOf aMallocSizeOf,
                                        bool clear)
 {
   NS_PRECONDITION(aFrame, "NULL frame pointer");
 
   size_t total = 0;
 
-  if (aFrame->GetType() == nsGkAtoms::textFrame) {
+  if (aFrame->IsTextFrame()) {
     nsTextFrame* textFrame = static_cast<nsTextFrame*>(aFrame);
     for (uint32_t i = 0; i < 2; ++i) {
       gfxTextRun *run = textFrame->GetTextRun(
         (i != 0) ? nsTextFrame::eInflated : nsTextFrame::eNotInflated);
       if (run) {
         if (clear) {
           run->ResetSizeOfAccountingFlags();
         } else {
@@ -7929,34 +7932,32 @@ nsLayoutUtils::FontSizeInflationInner(co
 
   // If between this current frame and its font inflation container there is a
   // non-inline element with fixed width or height, then we should not inflate
   // fonts for this frame.
   for (const nsIFrame* f = aFrame;
        f && !f->IsContainerForFontSizeInflation();
        f = f->GetParent()) {
     nsIContent* content = f->GetContent();
-    nsIAtom* fType = f->GetType();
+    FrameType fType = f->Type();
     nsIFrame* parent = f->GetParent();
     // Also, if there is more than one frame corresponding to a single
     // content node, we want the outermost one.
     if (!(parent && parent->GetContent() == content) &&
         // ignore width/height on inlines since they don't apply
-        fType != nsGkAtoms::inlineFrame &&
+        fType != FrameType::Inline &&
         // ignore width on radios and checkboxes since we enlarge them and
         // they have width/height in ua.css
-        fType != nsGkAtoms::formControlFrame) {
+        fType != FrameType::FormControl) {
       // ruby annotations should have the same inflation as its
       // grandparent, which is the ruby frame contains the annotation.
-      if (fType == nsGkAtoms::rubyTextFrame) {
-        MOZ_ASSERT(parent &&
-                   parent->GetType() == nsGkAtoms::rubyTextContainerFrame);
+      if (fType == FrameType::RubyText) {
+        MOZ_ASSERT(parent && parent->IsRubyTextContainerFrame());
         nsIFrame* grandparent = parent->GetParent();
-        MOZ_ASSERT(grandparent &&
-                   grandparent->GetType() == nsGkAtoms::rubyFrame);
+        MOZ_ASSERT(grandparent && grandparent->IsRubyFrame());
         return FontSizeInflationFor(grandparent);
       }
       nsStyleCoord stylePosWidth = f->StylePosition()->mWidth;
       nsStyleCoord stylePosHeight = f->StylePosition()->mHeight;
       if (stylePosWidth.GetUnit() != eStyleUnit_Auto ||
           stylePosHeight.GetUnit() != eStyleUnit_Auto) {
 
         return 1.0;
@@ -8061,17 +8062,17 @@ nsLayoutUtils::InflationMinFontSizeFor(c
   return 0;
 }
 
 float
 nsLayoutUtils::FontSizeInflationFor(const nsIFrame *aFrame)
 {
   if (nsSVGUtils::IsInSVGTextSubtree(aFrame)) {
     const nsIFrame* container = aFrame;
-    while (container->GetType() != nsGkAtoms::svgTextFrame) {
+    while (!container->IsSVGTextFrame()) {
       container = container->GetParent();
     }
     NS_ASSERTION(container, "expected to find an ancestor SVGTextFrame");
     return
       static_cast<const SVGTextFrame*>(container)->GetFontSizeScaleFactor();
   }
 
   if (!FontSizeInflationEnabled(aFrame->PresContext())) {
@@ -8980,17 +8981,17 @@ nsLayoutUtils::GetFrameTextContent(nsIFr
 {
   aResult.Truncate();
   AppendFrameTextContent(aFrame, aResult);
 }
 
 /* static */ void
 nsLayoutUtils::AppendFrameTextContent(nsIFrame* aFrame, nsAString& aResult)
 {
-  if (aFrame->GetType() == nsGkAtoms::textFrame) {
+  if (aFrame->IsTextFrame()) {
     auto textFrame = static_cast<nsTextFrame*>(aFrame);
     auto offset = textFrame->GetContentOffset();
     auto length = textFrame->GetContentLength();
     textFrame->GetContent()->
       GetText()->AppendTo(aResult, offset, length);
   } else {
     for (nsIFrame* child : aFrame->PrincipalChildList()) {
       AppendFrameTextContent(child, aResult);
@@ -9199,25 +9200,24 @@ nsLayoutUtils::SupportsServoStyleBackend
 }
 
 static
 bool
 LineHasNonEmptyContentWorker(nsIFrame* aFrame)
 {
   // Look for non-empty frames, but ignore inline and br frames.
   // For inline frames, descend into the children, if any.
-  if (aFrame->GetType() == nsGkAtoms::inlineFrame) {
+  if (aFrame->IsInlineFrame()) {
     for (nsIFrame* child : aFrame->PrincipalChildList()) {
       if (LineHasNonEmptyContentWorker(child)) {
         return true;
       }
     }
   } else {
-    if (aFrame->GetType() != nsGkAtoms::brFrame &&
-        !aFrame->IsEmpty()) {
+    if (!aFrame->IsBrFrame() && !aFrame->IsEmpty()) {
       return true;
     }
   }
   return false;
 }
 
 static
 bool
@@ -9239,17 +9239,17 @@ nsLayoutUtils::IsInvisibleBreak(nsINode*
   if (aNextLineFrame) {
     *aNextLineFrame = nullptr;
   }
 
   if (!aNode->IsElement() || !aNode->IsEditable()) {
     return false;
   }
   nsIFrame* frame = aNode->AsElement()->GetPrimaryFrame();
-  if (!frame || frame->GetType() != nsGkAtoms::brFrame) {
+  if (!frame || !frame->IsBrFrame()) {
     return false;
   }
 
   nsContainerFrame* f = frame->GetParent();
   while (f && f->IsFrameOfType(nsBox::eLineParticipant)) {
     f = f->GetParent();
   }
   nsBlockFrame* blockAncestor = do_QueryFrame(f);
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -61,16 +61,17 @@ class nsIDocument;
 struct gfxPoint;
 struct nsStyleFont;
 struct nsStyleImageOrientation;
 struct nsOverflowAreas;
 
 namespace mozilla {
 enum class CSSPseudoElementType : uint8_t;
 class EventListenerManager;
+enum class FrameType : uint8_t;
 struct IntrinsicSize;
 struct ContainerLayerParameters;
 class WritingMode;
 namespace dom {
 class CanvasRenderingContext2D;
 class DOMRectList;
 class Element;
 class HTMLImageElement;
@@ -313,31 +314,28 @@ public:
    *
    * @param aFrame the frame to start at
    * @param aFrameType the frame type to look for
    * @param aStopAt a frame to stop at after we checked it
    * @return a frame of the given type or nullptr if no
    *         such ancestor exists
    */
   static nsIFrame* GetClosestFrameOfType(nsIFrame* aFrame,
-                                         nsIAtom* aFrameType,
+                                         mozilla::FrameType aFrameType,
                                          nsIFrame* aStopAt = nullptr);
 
   /**
    * Given a frame, search up the frame tree until we find an
    * ancestor that (or the frame itself) is a "Page" frame, if any.
    *
    * @param aFrame the frame to start at
-   * @return a frame of type nsGkAtoms::pageFrame or nullptr if no
+   * @return a frame of type mozilla::FrameType::Page or nullptr if no
    *         such ancestor exists
    */
-  static nsIFrame* GetPageFrame(nsIFrame* aFrame)
-  {
-    return GetClosestFrameOfType(aFrame, nsGkAtoms::pageFrame);
-  }
+  static nsIFrame* GetPageFrame(nsIFrame* aFrame);
 
   /**
    * Given a frame which is the primary frame for an element,
    * return the frame that has the non-pseudoelement style context for
    * the content.
    * This is aPrimaryFrame itself except for tableWrapper frames.
    *
    * Given a non-null input, this will return null if and only if its
--- a/layout/forms/nsColorControlFrame.cpp
+++ b/layout/forms/nsColorControlFrame.cpp
@@ -18,17 +18,17 @@
 #include "mozilla/dom/HTMLInputElement.h"
 #include "nsIDocument.h"
 
 using mozilla::dom::Element;
 using mozilla::dom::HTMLInputElement;
 using mozilla::dom::CallerType;
 
 nsColorControlFrame::nsColorControlFrame(nsStyleContext* aContext)
-  : nsHTMLButtonControlFrame(aContext)
+  : nsHTMLButtonControlFrame(aContext, FrameType::ColorControl)
 {
 }
 
 nsIFrame*
 NS_NewColorControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsColorControlFrame(aContext);
 }
@@ -43,22 +43,16 @@ NS_QUERYFRAME_TAIL_INHERITING(nsHTMLButt
 
 void nsColorControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
   nsContentUtils::DestroyAnonymousContent(&mColorContent);
   nsHTMLButtonControlFrame::DestroyFrom(aDestructRoot);
 }
 
-nsIAtom*
-nsColorControlFrame::GetType() const
-{
-  return nsGkAtoms::colorControlFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsColorControlFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("ColorControl"), aResult);
 }
 #endif
 
--- a/layout/forms/nsColorControlFrame.h
+++ b/layout/forms/nsColorControlFrame.h
@@ -27,18 +27,16 @@ public:
                                            nsStyleContext* aContext);
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
   NS_DECL_QUERYFRAME_TARGET(nsColorControlFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
   virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
                                         uint32_t aFilter) override;
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -218,17 +218,17 @@ static int32_t gReflowInx = -1;
 #define PX(__v) __v
 #endif
 
 //------------------------------------------------------
 //-- Done with macros
 //------------------------------------------------------
 
 nsComboboxControlFrame::nsComboboxControlFrame(nsStyleContext* aContext)
-  : nsBlockFrame(aContext)
+  : nsBlockFrame(aContext, FrameType::ComboboxControl)
   , mDisplayFrame(nullptr)
   , mButtonFrame(nullptr)
   , mDropdownFrame(nullptr)
   , mListControlFrame(nullptr)
   , mDisplayISize(0)
   , mRecentSelectedIndex(NS_SKIP_NOTIFY_INDEX)
   , mDisplayedIndex(-1)
   , mLastDropDownBeforeScreenBCoord(nscoord_MIN)
@@ -903,22 +903,16 @@ nsComboboxControlFrame::Reflow(nsPresCon
     // This frame didn't fit inside a fragmentation container.  Splitting
     // a nsComboboxControlFrame makes no sense, so we override the status here.
     aStatus.Reset();
   }
 }
 
 //--------------------------------------------------------------
 
-nsIAtom*
-nsComboboxControlFrame::GetType() const
-{
-  return nsGkAtoms::comboboxControlFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsComboboxControlFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("ComboboxControl"), aResult);
 }
 #endif
 
@@ -1277,26 +1271,22 @@ nsComboboxControlFrame::AppendAnonymousC
 }
 
 // XXXbz this is a for-now hack.  Now that display:inline-block works,
 // need to revisit this.
 class nsComboboxDisplayFrame : public nsBlockFrame {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
-  nsComboboxDisplayFrame (nsStyleContext* aContext,
-                          nsComboboxControlFrame* aComboBox)
-    : nsBlockFrame(aContext),
-      mComboBox(aComboBox)
+  nsComboboxDisplayFrame(nsStyleContext* aContext,
+                         nsComboboxControlFrame* aComboBox)
+    : nsBlockFrame(aContext, FrameType::ComboboxDisplay)
+    , mComboBox(aComboBox)
   {}
 
-  // Need this so that line layout knows that this block's inline size
-  // depends on the available inline size.
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("ComboboxDisplay"), aResult);
   }
 #endif
 
   virtual bool IsFrameOfType(uint32_t aFlags) const override
@@ -1315,22 +1305,16 @@ public:
                                 const nsDisplayListSet& aLists) override;
 
 protected:
   nsComboboxControlFrame* mComboBox;
 };
 
 NS_IMPL_FRAMEARENA_HELPERS(nsComboboxDisplayFrame)
 
-nsIAtom*
-nsComboboxDisplayFrame::GetType() const
-{
-  return nsGkAtoms::comboboxDisplayFrame;
-}
-
 void
 nsComboboxDisplayFrame::Reflow(nsPresContext*           aPresContext,
                                ReflowOutput&     aDesiredSize,
                                const ReflowInput& aReflowInput,
                                nsReflowStatus&          aStatus)
 {
   ReflowInput state(aReflowInput);
   if (state.ComputedBSize() == NS_INTRINSICSIZE) {
--- a/layout/forms/nsComboboxControlFrame.h
+++ b/layout/forms/nsComboboxControlFrame.h
@@ -92,21 +92,16 @@ public:
                                nsEventStatus* aEventStatus) override;
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
   void PaintFocus(DrawTarget& aDrawTarget, nsPoint aPt);
 
-  // XXXbz this is only needed to prevent the quirk percent height stuff from
-  // leaking out of the combobox.  We may be able to get rid of this as more
-  // things move to IsFrameOfType.
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsBlockFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
   virtual nsIScrollableFrame* GetScrollTargetFrame() override {
     return do_QueryFrame(mDropdownFrame);
--- a/layout/forms/nsDateTimeControlFrame.cpp
+++ b/layout/forms/nsDateTimeControlFrame.cpp
@@ -38,17 +38,17 @@ NS_NewDateTimeControlFrame(nsIPresShell*
 NS_IMPL_FRAMEARENA_HELPERS(nsDateTimeControlFrame)
 
 NS_QUERYFRAME_HEAD(nsDateTimeControlFrame)
   NS_QUERYFRAME_ENTRY(nsDateTimeControlFrame)
   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
 
 nsDateTimeControlFrame::nsDateTimeControlFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::DateTimeControl)
 {
 }
 
 void
 nsDateTimeControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsContentUtils::DestroyAnonymousContent(&mInputAreaContent);
   nsContainerFrame::DestroyFrom(aDestructRoot);
@@ -419,14 +419,8 @@ nsDateTimeControlFrame::AttributeChanged
 
 void
 nsDateTimeControlFrame::ContentStatesChanged(EventStates aStates)
 {
   if (aStates.HasState(NS_EVENT_STATE_DISABLED)) {
     nsContentUtils::AddScriptRunner(new SyncDisabledStateEvent(this));
   }
 }
-
-nsIAtom*
-nsDateTimeControlFrame::GetType() const
-{
-  return nsGkAtoms::dateTimeControlFrame;
-}
--- a/layout/forms/nsDateTimeControlFrame.h
+++ b/layout/forms/nsDateTimeControlFrame.h
@@ -45,18 +45,16 @@ public:
   NS_DECL_FRAMEARENA_HELPERS
 
 #ifdef DEBUG_FRAME_DUMP
   nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("DateTimeControl"), aResult);
   }
 #endif
 
-  nsIAtom* GetType() const override;
-
   bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsContainerFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
   // Reflow
   nscoord GetMinISize(nsRenderingContext* aRenderingContext) override;
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -27,28 +27,22 @@ nsContainerFrame*
 NS_NewFieldSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsFieldSetFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsFieldSetFrame)
 
 nsFieldSetFrame::nsFieldSetFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::FieldSet)
   , mLegendRect(GetWritingMode())
 {
   mLegendSpace  = 0;
 }
 
-nsIAtom*
-nsFieldSetFrame::GetType() const
-{
-  return nsGkAtoms::fieldSetFrame;
-}
-
 nsRect
 nsFieldSetFrame::VisualBorderRectRelativeToSelf() const
 {
   WritingMode wm = GetWritingMode();
   Side legendSide = wm.PhysicalSide(eLogicalSideBStart);
   nscoord legendBorder = StyleBorder()->GetComputedBorderWidth(legendSide);
   LogicalRect r(wm, LogicalPoint(wm, 0, 0), GetLogicalSize(wm));
   nsSize containerSize = r.Size(wm).GetPhysicalSize(wm);
@@ -75,18 +69,17 @@ nsFieldSetFrame::GetInner() const
 nsIFrame*
 nsFieldSetFrame::GetLegend() const
 {
   if (mFrames.FirstChild() == GetInner()) {
     MOZ_ASSERT(mFrames.LastChild() == mFrames.FirstChild());
     return nullptr;
   }
   MOZ_ASSERT(mFrames.FirstChild() &&
-             mFrames.FirstChild()->GetContentInsertionFrame()->GetType() ==
-               nsGkAtoms::legendFrame);
+             mFrames.FirstChild()->GetContentInsertionFrame()->IsLegendFrame());
   return mFrames.FirstChild();
 }
 
 class nsDisplayFieldSetBorder : public nsDisplayItem {
 public:
   nsDisplayFieldSetBorder(nsDisplayListBuilder* aBuilder,
                           nsFieldSetFrame* aFrame)
     : nsDisplayItem(aBuilder, aFrame) {
--- a/layout/forms/nsFieldSetFrame.h
+++ b/layout/forms/nsFieldSetFrame.h
@@ -26,21 +26,21 @@ public:
   virtual nscoord GetPrefISize(nsRenderingContext* aRenderingContext) override;
 
   /**
    * The area to paint box-shadows around.  It's the border rect except
    * when there's a <legend> we offset the y-position to the center of it.
    */
   virtual nsRect VisualBorderRectRelativeToSelf() const override;
 
-  virtual void Reflow(nsPresContext*           aPresContext,
-                      ReflowOutput&     aDesiredSize,
+  virtual void Reflow(nsPresContext* aPresContext,
+                      ReflowOutput& aDesiredSize,
                       const ReflowInput& aReflowInput,
-                      nsReflowStatus&          aStatus) override;
-                               
+                      nsReflowStatus& aStatus) override;
+
   nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const override;
   bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
                                 nscoord* aBaseline) const override;
   bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
                                  BaselineSharingGroup aBaselineGroup,
                                  nscoord* aBaseline) const override;
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
@@ -58,17 +58,16 @@ public:
                             nsFrameList&   aFrameList) override;
   virtual void InsertFrames(ChildListID    aListID,
                             nsIFrame*      aPrevFrame,
                             nsFrameList&   aFrameList) override;
   virtual void RemoveFrame(ChildListID    aListID,
                            nsIFrame*      aOldFrame) override;
 #endif
 
-  virtual nsIAtom* GetType() const override;
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsContainerFrame::IsFrameOfType(aFlags &
              ~nsIFrame::eCanContainOverflowContainers);
   }
   virtual nsIScrollableFrame* GetScrollTargetFrame() override
   {
     return do_QueryFrame(GetInner());
--- a/layout/forms/nsFormControlFrame.cpp
+++ b/layout/forms/nsFormControlFrame.cpp
@@ -13,30 +13,24 @@
 #include "nsDeviceContext.h"
 #include "nsIContent.h"
 
 using namespace mozilla;
 
 //#define FCF_NOISY
 
 nsFormControlFrame::nsFormControlFrame(nsStyleContext* aContext)
-  : nsAtomicContainerFrame(aContext)
+  : nsAtomicContainerFrame(aContext, FrameType::FormControl)
 {
 }
 
 nsFormControlFrame::~nsFormControlFrame()
 {
 }
 
-nsIAtom*
-nsFormControlFrame::GetType() const
-{
-  return nsGkAtoms::formControlFrame;
-}
-
 void
 nsFormControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Unregister the access key registered in reflow
   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
   nsAtomicContainerFrame::DestroyFrom(aDestructRoot);
 }
 
--- a/layout/forms/nsFormControlFrame.h
+++ b/layout/forms/nsFormControlFrame.h
@@ -22,18 +22,16 @@ class nsFormControlFrame : public nsAtom
 public:
   /**
     * Main constructor
     * @param aContent the content representing this frame
     * @param aParentFrame the parent frame
     */
   explicit nsFormControlFrame(nsStyleContext*);
 
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsAtomicContainerFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
   NS_DECL_QUERYFRAME
   NS_DECL_ABSTRACT_FRAME(nsFormControlFrame)
--- a/layout/forms/nsGfxButtonControlFrame.cpp
+++ b/layout/forms/nsGfxButtonControlFrame.cpp
@@ -13,18 +13,18 @@
 // MouseEvent suppression in PP
 #include "nsContentList.h"
 
 #include "nsIDOMHTMLInputElement.h"
 #include "nsTextNode.h"
 
 using namespace mozilla;
 
-nsGfxButtonControlFrame::nsGfxButtonControlFrame(nsStyleContext* aContext):
-  nsHTMLButtonControlFrame(aContext)
+nsGfxButtonControlFrame::nsGfxButtonControlFrame(nsStyleContext* aContext)
+  : nsHTMLButtonControlFrame(aContext, FrameType::GfxButtonControl)
 {
 }
 
 nsContainerFrame*
 NS_NewGfxButtonControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsGfxButtonControlFrame(aContext);
 }
@@ -32,22 +32,16 @@ NS_NewGfxButtonControlFrame(nsIPresShell
 NS_IMPL_FRAMEARENA_HELPERS(nsGfxButtonControlFrame)
 
 void nsGfxButtonControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsContentUtils::DestroyAnonymousContent(&mTextContent);
   nsHTMLButtonControlFrame::DestroyFrom(aDestructRoot);
 }
 
-nsIAtom*
-nsGfxButtonControlFrame::GetType() const
-{
-  return nsGkAtoms::gfxButtonControlFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsGfxButtonControlFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("ButtonControl"), aResult);
 }
 #endif
 
--- a/layout/forms/nsGfxButtonControlFrame.h
+++ b/layout/forms/nsGfxButtonControlFrame.h
@@ -11,32 +11,31 @@
 #include "nsCOMPtr.h"
 #include "nsIAnonymousContentCreator.h"
 
 // Class which implements the input[type=button, reset, submit] and
 // browse button for input[type=file].
 // The label for button is specified through generated content
 // in the ua.css file.
 
-class nsGfxButtonControlFrame : public nsHTMLButtonControlFrame,
-                                public nsIAnonymousContentCreator
+class nsGfxButtonControlFrame final
+  : public nsHTMLButtonControlFrame
+  , public nsIAnonymousContentCreator
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   explicit nsGfxButtonControlFrame(nsStyleContext* aContext);
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
-  virtual nsresult HandleEvent(nsPresContext* aPresContext, 
+  virtual nsresult HandleEvent(nsPresContext* aPresContext,
                                mozilla::WidgetGUIEvent* aEvent,
                                nsEventStatus* aEventStatus) override;
 
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   NS_DECL_QUERYFRAME
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -21,18 +21,19 @@ using namespace mozilla;
 nsContainerFrame*
 NS_NewHTMLButtonControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsHTMLButtonControlFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsHTMLButtonControlFrame)
 
-nsHTMLButtonControlFrame::nsHTMLButtonControlFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+nsHTMLButtonControlFrame::nsHTMLButtonControlFrame(nsStyleContext* aContext,
+                                                   FrameType aType)
+  : nsContainerFrame(aContext, aType)
 {
 }
 
 nsHTMLButtonControlFrame::~nsHTMLButtonControlFrame()
 {
 }
 
 void
@@ -58,22 +59,16 @@ NS_QUERYFRAME_TAIL_INHERITING(nsContaine
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsHTMLButtonControlFrame::AccessibleType()
 {
   return a11y::eHTMLButtonType;
 }
 #endif
 
-nsIAtom*
-nsHTMLButtonControlFrame::GetType() const
-{
-  return nsGkAtoms::HTMLButtonControlFrame;
-}
-
 void 
 nsHTMLButtonControlFrame::SetFocus(bool aOn, bool aRepaint)
 {
 }
 
 nsresult
 nsHTMLButtonControlFrame::HandleEvent(nsPresContext* aPresContext, 
                                       WidgetGUIEvent* aEvent,
--- a/layout/forms/nsHTMLButtonControlFrame.h
+++ b/layout/forms/nsHTMLButtonControlFrame.h
@@ -10,20 +10,23 @@
 #include "nsContainerFrame.h"
 #include "nsIFormControlFrame.h"
 #include "nsButtonFrameRenderer.h"
 
 class nsRenderingContext;
 class nsPresContext;
 
 class nsHTMLButtonControlFrame : public nsContainerFrame,
-                                 public nsIFormControlFrame 
+                                 public nsIFormControlFrame
 {
 public:
-  explicit nsHTMLButtonControlFrame(nsStyleContext* aContext);
+  explicit nsHTMLButtonControlFrame(nsStyleContext* aContext)
+    : nsHTMLButtonControlFrame(aContext, mozilla::FrameType::HTMLButtonControl)
+  {}
+
   ~nsHTMLButtonControlFrame();
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
@@ -67,18 +70,16 @@ public:
   virtual void RemoveFrame(ChildListID     aListID,
                            nsIFrame*       aOldFrame) override;
 #endif
 
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() override;
 #endif
 
-  virtual nsIAtom* GetType() const override;
-  
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("HTMLButtonControl"), aResult);
   }
 #endif
 
   virtual bool HonorPrintBackgroundSettings() override { return false; }
 
@@ -99,16 +100,18 @@ public:
 
   /**
    * Update the style of our ::-moz-button-content anonymous box.
    */
   void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
                                      nsStyleChangeList& aChangeList,
                                      nsChangeHint aHintForThisFrame) override;
 protected:
+  nsHTMLButtonControlFrame(nsStyleContext* aContext, mozilla::FrameType aType);
+
   virtual bool IsInput() { return false; }
 
   // Indicates whether we should clip our children's painting to our
   // border-box (either because of "overflow" or because of legacy reasons
   // about how <input>-flavored buttons work).
   bool ShouldClipPaintingToBorderBox();
 
   // Reflows the button's sole child frame, and computes the desired size
--- a/layout/forms/nsImageControlFrame.cpp
+++ b/layout/forms/nsImageControlFrame.cpp
@@ -25,27 +25,25 @@ public:
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
-  virtual void Reflow(nsPresContext*           aPresContext,
-                          ReflowOutput&     aDesiredSize,
-                          const ReflowInput& aReflowInput,
-                          nsReflowStatus&          aStatus) override;
+  virtual void Reflow(nsPresContext* aPresContext,
+                      ReflowOutput& aDesiredSize,
+                      const ReflowInput& aReflowInput,
+                      nsReflowStatus& aStatus) override;
 
   virtual nsresult HandleEvent(nsPresContext* aPresContext,
                                WidgetGUIEvent* aEvent,
                                nsEventStatus* aEventStatus) override;
 
-  virtual nsIAtom* GetType() const override;
-
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() override;
 #endif
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("ImageControl"), aResult);
   }
@@ -54,19 +52,18 @@ public:
   virtual nsresult GetCursor(const nsPoint&    aPoint,
                              nsIFrame::Cursor& aCursor) override;
   // nsIFormContromFrame
   virtual void SetFocus(bool aOn, bool aRepaint) override;
   virtual nsresult SetFormProperty(nsIAtom* aName,
                                    const nsAString& aValue) override;
 };
 
-
 nsImageControlFrame::nsImageControlFrame(nsStyleContext* aContext)
-  : nsImageFrame(aContext)
+  : nsImageFrame(aContext, FrameType::ImageControl)
 {
 }
 
 nsImageControlFrame::~nsImageControlFrame()
 {
 }
 
 void
@@ -113,22 +110,16 @@ nsImageControlFrame::AccessibleType()
   if (mContent->IsAnyOfHTMLElements(nsGkAtoms::button, nsGkAtoms::input)) {
     return a11y::eHTMLButtonType;
   }
 
   return a11y::eNoType;
 }
 #endif
 
-nsIAtom*
-nsImageControlFrame::GetType() const
-{
-  return nsGkAtoms::imageControlFrame;
-}
-
 void
 nsImageControlFrame::Reflow(nsPresContext*           aPresContext,
                             ReflowOutput&     aDesiredSize,
                             const ReflowInput& aReflowInput,
                             nsReflowStatus&          aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("nsImageControlFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
--- a/layout/forms/nsLegendFrame.cpp
+++ b/layout/forms/nsLegendFrame.cpp
@@ -23,22 +23,16 @@ NS_NewLegendFrame(nsIPresShell* aPresShe
 
   nsIFrame* f = new (aPresShell) nsLegendFrame(aContext);
   f->AddStateBits(NS_BLOCK_FORMATTING_CONTEXT_STATE_BITS);
   return f;
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsLegendFrame)
 
-nsIAtom*
-nsLegendFrame::GetType() const
-{
-  return nsGkAtoms::legendFrame; 
-}
-
 void
 nsLegendFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
   nsBlockFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_QUERYFRAME_HEAD(nsLegendFrame)
--- a/layout/forms/nsLegendFrame.h
+++ b/layout/forms/nsLegendFrame.h
@@ -11,27 +11,27 @@
 
 class nsLegendFrame final : public nsBlockFrame
 {
 public:
   NS_DECL_QUERYFRAME_TARGET(nsLegendFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
-  explicit nsLegendFrame(nsStyleContext* aContext) : nsBlockFrame(aContext) {}
+  explicit nsLegendFrame(nsStyleContext* aContext)
+    : nsBlockFrame(aContext, mozilla::FrameType::Legend)
+  {}
 
-  virtual void Reflow(nsPresContext*           aPresContext,
-                      ReflowOutput&     aDesiredSize,
+  virtual void Reflow(nsPresContext* aPresContext,
+                      ReflowOutput& aDesiredSize,
                       const ReflowInput& aReflowInput,
-                      nsReflowStatus&          aStatus) override;
+                      nsReflowStatus& aStatus) override;
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   int32_t GetLogicalAlign(mozilla::WritingMode aCBWM);
 };
 
 
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -87,23 +87,23 @@ NS_NewListControlFrame(nsIPresShell* aPr
 
   return it;
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsListControlFrame)
 
 //---------------------------------------------------------
 nsListControlFrame::nsListControlFrame(nsStyleContext* aContext)
-  : nsHTMLScrollFrame(aContext, false),
-    mView(nullptr),
-    mMightNeedSecondPass(false),
-    mHasPendingInterruptAtStartOfReflow(false),
-    mDropdownCanGrow(false),
-    mForceSelection(false),
-    mLastDropdownComputedBSize(NS_UNCONSTRAINEDSIZE)
+  : nsHTMLScrollFrame(aContext, FrameType::ListControl, false)
+  , mView(nullptr)
+  , mMightNeedSecondPass(false)
+  , mHasPendingInterruptAtStartOfReflow(false)
+  , mDropdownCanGrow(false)
+  , mForceSelection(false)
+  , mLastDropdownComputedBSize(NS_UNCONSTRAINEDSIZE)
 {
   mComboboxFrame      = nullptr;
   mChangesSinceDragStart = false;
   mButtonDown         = false;
 
   mIsAllContentHere   = false;
   mIsAllFramesHere    = false;
   mHasBeenInitialized = false;
@@ -1531,22 +1531,16 @@ nsListControlFrame::DidReflow(nsPresCont
     // scrolling to the selected element, when the ResetList was probably only
     // caused by content loading normally.
     ResetList(!DidHistoryRestore() || mPostChildrenLoadedReset);
   }
 
   mHasPendingInterruptAtStartOfReflow = false;
 }
 
-nsIAtom*
-nsListControlFrame::GetType() const
-{
-  return nsGkAtoms::listControlFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsListControlFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("ListControl"), aResult);
 }
 #endif
 
--- a/layout/forms/nsListControlFrame.h
+++ b/layout/forms/nsListControlFrame.h
@@ -83,23 +83,16 @@ public:
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
   virtual nsContainerFrame* GetContentInsertionFrame() override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::scrollFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsHTMLScrollFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
--- a/layout/forms/nsMeterFrame.cpp
+++ b/layout/forms/nsMeterFrame.cpp
@@ -34,17 +34,17 @@ nsIFrame*
 NS_NewMeterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsMeterFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsMeterFrame)
 
 nsMeterFrame::nsMeterFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::Meter)
   , mBarDiv(nullptr)
 {
 }
 
 nsMeterFrame::~nsMeterFrame()
 {
 }
 
@@ -54,22 +54,16 @@ nsMeterFrame::DestroyFrom(nsIFrame* aDes
   NS_ASSERTION(!GetPrevContinuation(),
                "nsMeterFrame should not have continuations; if it does we "
                "need to call RegUnregAccessKey only for the first.");
   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
   nsContentUtils::DestroyAnonymousContent(&mBarDiv);
   nsContainerFrame::DestroyFrom(aDestructRoot);
 }
 
-nsIAtom*
-nsMeterFrame::GetType() const
-{
-  return nsGkAtoms::meterFrame;
-}
-
 nsresult
 nsMeterFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
 {
   // Get the NodeInfoManager and tag necessary to create the meter bar div.
   nsCOMPtr<nsIDocument> doc = mContent->GetComposedDoc();
 
   // Create the div.
   mBarDiv = doc->CreateHTMLElement(nsGkAtoms::div);
--- a/layout/forms/nsMeterFrame.h
+++ b/layout/forms/nsMeterFrame.h
@@ -28,18 +28,16 @@ public:
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
   virtual void Reflow(nsPresContext*           aCX,
                       ReflowOutput&     aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus&          aStatus) override;
 
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("Meter"), aResult);
   }
 #endif
 
   virtual bool IsLeaf() const override { return true; }
 
--- a/layout/forms/nsNumberControlFrame.cpp
+++ b/layout/forms/nsNumberControlFrame.cpp
@@ -45,17 +45,17 @@ NS_IMPL_FRAMEARENA_HELPERS(nsNumberContr
 
 NS_QUERYFRAME_HEAD(nsNumberControlFrame)
   NS_QUERYFRAME_ENTRY(nsNumberControlFrame)
   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
   NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
 
 nsNumberControlFrame::nsNumberControlFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::NumberControl)
   , mHandlingInputEvent(false)
 {
 }
 
 void
 nsNumberControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   NS_ASSERTION(!GetPrevContinuation() && !GetNextContinuation(),
@@ -444,22 +444,16 @@ nsNumberControlFrame::CreateAnonymousCon
                             nsGkAtoms::div,
                             CSSPseudoElementType::mozNumberSpinDown);
 
   SyncDisabledState();
 
   return rv;
 }
 
-nsIAtom*
-nsNumberControlFrame::GetType() const
-{
-  return nsGkAtoms::numberControlFrame;
-}
-
 void
 nsNumberControlFrame::SetFocus(bool aOn, bool aRepaint)
 {
   GetTextFieldFrame()->SetFocus(aOn, aRepaint);
 }
 
 nsresult
 nsNumberControlFrame::SetFormProperty(nsIAtom* aName, const nsAString& aValue)
--- a/layout/forms/nsNumberControlFrame.h
+++ b/layout/forms/nsNumberControlFrame.h
@@ -74,18 +74,16 @@ public:
                                         uint32_t aFilter) override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("NumberControl"), aResult);
   }
 #endif
 
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsContainerFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
   // nsIFormControlFrame
   virtual void SetFocus(bool aOn, bool aRepaint) override;
--- a/layout/forms/nsProgressFrame.cpp
+++ b/layout/forms/nsProgressFrame.cpp
@@ -33,17 +33,17 @@ nsIFrame*
 NS_NewProgressFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsProgressFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsProgressFrame)
 
 nsProgressFrame::nsProgressFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::Progress)
   , mBarDiv(nullptr)
 {
 }
 
 nsProgressFrame::~nsProgressFrame()
 {
 }
 
@@ -53,22 +53,16 @@ nsProgressFrame::DestroyFrom(nsIFrame* a
   NS_ASSERTION(!GetPrevContinuation(),
                "nsProgressFrame should not have continuations; if it does we "
                "need to call RegUnregAccessKey only for the first.");
   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
   nsContentUtils::DestroyAnonymousContent(&mBarDiv);
   nsContainerFrame::DestroyFrom(aDestructRoot);
 }
 
-nsIAtom*
-nsProgressFrame::GetType() const
-{
-  return nsGkAtoms::progressFrame;
-}
-
 nsresult
 nsProgressFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
 {
   // Create the progress bar div.
   nsCOMPtr<nsIDocument> doc = mContent->GetComposedDoc();
   mBarDiv = doc->CreateHTMLElement(nsGkAtoms::div);
 
   // Associate ::-moz-progress-bar pseudo-element to the anonymous child.
--- a/layout/forms/nsProgressFrame.h
+++ b/layout/forms/nsProgressFrame.h
@@ -10,18 +10,19 @@
 #include "nsContainerFrame.h"
 #include "nsIAnonymousContentCreator.h"
 #include "nsCOMPtr.h"
 
 namespace mozilla {
 enum class CSSPseudoElementType : uint8_t;
 } // namespace mozilla
 
-class nsProgressFrame : public nsContainerFrame,
-                        public nsIAnonymousContentCreator
+class nsProgressFrame final
+  : public nsContainerFrame
+  , public nsIAnonymousContentCreator
 {
   typedef mozilla::CSSPseudoElementType CSSPseudoElementType;
   typedef mozilla::dom::Element Element;
 
 public:
   NS_DECL_QUERYFRAME_TARGET(nsProgressFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
@@ -35,18 +36,16 @@ public:
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
   virtual void Reflow(nsPresContext*           aCX,
                       ReflowOutput&     aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus&          aStatus) override;
 
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("Progress"), aResult);
   }
 #endif
 
   virtual bool IsLeaf() const override { return true; }
 
--- a/layout/forms/nsRangeFrame.cpp
+++ b/layout/forms/nsRangeFrame.cpp
@@ -42,17 +42,17 @@ NS_IMPL_ISUPPORTS(nsRangeFrame::DummyTou
 
 nsIFrame*
 NS_NewRangeFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsRangeFrame(aContext);
 }
 
 nsRangeFrame::nsRangeFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::Range)
 {
 }
 
 nsRangeFrame::~nsRangeFrame()
 {
 #ifdef DEBUG
   if (mOuterFocusStyle) {
     mOuterFocusStyle->FrameRelease();
@@ -861,22 +861,16 @@ nsRangeFrame::GetMax() const
 }
 
 double
 nsRangeFrame::GetValue() const
 {
   return static_cast<dom::HTMLInputElement*>(mContent)->GetValueAsDecimal().toDouble();
 }
 
-nsIAtom*
-nsRangeFrame::GetType() const
-{
-  return nsGkAtoms::rangeFrame;
-}
-
 #define STYLES_DISABLING_NATIVE_THEMING \
   NS_AUTHOR_SPECIFIED_BACKGROUND | \
   NS_AUTHOR_SPECIFIED_PADDING | \
   NS_AUTHOR_SPECIFIED_BORDER
 
 bool
 nsRangeFrame::ShouldUseNativeStyle() const
 {
--- a/layout/forms/nsRangeFrame.h
+++ b/layout/forms/nsRangeFrame.h
@@ -11,18 +11,18 @@
 #include "mozilla/EventForwards.h"
 #include "nsContainerFrame.h"
 #include "nsIAnonymousContentCreator.h"
 #include "nsIDOMEventListener.h"
 #include "nsCOMPtr.h"
 
 class nsDisplayRangeFocusRing;
 
-class nsRangeFrame : public nsContainerFrame,
-                     public nsIAnonymousContentCreator
+class nsRangeFrame final : public nsContainerFrame,
+                           public nsIAnonymousContentCreator
 {
   friend nsIFrame*
   NS_NewRangeFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   friend class nsDisplayRangeFocusRing;
 
   explicit nsRangeFrame(nsStyleContext* aContext);
   virtual ~nsRangeFrame();
@@ -80,18 +80,16 @@ public:
                   const mozilla::LogicalSize& aMargin,
                   const mozilla::LogicalSize& aBorder,
                   const mozilla::LogicalSize& aPadding,
                   ComputeSizeFlags            aFlags) override;
 
   virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
   virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
 
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsContainerFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
   nsStyleContext* GetAdditionalStyleContext(int32_t aIndex) const override;
   void SetAdditionalStyleContext(int32_t aIndex,
--- a/layout/forms/nsSelectsAreaFrame.cpp
+++ b/layout/forms/nsSelectsAreaFrame.cpp
@@ -81,17 +81,17 @@ public:
     return new (aBuilder) nsDisplayOptionEventGrabber(aBuilder, aItem->Frame(), aItem);
   }
 };
 
 static nsListControlFrame* GetEnclosingListFrame(nsIFrame* aSelectsAreaFrame)
 {
   nsIFrame* frame = aSelectsAreaFrame->GetParent();
   while (frame) {
-    if (frame->GetType() == nsGkAtoms::listControlFrame)
+    if (frame->IsListControlFrame())
       return static_cast<nsListControlFrame*>(frame);
     frame = frame->GetParent();
   }
   return nullptr;
 }
 
 class nsDisplayListFocus : public nsDisplayItem {
 public:
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -99,17 +99,17 @@ public:
   bool EnteredMoreThanOnce() const { return !mFirstEntry; }
 private:
   nsTextControlFrame &mFrame;
   bool mFirstEntry;
 };
 #endif
 
 nsTextControlFrame::nsTextControlFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::TextInput)
   , mFirstBaseline(NS_INTRINSIC_WIDTH_UNKNOWN)
   , mEditorHasBeenInitialized(false)
   , mIsProcessing(false)
   , mUsePlaceholder(false)
   , mUsePreview(false)
 #ifdef DEBUG
   , mInEditorInitialization(false)
 #endif
@@ -137,22 +137,16 @@ nsTextControlFrame::DestroyFrom(nsIFrame
   NS_ASSERTION(txtCtrl, "Content not a text control element");
   txtCtrl->UnbindFromFrame(this);
 
   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
 
   nsContainerFrame::DestroyFrom(aDestructRoot);
 }
 
-nsIAtom*
-nsTextControlFrame::GetType() const 
-{ 
-  return nsGkAtoms::textInputFrame;
-}
-
 LogicalSize
 nsTextControlFrame::CalcIntrinsicSize(nsRenderingContext* aRenderingContext,
                                       WritingMode aWM,
                                       float aFontSizeInflation) const
 {
   LogicalSize intrinsicSize(aWM);
   // Get leading and the Average/MaxAdvance char width 
   nscoord lineHeight  = 0;
--- a/layout/forms/nsTextControlFrame.h
+++ b/layout/forms/nsTextControlFrame.h
@@ -162,17 +162,16 @@ public:
 //==== NSISTATEFULFRAME
 
   NS_IMETHOD SaveState(nsPresState** aState) override;
   NS_IMETHOD RestoreState(nsPresState* aState) override;
 
 //=== END NSISTATEFULFRAME
 
 //==== OVERLOAD of nsIFrame
-  virtual nsIAtom* GetType() const override;
 
   /** handler for attribute changes to mContent */
   virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
                                     nsIAtom*        aAttribute,
                                     int32_t         aModType) override;
 
   nsresult GetText(nsString& aText);
 
--- a/layout/generic/BRFrame.cpp
+++ b/layout/generic/BRFrame.cpp
@@ -19,17 +19,18 @@
 //FOR SELECTION
 #include "nsIContent.h"
 //END INCLUDES FOR SELECTION
 
 using namespace mozilla;
 
 namespace mozilla {
 
-class BRFrame : public nsFrame {
+class BRFrame final : public nsFrame
+{
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   friend nsIFrame* ::NS_NewBRFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint) override;
 
   virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) override;
@@ -44,31 +45,33 @@ public:
                           const ReflowInput& aReflowInput,
                           nsReflowStatus& aStatus) override;
   virtual void AddInlineMinISize(nsRenderingContext *aRenderingContext,
                                  InlineMinISizeData *aData) override;
   virtual void AddInlinePrefISize(nsRenderingContext *aRenderingContext,
                                   InlinePrefISizeData *aData) override;
   virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
   virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
-  virtual nsIAtom* GetType() const override;
   virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) const override;
 
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced |
                                              nsIFrame::eLineParticipant));
   }
 
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() override;
 #endif
 
 protected:
-  explicit BRFrame(nsStyleContext* aContext) : nsFrame(aContext) {}
+  explicit BRFrame(nsStyleContext* aContext)
+    : nsFrame(aContext, FrameType::Br)
+  {}
+
   virtual ~BRFrame();
 
   nscoord mAscent;
 };
 
 } // namespace mozilla
 
 nsIFrame*
@@ -201,22 +204,16 @@ BRFrame::GetMinISize(nsRenderingContext 
 /* virtual */ nscoord
 BRFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
 {
   nscoord result = 0;
   DISPLAY_PREF_WIDTH(this, result);
   return result;
 }
 
-nsIAtom*
-BRFrame::GetType() const
-{
-  return nsGkAtoms::brFrame;
-}
-
 nscoord
 BRFrame::GetLogicalBaseline(mozilla::WritingMode aWritingMode) const
 {
   return mAscent;
 }
 
 nsIFrame::ContentOffsets BRFrame::CalcContentOffsetsFromFramePoint(nsPoint aPoint)
 {
--- a/layout/generic/BlockReflowInput.cpp
+++ b/layout/generic/BlockReflowInput.cpp
@@ -766,18 +766,17 @@ BlockReflowInput::FlowAndPlaceFloat(nsIF
 
   // If it's a floating first-letter, we need to reflow it before we
   // know how wide it is (since we don't compute which letters are part
   // of the first letter until reflow!).
   // We also need to do this early reflow if FloatMarginISize returned
   // an unconstrained inline-size, which can occur if the float had an
   // orthogonal writing mode and 'auto' block-size (in its mode).
   bool earlyFloatReflow =
-    aFloat->GetType() == nsGkAtoms::letterFrame ||
-    floatMarginISize == NS_UNCONSTRAINEDSIZE;
+    aFloat->IsLetterFrame() || floatMarginISize == NS_UNCONSTRAINEDSIZE;
   if (earlyFloatReflow) {
     mBlock->ReflowFloat(*this, adjustedAvailableSpace, aFloat, floatMargin,
                         floatOffsets, false, reflowStatus);
     floatMarginISize = aFloat->ISize(wm) + floatMargin.IStartEnd(wm);
     NS_ASSERTION(reflowStatus.IsComplete(),
                  "letter frames and orthogonal floats with auto block-size "
                  "shouldn't break, and if they do now, then they're breaking "
                  "at the wrong point");
@@ -831,20 +830,20 @@ BlockReflowInput::FlowAndPlaceFloat(nsIF
       nsIFrame* prevFrame = nullptr;
       while (fc) {
         if (fc->mFloat == aFloat) {
           break;
         }
         prevFrame = fc->mFloat;
         fc = fc->Next();
       }
-      
+
       if(prevFrame) {
         //get the frame type
-        if (nsGkAtoms::tableWrapperFrame == prevFrame->GetType()) {
+        if (prevFrame->IsTableWrapperFrame()) {
           //see if it has "align="
           // IE makes a difference between align and he float property
           nsIContent* content = prevFrame->GetContent();
           if (content) {
             // we're interested only if previous frame is align=left
             // IE messes things up when "right" (overlapping frames) 
             if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::align,
                                      NS_LITERAL_STRING("left"), eIgnoreCase)) {
--- a/layout/generic/CSSOrderAwareFrameIterator.h
+++ b/layout/generic/CSSOrderAwareFrameIterator.h
@@ -73,24 +73,19 @@ public:
     , mArrayIndex(0)
     , mItemIndex(0)
     , mSkipPlaceholders(aFilter == eSkipPlaceholders)
 #ifdef DEBUG
     , mContainer(aContainer)
     , mListID(aListID)
 #endif
   {
-#ifdef DEBUG
-    {
-      const nsIAtom* type = aContainer->GetType();
-      MOZ_ASSERT(type == nsGkAtoms::flexContainerFrame ||
-                 type == nsGkAtoms::gridContainerFrame,
-                 "Only use this iterator in a container that honors 'order'");
-    }
-#endif
+    MOZ_ASSERT(aContainer->IsFlexOrGridContainer(),
+               "Only use this iterator in a container that honors 'order'");
+
     size_t count = 0;
     bool isOrdered = aState != eKnownUnordered;
     if (aState == eUnknownOrder) {
       auto maxOrder = std::numeric_limits<int32_t>::min();
       for (auto child : mChildren) {
         ++count;
 
         int32_t order;
@@ -157,17 +152,17 @@ public:
 
   /**
    * Return the child index of the current item, placeholders not counted.
    * It's forbidden to call this method when the current frame is placeholder.
    */
   size_t ItemIndex() const
   {
     MOZ_ASSERT(!AtEnd());
-    MOZ_ASSERT((**this)->GetType() != nsGkAtoms::placeholderFrame,
+    MOZ_ASSERT(!(**this)->IsPlaceholderFrame(),
                "MUST not call this when at a placeholder");
     MOZ_ASSERT(IsForward() || mItemIndex < *mItemCount,
                "Returning an out-of-range mItemIndex...");
     return mItemIndex;
   }
 
   void SetItemCount(size_t aItemCount)
   {
@@ -184,24 +179,24 @@ public:
   /**
    * Skip over placeholder children.
    */
   void SkipPlaceholders()
   {
     if (mIter.isSome()) {
       for (; *mIter != *mIterEnd; ++*mIter) {
         nsIFrame* child = **mIter;
-        if (child->GetType() != nsGkAtoms::placeholderFrame) {
+        if (!child->IsPlaceholderFrame()) {
           return;
         }
       }
     } else {
       for (; mArrayIndex < mArray->Length(); ++mArrayIndex) {
         nsIFrame* child = (*mArray)[mArrayIndex];
-        if (child->GetType() != nsGkAtoms::placeholderFrame) {
+        if (!child->IsPlaceholderFrame()) {
           return;
         }
       }
     }
   }
 
   bool AtEnd() const
   {
@@ -216,18 +211,17 @@ public:
   {
 #ifdef DEBUG
     MOZ_ASSERT(!AtEnd());
     nsFrameList list = mContainer->GetChildList(mListID);
     MOZ_ASSERT(list.FirstChild() == mChildren.FirstChild() &&
                list.LastChild() == mChildren.LastChild(),
                "the list of child frames must not change while iterating!");
 #endif
-    if (mSkipPlaceholders ||
-        (**this)->GetType() != nsGkAtoms::placeholderFrame) {
+    if (mSkipPlaceholders || !(**this)->IsPlaceholderFrame()) {
       IsForward() ? ++mItemIndex : --mItemIndex;
     }
     if (mIter.isSome()) {
       ++*mIter;
     } else {
       ++mArrayIndex;
     }
     if (mSkipPlaceholders) {
--- a/layout/generic/DetailsFrame.cpp
+++ b/layout/generic/DetailsFrame.cpp
@@ -26,30 +26,24 @@ nsBlockFrame*
 NS_NewDetailsFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) DetailsFrame(aContext);
 }
 
 namespace mozilla {
 
 DetailsFrame::DetailsFrame(nsStyleContext* aContext)
-  : nsBlockFrame(aContext)
+  : nsBlockFrame(aContext, FrameType::Details)
 {
 }
 
 DetailsFrame::~DetailsFrame()
 {
 }
 
-nsIAtom*
-DetailsFrame::GetType() const
-{
-  return nsGkAtoms::detailsFrame;
-}
-
 void
 DetailsFrame::SetInitialChildList(ChildListID aListID, nsFrameList& aChildList)
 {
 #ifdef DEBUG
   if (aListID == kPrincipalList) {
     CheckValidMainSummary(aChildList);
   }
 #endif
--- a/layout/generic/DetailsFrame.h
+++ b/layout/generic/DetailsFrame.h
@@ -26,18 +26,16 @@ public:
   NS_DECL_FRAMEARENA_HELPERS
   NS_DECL_QUERYFRAME_TARGET(DetailsFrame)
   NS_DECL_QUERYFRAME
 
   explicit DetailsFrame(nsStyleContext* aContext);
 
   virtual ~DetailsFrame();
 
-  nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("Details"), aResult);
   }
 #endif
 
 #ifdef DEBUG
new file mode 100644
--- /dev/null
+++ b/layout/generic/FrameTypeList.h
@@ -0,0 +1,102 @@
+/* -*- 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/. */
+
+/*
+ * This file contains the list of frame types in order to be processed via
+ * macros.
+ */
+FRAME_TYPE(Backdrop)
+FRAME_TYPE(Block)
+FRAME_TYPE(Box)
+FRAME_TYPE(Br)
+FRAME_TYPE(Bullet)
+FRAME_TYPE(BCTableCell)
+FRAME_TYPE(Canvas)
+FRAME_TYPE(ColorControl)
+FRAME_TYPE(ColumnSet)
+FRAME_TYPE(ComboboxControl)
+FRAME_TYPE(ComboboxDisplay)
+FRAME_TYPE(Deck)
+FRAME_TYPE(DateTimeControl)
+FRAME_TYPE(Details)
+FRAME_TYPE(FieldSet)
+FRAME_TYPE(FlexContainer)
+FRAME_TYPE(FrameSet)
+FRAME_TYPE(FormControl)
+FRAME_TYPE(GfxButtonControl)
+FRAME_TYPE(GridContainer)
+FRAME_TYPE(HTMLButtonControl)
+FRAME_TYPE(HTMLCanvas)
+FRAME_TYPE(HTMLVideo)
+FRAME_TYPE(Image)
+FRAME_TYPE(ImageBox)
+FRAME_TYPE(ImageControl)
+FRAME_TYPE(Inline)
+FRAME_TYPE(LeafBox)
+FRAME_TYPE(Legend)
+FRAME_TYPE(Letter)
+FRAME_TYPE(Line)
+FRAME_TYPE(ListControl)
+FRAME_TYPE(Menu)
+FRAME_TYPE(MenuPopup)
+FRAME_TYPE(Meter)
+FRAME_TYPE(None)
+FRAME_TYPE(NumberControl)
+FRAME_TYPE(Object)
+FRAME_TYPE(Page)
+FRAME_TYPE(PageBreak)
+FRAME_TYPE(PageContent)
+FRAME_TYPE(Placeholder)
+FRAME_TYPE(Progress)
+FRAME_TYPE(PopupSet)
+FRAME_TYPE(Range)
+FRAME_TYPE(Root)
+FRAME_TYPE(Ruby)
+FRAME_TYPE(RubyBase)
+FRAME_TYPE(RubyBaseContainer)
+FRAME_TYPE(RubyText)
+FRAME_TYPE(RubyTextContainer)
+FRAME_TYPE(Scroll)
+FRAME_TYPE(Scrollbar)
+FRAME_TYPE(Sequence)
+FRAME_TYPE(Slider)
+FRAME_TYPE(SubDocument)
+FRAME_TYPE(SVGA)
+FRAME_TYPE(SVGClipPath)
+FRAME_TYPE(SVGFilter)
+FRAME_TYPE(SVGForeignObject)
+FRAME_TYPE(SVGFEContainer)
+FRAME_TYPE(SVGFELeaf)
+FRAME_TYPE(SVGFEImage)
+FRAME_TYPE(SVGFEUnstyledLeaf)
+FRAME_TYPE(SVGG)
+FRAME_TYPE(SVGGenericContainer)
+FRAME_TYPE(SVGGeometry)
+FRAME_TYPE(SVGImage)
+FRAME_TYPE(SVGInnerSVG)
+FRAME_TYPE(SVGLinearGradient)
+FRAME_TYPE(SVGMask)
+FRAME_TYPE(SVGMarker)
+FRAME_TYPE(SVGMarkerAnonChild)
+FRAME_TYPE(SVGOuterSVG)
+FRAME_TYPE(SVGOuterSVGAnonChild)
+FRAME_TYPE(SVGPattern)
+FRAME_TYPE(SVGRadialGradient)
+FRAME_TYPE(SVGStop)
+FRAME_TYPE(SVGSwitch)
+FRAME_TYPE(SVGText)
+FRAME_TYPE(SVGUse)
+FRAME_TYPE(SVGView)
+FRAME_TYPE(Table)
+FRAME_TYPE(TableCell)
+FRAME_TYPE(TableCol)
+FRAME_TYPE(TableColGroup)
+FRAME_TYPE(TableRow)
+FRAME_TYPE(TableRowGroup)
+FRAME_TYPE(TableWrapper)
+FRAME_TYPE(Text)
+FRAME_TYPE(TextInput)
+FRAME_TYPE(Viewport)
+FRAME_TYPE(XULLabel)
--- a/layout/generic/ReflowInput.cpp
+++ b/layout/generic/ReflowInput.cpp
@@ -171,17 +171,17 @@ SizeComputationInput::SizeComputationInp
              "We're about to resolve percent margin & padding "
              "values against CB inline size, which is incorrect for "
              "flex/grid items. "
              "Additionally for grid items, this path doesn't handle baseline "
              "padding contribution - see SizeComputationInput::InitOffsets");
   LogicalSize cbSize(aContainingBlockWritingMode, aContainingBlockISize,
                      aContainingBlockISize);
   ReflowInputFlags flags;
-  InitOffsets(aContainingBlockWritingMode, cbSize, mFrame->GetType(), flags);
+  InitOffsets(aContainingBlockWritingMode, cbSize, mFrame->Type(), flags);
 }
 
 // Initialize a reflow state for a child frame's reflow. Some state
 // is copied from the parent reflow state; the remaining state is
 // computed.
 ReflowInput::ReflowInput(
                      nsPresContext*           aPresContext,
                      const ReflowInput& aParentReflowInput,
@@ -249,17 +249,17 @@ ReflowInput::ReflowInput(
 
   mDiscoveredClearance = nullptr;
   mPercentBSizeObserver = (aParentReflowInput.mPercentBSizeObserver &&
                             aParentReflowInput.mPercentBSizeObserver->NeedsToObserve(*this))
                            ? aParentReflowInput.mPercentBSizeObserver : nullptr;
 
   if ((aFlags & DUMMY_PARENT_REFLOW_STATE) ||
       (mParentReflowInput->mFlags.mDummyParentReflowInput &&
-       mFrame->GetType() == nsGkAtoms::tableFrame)) {
+       mFrame->IsTableFrame())) {
     mFlags.mDummyParentReflowInput = true;
   }
 
   if (!(aFlags & CALLER_WILL_INIT)) {
     Init(aPresContext, aContainingBlockSize);
   }
 }
 
@@ -322,18 +322,18 @@ ReflowInput::SetComputedWidth(nscoord aC
   //    state is not used to reflow the parent, but just as a parent for the
   //    frame's own reflow state.  So given a nsBoxFrame inside some non-XUL
   //    (like a text control, for example), we'll end up creating a reflow
   //    state for the parent while the parent is reflowing.
 
   NS_PRECONDITION(aComputedWidth >= 0, "Invalid computed width");
   if (ComputedWidth() != aComputedWidth) {
     ComputedWidth() = aComputedWidth;
-    nsIAtom* frameType = mFrame->GetType();
-    if (frameType != nsGkAtoms::viewportFrame || // Or check GetParent()?
+    FrameType frameType = mFrame->Type();
+    if (frameType != FrameType::Viewport || // Or check GetParent()?
         mWritingMode.IsVertical()) {
       InitResizeFlags(mFrame->PresContext(), frameType);
     }
   }
 }
 
 void
 ReflowInput::SetComputedHeight(nscoord aComputedHeight)
@@ -346,18 +346,18 @@ ReflowInput::SetComputedHeight(nscoord a
   //    state is not used to reflow the parent, but just as a parent for the
   //    frame's own reflow state.  So given a nsBoxFrame inside some non-XUL
   //    (like a text control, for example), we'll end up creating a reflow
   //    state for the parent while the parent is reflowing.
 
   NS_PRECONDITION(aComputedHeight >= 0, "Invalid computed height");
   if (ComputedHeight() != aComputedHeight) {
     ComputedHeight() = aComputedHeight;
-    nsIAtom* frameType = mFrame->GetType();
-    if (frameType != nsGkAtoms::viewportFrame || !mWritingMode.IsVertical()) {
+    FrameType frameType = mFrame->Type();
+    if (frameType != FrameType::Viewport || !mWritingMode.IsVertical()) {
       InitResizeFlags(mFrame->PresContext(), frameType);
     }
   }
 }
 
 void
 ReflowInput::Init(nsPresContext*     aPresContext,
                         const LogicalSize* aContainingBlockSize,
@@ -385,37 +385,37 @@ ReflowInput::Init(nsPresContext*     aPr
   mStylePosition = mFrame->StylePosition();
   mStyleDisplay = mFrame->StyleDisplay();
   mStyleVisibility = mFrame->StyleVisibility();
   mStyleBorder = mFrame->StyleBorder();
   mStyleMargin = mFrame->StyleMargin();
   mStylePadding = mFrame->StylePadding();
   mStyleText = mFrame->StyleText();
 
-  nsIAtom* type = mFrame->GetType();
+  FrameType type = mFrame->Type();
 
   InitFrameType(type);
   InitCBReflowInput();
 
   LogicalSize cbSize(mWritingMode, -1, -1);
   if (aContainingBlockSize) {
     cbSize = *aContainingBlockSize;
   }
 
   InitConstraints(aPresContext, cbSize, aBorder, aPadding, type);
 
   InitResizeFlags(aPresContext, type);
 
   nsIFrame *parent = mFrame->GetParent();
   if (parent &&
       (parent->GetStateBits() & NS_FRAME_IN_CONSTRAINED_BSIZE) &&
-      !(parent->GetType() == nsGkAtoms::scrollFrame &&
+      !(parent->IsScrollFrame() &&
         parent->StyleDisplay()->mOverflowY != NS_STYLE_OVERFLOW_HIDDEN)) {
     mFrame->AddStateBits(NS_FRAME_IN_CONSTRAINED_BSIZE);
-  } else if (type == nsGkAtoms::svgForeignObjectFrame) {
+  } else if (type == FrameType::SVGForeignObject) {
     // An SVG foreignObject frame is inherently constrained block-size.
     mFrame->AddStateBits(NS_FRAME_IN_CONSTRAINED_BSIZE);
   } else {
     const nsStyleCoord& bSizeCoord = mStylePosition->BSize(mWritingMode);
     const nsStyleCoord& maxBSizeCoord = mStylePosition->MaxBSize(mWritingMode);
     if ((bSizeCoord.GetUnit() != eStyleUnit_Auto ||
          maxBSizeCoord.GetUnit() != eStyleUnit_None) &&
          // Don't set NS_FRAME_IN_CONSTRAINED_BSIZE on body or html elements.
@@ -461,27 +461,27 @@ ReflowInput::Init(nsPresContext*     aPr
 
   if (mParentReflowInput &&
       mParentReflowInput->GetWritingMode().IsOrthogonalTo(mWritingMode)) {
     // Orthogonal frames are always reflowed with an unconstrained
     // dimension to avoid incomplete reflow across an orthogonal
     // boundary. Normally this is the block-size, but for column sets
     // with auto-height it's the inline-size, so that they can add
     // columns in the container's block direction
-    if (type == nsGkAtoms::columnSetFrame &&
+    if (type == FrameType::ColumnSet &&
         eStyleUnit_Auto == mStylePosition->ISize(mWritingMode).GetUnit()) {
       ComputedISize() = NS_UNCONSTRAINEDSIZE;
     } else {
       AvailableBSize() = NS_UNCONSTRAINEDSIZE;
     }
   }
 
   LAYOUT_WARN_IF_FALSE((mFrameType == NS_CSS_FRAME_TYPE_INLINE &&
                         !mFrame->IsFrameOfType(nsIFrame::eReplaced)) ||
-                       type == nsGkAtoms::textFrame ||
+                       type == FrameType::Text ||
                        ComputedISize() != NS_UNCONSTRAINEDSIZE,
                        "have unconstrained inline-size; this should only "
                        "result from very large sizes, not attempts at "
                        "intrinsic inline-size calculation");
 }
 
 void ReflowInput::InitCBReflowInput()
 {
@@ -492,17 +492,17 @@ void ReflowInput::InitCBReflowInput()
   if (mParentReflowInput->mFlags.mDummyParentReflowInput) {
     mCBReflowInput = mParentReflowInput;
     return;
   }
 
   if (mParentReflowInput->mFrame == mFrame->GetContainingBlock()) {
     // Inner table frames need to use the containing block of the outer
     // table frame.
-    if (mFrame->GetType() == nsGkAtoms::tableFrame) {
+    if (mFrame->IsTableFrame()) {
       mCBReflowInput = mParentReflowInput->mCBReflowInput;
     } else {
       mCBReflowInput = mParentReflowInput;
     }
   } else {
     mCBReflowInput = mParentReflowInput->mCBReflowInput;
   }
 }
@@ -511,37 +511,36 @@ void ReflowInput::InitCBReflowInput()
  * given reflow state, using its block as a height.  (essentially 
  * returns false for any case in which CalcQuirkContainingBlockHeight 
  * has a "continue" in its main loop.)
  *
  * XXX Maybe refactor CalcQuirkContainingBlockHeight so it uses 
  * this function as well
  */
 static bool
-IsQuirkContainingBlockHeight(const ReflowInput* rs, nsIAtom* aFrameType)
+IsQuirkContainingBlockHeight(const ReflowInput* rs, FrameType aFrameType)
 {
-  if (nsGkAtoms::blockFrame == aFrameType ||
+  if (FrameType::Block == aFrameType ||
 #ifdef MOZ_XUL
-      nsGkAtoms::XULLabelFrame == aFrameType ||
+      FrameType::XULLabel == aFrameType ||
 #endif
-      nsGkAtoms::scrollFrame == aFrameType) {
+      FrameType::Scroll == aFrameType) {
     // Note: This next condition could change due to a style change,
     // but that would cause a style reflow anyway, which means we're ok.
     if (NS_AUTOHEIGHT == rs->ComputedHeight()) {
       if (!rs->mFrame->IsAbsolutelyPositioned()) {
         return false;
       }
     }
   }
   return true;
 }
 
-
 void
-ReflowInput::InitResizeFlags(nsPresContext* aPresContext, nsIAtom* aFrameType)
+ReflowInput::InitResizeFlags(nsPresContext* aPresContext, FrameType aFrameType)
 {
   SetBResize(false);
   SetIResize(false);
 
   const WritingMode wm = mWritingMode; // just a shorthand
   // We should report that we have a resize in the inline dimension if
   // *either* the border-box size or the content-box size in that
   // dimension has changed.  It might not actually be necessary to do
@@ -601,17 +600,17 @@ ReflowInput::InitResizeFlags(nsPresConte
       // caused by script where a style or content change in one place
       // causes a resize in another (e.g., rebalancing a table).
 
       // FIXME: This isn't so great for the cases where
       // ReflowInput::SetComputedWidth is called, if the first time
       // we go through InitResizeFlags we set IsHResize() to true, and then
       // the second time we'd set it to false even without the
       // NS_FRAME_IS_DIRTY bit already set.
-      if (mFrame->GetType() == nsGkAtoms::svgForeignObjectFrame) {
+      if (mFrame->IsSVGForeignObjectFrame()) {
         // Foreign object frames use dirty bits in a special way.
         mFrame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
         nsIFrame *kid = mFrame->PrincipalChildList().FirstChild();
         if (kid) {
           kid->AddStateBits(NS_FRAME_IS_DIRTY);
         }
       } else {
         mFrame->AddStateBits(NS_FRAME_IS_DIRTY);
@@ -737,19 +736,19 @@ ReflowInput::InitResizeFlags(nsPresConte
 
   // If we're the descendant of a table cell that performs special bsize
   // reflows and we could be the child that requires them, always set
   // the block-axis resize in case this is the first pass before the
   // special bsize reflow.  However, don't do this if it actually is
   // the special bsize reflow, since in that case it will already be
   // set correctly above if we need it set.
   if (!IsBResize() && mCBReflowInput &&
-      (IS_TABLE_CELL(mCBReflowInput->mFrame->GetType()) || 
+      (IS_TABLE_CELL(mCBReflowInput->mFrame->Type()) ||
        mCBReflowInput->mFlags.mHeightDependsOnAncestorCell) &&
-      !mCBReflowInput->mFlags.mSpecialBSizeReflow && 
+      !mCBReflowInput->mFlags.mSpecialBSizeReflow &&
       dependsOnCBBSize) {
     SetBResize(true);
     mFlags.mHeightDependsOnAncestorCell = true;
   }
 
   // Set NS_FRAME_CONTAINS_RELATIVE_BSIZE if it's needed.
 
   // It would be nice to check that |ComputedBSize != NS_AUTOHEIGHT|
@@ -778,17 +777,17 @@ ReflowInput::InitResizeFlags(nsPresConte
         hitCBReflowInput = true;
       }
 
       // XXX What about orthogonal flows? It doesn't make sense to
       // keep propagating this bit across an orthogonal boundary,
       // where the meaning of BSize changes. Bug 1175517.
     } while (!hitCBReflowInput ||
              (eCompatibility_NavQuirks == aPresContext->CompatibilityMode() &&
-              !IsQuirkContainingBlockHeight(rs, rs->mFrame->GetType())));
+              !IsQuirkContainingBlockHeight(rs, rs->mFrame->Type())));
     // Note: We actually don't need to set the
     // NS_FRAME_CONTAINS_RELATIVE_BSIZE bit for the cases
     // where we hit the early break statements in
     // CalcQuirkContainingBlockHeight. But it doesn't hurt
     // us to set the bit in these cases.
     
   }
   if (mFrame->GetStateBits() & NS_FRAME_IS_DIRTY) {
@@ -805,31 +804,31 @@ ReflowInput::GetContainingBlockContentIS
     return 0;
   }
   return mCBReflowInput->GetWritingMode().IsOrthogonalTo(aWritingMode)
     ? mCBReflowInput->ComputedBSize()
     : mCBReflowInput->ComputedISize();
 }
 
 void
-ReflowInput::InitFrameType(nsIAtom* aFrameType)
+ReflowInput::InitFrameType(FrameType aFrameType)
 {
   const nsStyleDisplay *disp = mStyleDisplay;
   nsCSSFrameType frameType;
 
   // Section 9.7 of the CSS2 spec indicates that absolute position
   // takes precedence over float which takes precedence over display.
   // XXXldb nsRuleNode::ComputeDisplayData should take care of this, right?
   // Make sure the frame was actually moved out of the flow, and don't
   // just assume what the style says, because we might not have had a
   // useful float/absolute containing block
 
   DISPLAY_INIT_TYPE(mFrame, this);
 
-  if (aFrameType == nsGkAtoms::tableFrame) {
+  if (aFrameType == FrameType::Table) {
     mFrameType = NS_CSS_FRAME_TYPE_BLOCK;
     return;
   }
 
   NS_ASSERTION(mFrame->StyleDisplay()->IsAbsolutelyPositionedStyle() ==
                  disp->IsAbsolutelyPositionedStyle(),
                "Unexpected position style");
   NS_ASSERTION(mFrame->StyleDisplay()->IsFloatingStyle() ==
@@ -1115,26 +1114,28 @@ struct nsHypotheticalPosition {
   // offset from inline-start edge of containing block (which is a padding edge)
   nscoord       mIStart;
   // offset from block-start edge of containing block (which is a padding edge)
   nscoord       mBStart;
   WritingMode   mWritingMode;
 };
 
 static bool
-GetIntrinsicSizeFor(nsIFrame* aFrame, nsSize& aIntrinsicSize, nsIAtom* aFrameType)
+GetIntrinsicSizeFor(nsIFrame* aFrame,
+                    nsSize& aIntrinsicSize,
+                    FrameType aFrameType)
 {
   // See if it is an image frame
   bool success = false;
 
   // Currently the only type of replaced frame that we can get the intrinsic
   // size for is an image frame
   // XXX We should add back the GetReflowOutput() function and one of the
   // things should be the intrinsic size...
-  if (aFrameType == nsGkAtoms::imageFrame) {
+  if (aFrameType == FrameType::Image) {
     nsImageFrame* imageFrame = (nsImageFrame*)aFrame;
 
     if (NS_SUCCEEDED(imageFrame->GetIntrinsicImageSize(aIntrinsicSize))) {
       success = (aIntrinsicSize != nsSize(0, 0));
     }
   }
   return success;
 }
@@ -1247,22 +1248,22 @@ static bool AreAllEarlierInFlowFramesEmp
 // The values returned are relative to the padding edge of the absolute
 // containing block. The writing-mode of the hypothetical box position will
 // have the same block direction as the absolute containing block, but may
 // differ in inline-bidi direction.
 // In the code below, |cbrs->frame| is the absolute containing block, while
 // |containingBlock| is the nearest block container of the placeholder frame,
 // which may be different from the absolute containing block.
 void
-ReflowInput::CalculateHypotheticalPosition
-                     (nsPresContext*           aPresContext,
-                      nsIFrame*                aPlaceholderFrame,
-                      const ReflowInput* cbrs,
-                      nsHypotheticalPosition&  aHypotheticalPos,
-                      nsIAtom*                 aFrameType) const
+ReflowInput::CalculateHypotheticalPosition(
+  nsPresContext* aPresContext,
+  nsIFrame* aPlaceholderFrame,
+  const ReflowInput* cbrs,
+  nsHypotheticalPosition& aHypotheticalPos,
+  FrameType aFrameType) const
 {
   NS_ASSERTION(mStyleDisplay->mOriginalDisplay != StyleDisplay::None,
                "mOriginalDisplay has not been properly initialized");
 
   // Find the nearest containing block frame to the placeholder frame,
   // and its inline-start edge and width.
   nscoord blockIStartContentEdge;
   // Dummy writing mode for blockContentSize, will be changed as needed by
@@ -1549,26 +1550,26 @@ ReflowInput::CalculateHypotheticalPositi
     aHypotheticalPos.mWritingMode = cbwm;
   } else {
     aHypotheticalPos.mWritingMode = wm;
   }
 }
 
 void
 ReflowInput::InitAbsoluteConstraints(nsPresContext* aPresContext,
-                                           const ReflowInput* cbrs,
-                                           const LogicalSize& aCBSize,
-                                           nsIAtom* aFrameType)
+                                     const ReflowInput* cbrs,
+                                     const LogicalSize& aCBSize,
+                                     FrameType aFrameType)
 {
   WritingMode wm = GetWritingMode();
   WritingMode cbwm = cbrs->GetWritingMode();
   NS_PRECONDITION(aCBSize.BSize(cbwm) != NS_AUTOHEIGHT,
                   "containing block bsize must be constrained");
 
-  NS_ASSERTION(aFrameType != nsGkAtoms::tableFrame,
+  NS_ASSERTION(aFrameType != FrameType::Table,
                "InitAbsoluteConstraints should not be called on table frames");
   NS_ASSERTION(mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW,
                "Why are we here?");
 
   const auto& styleOffset = mStylePosition->mOffset;
   bool iStartIsAuto = styleOffset.GetIStartUnit(cbwm) == eStyleUnit_Auto;
   bool iEndIsAuto   = styleOffset.GetIEndUnit(cbwm) == eStyleUnit_Auto;
   bool bStartIsAuto = styleOffset.GetBStartUnit(cbwm) == eStyleUnit_Auto;
@@ -1952,68 +1953,66 @@ static nscoord
 CalcQuirkContainingBlockHeight(const ReflowInput* aCBReflowInput)
 {
   const ReflowInput* firstAncestorRI = nullptr; // a candidate for html frame
   const ReflowInput* secondAncestorRI = nullptr; // a candidate for body frame
   
   // initialize the default to NS_AUTOHEIGHT as this is the containings block
   // computed height when this function is called. It is possible that we 
   // don't alter this height especially if we are restricted to one level
-  nscoord result = NS_AUTOHEIGHT; 
-                             
+  nscoord result = NS_AUTOHEIGHT;
+
   const ReflowInput* rs = aCBReflowInput;
   for (; rs; rs = rs->mParentReflowInput) {
-    nsIAtom* frameType = rs->mFrame->GetType();
-    // if the ancestor is auto height then skip it and continue up if it 
+    FrameType frameType = rs->mFrame->Type();
+    // if the ancestor is auto height then skip it and continue up if it
     // is the first block frame and possibly the body/html
-    if (nsGkAtoms::blockFrame == frameType ||
+    if (FrameType::Block == frameType ||
 #ifdef MOZ_XUL
-        nsGkAtoms::XULLabelFrame == frameType ||
+        FrameType::XULLabel == frameType ||
 #endif
-        nsGkAtoms::scrollFrame == frameType) {
+        FrameType::Scroll == frameType) {
 
       secondAncestorRI = firstAncestorRI;
       firstAncestorRI = rs;
 
       // If the current frame we're looking at is positioned, we don't want to
       // go any further (see bug 221784).  The behavior we want here is: 1) If
       // not auto-height, use this as the percentage base.  2) If auto-height,
       // keep looking, unless the frame is positioned.
       if (NS_AUTOHEIGHT == rs->ComputedHeight()) {
         if (rs->mFrame->IsAbsolutelyPositioned()) {
           break;
         } else {
           continue;
         }
       }
-    }
-    else if (nsGkAtoms::canvasFrame == frameType) {
+    } else if (FrameType::Canvas == frameType) {
       // Always continue on to the height calculation
-    }
-    else if (nsGkAtoms::pageContentFrame == frameType) {
+    } else if (FrameType::PageContent == frameType) {
       nsIFrame* prevInFlow = rs->mFrame->GetPrevInFlow();
       // only use the page content frame for a height basis if it is the first in flow
       if (prevInFlow) 
         break;
     }
     else {
       break;
     }
 
     // if the ancestor is the page content frame then the percent base is 
     // the avail height, otherwise it is the computed height
-    result = (nsGkAtoms::pageContentFrame == frameType)
-             ? rs->AvailableHeight() : rs->ComputedHeight();
+    result = (FrameType::PageContent == frameType) ? rs->AvailableHeight()
+                                                   : rs->ComputedHeight();
     // if unconstrained - don't sutract borders - would result in huge height
     if (NS_AUTOHEIGHT == result) return result;
 
     // if we got to the canvas or page content frame, then subtract out 
     // margin/border/padding for the BODY and HTML elements
-    if ((nsGkAtoms::canvasFrame == frameType) || 
-        (nsGkAtoms::pageContentFrame == frameType)) {
+    if ((FrameType::Canvas == frameType) ||
+        (FrameType::PageContent == frameType)) {
 
       result -= GetBlockMarginBorderPadding(firstAncestorRI);
       result -= GetBlockMarginBorderPadding(secondAncestorRI);
 
 #ifdef DEBUG
       // make sure the first ancestor is the HTML and the second is the BODY
       if (firstAncestorRI) {
         nsIContent* frameContent = firstAncestorRI->mFrame->GetContent();
@@ -2025,23 +2024,21 @@ CalcQuirkContainingBlockHeight(const Ref
       if (secondAncestorRI) {
         nsIContent* frameContent = secondAncestorRI->mFrame->GetContent();
         if (frameContent) {
           NS_ASSERTION(frameContent->IsHTMLElement(nsGkAtoms::body),
                        "Second ancestor is not BODY");
         }
       }
 #endif
-      
+
     }
     // if we got to the html frame (a block child of the canvas) ...
-    else if (nsGkAtoms::blockFrame == frameType &&
-             rs->mParentReflowInput &&
-             nsGkAtoms::canvasFrame ==
-               rs->mParentReflowInput->mFrame->GetType()) {
+    else if (FrameType::Block == frameType && rs->mParentReflowInput &&
+             rs->mParentReflowInput->mFrame->IsCanvasFrame()) {
       // ... then subtract out margin/border/padding for the BODY element
       result -= GetBlockMarginBorderPadding(secondAncestorRI);
     }
     break;
   }
 
   // Make sure not to return a negative height here!
   return std::max(result, 0);
@@ -2058,18 +2055,17 @@ ReflowInput::ComputeContainingBlockRecta
   // formed by the content edge of the nearest block-level ancestor
   LogicalSize cbSize = aContainingBlockRI->ComputedSize();
 
   WritingMode wm = aContainingBlockRI->GetWritingMode();
 
   // mFrameType for abs-pos tables is NS_CSS_FRAME_TYPE_BLOCK, so we need to
   // special case them here.
   if (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE ||
-      (mFrame->GetType() == nsGkAtoms::tableFrame &&
-       mFrame->IsAbsolutelyPositioned() &&
+      (mFrame->IsTableFrame() && mFrame->IsAbsolutelyPositioned() &&
        (mFrame->GetParent()->GetStateBits() & NS_FRAME_OUT_OF_FLOW))) {
     // See if the ancestor is block-level or inline-level
     if (NS_FRAME_GET_TYPE(aContainingBlockRI->mFrameType) == NS_CSS_FRAME_TYPE_INLINE) {
       // Base our size on the actual size of the frame.  In cases when this is
       // completely bogus (eg initial reflow), this code shouldn't even be
       // called, since the code in nsInlineFrame::Reflow will pass in
       // the containing block dimensions to our constructor.
       // XXXbz we should be taking the in-flows into account too, but
@@ -2156,21 +2152,21 @@ OffsetPercentBasis(const nsIFrame*    aF
 
   return offsetPercentBasis;
 }
 
 // XXX refactor this code to have methods for each set of properties
 // we are computing: width,height,line-height; margin; offsets
 
 void
-ReflowInput::InitConstraints(nsPresContext*     aPresContext,
-                                   const LogicalSize& aContainingBlockSize,
-                                   const nsMargin*    aBorder,
-                                   const nsMargin*    aPadding,
-                                   nsIAtom*           aFrameType)
+ReflowInput::InitConstraints(nsPresContext* aPresContext,
+                             const LogicalSize& aContainingBlockSize,
+                             const nsMargin* aBorder,
+                             const nsMargin* aPadding,
+                             FrameType aFrameType)
 {
   WritingMode wm = GetWritingMode();
   DISPLAY_INIT_CONSTRAINTS(mFrame, this,
                            aContainingBlockSize.ISize(wm),
                            aContainingBlockSize.BSize(wm),
                            aBorder, aPadding);
 
   // If this is a reflow root, then set the computed width and
@@ -2209,23 +2205,23 @@ ReflowInput::InitConstraints(nsPresConte
     // If we weren't given a containing block width and height, then
     // compute one
     LogicalSize cbSize = (aContainingBlockSize == LogicalSize(wm, -1, -1))
       ? ComputeContainingBlockRectangle(aPresContext, cbrs)
       : aContainingBlockSize;
 
     // See if the containing block height is based on the size of its
     // content
-    nsIAtom* fType;
+    FrameType fType;
     if (NS_AUTOHEIGHT == cbSize.BSize(wm)) {
       // See if the containing block is a cell frame which needs
       // to use the mComputedHeight of the cell instead of what the cell block passed in.
       // XXX It seems like this could lead to bugs with min-height and friends
       if (cbrs->mParentReflowInput) {
-        fType = cbrs->mFrame->GetType();
+        fType = cbrs->mFrame->Type();
         if (IS_TABLE_CELL(fType)) {
           // use the cell's computed block size
           cbSize.BSize(wm) = cbrs->ComputedSize(wm).BSize(wm);
         }
       }
     }
 
     // XXX Might need to also pass the CB height (not width) for page boxes,
@@ -2396,27 +2392,23 @@ ReflowInput::InitConstraints(nsPresConte
           ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
       }
       if (mFlags.mUseAutoBSize) {
         computeSizeFlags =
           ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eUseAutoBSize);
       }
 
       nsIFrame* alignCB = mFrame->GetParent();
-      nsIAtom* alignCBType = alignCB ? alignCB->GetType() : nullptr;
-      if (alignCBType == nsGkAtoms::tableWrapperFrame &&
-          alignCB->GetParent()) {
-        auto parentCBType = alignCB->GetParent()->GetType();
+      if (alignCB && alignCB->IsTableWrapperFrame() && alignCB->GetParent()) {
         // XXX grid-specific for now; maybe remove this check after we address bug 799725
-        if (parentCBType == nsGkAtoms::gridContainerFrame) {
+        if (alignCB->GetParent()->IsGridContainerFrame()) {
           alignCB = alignCB->GetParent();
-          alignCBType = parentCBType;
         }
       }
-      if (alignCBType == nsGkAtoms::gridContainerFrame) {
+      if (alignCB->IsGridContainerFrame()) {
         // Shrink-wrap grid items that will be aligned (rather than stretched)
         // in its inline axis.
         auto inlineAxisAlignment =
           wm.IsOrthogonalTo(cbwm)
             ? mStylePosition->UsedAlignSelf(alignCB->StyleContext())
             : mStylePosition->UsedJustifySelf(alignCB->StyleContext());
         if ((inlineAxisAlignment != NS_STYLE_ALIGN_STRETCH &&
              inlineAxisAlignment != NS_STYLE_ALIGN_NORMAL) ||
@@ -2425,27 +2417,27 @@ ReflowInput::InitConstraints(nsPresConte
           computeSizeFlags =
             ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
         }
       } else {
         // Make sure legend frames with display:block and width:auto still
         // shrink-wrap.
         // Also shrink-wrap blocks that are orthogonal to their container.
         if (isBlock &&
-            ((aFrameType == nsGkAtoms::legendFrame &&
+            ((aFrameType == FrameType::Legend &&
               mFrame->StyleContext()->GetPseudo() != nsCSSAnonBoxes::scrolledContent) ||
-             (aFrameType == nsGkAtoms::scrollFrame &&
-              mFrame->GetContentInsertionFrame()->GetType() == nsGkAtoms::legendFrame) ||
+             (aFrameType == FrameType::Scroll &&
+              mFrame->GetContentInsertionFrame()->IsLegendFrame()) ||
              (mCBReflowInput &&
               mCBReflowInput->GetWritingMode().IsOrthogonalTo(mWritingMode)))) {
           computeSizeFlags =
             ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
         }
 
-        if (alignCBType == nsGkAtoms::flexContainerFrame) {
+        if (alignCB && alignCB->IsFlexContainerFrame()) {
           computeSizeFlags =
             ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
 
           // If we're inside of a flex container that needs to measure our
           // auto height, pass that information along to ComputeSize().
           if (mFlags.mIsFlexContainerMeasuringHeight) {
             computeSizeFlags =
               ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eUseAutoBSize);
@@ -2474,21 +2466,20 @@ ReflowInput::InitConstraints(nsPresConte
       ComputedISize() = size.ISize(wm);
       ComputedBSize() = size.BSize(wm);
       NS_ASSERTION(ComputedISize() >= 0, "Bogus inline-size");
       NS_ASSERTION(ComputedBSize() == NS_UNCONSTRAINEDSIZE ||
                    ComputedBSize() >= 0, "Bogus block-size");
 
       // Exclude inline tables, side captions, flex and grid items from block
       // margin calculations.
-      if (isBlock &&
-          !IsSideCaption(mFrame, mStyleDisplay, cbwm) &&
+      if (isBlock && !IsSideCaption(mFrame, mStyleDisplay, cbwm) &&
           mStyleDisplay->mDisplay != StyleDisplay::InlineTable &&
-          alignCBType != nsGkAtoms::flexContainerFrame &&
-          alignCBType != nsGkAtoms::gridContainerFrame) {
+          (!alignCB || (!alignCB->IsFlexContainerFrame() &&
+                        !alignCB->IsGridContainerFrame()))) {
         CalculateBlockSideMargins(aFrameType);
       }
     }
   }
 }
 
 static void
 UpdateProp(FrameProperties& aProps,
@@ -2505,21 +2496,21 @@ UpdateProp(FrameProperties& aProps,
     }
   } else {
     aProps.Delete(aProperty);
   }
 }
 
 void
 SizeComputationInput::InitOffsets(WritingMode aWM,
-                              const LogicalSize& aPercentBasis,
-                              nsIAtom* aFrameType,
-                              ReflowInputFlags aFlags,
-                              const nsMargin* aBorder,
-                              const nsMargin* aPadding)
+                                  const LogicalSize& aPercentBasis,
+                                  FrameType aFrameType,
+                                  ReflowInputFlags aFlags,
+                                  const nsMargin* aBorder,
+                                  const nsMargin* aPadding)
 {
   DISPLAY_INIT_OFFSETS(mFrame, this, aPercentBasis, aBorder, aPadding);
 
   // Since we are in reflow, we don't need to store these properties anymore
   // unless they are dependent on width, in which case we store the new value.
   nsPresContext *presContext = mFrame->PresContext();
   FrameProperties props(presContext->PropertyTable(), mFrame);
   props.Delete(nsIFrame::UsedBorderProperty());
@@ -2611,33 +2602,33 @@ SizeComputationInput::InitOffsets(Writin
   else if (aBorder) {  // border is an input arg
     ComputedPhysicalBorderPadding() = *aBorder;
   }
   else {
     ComputedPhysicalBorderPadding() = mFrame->StyleBorder()->GetComputedBorder();
   }
   ComputedPhysicalBorderPadding() += ComputedPhysicalPadding();
 
-  if (aFrameType == nsGkAtoms::tableFrame) {
+  if (aFrameType == FrameType::Table) {
     nsTableFrame *tableFrame = static_cast<nsTableFrame*>(mFrame);
 
     if (tableFrame->IsBorderCollapse()) {
       // border-collapsed tables don't use any of their padding, and
       // only part of their border.  We need to do this here before we
       // try to do anything like handling 'auto' widths,
       // 'box-sizing', or 'auto' margins.
       ComputedPhysicalPadding().SizeTo(0,0,0,0);
       SetComputedLogicalBorderPadding(
         tableFrame->GetIncludedOuterBCBorder(mWritingMode));
     }
 
     // The margin is inherited to the table wrapper frame via
     // the ::-moz-table-wrapper rule in ua.css.
     ComputedPhysicalMargin().SizeTo(0, 0, 0, 0);
-  } else if (aFrameType == nsGkAtoms::scrollbarFrame) {
+  } else if (aFrameType == FrameType::Scrollbar) {
     // scrollbars may have had their width or height smashed to zero
     // by the associated scrollframe, in which case we must not report
     // any padding or border.
     nsSize size(mFrame->GetSize());
     if (size.width == 0 || size.height == 0) {
       ComputedPhysicalPadding().SizeTo(0,0,0,0);
       ComputedPhysicalBorderPadding().SizeTo(0,0,0,0);
     }
@@ -2649,17 +2640,17 @@ SizeComputationInput::InitOffsets(Writin
 // This code enforces section 10.3.3 of the CSS2 spec for this formula:
 //
 // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' +
 //   'padding-right' + 'border-right-width' + 'margin-right'
 //   = width of containing block 
 //
 // Note: the width unit is not auto when this is called
 void
-ReflowInput::CalculateBlockSideMargins(nsIAtom* aFrameType)
+ReflowInput::CalculateBlockSideMargins(FrameType aFrameType)
 {
   // Calculations here are done in the containing block's writing mode,
   // which is where margins will eventually be applied: we're calculating
   // margins that will be used by the container in its inline direction,
   // which in the case of an orthogonal contained block will correspond to
   // the block direction of this reflow state. So in the orthogonal-flow
   // case, "CalculateBlock*Side*Margins" will actually end up adjusting
   // the BStart/BEnd margins; those are the "sides" of the block from its
@@ -2712,18 +2703,18 @@ ReflowInput::CalculateBlockSideMargins(n
   bool isAutoStartMargin = eStyleUnit_Auto == styleSides.GetIStartUnit(cbWM);
   bool isAutoEndMargin = eStyleUnit_Auto == styleSides.GetIEndUnit(cbWM);
   if (!isAutoStartMargin && !isAutoEndMargin) {
     // Neither margin is 'auto' so we're over constrained. Use the
     // 'direction' property of the parent to tell which margin to
     // ignore
     // First check if there is an HTML alignment that we should honor
     const ReflowInput* prs = mParentReflowInput;
-    if (aFrameType == nsGkAtoms::tableFrame) {
-      NS_ASSERTION(prs->mFrame->GetType() == nsGkAtoms::tableWrapperFrame,
+    if (aFrameType == FrameType::Table) {
+      NS_ASSERTION(prs->mFrame->IsTableWrapperFrame(),
                    "table not inside table wrapper");
       // Center the table within the table wrapper based on the alignment
       // of the table wrapper's parent.
       prs = prs->mParentReflowInput;
     }
     if (prs &&
         (prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_LEFT ||
          prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_CENTER ||
@@ -2924,28 +2915,28 @@ SizeComputationInput::ComputeMargin(Writ
     SetComputedLogicalMargin(m);
   }
 
   return isCBDependent;
 }
 
 bool
 SizeComputationInput::ComputePadding(WritingMode aWM,
-                                 const LogicalSize& aPercentBasis,
-                                 nsIAtom* aFrameType)
+                                     const LogicalSize& aPercentBasis,
+                                     FrameType aFrameType)
 {
   // If style can provide us the padding directly, then use it.
   const nsStylePadding *stylePadding = mFrame->StylePadding();
   bool isCBDependent = !stylePadding->GetPadding(ComputedPhysicalPadding());
   // a table row/col group, row/col doesn't have padding
   // XXXldb Neither do border-collapse tables.
-  if (nsGkAtoms::tableRowGroupFrame == aFrameType ||
-      nsGkAtoms::tableColGroupFrame == aFrameType ||
-      nsGkAtoms::tableRowFrame      == aFrameType ||
-      nsGkAtoms::tableColFrame      == aFrameType) {
+  if (FrameType::TableRowGroup == aFrameType ||
+      FrameType::TableColGroup == aFrameType ||
+      FrameType::TableRow      == aFrameType ||
+      FrameType::TableCol      == aFrameType) {
     ComputedPhysicalPadding().SizeTo(0,0,0,0);
   }
   else if (isCBDependent) {
     // We have to compute the value. This calculation is performed
     // according to the writing mode of the containing block
     // (http://dev.w3.org/csswg/css-writing-modes-3/#orthogonal-flows)
     // clamp negative calc() results to 0
     LogicalMargin p(aWM);
--- a/layout/generic/ReflowInput.h
+++ b/layout/generic/ReflowInput.h
@@ -288,23 +288,22 @@ private:
    *    The block size is usually the containing block inline-size, per
    *    CSS21 sec 8.3 (read in conjunction with CSS Writing Modes sec
    *    7.2), but may be the containing block block-size, e.g. in CSS3
    *    Flexbox and Grid.
    * @return true if the padding is dependent on the containing block size.
    */
   bool ComputePadding(mozilla::WritingMode aWM,
                       const mozilla::LogicalSize& aPercentBasis,
-                      nsIAtom* aFrameType);
+                      mozilla::FrameType aFrameType);
 
 protected:
-
   void InitOffsets(mozilla::WritingMode aWM,
                    const mozilla::LogicalSize& aPercentBasis,
-                   nsIAtom* aFrameType,
+                   mozilla::FrameType aFrameType,
                    ReflowInputFlags aFlags,
                    const nsMargin* aBorder = nullptr,
                    const nsMargin* aPadding = nullptr);
 
   /*
    * Convert nsStyleCoord to nscoord when percentages depend on the
    * inline size of the containing block, and enumerated values are for
    * inline size, min-inline-size, or max-inline-size.  Does not handle
@@ -961,25 +960,26 @@ public:
   static void* DisplayInitFrameTypeEnter(nsIFrame* aFrame,
                                          ReflowInput* aState);
   static void DisplayInitFrameTypeExit(nsIFrame* aFrame,
                                        ReflowInput* aState,
                                        void* aValue);
 #endif
 
 protected:
-  void InitFrameType(nsIAtom* aFrameType);
+  void InitFrameType(FrameType aFrameType);
   void InitCBReflowInput();
-  void InitResizeFlags(nsPresContext* aPresContext, nsIAtom* aFrameType);
+  void InitResizeFlags(nsPresContext* aPresContext,
+                       mozilla::FrameType aFrameType);
 
-  void InitConstraints(nsPresContext*              aPresContext,
+  void InitConstraints(nsPresContext* aPresContext,
                        const mozilla::LogicalSize& aContainingBlockSize,
-                       const nsMargin*             aBorder,
-                       const nsMargin*             aPadding,
-                       nsIAtom*                    aFrameType);
+                       const nsMargin* aBorder,
+                       const nsMargin* aPadding,
+                       mozilla::FrameType aFrameType);
 
   // Returns the nearest containing block or block frame (whether or not
   // it is a containing block) for the specified frame.  Also returns
   // the inline-start edge and logical size of the containing block's
   // content area.
   // These are returned in the coordinate space of the containing block.
   nsIFrame* GetHypotheticalBoxContainer(nsIFrame* aFrame,
                                         nscoord& aCBIStartEdge,
@@ -989,34 +989,34 @@ protected:
   // (for a position:fixed/absolute element) would have been placed if it were
   // positioned statically. The hypothetical box position will have a writing
   // mode with the same block direction as the absolute containing block
   // (cbrs->frame), though it may differ in inline direction.
   void CalculateHypotheticalPosition(nsPresContext* aPresContext,
                                      nsIFrame* aPlaceholderFrame,
                                      const ReflowInput* cbrs,
                                      nsHypotheticalPosition& aHypotheticalPos,
-                                     nsIAtom* aFrameType) const;
+                                     mozilla::FrameType aFrameType) const;
 
   void InitAbsoluteConstraints(nsPresContext* aPresContext,
                                const ReflowInput* cbrs,
                                const mozilla::LogicalSize& aContainingBlockSize,
-                               nsIAtom* aFrameType);
+                               mozilla::FrameType aFrameType);
 
   // Calculates the computed values for the 'min-Width', 'max-Width',
   // 'min-Height', and 'max-Height' properties, and stores them in the assorted
   // data members
   void ComputeMinMaxValues(const mozilla::LogicalSize& aContainingBlockSize);
 
   // aInsideBoxSizing returns the part of the padding, border, and margin
   // in the aAxis dimension that goes inside the edge given by box-sizing;
   // aOutsideBoxSizing returns the rest.
   void CalculateBorderPaddingMargin(mozilla::LogicalAxis aAxis,
                                     nscoord aContainingBlockSize,
                                     nscoord* aInsideBoxSizing,
                                     nscoord* aOutsideBoxSizing) const;
 
-  void CalculateBlockSideMargins(nsIAtom* aFrameType);
+  void CalculateBlockSideMargins(FrameType aFrameType);
 };
 
 } // namespace mozilla
 
 #endif // mozilla_ReflowInput_h
--- a/layout/generic/RubyUtils.cpp
+++ b/layout/generic/RubyUtils.cpp
@@ -35,17 +35,17 @@ RubyUtils::GetReservedISize(nsIFrame* aF
   MOZ_ASSERT(IsExpandableRubyBox(aFrame));
   return aFrame->Properties().Get(ReservedISize());
 }
 
 AutoRubyTextContainerArray::AutoRubyTextContainerArray(
   nsRubyBaseContainerFrame* aBaseContainer)
 {
   for (nsIFrame* frame = aBaseContainer->GetNextSibling();
-       frame && frame->GetType() == nsGkAtoms::rubyTextContainerFrame;
+       frame && frame->IsRubyTextContainerFrame();
        frame = frame->GetNextSibling()) {
     AppendElement(static_cast<nsRubyTextContainerFrame*>(frame));
   }
 }
 
 nsIFrame*
 RubyColumn::Iterator::operator*() const
 {
@@ -74,50 +74,49 @@ RubyColumn::Iterator::SkipUntilExistingF
       break;
     }
   }
 }
 
 RubySegmentEnumerator::RubySegmentEnumerator(nsRubyFrame* aRubyFrame)
 {
   nsIFrame* frame = aRubyFrame->PrincipalChildList().FirstChild();
-  MOZ_ASSERT(!frame ||
-             frame->GetType() == nsGkAtoms::rubyBaseContainerFrame);
+  MOZ_ASSERT(!frame || frame->IsRubyBaseContainerFrame());
   mBaseContainer = static_cast<nsRubyBaseContainerFrame*>(frame);
 }
 
 void
 RubySegmentEnumerator::Next()
 {
   MOZ_ASSERT(mBaseContainer);
   nsIFrame* frame = mBaseContainer->GetNextSibling();
-  while (frame && frame->GetType() != nsGkAtoms::rubyBaseContainerFrame) {
+  while (frame && !frame->IsRubyBaseContainerFrame()) {
     frame = frame->GetNextSibling();
   }
   mBaseContainer = static_cast<nsRubyBaseContainerFrame*>(frame);
 }
 
 RubyColumnEnumerator::RubyColumnEnumerator(
   nsRubyBaseContainerFrame* aBaseContainer,
   const AutoRubyTextContainerArray& aTextContainers)
   : mAtIntraLevelWhitespace(false)
 {
   const uint32_t rtcCount = aTextContainers.Length();
   mFrames.SetCapacity(rtcCount + 1);
 
   nsIFrame* rbFrame = aBaseContainer->PrincipalChildList().FirstChild();
-  MOZ_ASSERT(!rbFrame || rbFrame->GetType() == nsGkAtoms::rubyBaseFrame);
+  MOZ_ASSERT(!rbFrame || rbFrame->IsRubyBaseFrame());
   mFrames.AppendElement(static_cast<nsRubyContentFrame*>(rbFrame));
   for (uint32_t i = 0; i < rtcCount; i++) {
     nsRubyTextContainerFrame* container = aTextContainers[i];
     // If the container is for span, leave a nullptr here.
     // Spans do not take part in pairing.
     nsIFrame* rtFrame = !container->IsSpanContainer() ?
       container->PrincipalChildList().FirstChild() : nullptr;
-    MOZ_ASSERT(!rtFrame || rtFrame->GetType() == nsGkAtoms::rubyTextFrame);
+    MOZ_ASSERT(!rtFrame || rtFrame->IsRubyTextFrame());
     mFrames.AppendElement(static_cast<nsRubyContentFrame*>(rtFrame));
   }
 
   // We have to init mAtIntraLevelWhitespace to be correct for the
   // first column. There are two ways we could end up with intra-level
   // whitespace in our first colum:
   // 1. The current segment itself is an inter-segment whitespace;
   // 2. If our ruby segment is split across multiple lines, and some
@@ -143,17 +142,17 @@ RubyColumnEnumerator::Next()
     // If we've got intra-level whitespace frames at some levels in the
     // current ruby column, we "faked" an anonymous box for all other
     // levels for this column. So when we advance off this column, we
     // don't advance any of the frames in those levels, because we're
     // just advancing across the "fake" frames.
     if (frame && (!mAtIntraLevelWhitespace ||
                   frame->IsIntraLevelWhitespace())) {
       nsIFrame* nextSibling = frame->GetNextSibling();
-      MOZ_ASSERT(!nextSibling || nextSibling->GetType() == frame->GetType(),
+      MOZ_ASSERT(!nextSibling || nextSibling->Type() == frame->Type(),
                  "Frame type should be identical among a level");
       mFrames[i] = frame = static_cast<nsRubyContentFrame*>(nextSibling);
       if (!advancingToIntraLevelWhitespace &&
           frame && frame->IsIntraLevelWhitespace()) {
         advancingToIntraLevelWhitespace = true;
       }
     }
   }
@@ -186,18 +185,18 @@ RubyColumnEnumerator::GetFrameAtLevel(ui
   return !mAtIntraLevelWhitespace ||
          (frame && frame->IsIntraLevelWhitespace()) ? frame : nullptr;
 }
 
 void
 RubyColumnEnumerator::GetColumn(RubyColumn& aColumn) const
 {
   nsRubyContentFrame* rbFrame = GetFrameAtLevel(0);
-  MOZ_ASSERT(!rbFrame || rbFrame->GetType() == nsGkAtoms::rubyBaseFrame);
+  MOZ_ASSERT(!rbFrame || rbFrame->IsRubyBaseFrame());
   aColumn.mBaseFrame = static_cast<nsRubyBaseFrame*>(rbFrame);
   aColumn.mTextFrames.ClearAndRetainStorage();
   for (uint32_t i = 1, iend = mFrames.Length(); i < iend; i++) {
     nsRubyContentFrame* rtFrame = GetFrameAtLevel(i);
-    MOZ_ASSERT(!rtFrame || rtFrame->GetType() == nsGkAtoms::rubyTextFrame);
+    MOZ_ASSERT(!rtFrame || rtFrame->IsRubyTextFrame());
     aColumn.mTextFrames.AppendElement(static_cast<nsRubyTextFrame*>(rtFrame));
   }
   aColumn.mIsIntraLevelWhitespace = mAtIntraLevelWhitespace;
 }
--- a/layout/generic/RubyUtils.h
+++ b/layout/generic/RubyUtils.h
@@ -50,37 +50,37 @@ namespace mozilla {
  *    one of its ruby text containers does.
  * 3. If a ruby text container has a larger final isize, its children
  *    must not have.
  */
 
 class RubyUtils
 {
 public:
-  static inline bool IsRubyContentBox(nsIAtom* aFrameType)
+  static inline bool IsRubyContentBox(FrameType aFrameType)
   {
-    return aFrameType == nsGkAtoms::rubyBaseFrame ||
-           aFrameType == nsGkAtoms::rubyTextFrame;
+    return aFrameType == mozilla::FrameType::RubyBase ||
+           aFrameType == mozilla::FrameType::RubyText;
   }
 
-  static inline bool IsRubyContainerBox(nsIAtom* aFrameType)
+  static inline bool IsRubyContainerBox(FrameType aFrameType)
   {
-    return aFrameType == nsGkAtoms::rubyBaseContainerFrame ||
-           aFrameType == nsGkAtoms::rubyTextContainerFrame;
+    return aFrameType == mozilla::FrameType::RubyBaseContainer ||
+           aFrameType == mozilla::FrameType::RubyTextContainer;
   }
 
-  static inline bool IsRubyBox(nsIAtom* aFrameType)
+  static inline bool IsRubyBox(FrameType aFrameType)
   {
-    return aFrameType == nsGkAtoms::rubyFrame ||
-      IsRubyContentBox(aFrameType) || IsRubyContainerBox(aFrameType);
+    return aFrameType == mozilla::FrameType::Ruby ||
+           IsRubyContentBox(aFrameType) || IsRubyContainerBox(aFrameType);
   }
 
   static inline bool IsExpandableRubyBox(nsIFrame* aFrame)
   {
-    nsIAtom* type = aFrame->GetType();
+    mozilla::FrameType type = aFrame->Type();
     return IsRubyContentBox(type) || IsRubyContainerBox(type);
   }
 
   static inline bool IsRubyPseudo(nsIAtom* aPseudo)
   {
     return aPseudo == nsCSSAnonBoxes::ruby ||
            aPseudo == nsCSSAnonBoxes::rubyBase ||
            aPseudo == nsCSSAnonBoxes::rubyText ||
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -64,22 +64,22 @@ GetSelfOrNearestBlock(nsIFrame* aFrame)
   return nsLayoutUtils::GetAsBlock(aFrame) ? aFrame :
          nsLayoutUtils::FindNearestBlockAncestor(aFrame);
 }
 
 // Return true if the frame is an atomic inline-level element.
 // It's not supposed to be called for block frames since we never
 // process block descendants for text-overflow.
 static bool
-IsAtomicElement(nsIFrame* aFrame, const nsIAtom* aFrameType)
+IsAtomicElement(nsIFrame* aFrame, FrameType aFrameType)
 {
   NS_PRECONDITION(!nsLayoutUtils::GetAsBlock(aFrame) ||
                   !aFrame->IsBlockOutside(),
                   "unexpected block frame");
-  NS_PRECONDITION(aFrameType != nsGkAtoms::placeholderFrame,
+  NS_PRECONDITION(aFrameType != FrameType::Placeholder,
                   "unexpected placeholder frame");
   return !aFrame->IsFrameOfType(nsIFrame::eLineParticipant);
 }
 
 static bool
 IsFullyClipped(nsTextFrame* aFrame, nscoord aLeft, nscoord aRight,
                nscoord* aSnappedLeft, nscoord* aSnappedRight)
 {
@@ -94,18 +94,17 @@ IsFullyClipped(nsTextFrame* aFrame, nsco
 
 static bool
 IsInlineAxisOverflowVisible(nsIFrame* aFrame)
 {
   NS_PRECONDITION(nsLayoutUtils::GetAsBlock(aFrame) != nullptr,
                   "expected a block frame");
 
   nsIFrame* f = aFrame;
-  while (f && f->StyleContext()->GetPseudo() &&
-         f->GetType() != nsGkAtoms::scrollFrame) {
+  while (f && f->StyleContext()->GetPseudo() && !f->IsScrollFrame()) {
     f = f->GetParent();
   }
   if (!f) {
     return true;
   }
   auto overflow = aFrame->GetWritingMode().IsVertical() ?
     f->StyleDisplay()->mOverflowY : f->StyleDisplay()->mOverflowX;
   return overflow == NS_STYLE_OVERFLOW_VISIBLE;
@@ -343,19 +342,18 @@ void
 TextOverflow::ExamineFrameSubtree(nsIFrame*       aFrame,
                                   const LogicalRect& aContentArea,
                                   const LogicalRect& aInsideMarkersArea,
                                   FrameHashtable* aFramesToHide,
                                   AlignmentEdges* aAlignmentEdges,
                                   bool*           aFoundVisibleTextOrAtomic,
                                   InnerClipEdges* aClippedMarkerEdges)
 {
-  const nsIAtom* frameType = aFrame->GetType();
-  if (frameType == nsGkAtoms::brFrame ||
-      frameType == nsGkAtoms::placeholderFrame) {
+  const FrameType frameType = aFrame->Type();
+  if (frameType == FrameType::Br || frameType == FrameType::Placeholder) {
     return;
   }
   const bool isAtomic = IsAtomicElement(aFrame, frameType);
   if (aFrame->StyleVisibility()->IsVisible()) {
     LogicalRect childRect =
       GetLogicalScrollableOverflowRectRelativeToBlock(aFrame);
     bool overflowIStart =
       childRect.IStart(mBlockWM) < aContentArea.IStart(mBlockWM);
@@ -365,17 +363,17 @@ TextOverflow::ExamineFrameSubtree(nsIFra
       mIStart.mHasOverflow = true;
     }
     if (overflowIEnd) {
       mIEnd.mHasOverflow = true;
     }
     if (isAtomic && ((mIStart.mActive && overflowIStart) ||
                      (mIEnd.mActive && overflowIEnd))) {
       aFramesToHide->PutEntry(aFrame);
-    } else if (isAtomic || frameType == nsGkAtoms::textFrame) {
+    } else if (isAtomic || frameType == FrameType::Text) {
       AnalyzeMarkerEdges(aFrame, frameType, aInsideMarkersArea,
                          aFramesToHide, aAlignmentEdges,
                          aFoundVisibleTextOrAtomic,
                          aClippedMarkerEdges);
     }
   }
   if (isAtomic) {
     return;
@@ -385,22 +383,22 @@ TextOverflow::ExamineFrameSubtree(nsIFra
     ExamineFrameSubtree(child, aContentArea, aInsideMarkersArea,
                         aFramesToHide, aAlignmentEdges,
                         aFoundVisibleTextOrAtomic,
                         aClippedMarkerEdges);
   }
 }
 
 void
-TextOverflow::AnalyzeMarkerEdges(nsIFrame*       aFrame,
-                                 const nsIAtom*  aFrameType,
+TextOverflow::AnalyzeMarkerEdges(nsIFrame* aFrame,
+                                 FrameType aFrameType,
                                  const LogicalRect& aInsideMarkersArea,
                                  FrameHashtable* aFramesToHide,
                                  AlignmentEdges* aAlignmentEdges,
-                                 bool*           aFoundVisibleTextOrAtomic,
+                                 bool* aFoundVisibleTextOrAtomic,
                                  InnerClipEdges* aClippedMarkerEdges)
 {
   LogicalRect borderRect(mBlockWM,
                          nsRect(aFrame->GetOffsetTo(mBlock),
                                 aFrame->GetSize()),
                          mBlockSize);
   nscoord istartOverlap = std::max(
     aInsideMarkersArea.IStart(mBlockWM) - borderRect.IStart(mBlockWM), 0);
@@ -421,17 +419,17 @@ TextOverflow::AnalyzeMarkerEdges(nsIFram
     aClippedMarkerEdges->AccumulateIEnd(mBlockWM, borderRect);
     if (!mIEnd.mActive) {
       iendOverlap = 0;
     }
   }
 
   if ((istartOverlap > 0 && insideIStartEdge) ||
       (iendOverlap > 0 && insideIEndEdge)) {
-    if (aFrameType == nsGkAtoms::textFrame) {
+    if (aFrameType == FrameType::Text) {
       if (aInsideMarkersArea.IStart(mBlockWM) <
           aInsideMarkersArea.IEnd(mBlockWM)) {
         // a clipped text frame and there is some room between the markers
         nscoord snappedIStart, snappedIEnd;
         auto textFrame = static_cast<nsTextFrame*>(aFrame);
         bool isFullyClipped = mBlockWM.IsBidiLTR() ?
           IsFullyClipped(textFrame, istartOverlap, iendOverlap,
                          &snappedIStart, &snappedIEnd) :
@@ -756,17 +754,17 @@ TextOverflow::CanHaveTextOverflow(nsIFra
   // Nothing to do for text-overflow:clip or if 'overflow-x/y:visible'.
   if (HasClippedOverflow(aBlockFrame) ||
       IsInlineAxisOverflowVisible(aBlockFrame)) {
     return false;
   }
 
   // Skip ComboboxControlFrame because it would clip the drop-down arrow.
   // Its anon block inherits 'text-overflow' and does what is expected.
-  if (aBlockFrame->GetType() == nsGkAtoms::comboboxControlFrame) {
+  if (aBlockFrame->IsComboboxControlFrame()) {
     return false;
   }
 
   // Inhibit the markers if a descendant content owns the caret.
   RefPtr<nsCaret> caret = aBlockFrame->PresContext()->PresShell()->GetCaret();
   if (caret && caret->IsVisible()) {
     nsCOMPtr<nsISelection> domSelection = caret->GetSelection();
     if (domSelection) {
--- a/layout/generic/TextOverflow.h
+++ b/layout/generic/TextOverflow.h
@@ -169,22 +169,22 @@ class TextOverflow {
    * @param aAlignmentEdges the outermost edges of all text and atomic
    *   inline-level frames that are inside the area between the markers
    *                       inside aInsideMarkersArea
    * @param aFoundVisibleTextOrAtomic is set to true if a text or atomic
    *   inline-level frame is visible between the marker edges
    * @param aClippedMarkerEdges the innermost edges of all text and atomic
    *   inline-level frames that are clipped by the current marker width
    */
-  void AnalyzeMarkerEdges(nsIFrame*       aFrame,
-                          const nsIAtom*  aFrameType,
+  void AnalyzeMarkerEdges(nsIFrame* aFrame,
+                          mozilla::FrameType aFrameType,
                           const LogicalRect& aInsideMarkersArea,
                           FrameHashtable* aFramesToHide,
                           AlignmentEdges* aAlignmentEdges,
-                          bool*           aFoundVisibleTextOrAtomic,
+                          bool* aFoundVisibleTextOrAtomic,
                           InnerClipEdges* aClippedMarkerEdges);
 
   /**
    * Clip or remove items given the final marker edges. ("clip" here just means
    * assigning mVisIStartEdge/mVisIEndEdge for any nsCharClipDisplayItem that
    * needs it; see nsDisplayList.h for a description of that item).
    * @param aFramesToHide remove display items for these frames
    * @param aInsideMarkersArea is the area inside the markers
--- a/layout/generic/ViewportFrame.cpp
+++ b/layout/generic/ViewportFrame.cpp
@@ -156,17 +156,17 @@ ViewportFrame::BuildDisplayListForTopLay
       // be handled as top layer element here.
       if (!(frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
         MOZ_ASSERT(!elem->GetParent()->IsHTMLElement(), "HTML element "
                    "should always be out-of-flow if in the top layer");
         continue;
       }
       if (nsIFrame* backdropPh =
           frame->GetChildList(kBackdropList).FirstChild()) {
-        MOZ_ASSERT(backdropPh->GetType() == nsGkAtoms::placeholderFrame);
+        MOZ_ASSERT(backdropPh->IsPlaceholderFrame());
         nsIFrame* backdropFrame =
           static_cast<nsPlaceholderFrame*>(backdropPh)->GetOutOfFlowFrame();
         MOZ_ASSERT(backdropFrame);
         BuildDisplayListForTopLayerFrame(aBuilder, backdropFrame, aList);
       }
       BuildDisplayListForTopLayerFrame(aBuilder, frame, aList);
     }
   }
@@ -410,21 +410,15 @@ ViewportFrame::ComputeCustomOverflow(nsO
     PresContext()->PresShell()->GetRootScrollFrameAsScrollable();
   if (rootScrollFrame && !rootScrollFrame->IsIgnoringViewportClipping()) {
     return false;
   }
 
   return nsContainerFrame::ComputeCustomOverflow(aOverflowAreas);
 }
 
-nsIAtom*
-ViewportFrame::GetType() const
-{
-  return nsGkAtoms::viewportFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 ViewportFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Viewport"), aResult);
 }
 #endif
--- a/layout/generic/ViewportFrame.h
+++ b/layout/generic/ViewportFrame.h
@@ -25,19 +25,19 @@ namespace mozilla {
   */
 class ViewportFrame : public nsContainerFrame {
 public:
   NS_DECL_QUERYFRAME_TARGET(ViewportFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   explicit ViewportFrame(nsStyleContext* aContext)
-    : nsContainerFrame(aContext)
-    , mView(nullptr)
+    : ViewportFrame(aContext, mozilla::FrameType::Viewport)
   {}
+
   virtual ~ViewportFrame() { } // useful for debugging
 
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 
 #ifdef DEBUG
   virtual void AppendFrames(ChildListID     aListID,
@@ -53,43 +53,41 @@ public:
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
   void BuildDisplayListForTopLayer(nsDisplayListBuilder* aBuilder,
                                    nsDisplayList* aList);
 
   virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
   virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
-  virtual void Reflow(nsPresContext*           aPresContext,
-                      ReflowOutput&     aDesiredSize,
+  virtual void Reflow(nsPresContext* aPresContext,
+                      ReflowOutput& aDesiredSize,
                       const ReflowInput& aReflowInput,
-                      nsReflowStatus&          aStatus) override;
-
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::viewportFrame
-   */
-  virtual nsIAtom* GetType() const override;
+                      nsReflowStatus& aStatus) override;
 
   virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override;
 
   /**
    * Adjust aReflowInput to account for scrollbars and pres shell
    * GetScrollPositionClampingScrollPortSizeSet and
    * GetContentDocumentFixedPositionMargins adjustments.
    * @return the rect to use as containing block rect
    */
   nsRect AdjustReflowInputAsContainingBlock(ReflowInput* aReflowInput) const;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
 protected:
+  ViewportFrame(nsStyleContext* aContext, mozilla::FrameType aType)
+    : nsContainerFrame(aContext, aType)
+    , mView(nullptr)
+  {}
+
   /**
    * Calculate how much room is available for fixed frames. That means
    * determining if the viewport is scrollable and whether the vertical and/or
    * horizontal scrollbars are visible.  Adjust the computed width/height and
    * available width for aReflowInput accordingly.
    * @return the current scroll position, or 0,0 if not scrollable
    */
   nsPoint AdjustReflowInputForScrollbars(ReflowInput* aReflowInput) const;
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -106,16 +106,17 @@ EXPORTS += [
     'ScrollbarActivity.h',
     'ScrollSnap.h',
     'Visibility.h',
 ]
 
 EXPORTS.mozilla += [
     'CSSAlignUtils.h',
     'CSSOrderAwareFrameIterator.h',
+    'FrameTypeList.h',
     'ReflowInput.h',
     'ReflowOutput.h',
     'ViewportFrame.h',
     'WritingModes.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'Selection.h',
--- a/layout/generic/nsAbsoluteContainingBlock.cpp
+++ b/layout/generic/nsAbsoluteContainingBlock.cpp
@@ -420,25 +420,25 @@ OffsetToAlignedStaticPos(const ReflowInp
   WritingMode pcWM = aPlaceholderContainer->GetWritingMode();
 
   // Find what axis aAbsPosCBAxis corresponds to, in placeholder's parent's
   // writing-mode.
   LogicalAxis pcAxis = (pcWM.IsOrthogonalTo(aAbsPosCBWM)
                         ? GetOrthogonalAxis(aAbsPosCBAxis)
                         : aAbsPosCBAxis);
 
-  nsIAtom* parentType = aPlaceholderContainer->GetType();
+  FrameType parentType = aPlaceholderContainer->Type();
   LogicalSize alignAreaSize(pcWM);
-  if (parentType == nsGkAtoms::flexContainerFrame) {
+  if (parentType == FrameType::FlexContainer) {
     // The alignment container is the flex container's content box:
     alignAreaSize = aPlaceholderContainer->GetLogicalSize(pcWM);
     LogicalMargin pcBorderPadding =
       aPlaceholderContainer->GetLogicalUsedBorderAndPadding(pcWM);
     alignAreaSize -= pcBorderPadding.Size(pcWM);
-  } else if (parentType == nsGkAtoms::gridContainerFrame) {
+  } else if (parentType == FrameType::GridContainer) {
     // This abspos elem's parent is a grid container. Per CSS Grid 10.1 & 10.2:
     //  - If the grid container *also* generates the abspos containing block (a
     // grid area) for this abspos child, we use that abspos containing block as
     // the alignment container, too. (And its size is aAbsPosCBSize.)
     //  - Otherwise, we use the grid's padding box as the alignment container.
     // https://drafts.csswg.org/css-grid/#static-position
     if (aPlaceholderContainer == aKidReflowInput.mCBReflowInput->mFrame) {
       // The alignment container is the grid area that we're using as the
@@ -681,17 +681,17 @@ nsAbsoluteContainingBlock::ReflowAbsolut
   }
   if (kidReflowInput.mFlags.mBOffsetsNeedCSSAlign) {
     margin.BStart(outerWM) = margin.BEnd(outerWM) = 0;
   }
 
   bool constrainBSize = (aReflowInput.AvailableBSize() != NS_UNCONSTRAINEDSIZE)
     && (aFlags & AbsPosReflowFlags::eConstrainHeight)
        // Don't split if told not to (e.g. for fixed frames)
-    && (aDelegatingFrame->GetType() != nsGkAtoms::inlineFrame)
+    && !aDelegatingFrame->IsInlineFrame()
        //XXX we don't handle splitting frames for inline absolute containing blocks yet
     && (aKidFrame->GetLogicalRect(aContainingBlock.Size()).BStart(wm) <=
         aReflowInput.AvailableBSize());
        // Don't split things below the fold. (Ideally we shouldn't *have*
        // anything totally below the fold, but we can't position frames
        // across next-in-flow breaks yet.
   if (constrainBSize) {
     kidReflowInput.AvailableBSize() =
--- a/layout/generic/nsAtomicContainerFrame.h
+++ b/layout/generic/nsAtomicContainerFrame.h
@@ -35,13 +35,14 @@ public:
     return nsFrame::PeekOffsetCharacter(aForward, aOffset, aRespectClusters);
   }
   nsSplittableType GetSplittableType() const override
   {
     return nsFrame::GetSplittableType();
   }
 
 protected:
-  explicit nsAtomicContainerFrame(nsStyleContext* aContext)
-    : nsContainerFrame(aContext) {}
+  nsAtomicContainerFrame(nsStyleContext* aContext, mozilla::FrameType aType)
+    : nsContainerFrame(aContext, aType)
+  {}
 };
 
 #endif // nsAtomicContainerFrame_h___
--- a/layout/generic/nsBackdropFrame.cpp
+++ b/layout/generic/nsBackdropFrame.cpp
@@ -9,22 +9,16 @@
 #include "nsBackdropFrame.h"
 
 #include "nsDisplayList.h"
 
 using namespace mozilla;
 
 NS_IMPL_FRAMEARENA_HELPERS(nsBackdropFrame)
 
-/* virtual */ nsIAtom*
-nsBackdropFrame::GetType() const
-{
-  return nsGkAtoms::backdropFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsBackdropFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Backdrop"), aResult);
 }
 #endif
 
--- a/layout/generic/nsBackdropFrame.h
+++ b/layout/generic/nsBackdropFrame.h
@@ -12,20 +12,19 @@
 #include "nsFrame.h"
 
 class nsBackdropFrame final : public nsFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   explicit nsBackdropFrame(nsStyleContext* aContext)
-    : nsFrame(aContext) { }
+    : nsFrame(aContext, mozilla::FrameType::Backdrop)
+  {}
 
-  // nsIFrame overrides
-  virtual nsIAtom* GetType() const override;
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
   virtual nsStyleContext*
     GetParentStyleContext(nsIFrame** aProviderFrame) const override;
   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
                                 const nsRect& aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -455,39 +455,33 @@ nsFrameState
 nsBlockFrame::GetDebugStateBits() const
 {
   // We don't want to include our cursor flag in the bits the
   // regression tester looks at
   return nsContainerFrame::GetDebugStateBits() & ~NS_BLOCK_HAS_LINE_CURSOR;
 }
 #endif
 
-nsIAtom*
-nsBlockFrame::GetType() const
-{
-  return nsGkAtoms::blockFrame;
-}
-
 void
 nsBlockFrame::InvalidateFrame(uint32_t aDisplayItemKey)
 {
   if (nsSVGUtils::IsInSVGTextSubtree(this)) {
-    NS_ASSERTION(GetParent()->GetType() == nsGkAtoms::svgTextFrame,
+    NS_ASSERTION(GetParent()->IsSVGTextFrame(),
                  "unexpected block frame in SVG text");
     GetParent()->InvalidateFrame();
     return;
   }
   nsContainerFrame::InvalidateFrame(aDisplayItemKey);
 }
 
 void
 nsBlockFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
 {
   if (nsSVGUtils::IsInSVGTextSubtree(this)) {
-    NS_ASSERTION(GetParent()->GetType() == nsGkAtoms::svgTextFrame,
+    NS_ASSERTION(GetParent()->IsSVGTextFrame(),
                  "unexpected block frame in SVG text");
     GetParent()->InvalidateFrame();
     return;
   }
   nsContainerFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
 }
 
 nscoord
@@ -1016,34 +1010,34 @@ CalculateContainingBlockSizeForAbsolutes
     // Containing block is relative to the padding edge
   const LogicalMargin& border =
     LogicalMargin(aWM, aReflowInput.ComputedPhysicalBorderPadding() -
                        aReflowInput.ComputedPhysicalPadding());
   cbSize.ISize(aWM) -= border.IStartEnd(aWM);
   cbSize.BSize(aWM) -= border.BStartEnd(aWM);
 
   if (frame->GetParent()->GetContent() == frame->GetContent() &&
-      frame->GetParent()->GetType() != nsGkAtoms::canvasFrame) {
+      !frame->GetParent()->IsCanvasFrame()) {
     // We are a wrapped frame for the content (and the wrapper is not the
     // canvas frame, whose size is not meaningful here).
     // Use the container's dimensions, if they have been precomputed.
     // XXX This is a hack! We really should be waiting until the outermost
     // frame is fully reflowed and using the resulting dimensions, even
     // if they're intrinsic.
     // In fact we should be attaching absolute children to the outermost
     // frame and not always sticking them in block frames.
 
     // First, find the reflow state for the outermost frame for this
     // content, except for fieldsets where the inner anonymous frame has
     // the correct padding area with the legend taken into account.
     const ReflowInput* aLastRI = &aReflowInput;
     const ReflowInput* lastButOneRI = &aReflowInput;
     while (aLastRI->mParentReflowInput &&
            aLastRI->mParentReflowInput->mFrame->GetContent() == frame->GetContent() &&
-           aLastRI->mParentReflowInput->mFrame->GetType() != nsGkAtoms::fieldSetFrame) {
+           !aLastRI->mParentReflowInput->mFrame->IsFieldSetFrame()) {
       lastButOneRI = aLastRI;
       aLastRI = aLastRI->mParentReflowInput;
     }
     if (aLastRI != &aReflowInput) {
       // Scrollbars need to be specifically excluded, if present, because they are outside the
       // padding-edge. We need better APIs for getting the various boxes from a frame.
       nsIScrollableFrame* scrollFrame = do_QueryFrame(aLastRI->mFrame);
       nsMargin scrollbars(0,0,0,0);
@@ -1653,17 +1647,17 @@ nsBlockFrame::ComputeFinalSize(const Ref
     // block-end margin of any floated elements; e.g., inside a table cell.
     nscoord floatHeight =
       aState.ClearFloats(blockEndEdgeOfChildren, StyleClear::Both,
                          nullptr, nsFloatManager::DONT_CLEAR_PUSHED_FLOATS);
     blockEndEdgeOfChildren = std::max(blockEndEdgeOfChildren, floatHeight);
   }
 
   if (NS_UNCONSTRAINEDSIZE != aReflowInput.ComputedBSize()
-      && (GetParent()->GetType() != nsGkAtoms::columnSetFrame ||
+      && (!GetParent()->IsColumnSetFrame() ||
           aReflowInput.mParentReflowInput->AvailableBSize() == NS_UNCONSTRAINEDSIZE)) {
     ComputeFinalBSize(aReflowInput, &aState.mReflowStatus,
                       aState.mBCoord + nonCarriedOutBDirMargin,
                       borderPadding, finalSize, aState.mConsumedBSize);
     if (!aState.mReflowStatus.IsComplete()) {
       // Use the current height; continuations will take up the rest.
       // Do extend the height to at least consume the available
       // height, otherwise our left/right borders (for example) won't
@@ -3081,20 +3075,20 @@ nsBlockFrame::AttributeChanged(int32_t  
     const nsStyleDisplay* styleDisplay = StyleDisplay();
     if (mozilla::StyleDisplay::ListItem == styleDisplay->mDisplay) {
       // Search for the closest ancestor that's a block frame. We
       // make the assumption that all related list items share a
       // common block/grid/flex ancestor.
       // XXXldb I think that's a bad assumption.
       nsContainerFrame* ancestor = GetParent();
       for (; ancestor; ancestor = ancestor->GetParent()) {
-        auto frameType = ancestor->GetType();
-        if (frameType == nsGkAtoms::blockFrame ||
-            frameType == nsGkAtoms::flexContainerFrame ||
-            frameType == nsGkAtoms::gridContainerFrame) {
+        auto frameType = ancestor->Type();
+        if (frameType == FrameType::Block ||
+            frameType == FrameType::FlexContainer ||
+            frameType == FrameType::GridContainer) {
           break;
         }
       }
       // Tell the ancestor to renumber list items within itself.
       if (ancestor) {
         // XXX Not sure if this is necessary anymore
         if (ancestor->RenumberList()) {
           PresContext()->PresShell()->
@@ -4319,17 +4313,17 @@ nsBlockFrame::ReflowInlineFrame(BlockRef
     if (!aLineLayout.GetLineEndsInBR()) {
       aLine->SetLineWrapped(true);
     }
 
     // If we just ended a first-letter frame or reflowed a placeholder then
     // don't split the line and don't stop the line reflow...
     // But if we are going to stop anyways we'd better split the line.
     if ((!frameReflowStatus.FirstLetterComplete() &&
-         nsGkAtoms::placeholderFrame != aFrame->GetType()) ||
+         !aFrame->IsPlaceholderFrame()) ||
         *aLineReflowStatus == LineReflowStatus::Stop) {
       // Split line after the current frame
       *aLineReflowStatus = LineReflowStatus::Stop;
       SplitLine(aState, aLineLayout, aLine, aFrame->GetNextSibling(), aLineReflowStatus);
     }
   }
 }
 
@@ -5162,18 +5156,17 @@ nsBlockFrame::SetOverflowOutOfFlows(cons
 nsBulletFrame*
 nsBlockFrame::GetInsideBullet() const
 {
   if (!HasInsideBullet()) {
     return nullptr;
   }
   NS_ASSERTION(!HasOutsideBullet(), "invalid bullet state");
   nsBulletFrame* frame = Properties().Get(InsideBulletProperty());
-  NS_ASSERTION(frame && frame->GetType() == nsGkAtoms::bulletFrame,
-               "bogus inside bullet frame");
+  NS_ASSERTION(frame && frame->IsBulletFrame(), "bogus inside bullet frame");
   return frame;
 }
 
 nsBulletFrame*
 nsBlockFrame::GetOutsideBullet() const
 {
   nsFrameList* list = GetOutsideBulletList();
   return list ? static_cast<nsBulletFrame*>(list->FirstChild())
@@ -5185,17 +5178,17 @@ nsBlockFrame::GetOutsideBulletList() con
 {
   if (!HasOutsideBullet()) {
     return nullptr;
   }
   NS_ASSERTION(!HasInsideBullet(), "invalid bullet state");
   nsFrameList* list =
     Properties().Get(OutsideBulletProperty());
   NS_ASSERTION(list && list->GetLength() == 1 &&
-               list->FirstChild()->GetType() == nsGkAtoms::bulletFrame,
+               list->FirstChild()->IsBulletFrame(),
                "bogus outside bullet list");
   return list;
 }
 
 nsFrameList*
 nsBlockFrame::GetPushedFloats() const
 {
   if (!HasPushedFloats()) {
@@ -5355,22 +5348,22 @@ nsBlockFrame::RemoveFrame(ChildListID aL
   PresContext()->PresShell()->
     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                      NS_FRAME_HAS_DIRTY_CHILDREN); // XXX sufficient?
 }
 
 static bool
 ShouldPutNextSiblingOnNewLine(nsIFrame* aLastFrame)
 {
-  nsIAtom* type = aLastFrame->GetType();
-  if (type == nsGkAtoms::brFrame) {
+  FrameType type = aLastFrame->Type();
+  if (type == FrameType::Br) {
     return true;
   }
   // XXX the TEXT_OFFSETS_NEED_FIXING check is a wallpaper for bug 822910.
-  if (type == nsGkAtoms::textFrame &&
+  if (type == FrameType::Text &&
       !(aLastFrame->GetStateBits() & TEXT_OFFSETS_NEED_FIXING)) {
     return aLastFrame->HasSignificantTerminalNewline();
   }
   return false;
 }
 
 void
 nsBlockFrame::AddFrames(nsFrameList& aFrameList, nsIFrame* aPrevSibling)
@@ -5455,17 +5448,17 @@ nsBlockFrame::AddFrames(nsFrameList& aFr
     frames->InsertFrames(nullptr, aPrevSibling, aFrameList);
 
   // Walk through the new frames being added and update the line data
   // structures to fit.
   for (nsFrameList::Enumerator e(newFrames); !e.AtEnd(); e.Next()) {
     nsIFrame* newFrame = e.get();
     NS_ASSERTION(!aPrevSibling || aPrevSibling->GetNextSibling() == newFrame,
                  "Unexpected aPrevSibling");
-    NS_ASSERTION(newFrame->GetType() != nsGkAtoms::placeholderFrame ||
+    NS_ASSERTION(!newFrame->IsPlaceholderFrame() ||
                  (!newFrame->IsAbsolutelyPositioned() &&
                   !newFrame->IsFloating()),
                  "Placeholders should not float or be positioned");
 
     bool isBlock = newFrame->IsBlockOutside();
 
     // If the frame is a block frame, or if there is no previous line or if the
     // previous line is a block line we need to make a new line.  We also make
@@ -6233,17 +6226,17 @@ nsBlockFrame::AdjustFloatAvailableSpace(
   }
 
   nscoord availBSize = NS_UNCONSTRAINEDSIZE == aState.ContentBSize()
                        ? NS_UNCONSTRAINEDSIZE
                        : std::max(0, aState.ContentBEnd() - aState.mBCoord);
 
   if (availBSize != NS_UNCONSTRAINEDSIZE &&
       !aState.mFlags.mFloatFragmentsInsideColumnEnabled &&
-      nsLayoutUtils::GetClosestFrameOfType(this, nsGkAtoms::columnSetFrame)) {
+      nsLayoutUtils::GetClosestFrameOfType(this, FrameType::ColumnSet)) {
     // Tell the float it has unrestricted block-size, so it won't break.
     // If the float doesn't actually fit in the column it will fail to be
     // placed, and either move to the block-start of the next column or just
     // overflow.
     availBSize = NS_UNCONSTRAINEDSIZE;
   }
 
   return LogicalRect(wm, aState.ContentIStart(), aState.ContentBStart(),
@@ -6352,17 +6345,17 @@ nsBlockFrame::ReflowFloat(BlockReflowInp
     // if the height is constrained (bug 145305).
     aReflowStatus.Reset();
   }
 
   if (aReflowStatus.NextInFlowNeedsReflow()) {
     aState.mReflowStatus.SetNextInFlowNeedsReflow();
   }
 
-  if (aFloat->GetType() == nsGkAtoms::letterFrame) {
+  if (aFloat->IsLetterFrame()) {
     // We never split floating first letters; an incomplete state for
     // such frames simply means that there is more content to be
     // reflowed on the line.
     if (aReflowStatus.IsIncomplete())
       aReflowStatus.Reset();
   }
 
   // Capture the margin and offsets information for the caller
@@ -7021,19 +7014,19 @@ nsBlockFrame::SetInitialChildList(ChildL
     bool haveFirstLetterStyle =
       (!pseudo ||
        (pseudo == nsCSSAnonBoxes::cellContent &&
         GetParent()->StyleContext()->GetPseudo() == nullptr) ||
        pseudo == nsCSSAnonBoxes::fieldsetContent ||
        pseudo == nsCSSAnonBoxes::buttonContent ||
        pseudo == nsCSSAnonBoxes::columnContent ||
        (pseudo == nsCSSAnonBoxes::scrolledContent &&
-        GetParent()->GetType() != nsGkAtoms::listControlFrame) ||
+        !GetParent()->IsListControlFrame()) ||
        pseudo == nsCSSAnonBoxes::mozSVGText) &&
-      GetType() != nsGkAtoms::comboboxControlFrame &&
+      !IsComboboxControlFrame() &&
       !IsFrameOfType(eMathML) &&
       RefPtr<nsStyleContext>(GetFirstLetterStyle(PresContext())) != nullptr;
     NS_ASSERTION(haveFirstLetterStyle ==
                  ((mState & NS_BLOCK_HAS_FIRST_LETTER_STYLE) != 0),
                  "NS_BLOCK_HAS_FIRST_LETTER_STYLE state out of sync");
 #endif
 
     AddFrames(aChildList, nullptr);
@@ -7255,19 +7248,20 @@ nsBlockFrame::ReflowBullet(nsIFrame* aBu
 // are ignored (they are not added to aList).
 void
 nsBlockFrame::DoCollectFloats(nsIFrame* aFrame, nsFrameList& aList,
                               bool aCollectSiblings)
 {
   while (aFrame) {
     // Don't descend into float containing blocks.
     if (!aFrame->IsFloatContainingBlock()) {
-      nsIFrame *outOfFlowFrame =
-        aFrame->GetType() == nsGkAtoms::placeholderFrame ?
-          nsLayoutUtils::GetFloatFromPlaceholder(aFrame) : nullptr;
+      nsIFrame* outOfFlowFrame =
+        aFrame->IsPlaceholderFrame()
+          ? nsLayoutUtils::GetFloatFromPlaceholder(aFrame)
+          : nullptr;
       while (outOfFlowFrame && outOfFlowFrame->GetParent() == this) {
         RemoveFloat(outOfFlowFrame);
         // Remove the IS_PUSHED_FLOAT bit, in case |outOfFlowFrame| came from
         // the PushedFloats list.
         outOfFlowFrame->RemoveStateBits(NS_FRAME_IS_PUSHED_FLOAT);
         aList.AppendFrame(nullptr, outOfFlowFrame);
         outOfFlowFrame = outOfFlowFrame->GetNextInFlow();
         // FIXME: By not pulling floats whose parent is one of our
@@ -7358,17 +7352,17 @@ nsBlockFrame::IsMarginRoot(bool* aBStart
 {
   if (!(GetStateBits() & NS_BLOCK_MARGIN_ROOT)) {
     nsIFrame* parent = GetParent();
     if (!parent || parent->IsFloatContainingBlock()) {
       *aBStartMarginRoot = false;
       *aBEndMarginRoot = false;
       return;
     }
-    if (parent->GetType() == nsGkAtoms::columnSetFrame) {
+    if (parent->IsColumnSetFrame()) {
       *aBStartMarginRoot = GetPrevInFlow() == nullptr;
       *aBEndMarginRoot = GetNextInFlow() == nullptr;
       return;
     }
   }
 
   *aBStartMarginRoot = true;
   *aBEndMarginRoot = true;
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -136,17 +136,16 @@ public:
                                  nscoord*             aBaseline) const override;
   nscoord GetCaretBaseline() const override;
   void DestroyFrom(nsIFrame* aDestructRoot) override;
   nsSplittableType GetSplittableType() const override;
   bool IsFloatContainingBlock() const override;
   void BuildDisplayList(nsDisplayListBuilder* aBuilder,
                         const nsRect& aDirtyRect,
                         const nsDisplayListSet& aLists) override;
-  nsIAtom* GetType() const override;
   bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsContainerFrame::IsFrameOfType(aFlags &
              ~(nsIFrame::eCanContainOverflowContainers |
                nsIFrame::eBlockFrame));
   }
 
   void InvalidateFrame(uint32_t aDisplayItemKey = 0) override;
@@ -393,25 +392,30 @@ public:
   static nsBlockFrame* GetNearestAncestorBlock(nsIFrame* aCandidate);
 
   struct FrameLines {
     nsLineList mLines;
     nsFrameList mFrames;
   };
 
 protected:
-  explicit nsBlockFrame(nsStyleContext* aContext)
-    : nsContainerFrame(aContext)
+  nsBlockFrame(nsStyleContext* aContext, mozilla::FrameType aType)
+    : nsContainerFrame(aContext, aType)
     , mMinWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
     , mPrefWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
   {
 #ifdef DEBUG
   InitDebugFlags();
 #endif
   }
+
+  explicit nsBlockFrame(nsStyleContext* aContext)
+    : nsBlockFrame(aContext, mozilla::FrameType::Block)
+  {}
+
   virtual ~nsBlockFrame();
 
 #ifdef DEBUG
   already_AddRefed<nsStyleContext> GetFirstLetterStyle(nsPresContext* aPresContext);
 #endif
 
   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(LineCursorProperty, nsLineBox)
   bool HasLineCursor() { return GetStateBits() & NS_BLOCK_HAS_LINE_CURSOR; }
--- a/layout/generic/nsBlockReflowContext.cpp
+++ b/layout/generic/nsBlockReflowContext.cpp
@@ -33,18 +33,18 @@ nsBlockReflowContext::nsBlockReflowConte
     mOuterReflowInput(aParentRS),
     mSpace(aParentRS.GetWritingMode()),
     mMetrics(aParentRS)
 {
 }
 
 static nsIFrame* DescendIntoBlockLevelFrame(nsIFrame* aFrame)
 {
-  nsIAtom* type = aFrame->GetType();
-  if (type == nsGkAtoms::columnSetFrame) {
+  FrameType type = aFrame->Type();
+  if (type == FrameType::ColumnSet) {
     static_cast<nsColumnSetFrame*>(aFrame)->DrainOverflowColumns();
     nsIFrame* child = aFrame->PrincipalChildList().FirstChild();
     if (child) {
       return DescendIntoBlockLevelFrame(child);
     }
   }
   return aFrame;
 }
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -80,22 +80,16 @@ nsBulletFrame::DestroyFrom(nsIFrame* aDe
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsBulletFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Bullet"), aResult);
 }
 #endif
 
-nsIAtom*
-nsBulletFrame::GetType() const
-{
-  return nsGkAtoms::bulletFrame;
-}
-
 bool
 nsBulletFrame::IsEmpty()
 {
   return IsSelfEmpty();
 }
 
 bool
 nsBulletFrame::IsSelfEmpty()
--- a/layout/generic/nsBulletFrame.h
+++ b/layout/generic/nsBulletFrame.h
@@ -49,35 +49,35 @@ class nsBulletFrame final : public nsFra
 public:
   NS_DECL_FRAMEARENA_HELPERS
 #ifdef DEBUG
   NS_DECL_QUERYFRAME_TARGET(nsBulletFrame)
   NS_DECL_QUERYFRAME
 #endif
 
   explicit nsBulletFrame(nsStyleContext* aContext)
-    : nsFrame(aContext)
+    : nsFrame(aContext, mozilla::FrameType::Bullet)
     , mPadding(GetWritingMode())
     , mIntrinsicSize(GetWritingMode())
     , mOrdinal(0)
     , mRequestRegistered(false)
     , mBlockingOnload(false)
-  { }
+  {}
+
   virtual ~nsBulletFrame();
 
   NS_IMETHOD Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData);
   NS_IMETHOD BlockOnload(imgIRequest* aRequest);
   NS_IMETHOD UnblockOnload(imgIRequest* aRequest);
 
   // nsIFrame
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
-  virtual nsIAtom* GetType() const override;
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) override;
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   virtual void Reflow(nsPresContext* aPresContext,
                       ReflowOutput& aMetrics,
                       const ReflowInput& aReflowInput,
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -802,25 +802,18 @@ nsCanvasFrame::Reflow(nsPresContext*    
   }
 
   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowInput, aStatus);
 
   NS_FRAME_TRACE_REFLOW_OUT("nsCanvasFrame::Reflow", aStatus);
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
-nsIAtom*
-nsCanvasFrame::GetType() const
-{
-  return nsGkAtoms::canvasFrame;
-}
-
-nsresult 
-nsCanvasFrame::GetContentForEvent(WidgetEvent* aEvent,
-                                  nsIContent** aContent)
+nsresult
+nsCanvasFrame::GetContentForEvent(WidgetEvent* aEvent, nsIContent** aContent)
 {
   NS_ENSURE_ARG_POINTER(aContent);
   nsresult rv = nsFrame::GetContentForEvent(aEvent,
                                             aContent);
   if (NS_FAILED(rv) || !*aContent) {
     nsIFrame* kid = mFrames.FirstChild();
     if (kid) {
       rv = kid->GetContentForEvent(aEvent,
--- a/layout/generic/nsCanvasFrame.h
+++ b/layout/generic/nsCanvasFrame.h
@@ -29,19 +29,20 @@ class nsRenderingContext;
  * frame in the main child list.
  */
 class nsCanvasFrame final : public nsContainerFrame,
                             public nsIScrollPositionListener,
                             public nsIAnonymousContentCreator
 {
 public:
   explicit nsCanvasFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext),
-    mDoPaintFocus(false),
-    mAddedScrollPositionListener(false) {}
+    : nsContainerFrame(aContext, mozilla::FrameType::Canvas)
+    , mDoPaintFocus(false)
+    , mAddedScrollPositionListener(false)
+  {}
 
   NS_DECL_QUERYFRAME_TARGET(nsCanvasFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
@@ -100,23 +101,16 @@ public:
                                 const nsDisplayListSet& aLists) override;
 
   void PaintFocus(mozilla::gfx::DrawTarget* aRenderingContext, nsPoint aPt);
 
   // nsIScrollPositionListener
   virtual void ScrollPositionWillChange(nscoord aX, nscoord aY) override;
   virtual void ScrollPositionDidChange(nscoord aX, nscoord aY) override {}
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::canvasFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
   virtual nsresult GetContentForEvent(mozilla::WidgetEvent* aEvent,
                                       nsIContent** aContent) override;
 
   nsRect CanvasArea() const;
 
--- a/layout/generic/nsColumnSetFrame.cpp
+++ b/layout/generic/nsColumnSetFrame.cpp
@@ -124,27 +124,21 @@ NS_NewColumnSetFrame(nsIPresShell* aPres
   nsColumnSetFrame* it = new (aPresShell) nsColumnSetFrame(aContext);
   it->AddStateBits(aStateFlags | NS_BLOCK_MARGIN_ROOT);
   return it;
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsColumnSetFrame)
 
 nsColumnSetFrame::nsColumnSetFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::ColumnSet)
   , mLastBalanceBSize(NS_INTRINSICSIZE)
 {
 }
 
-nsIAtom*
-nsColumnSetFrame::GetType() const
-{
-  return nsGkAtoms::columnSetFrame;
-}
-
 void
 nsColumnSetFrame::CreateBorderRenderers(nsTArray<nsCSSBorderRenderer>& aBorderRenderers,
                                         nsRenderingContext* aCtx,
                                         const nsRect& aDirtyRect,
                                         const nsPoint& aPt)
 {
   nsIFrame* child = mFrames.FirstChild();
   if (!child)
--- a/layout/generic/nsColumnSetFrame.h
+++ b/layout/generic/nsColumnSetFrame.h
@@ -65,18 +65,16 @@ public:
      return nsContainerFrame::IsFrameOfType(aFlags &
               ~(nsIFrame::eCanContainOverflowContainers));
    }
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
-  virtual nsIAtom* GetType() const override;
-
   /**
    * Similar to nsBlockFrame::DrainOverflowLines. Locate any columns not
    * handled by our prev-in-flow, and any columns sitting on our own
    * overflow list, and put them in our primary child list for reflowing.
    */
   void DrainOverflowColumns();
 
   /**
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -82,20 +82,20 @@ nsContainerFrame::SetInitialChildList(Ch
     MOZ_ASSERT(GetStateBits() & NS_FRAME_OUT_OF_FLOW,
                "Top layer frames should be out-of-flow");
     MOZ_ASSERT(!Properties().Get(BackdropProperty()),
                "We shouldn't have setup backdrop frame list before");
 #ifdef DEBUG
     {
       nsIFrame* placeholder = aChildList.FirstChild();
       MOZ_ASSERT(aChildList.OnlyChild(), "Should have only one backdrop");
-      MOZ_ASSERT(placeholder->GetType() == nsGkAtoms::placeholderFrame,
+      MOZ_ASSERT(placeholder->IsPlaceholderFrame(),
                 "The frame to be stored should be a placeholder");
       MOZ_ASSERT(static_cast<nsPlaceholderFrame*>(placeholder)->
-                GetOutOfFlowFrame()->GetType() == nsGkAtoms::backdropFrame,
+                GetOutOfFlowFrame()->IsBackdropFrame(),
                 "The placeholder should points to a backdrop frame");
     }
 #endif
     nsFrameList* list =
       new (PresContext()->PresShell()) nsFrameList(aChildList);
     Properties().Set(BackdropProperty(), list);
   } else {
     MOZ_ASSERT_UNREACHABLE("Unexpected child list");
@@ -1287,17 +1287,17 @@ nsContainerFrame::StealFrame(nsIFrame* a
 }
 
 nsFrameList
 nsContainerFrame::StealFramesAfter(nsIFrame* aChild)
 {
   NS_ASSERTION(!aChild ||
                !(aChild->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER),
                "StealFramesAfter doesn't handle overflow containers");
-  NS_ASSERTION(GetType() != nsGkAtoms::blockFrame, "unexpected call");
+  NS_ASSERTION(!IsBlockFrame(), "unexpected call");
 
   if (!aChild) {
     nsFrameList copy(mFrames);
     mFrames.Clear();
     return copy;
   }
 
   for (nsFrameList::FrameLinkEnumerator iter(mFrames); !iter.AtEnd();
@@ -1326,17 +1326,17 @@ nsContainerFrame::StealFramesAfter(nsIFr
 /*
  * Create a next-in-flow for aFrame. Will return the newly created
  * frame <b>if and only if</b> a new frame is created; otherwise
  * nullptr is returned.
  */
 nsIFrame*
 nsContainerFrame::CreateNextInFlow(nsIFrame* aFrame)
 {
-  NS_PRECONDITION(GetType() != nsGkAtoms::blockFrame,
+  NS_PRECONDITION(!IsBlockFrame(),
                   "you should have called nsBlockFrame::CreateContinuationFor instead");
   NS_PRECONDITION(mFrames.ContainsFrame(aFrame), "expected an in-flow child frame");
 
   nsPresContext* pc = PresContext();
   nsIFrame* nextInFlow = aFrame->GetNextInFlow();
   if (nullptr == nextInFlow) {
     // Create a continuation frame for the child frame and insert it
     // into our child list.
@@ -1501,18 +1501,17 @@ nsContainerFrame::MoveOverflowToChildLis
   // Check for an overflow list with our prev-in-flow
   nsContainerFrame* prevInFlow = (nsContainerFrame*)GetPrevInFlow();
   if (nullptr != prevInFlow) {
     AutoFrameListPtr prevOverflowFrames(PresContext(),
                                         prevInFlow->StealOverflowFrames());
     if (prevOverflowFrames) {
       // Tables are special; they can have repeated header/footer
       // frames on mFrames at this point.
-      NS_ASSERTION(mFrames.IsEmpty() || GetType() == nsGkAtoms::tableFrame,
-                   "bad overflow list");
+      NS_ASSERTION(mFrames.IsEmpty() || IsTableFrame(), "bad overflow list");
       // When pushing and pulling frames we need to check for whether any
       // views need to be reparented.
       nsContainerFrame::ReparentFrameViewList(*prevOverflowFrames,
                                               prevInFlow, this);
       mFrames.AppendFrames(this, *prevOverflowFrames);
       result = true;
     }
   }
--- a/layout/generic/nsContainerFrame.h
+++ b/layout/generic/nsContainerFrame.h
@@ -529,17 +529,20 @@ public:
   // Use this to suppress the CRAZY_SIZE assertions.
   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugReflowingWithInfiniteISize, bool)
   bool IsCrazySizeAssertSuppressed() const {
     return Properties().Get(DebugReflowingWithInfiniteISize());
   }
 #endif
 
 protected:
-  explicit nsContainerFrame(nsStyleContext* aContext) : nsSplittableFrame(aContext) {}
+  nsContainerFrame(nsStyleContext* aContext, mozilla::FrameType aType)
+    : nsSplittableFrame(aContext, aType)
+  {}
+
   ~nsContainerFrame();
 
   /**
    * Helper for DestroyFrom. DestroyAbsoluteFrames is called before
    * destroying frames on lists that can contain placeholders.
    * Derived classes must do that too, if they destroy such frame lists.
    * See nsBlockFrame::DestroyFrom for an example.
    */
--- a/layout/generic/nsFirstLetterFrame.cpp
+++ b/layout/generic/nsFirstLetterFrame.cpp
@@ -37,22 +37,16 @@ NS_QUERYFRAME_TAIL_INHERITING(nsContaine
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsFirstLetterFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Letter"), aResult);
 }
 #endif
 
-nsIAtom*
-nsFirstLetterFrame::GetType() const
-{
-  return nsGkAtoms::letterFrame;
-}
-
 void
 nsFirstLetterFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                      const nsRect&           aDirtyRect,
                                      const nsDisplayListSet& aLists)
 {
   BuildDisplayListForInline(aBuilder, aDirtyRect, aLists);
 }
 
--- a/layout/generic/nsFirstLetterFrame.h
+++ b/layout/generic/nsFirstLetterFrame.h
@@ -12,31 +12,32 @@
 #include "nsContainerFrame.h"
 
 class nsFirstLetterFrame final : public nsContainerFrame {
 public:
   NS_DECL_QUERYFRAME_TARGET(nsFirstLetterFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
-  explicit nsFirstLetterFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
+  explicit nsFirstLetterFrame(nsStyleContext* aContext)
+    : nsContainerFrame(aContext, mozilla::FrameType::Letter)
+  {}
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
   virtual void SetInitialChildList(ChildListID     aListID,
                                    nsFrameList&    aChildList) override;
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
-  virtual nsIAtom* GetType() const override;
 
   bool IsFloating() const { return GetStateBits() & NS_FRAME_OUT_OF_FLOW; }
 
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     if (!IsFloating())
       aFlags = aFlags & ~(nsIFrame::eLineParticipant);
     return nsContainerFrame::IsFrameOfType(aFlags &
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -92,17 +92,17 @@ IsDisplayValueLegacyBox(const nsStyleDis
 
 // Returns true if aFlexContainer is the frame for an element with
 // "display:-webkit-box" or "display:-webkit-inline-box". aFlexContainer is
 // expected to be an instance of nsFlexContainerFrame (enforced with an assert);
 // otherwise, this function's state-bit-check here is bogus.
 static bool
 IsLegacyBox(const nsIFrame* aFlexContainer)
 {
-  MOZ_ASSERT(aFlexContainer->GetType() == nsGkAtoms::flexContainerFrame,
+  MOZ_ASSERT(aFlexContainer->IsFlexContainerFrame(),
              "only flex containers may be passed to this function");
   return aFlexContainer->HasAnyStateBits(NS_STATE_FLEX_IS_LEGACY_WEBKIT_BOX);
 }
 
 // Returns the OrderingProperty enum that we should pass to
 // CSSOrderAwareFrameIterator (depending on whether it's a legacy box).
 static CSSOrderAwareFrameIterator::OrderingProperty
 OrderingPropertyForIter(const nsFlexContainerFrame* aFlexContainer)
@@ -1758,17 +1758,17 @@ FlexItem::FlexItem(ReflowInput& aFlexIte
     mHadMeasuringReflow(false),
     mIsStretched(false),
     mIsStrut(false),
     // mNeedsMinSizeAutoResolution is initialized in CheckForMinSizeAuto()
     mWM(aFlexItemReflowInput.GetWritingMode())
     // mAlignSelf, see below
 {
   MOZ_ASSERT(mFrame, "expecting a non-null child frame");
-  MOZ_ASSERT(mFrame->GetType() != nsGkAtoms::placeholderFrame,
+  MOZ_ASSERT(!mFrame->IsPlaceholderFrame(),
              "placeholder frames should not be treated as flex items");
   MOZ_ASSERT(!(mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW),
              "out-of-flow frames should not be treated as flex items");
 
   const ReflowInput* containerRS = aFlexItemReflowInput.mParentReflowInput;
   if (IsLegacyBox(containerRS->mFrame)) {
     // For -webkit-box/-webkit-inline-box, we need to:
     // (1) Use "-webkit-box-align" instead of "align-items" to determine the
@@ -1856,17 +1856,17 @@ FlexItem::FlexItem(nsIFrame* aChildFrame
     mNeedsMinSizeAutoResolution(false),
     mWM(aContainerWM),
     mAlignSelf(NS_STYLE_ALIGN_FLEX_START)
 {
   MOZ_ASSERT(mFrame, "expecting a non-null child frame");
   MOZ_ASSERT(NS_STYLE_VISIBILITY_COLLAPSE ==
              mFrame->StyleVisibility()->mVisible,
              "Should only make struts for children with 'visibility:collapse'");
-  MOZ_ASSERT(mFrame->GetType() != nsGkAtoms::placeholderFrame,
+  MOZ_ASSERT(!mFrame->IsPlaceholderFrame(),
              "placeholder frames should not be treated as flex items");
   MOZ_ASSERT(!(mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW),
              "out-of-flow frames should not be treated as flex items");
 }
 
 void
 FlexItem::CheckForMinSizeAuto(const ReflowInput& aFlexItemReflowInput,
                               const FlexboxAxisTracker& aAxisTracker)
@@ -2199,23 +2199,16 @@ nsFlexContainerFrame::Init(nsIContent*  
     isLegacyBox = IsDisplayValueLegacyBox(parentStyleContext->StyleDisplay());
   }
 
   if (isLegacyBox) {
     AddStateBits(NS_STATE_FLEX_IS_LEGACY_WEBKIT_BOX);
   }
 }
 
-/* virtual */
-nsIAtom*
-nsFlexContainerFrame::GetType() const
-{
-  return nsGkAtoms::flexContainerFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsFlexContainerFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("FlexContainer"), aResult);
 }
 #endif
 
@@ -3584,17 +3577,17 @@ nsFlexContainerFrame::GenerateFlexLines(
     AddStateBits(NS_STATE_FLEX_NORMAL_FLOW_CHILDREN_IN_CSS_ORDER);
<