Bug 1360241: Devirtualize nsIFrame::GetType. r=heycam draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Sun, 30 Apr 2017 17:30:08 +0200
changeset 570756 4d0616cb638b7822039df6002e718f8cf4767e0f
parent 570708 2fe636103d7167f3a5d57f61bd19fddcc878ca3c
child 626562 efee1de183f3a504e9df707dbd3f2279772497d3
push id56569
push userbmo:emilio+bugs@crisal.io
push dateSun, 30 Apr 2017 17:34:45 +0000
reviewersheycam
bugs1360241
milestone55.0a1
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);
   } else {
     RemoveStateBits(NS_STATE_FLEX_NORMAL_FLOW_CHILDREN_IN_CSS_ORDER);
   }
 
   for (; !iter.AtEnd(); iter.Next()) {
     nsIFrame* childFrame = *iter;
     // Don't create flex items / lines for placeholder frames:
-    if (childFrame->GetType() == nsGkAtoms::placeholderFrame) {
+    if (childFrame->IsPlaceholderFrame()) {
       aPlaceholders.AppendElement(childFrame);
       continue;
     }
 
     // Honor "page-break-before", if we're multi-line and this line isn't empty:
     if (!isSingleLine && !curLine->IsEmpty() &&
         childFrame->StyleDisplay()->mBreakBefore) {
       curLine = AddNewFlexLineToList(aLines, shouldInsertAtFront);
@@ -3901,18 +3894,17 @@ nsFlexContainerFrame::SizeItemInCrossAxi
   nscoord crossAxisBorderPadding = aItem.GetBorderPadding().TopBottom();
   if (reflowResult.Height() < crossAxisBorderPadding) {
     // Child's requested size isn't large enough for its border/padding!
     // This is OK for the trivial nsFrame::Reflow() impl, but other frame
     // classes should know better. So, if we get here, the child had better be
     // an instance of nsFrame (i.e. it should return null from GetType()).
     // XXXdholbert Once we've fixed bug 765861, we should upgrade this to an
     // assertion that trivially passes if bug 765861's flag has been flipped.
-    NS_WARNING_ASSERTION(
-      !aItem.Frame()->GetType(),
+    NS_WARNING_ASSERTION(aItem.Frame()->Type() == FrameType::None,
       "Child should at least request space for border/padding");
     aItem.SetCrossSize(0);
   } else {
     // (normal case)
     aItem.SetCrossSize(reflowResult.Height() - crossAxisBorderPadding);
   }
 
   aItem.SetAscent(reflowResult.Ascent());
@@ -4608,17 +4600,17 @@ nsFlexContainerFrame::ReflowPlaceholders
                                          const LogicalPoint& aContentBoxOrigin,
                                          const nsSize& aContainerSize)
 {
   WritingMode outerWM = aReflowInput.GetWritingMode();
 
   // As noted in this method's documentation, we'll reflow every entry in
   // |aPlaceholders| at the container's content-box origin.
   for (nsIFrame* placeholder : aPlaceholders) {
-    MOZ_ASSERT(placeholder->GetType() == nsGkAtoms::placeholderFrame,
+    MOZ_ASSERT(placeholder->IsPlaceholderFrame(),
                "placeholders array should only contain placeholder frames");
     WritingMode wm = placeholder->GetWritingMode();
     LogicalSize availSize = aReflowInput.ComputedSize(wm);
     ReflowInput childReflowInput(aPresContext, aReflowInput,
                                  placeholder, availSize);
     ReflowOutput childDesiredSize(childReflowInput);
     nsReflowStatus childReflowStatus;
     ReflowChild(placeholder, aPresContext,
--- a/layout/generic/nsFlexContainerFrame.h
+++ b/layout/generic/nsFlexContainerFrame.h
@@ -36,17 +36,18 @@ nsContainerFrame* NS_NewFlexContainerFra
  * "legacy" properties for alignment/flexibility/etc. *instead of* honoring the
  * modern flexbox & alignment properties.  For brevity, many comments in
  * nsFlexContainerFrame.cpp simply refer to these properties using their
  * "-webkit" versions, since we're mostly expecting to encounter them in that
  * form. (Technically, the "-moz" versions of these properties *can* influence
  * layout here as well (since that's what the -webkit versions are aliased to)
  * -- but only inside of a "display:-webkit-{inline-}box" container.)
  */
-class nsFlexContainerFrame : public nsContainerFrame {
+class nsFlexContainerFrame final : public nsContainerFrame
+{
 public:
   NS_DECL_FRAMEARENA_HELPERS
   NS_DECL_QUERYFRAME_TARGET(nsFlexContainerFrame)
   NS_DECL_QUERYFRAME
 
   // Factory method:
   friend nsContainerFrame* NS_NewFlexContainerFrame(nsIPresShell* aPresShell,
                                                     nsStyleContext* aContext);
@@ -72,17 +73,16 @@ public:
   void Reflow(nsPresContext* aPresContext,
               ReflowOutput& aDesiredSize,
               const ReflowInput& aReflowInput,
               nsReflowStatus& aStatus) override;
 
   nscoord GetMinISize(nsRenderingContext* aRenderingContext) override;
   nscoord GetPrefISize(nsRenderingContext* aRenderingContext) override;
 
-  nsIAtom* GetType() const override;
 #ifdef DEBUG_FRAME_DUMP
   nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const override;
 
   bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
                                 nscoord* aBaseline) const override
@@ -128,20 +128,21 @@ public:
                                     uint8_t aAlignVal,
                                     nscoord* aFirstSubjectOffset,
                                     uint32_t* aNumPackingSpacesRemaining,
                                     nscoord* aPackingSpaceRemaining);
 
 protected:
   // Protected constructor & destructor
   explicit nsFlexContainerFrame(nsStyleContext* aContext)
-    : nsContainerFrame(aContext)
+    : nsContainerFrame(aContext, mozilla::FrameType::FlexContainer)
     , mBaselineFromLastReflow(NS_INTRINSIC_WIDTH_UNKNOWN)
     , mLastBaselineFromLastReflow(NS_INTRINSIC_WIDTH_UNKNOWN)
   {}
+
   virtual ~nsFlexContainerFrame();
 
   /*
    * This method does the bulk of the flex layout, implementing the algorithm
    * described at:
    *   http://dev.w3.org/csswg/css-flexbox/#layout-algorithm
    * (with a few initialization pieces happening in the caller, Reflow().
    *
--- a/layout/generic/nsFontInflationData.cpp
+++ b/layout/generic/nsFontInflationData.cpp
@@ -245,17 +245,17 @@ nsFontInflationData::FindEdgeInflatableF
          kid;
          kid = (aDirection == eFromStart) ? kid->GetNextSibling()
                                           : kid->GetPrevSibling()) {
       if (kid->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT) {
         // Goes in a different set of inflation data.
         continue;
       }
 
-      if (kid->GetType() == nsGkAtoms::textFrame) {
+      if (kid->IsTextFrame()) {
         nsIContent *content = kid->GetContent();
         if (content && kid == content->GetPrimaryFrame()) {
           uint32_t len = nsTextFrameUtils::
             ComputeApproximateLengthWithWhitespaceCompression(
               content, kid->StyleText());
           if (len != 0) {
             return kid;
           }
@@ -289,17 +289,17 @@ DoCharCountOfLargestOption(nsIFrame *aCo
   for (nsIFrame* option : aContainer->PrincipalChildList()) {
     uint32_t optionResult;
     if (option->GetContent()->IsHTMLElement(nsGkAtoms::optgroup)) {
       optionResult = DoCharCountOfLargestOption(option);
     } else {
       // REVIEW: Check the frame structure for this!
       optionResult = 0;
       for (nsIFrame* optionChild : option->PrincipalChildList()) {
-        if (optionChild->GetType() == nsGkAtoms::textFrame) {
+        if (optionChild->IsTextFrame()) {
           optionResult += nsTextFrameUtils::
             ComputeApproximateLengthWithWhitespaceCompression(
               optionChild->GetContent(), optionChild->StyleText());
         }
       }
     }
     if (optionResult > result) {
       result = optionResult;
@@ -328,45 +328,45 @@ nsFontInflationData::ScanTextIn(nsIFrame
     nsFrameList::Enumerator kids(lists.CurrentList());
     for (; !kids.AtEnd(); kids.Next()) {
       nsIFrame *kid = kids.get();
       if (kid->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT) {
         // Goes in a different set of inflation data.
         continue;
       }
 
-      nsIAtom *fType = kid->GetType();
-      if (fType == nsGkAtoms::textFrame) {
+      FrameType fType = kid->Type();
+      if (fType == FrameType::Text) {
         nsIContent *content = kid->GetContent();
         if (content && kid == content->GetPrimaryFrame()) {
           uint32_t len = nsTextFrameUtils::
             ComputeApproximateLengthWithWhitespaceCompression(
               content, kid->StyleText());
           if (len != 0) {
             nscoord fontSize = kid->StyleFont()->mFont.size;
             if (fontSize > 0) {
               mTextAmount += fontSize * len;
             }
           }
         }
-      } else if (fType == nsGkAtoms::textInputFrame) {
+      } else if (fType == FrameType::TextInput) {
         // We don't want changes to the amount of text in a text input
         // to change what we count towards inflation.
         nscoord fontSize = kid->StyleFont()->mFont.size;
         int32_t charCount = static_cast<nsTextControlFrame*>(kid)->GetCols();
         mTextAmount += charCount * fontSize;
-      } else if (fType == nsGkAtoms::comboboxControlFrame) {
+      } else if (fType == FrameType::ComboboxControl) {
         // See textInputFrame above (with s/amount of text/selected option/).
         // Don't just recurse down to the list control inside, since we
         // need to exclude the display frame.
         nscoord fontSize = kid->StyleFont()->mFont.size;
         int32_t charCount = CharCountOfLargestOption(
           static_cast<nsComboboxControlFrame*>(kid)->GetDropDown());
         mTextAmount += charCount * fontSize;
-      } else if (fType == nsGkAtoms::listControlFrame) {
+      } else if (fType == FrameType::ListControl) {
         // See textInputFrame above (with s/amount of text/selected option/).
         nscoord fontSize = kid->StyleFont()->mFont.size;
         int32_t charCount = CharCountOfLargestOption(kid);
         mTextAmount += charCount * fontSize;
       } else {
         // recursive step
         ScanTextIn(kid);
       }
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -444,20 +444,21 @@ WeakFrame::Init(nsIFrame* aFrame)
       mFrame = nullptr;
     }
   }
 }
 
 nsIFrame*
 NS_NewEmptyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
-  return new (aPresShell) nsFrame(aContext);
-}
-
-nsFrame::nsFrame(nsStyleContext* aContext)
+  return new (aPresShell) nsFrame(aContext, FrameType::None);
+}
+
+nsFrame::nsFrame(nsStyleContext* aContext, FrameType aType)
+  : nsBox(aType)
 {
   MOZ_COUNT_CTOR(nsFrame);
 
   mState = NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY;
   mStyleContext = aContext;
   mWritingMode = WritingMode(mStyleContext);
   mStyleContext->AddRef();
 #ifdef DEBUG
@@ -534,39 +535,39 @@ IsFontSizeInflationContainer(nsIFrame* a
    */
 
   // The root frame should always be an inflation container.
   if (!aFrame->GetParent()) {
     return true;
   }
 
   nsIContent *content = aFrame->GetContent();
-  nsIAtom* frameType = aFrame->GetType();
+  FrameType frameType = aFrame->Type();
   bool isInline = (aFrame->GetDisplay() == StyleDisplay::Inline ||
                    RubyUtils::IsRubyBox(frameType) ||
                    (aFrame->IsFloating() &&
-                    frameType == nsGkAtoms::letterFrame) ||
+                    frameType == FrameType::Letter) ||
                    // Given multiple frames for the same node, only the
                    // outer one should be considered a container.
                    // (Important, e.g., for nsSelectsAreaFrame.)
                    (aFrame->GetParent()->GetContent() == content) ||
                    (content && (content->IsAnyOfHTMLElements(nsGkAtoms::option,
                                                              nsGkAtoms::optgroup,
                                                              nsGkAtoms::select) ||
                                 content->IsInNativeAnonymousSubtree()))) &&
                   !(aFrame->IsXULBoxFrame() && aFrame->GetParent()->IsXULBoxFrame());
   NS_ASSERTION(!aFrame->IsFrameOfType(nsIFrame::eLineParticipant) ||
                isInline ||
                // br frames and mathml frames report being line
                // participants even when their position or display is
                // set
-               aFrame->GetType() == nsGkAtoms::brFrame ||
+               aFrame->IsBrFrame() ||
                aFrame->IsFrameOfType(nsIFrame::eMathML),
                "line participants must not be containers");
-  NS_ASSERTION(aFrame->GetType() != nsGkAtoms::bulletFrame || isInline,
+  NS_ASSERTION(!aFrame->IsBulletFrame() || isInline,
                "bullets should not be containers");
   return !isInline;
 }
 
 void
 nsFrame::Init(nsIContent*       aContent,
               nsContainerFrame* aParent,
               nsIFrame*         aPrevInFlow)
@@ -870,17 +871,17 @@ AddAndRemoveImageAssociations(nsFrame* a
 }
 
 // Subclass hook for style post processing
 /* virtual */ void
 nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   if (nsSVGUtils::IsInSVGTextSubtree(this)) {
     SVGTextFrame* svgTextFrame = static_cast<SVGTextFrame*>(
-        nsLayoutUtils::GetClosestFrameOfType(this, nsGkAtoms::svgTextFrame));
+      nsLayoutUtils::GetClosestFrameOfType(this, FrameType::SVGText));
     nsIFrame* anonBlock = svgTextFrame->PrincipalChildList().FirstChild();
     // Just as in SVGTextFrame::DidSetStyleContext, we need to ensure that
     // any non-display SVGTextFrames get reflowed when a child text frame
     // gets new style.
     //
     // Note that we must check NS_FRAME_FIRST_REFLOW on our SVGTextFrame's
     // anonymous block frame rather than our self, since NS_FRAME_FIRST_REFLOW
     // may be set on us if we're a new frame that has been inserted after the
@@ -982,17 +983,17 @@ nsFrame::DidSetStyleContext(nsStyleConte
 
 void
 nsIFrame::ReparentFrameViewTo(nsViewManager* aViewManager,
                               nsView*        aNewParentView,
                               nsView*        aOldParentView)
 {
   if (HasView()) {
 #ifdef MOZ_XUL
-    if (GetType() == nsGkAtoms::menuPopupFrame) {
+    if (IsMenuPopupFrame()) {
       // This view must be parented by the root view, don't reparent it.
       return;
     }
 #endif
     nsView* view = GetView();
     // Verify that the current parent view is what we think it is
     //nsView*  parentView;
     //NS_ASSERTION(parentView == aOldParentView, "unexpected parent view");
@@ -1345,17 +1346,17 @@ nsIFrame::Extend3DContext() const
 {
   const nsStyleDisplay* disp = StyleDisplay();
   if (disp->mTransformStyle != NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
       !IsFrameOfType(nsIFrame::eSupportsCSSTransforms)) {
     return false;
   }
 
   // If we're all scroll frame, then all descendants will be clipped, so we can't preserve 3d.
-  if (GetType() == nsGkAtoms::scrollFrame) {
+  if (IsScrollFrame()) {
     return false;
   }
 
   if (HasOpacity()) {
     return false;
   }
 
   const nsStyleEffects* effects = StyleEffects();
@@ -2872,17 +2873,17 @@ nsIFrame::BuildDisplayListForChild(nsDis
                                    uint32_t                aFlags) {
   // If painting is restricted to just the background of the top level frame,
   // then we have nothing to do here.
   if (aBuilder->IsBackgroundOnly())
     return;
 
   if (aBuilder->IsForGenerateGlyphMask() ||
       aBuilder->IsForPaintingSelectionBG()) {
-    if (nsGkAtoms::textFrame != aChild->GetType() && aChild->IsLeaf()) {
+    if (!aChild->IsTextFrame() && aChild->IsLeaf()) {
       return;
     }
   }
 
   nsIFrame* child = aChild;
   if (child->GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
     return;
 
@@ -2898,20 +2899,19 @@ nsIFrame::BuildDisplayListForChild(nsDis
     // it acts like inline-block or inline-table. Therefore it is a
     // pseudo-stacking-context.
     pseudoStackingContext = true;
   }
 
   // dirty rect in child-relative coordinates
   nsRect dirty = aDirtyRect - child->GetOffsetTo(this);
 
-  nsIAtom* childType = child->GetType();
   nsDisplayListBuilder::OutOfFlowDisplayData* savedOutOfFlowData = nullptr;
   bool isPlaceholder = false;
-  if (childType == nsGkAtoms::placeholderFrame) {
+  if (child->IsPlaceholderFrame()) {
     isPlaceholder = true;
     nsPlaceholderFrame* placeholder = static_cast<nsPlaceholderFrame*>(child);
     child = placeholder->GetOutOfFlowFrame();
     NS_ASSERTION(child, "No out of flow frame?");
     // If 'child' is a pushed float then it's owned by a block that's not an
     // ancestor of the placeholder, and it will be painted by that block and
     // should not be painted through the placeholder.
     if (!child || nsLayoutUtils::IsPopup(child) ||
@@ -2921,36 +2921,32 @@ nsIFrame::BuildDisplayListForChild(nsDis
     // If the out-of-flow frame is in the top layer, the viewport frame
     // will paint it. Skip it here. Note that, only out-of-flow frames
     // with this property should be skipped, because non-HTML elements
     // may stop their children from being out-of-flow. Those frames
     // should still be handled in the normal in-flow path.
     if (placeholder->GetStateBits() & PLACEHOLDER_FOR_TOPLAYER) {
       return;
     }
-    // Make sure that any attempt to use childType below is disappointed. We
-    // could call GetType again but since we don't currently need it, let's
-    // avoid the virtual call.
-    childType = nullptr;
     // Recheck NS_FRAME_TOO_DEEP_IN_FRAME_TREE
     if (child->GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
       return;
     savedOutOfFlowData = nsDisplayListBuilder::GetOutOfFlowData(child);
     if (savedOutOfFlowData) {
       dirty = savedOutOfFlowData->mDirtyRect;
     } else {
       // The out-of-flow frame did not intersect the dirty area. We may still
       // need to traverse into it, since it may contain placeholders we need
       // to enter to reach other out-of-flow frames that are visible.
       dirty.SetEmpty();
     }
     pseudoStackingContext = true;
   }
 
-  NS_ASSERTION(childType != nsGkAtoms::placeholderFrame,
+  NS_ASSERTION(!child->IsPlaceholderFrame(),
                "Should have dealt with placeholders already");
   if (aBuilder->GetSelectedFramesOnly() &&
       child->IsLeaf() &&
       !aChild->IsSelected()) {
     return;
   }
 
   if (aBuilder->GetIncludeAllOutOfFlows() &&
@@ -3859,17 +3855,17 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsPres
 
   RefPtr<nsFrameSelection> frameselection = GetFrameSelection();
   bool mouseDown = frameselection->GetDragState();
   if (!mouseDown) {
     return NS_OK;
   }
 
   nsIFrame* scrollbar =
-    nsLayoutUtils::GetClosestFrameOfType(this, nsGkAtoms::scrollbarFrame);
+    nsLayoutUtils::GetClosestFrameOfType(this, FrameType::Scrollbar);
   if (!scrollbar) {
     // XXX Do we really need to exclude non-selectable content here?
     // GetContentOffsetsFromPoint can handle it just fine, although some
     // other stuff might not like it.
     // NOTE: DisplaySelection() returns SELECTION_OFF for non-selectable frames.
     if (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF) {
       return NS_OK;
     }
@@ -4091,23 +4087,23 @@ struct MOZ_STACK_CLASS FrameContentRange
 // Retrieve the content offsets of a frame
 static FrameContentRange GetRangeForFrame(nsIFrame* aFrame) {
   nsCOMPtr<nsIContent> content, parent;
   content = aFrame->GetContent();
   if (!content) {
     NS_WARNING("Frame has no content");
     return FrameContentRange(nullptr, -1, -1);
   }
-  nsIAtom* type = aFrame->GetType();
-  if (type == nsGkAtoms::textFrame) {
+  FrameType type = aFrame->Type();
+  if (type == FrameType::Text) {
     int32_t offset, offsetEnd;
     aFrame->GetOffsets(offset, offsetEnd);
     return FrameContentRange(content, offset, offsetEnd);
   }
-  if (type == nsGkAtoms::brFrame) {
+  if (type == FrameType::Br) {
     parent = content->GetParent();
     int32_t beginOffset = parent->IndexOf(content);
     return FrameContentRange(parent, beginOffset, beginOffset);
   }
   // Loop to deal with anonymous content, which has no index; this loop
   // probably won't run more than twice under normal conditions
   do {
     parent  = content->GetParent();
@@ -4239,17 +4235,17 @@ static FrameTarget GetSelectionClosestFr
   WritingMode wm = aLine->mWritingMode;
   LogicalPoint pt(wm, aPoint, aLine->mContainerSize);
   bool canSkipBr = false;
   for (int32_t n = aLine->GetChildCount(); n;
        --n, frame = frame->GetNextSibling()) {
     // Skip brFrames. Can only skip if the line contains at least
     // one selectable and non-empty frame before
     if (!SelfIsSelectable(frame, aFlags) || frame->IsEmpty() ||
-        (canSkipBr && frame->GetType() == nsGkAtoms::brFrame)) {
+        (canSkipBr && frame->IsBrFrame())) {
       continue;
     }
     canSkipBr = true;
     LogicalRect frameRect = LogicalRect(wm, frame->GetRect(),
                                         aLine->mContainerSize);
     if (pt.I(wm) >= frameRect.IStart(wm)) {
       if (pt.I(wm) < frameRect.IEnd(wm)) {
         return GetSelectionClosestFrameForChild(frame, aPoint, aFlags);
@@ -4958,37 +4954,36 @@ nsFrame::ComputeSize(nsRenderingContext*
   }
   nscoord boxSizingToMarginEdgeISize =
     aMargin.ISize(aWM) + aBorder.ISize(aWM) + aPadding.ISize(aWM) -
     boxSizingAdjust.ISize(aWM);
 
   const nsStyleCoord* inlineStyleCoord = &stylePos->ISize(aWM);
   const nsStyleCoord* blockStyleCoord = &stylePos->BSize(aWM);
 
-  nsIAtom* parentFrameType = GetParent() ? GetParent()->GetType() : nullptr;
-  auto alignCB = GetParent();
-  bool isGridItem = (parentFrameType == nsGkAtoms::gridContainerFrame &&
-                     !(GetStateBits() & NS_FRAME_OUT_OF_FLOW));
-  if (parentFrameType == nsGkAtoms::tableWrapperFrame &&
-      GetType() == nsGkAtoms::tableFrame) {
+  auto parentFrame = GetParent();
+  auto alignCB = parentFrame;
+  bool isGridItem = parentFrame && parentFrame->IsGridContainerFrame() &&
+                    !(GetStateBits() & NS_FRAME_OUT_OF_FLOW);
+  if (parentFrame && parentFrame->IsTableWrapperFrame() && IsTableFrame()) {
     // An inner table frame is sized as a grid item if its table wrapper is,
     // because they actually have the same CB (the wrapper's CB).
     // @see ReflowInput::InitCBReflowInput
     auto tableWrapper = GetParent();
     auto grandParent = tableWrapper->GetParent();
-    isGridItem = (grandParent->GetType() == nsGkAtoms::gridContainerFrame &&
+    isGridItem = (grandParent->IsGridContainerFrame() &&
                   !(tableWrapper->GetStateBits() & NS_FRAME_OUT_OF_FLOW));
     if (isGridItem) {
       // When resolving justify/align-self below, we want to use the grid
       // container's justify/align-items value and WritingMode.
       alignCB = grandParent;
     }
   }
-  bool isFlexItem = (parentFrameType == nsGkAtoms::flexContainerFrame &&
-                     !(GetStateBits() & NS_FRAME_OUT_OF_FLOW));
+  bool isFlexItem = parentFrame && parentFrame->IsFlexContainerFrame() &&
+                    !(GetStateBits() & NS_FRAME_OUT_OF_FLOW);
   bool isInlineFlexItem = false;
   if (isFlexItem) {
     // Flex items use their "flex-basis" property in place of their main-size
     // property (e.g. "width") for sizing purposes, *unless* they have
     // "flex-basis:auto", in which case they use their main-size property after
     // all.
     uint32_t flexDirection = GetParent()->StylePosition()->mFlexDirection;
     isInlineFlexItem =
@@ -5204,22 +5199,21 @@ nsFrame::ComputeSizeWithIntrinsicDimensi
                                             const LogicalSize&   aMargin,
                                             const LogicalSize&   aBorder,
                                             const LogicalSize&   aPadding,
                                             ComputeSizeFlags     aFlags)
 {
   const nsStylePosition* stylePos = StylePosition();
   const nsStyleCoord* inlineStyleCoord = &stylePos->ISize(aWM);
   const nsStyleCoord* blockStyleCoord = &stylePos->BSize(aWM);
-  const nsIAtom* parentFrameType =
-    GetParent() ? GetParent()->GetType() : nullptr;
-  const bool isGridItem = (parentFrameType == nsGkAtoms::gridContainerFrame &&
-                           !(GetStateBits() & NS_FRAME_OUT_OF_FLOW));
-  const bool isFlexItem = (parentFrameType == nsGkAtoms::flexContainerFrame &&
-                           !(GetStateBits() & NS_FRAME_OUT_OF_FLOW));
+  auto* parentFrame = GetParent();
+  const bool isGridItem = parentFrame && parentFrame->IsGridContainerFrame() &&
+                          !(GetStateBits() & NS_FRAME_OUT_OF_FLOW);
+  const bool isFlexItem = parentFrame && parentFrame->IsFlexContainerFrame() &&
+                          !(GetStateBits() & NS_FRAME_OUT_OF_FLOW);
   bool isInlineFlexItem = false;
   Maybe<nsStyleCoord> imposedMainSizeStyleCoord;
 
   // If this is a flex item, and we're measuring its cross size after flexing
   // to resolve its main size, then we need to use the resolved main size
   // that the container provides to us *instead of* the main-size coordinate
   // from our style struct. (Otherwise, we'll be using an irrelevant value in
   // the aspect-ratio calculations below.)
@@ -5966,22 +5960,22 @@ nsIFrame* nsIFrame::GetTailContinuation(
 // Associated view object
 void
 nsIFrame::SetView(nsView* aView)
 {
   if (aView) {
     aView->SetFrame(this);
 
 #ifdef DEBUG
-    nsIAtom* frameType = GetType();
-    NS_ASSERTION(frameType == nsGkAtoms::subDocumentFrame ||
-                 frameType == nsGkAtoms::listControlFrame ||
-                 frameType == nsGkAtoms::objectFrame ||
-                 frameType == nsGkAtoms::viewportFrame ||
-                 frameType == nsGkAtoms::menuPopupFrame,
+    FrameType frameType = Type();
+    NS_ASSERTION(frameType == FrameType::SubDocument ||
+                 frameType == FrameType::ListControl ||
+                 frameType == FrameType::Object ||
+                 frameType == FrameType::Viewport ||
+                 frameType == FrameType::MenuPopup,
                  "Only specific frame types can have an nsView");
 #endif
 
     // Store the view on the frame.
     SetViewInternal(aView);
 
     // Set the frame state bit that says the frame has a view
     AddStateBits(NS_FRAME_HAS_VIEW);
@@ -6165,22 +6159,16 @@ nsIFrame::GetNearestWidget(nsPoint& aOff
   nsPoint offsetToView;
   nsPoint offsetToWidget;
   nsIWidget* widget =
     GetClosestView(&offsetToView)->GetNearestWidget(&offsetToWidget);
   aOffset = offsetToView + offsetToWidget;
   return widget;
 }
 
-nsIAtom*
-nsFrame::GetType() const
-{
-  return nullptr;
-}
-
 bool
 nsIFrame::IsLeaf() const
 {
   return true;
 }
 
 Matrix4x4
 nsIFrame::GetTransformMatrix(const nsIFrame* aStopAtAncestor,
@@ -6209,18 +6197,17 @@ nsIFrame::GetTransformMatrix(const nsIFr
     /* Combine the raw transform with a translation to our parent. */
     result.PostTranslate(NSAppUnitsToFloatPixels(delta.x, scaleFactor),
                          NSAppUnitsToFloatPixels(delta.y, scaleFactor),
                          0.0f);
 
     return result;
   }
 
-  if (nsLayoutUtils::IsPopup(this) &&
-      GetType() == nsGkAtoms::listControlFrame) {
+  if (nsLayoutUtils::IsPopup(this) && IsListControlFrame()) {
     nsPresContext* presContext = PresContext();
     nsIFrame* docRootFrame = presContext->PresShell()->GetRootFrame();
 
     // Compute a matrix that transforms from the popup widget to the toplevel
     // widget. We use the widgets because they're the simplest and most
     // accurate approach --- this should work no matter how the widget position
     // was chosen.
     nsIWidget* widget = GetView()->GetWidget();
@@ -6927,17 +6914,17 @@ GetNearestBlockContainer(nsIFrame* frame
   // described in the CSS spec.  We need to make them not be containing
   // blocks.
   // Since the parent of such a block is either a normal block or
   // another such pseudo, this shouldn't cause anything bad to happen.
   // Also the anonymous blocks inside table cells are not containing blocks.
   while (frame->IsFrameOfType(nsIFrame::eLineParticipant) ||
          frame->IsBlockWrapper() ||
          // Table rows are not containing blocks either
-         frame->GetType() == nsGkAtoms::tableRowFrame) {
+         frame->IsTableRowFrame()) {
     frame = frame->GetParent();
     NS_ASSERTION(frame, "How come we got to the root frame without seeing a containing block?");
   }
   return frame;
 }
 
 nsIFrame*
 nsIFrame::GetContainingBlock(uint32_t aFlags) const
@@ -7130,17 +7117,17 @@ nsFrame::GetFrameName(nsAString& aResult
 
 nsresult
 nsFrame::MakeFrameName(const nsAString& aType, nsAString& aResult) const
 {
   aResult = aType;
   if (mContent && !mContent->IsNodeOfType(nsINode::eTEXT)) {
     nsAutoString buf;
     mContent->NodeInfo()->NameAtom()->ToString(buf);
-    if (GetType() == nsGkAtoms::subDocumentFrame) {
+    if (IsSubDocumentFrame()) {
       nsAutoString src;
       mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
       buf.AppendLiteral(" src=");
       buf.Append(src);
     }
     aResult.Append('(');
     aResult.Append(buf);
     aResult.Append(')');
@@ -7626,18 +7613,17 @@ nsFrame::GetNextPrevLineFromeBlockFrame(
         //otherwise there is no way to get and click signal to fall before a table (it being a line iterator itself)
         nsIPresShell *shell = aPresContext->GetPresShell();
         if (!shell)
           return NS_ERROR_FAILURE;
         int16_t isEditor = shell->GetSelectionFlags();
         isEditor = isEditor == nsISelectionDisplay::DISPLAY_ALL;
         if ( isEditor )
         {
-          if (resultFrame->GetType() == nsGkAtoms::tableWrapperFrame)
-          {
+          if (resultFrame->IsTableWrapperFrame()) {
             if (((point.x - offset.x + tempRect.x)<0) ||  ((point.x - offset.x+ tempRect.x)>tempRect.width))//off left/right side
             {
               nsIContent* content = resultFrame->GetContent();
               if (content)
               {
                 nsIContent* parent = content->GetParent();
                 if (parent)
                 {
@@ -7780,17 +7766,17 @@ FindBlockFrameOrBR(nsIFrame* aFrame, nsD
   
   // Check the frame itself
   // Fall through block-in-inline split frames because their mContent is
   // the content of the inline frames they were created from. The
   // first/last child of such frames is the real block frame we're
   // looking for.
   if ((nsLayoutUtils::GetAsBlock(aFrame) &&
        !(aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT)) ||
-      aFrame->GetType() == nsGkAtoms::brFrame) {
+      aFrame->IsBrFrame()) {
     nsIContent* content = aFrame->GetContent();
     result.mContent = content->GetParent();
     // In some cases (bug 310589, bug 370174) we end up here with a null content.
     // This probably shouldn't ever happen, but since it sometimes does, we want
     // to avoid crashing here.
     NS_ASSERTION(result.mContent, "Unexpected orphan content");
     if (result.mContent)
       result.mOffset = result.mContent->IndexOf(content) + 
@@ -8123,18 +8109,18 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct*
             /* SPECIAL CHECK FOR TABLE NAVIGATION
                tables need to navigate also and the frame that supports it is
                nsTableRowGroupFrame which is INSIDE nsTableWrapperFrame.
                If we have stumbled onto an nsTableWrapperFrame we need to drill
                into nsTableRowGroup if we hit a header or footer that's ok just
                go into them.
              */
             bool searchTableBool = false;
-            if (aPos->mResultFrame->GetType() == nsGkAtoms::tableWrapperFrame ||
-                aPos->mResultFrame->GetType() == nsGkAtoms::tableCellFrame) {
+            if (aPos->mResultFrame->IsTableWrapperFrame() ||
+                aPos->mResultFrame->IsTableCellFrame()) {
               nsIFrame* frame = aPos->mResultFrame->PrincipalChildList().FirstChild();
               // got the table frame now
               // ok time to drill down to find iterator
               while (frame) {
                 iter = frame->GetLineIterator();
                 if (iter) {
                   aPos->mResultFrame = frame;
                   searchTableBool = true;
@@ -8212,18 +8198,17 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct*
         it->GetLine(thisLine, &firstFrame, &lineFrameCount, usedRect);
 
         nsIFrame* frame = firstFrame;
         for (int32_t count = lineFrameCount; count;
              --count, frame = frame->GetNextSibling()) {
           if (!frame->IsGeneratedContentFrame()) {
             // When jumping to the end of the line with the "end" key,
             // skip over brFrames
-            if (endOfLine && lineFrameCount > 1 &&
-                frame->GetType() == nsGkAtoms::brFrame) {
+            if (endOfLine && lineFrameCount > 1 && frame->IsBrFrame()) {
               continue;
             }
             baseFrame = frame;
             if (!endOfLine)
               break;
           }
         }
       }
@@ -8379,17 +8364,17 @@ nsFrame::GetLineNumber(nsIFrame *aFrame,
       }
       thisBlock = frameManager->GetPlaceholderFrameFor(thisBlock);
       if (!thisBlock)
         return -1;
     }  
     blockFrame = thisBlock->GetParent();
     result = NS_OK;
     if (blockFrame) {
-      if (aLockScroll && blockFrame->GetType() == nsGkAtoms::scrollFrame)
+      if (aLockScroll && blockFrame->IsScrollFrame())
         return -1;
       it = blockFrame->GetLineIterator();
       if (!it)
         result = NS_ERROR_FAILURE;
     }
   }
   if (!blockFrame || !it)
     return -1;
@@ -8518,17 +8503,17 @@ nsIFrame::GetFrameFromDirection(nsDirect
     if (!traversedFrame ||
         (!traversedFrame->IsGeneratedContentFrame() &&
          traversedFrame->GetContent()->IsRootOfNativeAnonymousSubtree())) {
       return NS_ERROR_FAILURE;
     }
 
     // Skip brFrames, but only if they are not the only frame in the line
     if (atLineEdge && aDirection == eDirPrevious &&
-        traversedFrame->GetType() == nsGkAtoms::brFrame) {
+        traversedFrame->IsBrFrame()) {
       int32_t lineFrameCount;
       nsIFrame *currentBlockFrame, *currentFirstFrame;
       nsRect usedRect;
       int32_t currentLine = nsFrame::GetLineNumber(traversedFrame, aScrollViewStop, &currentBlockFrame);
       nsAutoLineIterator iter = currentBlockFrame->GetLineIterator();
       result = iter->GetLine(currentLine, &currentFirstFrame, &lineFrameCount, usedRect);
       if (NS_FAILED(result)) {
         return result;
@@ -8680,23 +8665,16 @@ nsIFrame::SetOverflowAreas(const nsOverf
     mOverflow.mType = NS_FRAME_OVERFLOW_LARGE;
     nsOverflowAreas* overflow = GetOverflowAreasProperty();
     NS_ASSERTION(overflow, "should have created areas");
     *overflow = aOverflowAreas;
     return changed;
   }
 }
 
-inline bool
-IsInlineFrame(nsIFrame *aFrame)
-{
-  nsIAtom *type = aFrame->GetType();
-  return type == nsGkAtoms::inlineFrame;
-}
-
 /**
  * Compute the union of the border boxes of aFrame and its descendants,
  * in aFrame's coordinate space (if aApplyTransform is false) or its
  * post-transform coordinate space (if aApplyTransform is true).
  */
 static nsRect
 UnionBorderBoxes(nsIFrame* aFrame, bool aApplyTransform,
                  bool& aOutValid,
@@ -8706,19 +8684,19 @@ UnionBorderBoxes(nsIFrame* aFrame, bool 
   const nsRect bounds(nsPoint(0, 0),
                       aSizeOverride ? *aSizeOverride : aFrame->GetSize());
 
   // The SVG container frames besides SVGTextFrame do not maintain
   // an accurate mRect. It will make the outline be larger than
   // we expect, we need to make them narrow to their children's outline.
   // aOutValid is set to false if the returned nsRect is not valid
   // and should not be included in the outline rectangle.
-  aOutValid = !(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)
-              || !aFrame->IsFrameOfType(nsIFrame::eSVGContainer)
-              || aFrame->GetType() == nsGkAtoms::svgTextFrame;
+  aOutValid = !(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) ||
+              !aFrame->IsFrameOfType(nsIFrame::eSVGContainer) ||
+              aFrame->IsSVGTextFrame();
 
   nsRect u;
 
   if (!aFrame->FrameMaintainsOverflow()) {
     return u;
   }
 
   // Start from our border-box, transformed.  See comment below about
@@ -8742,21 +8720,21 @@ UnionBorderBoxes(nsIFrame* aFrame, bool 
   } else {
     if (!doTransform &&
         bounds.IsEqualEdges(aFrame->GetVisualOverflowRect()) &&
         bounds.IsEqualEdges(aFrame->GetScrollableOverflowRect())) {
       return u;
     }
   }
   const nsStyleDisplay* disp = aFrame->StyleDisplay();
-  nsIAtom* fType = aFrame->GetType();
+  FrameType fType = aFrame->Type();
   if (nsFrame::ShouldApplyOverflowClipping(aFrame, disp) ||
-      fType == nsGkAtoms::scrollFrame ||
-      fType == nsGkAtoms::listControlFrame ||
-      fType == nsGkAtoms::svgOuterSVGFrame) {
+      fType == FrameType::Scroll ||
+      fType == FrameType::ListControl ||
+      fType == FrameType::SVGOuterSVG) {
     return u;
   }
 
   const nsStyleEffects* effects = aFrame->StyleEffects();
   Maybe<nsRect> clipPropClipRect =
     aFrame->GetClipPropClipRect(disp, effects, bounds.Size());
 
   // Iterate over all children except pop-ups.
@@ -8971,17 +8949,17 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
   }
 
   // Overflow area must always include the frame's top-left and bottom-right,
   // even if the frame rect is empty (so we can scroll to those positions).
   // Pending a real fix for bug 426879, don't do this for inline frames
   // with zero width.
   // Do not do this for SVG either, since it will usually massively increase
   // the area unnecessarily.
-  if ((aNewSize.width != 0 || !IsInlineFrame(this)) &&
+  if ((aNewSize.width != 0 || !IsInlineFrame()) &&
       !(GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
     NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
       nsRect& o = aOverflowAreas.Overflow(otype);
       o.UnionRectEdges(o, bounds);
     }
   }
 
   // Note that NS_STYLE_OVERFLOW_CLIP doesn't clip the frame background,
@@ -9302,17 +9280,17 @@ nsFrame::CorrectStyleParentFrame(nsIFram
       nsIFrame* sibling = GetIBSplitSiblingForAnonymousBlock(parent);
 
       if (sibling) {
         // |parent| was a block in an {ib} split; use the inline as
         // |the style parent.
         parent = sibling;
       }
     }
-      
+
     nsIAtom* parentPseudo = parent->StyleContext()->GetPseudo();
     if (!parentPseudo ||
         (!nsCSSAnonBoxes::IsAnonBox(parentPseudo) &&
          // nsPlaceholderFrame pases in nsGkAtoms::placeholderFrame for
          // aChildPseudo (even though that's not a valid pseudo-type) just to
          // trigger this behavior of walking up to the nearest non-pseudo
          // ancestor.
          aChildPseudo != nsGkAtoms::placeholderFrame)) {
@@ -9327,17 +9305,17 @@ nsFrame::CorrectStyleParentFrame(nsIFram
     // aProspectiveParent is the scrollframe for a viewport
     // and the kids are the anonymous scrollbars
     return aProspectiveParent;
   }
 
   // We can get here if the root element is absolutely positioned.
   // We can't test for this very accurately, but it can only happen
   // when the prospective parent is a canvas frame.
-  NS_ASSERTION(aProspectiveParent->GetType() == nsGkAtoms::canvasFrame,
+  NS_ASSERTION(aProspectiveParent->IsCanvasFrame(),
                "Should have found a parent before this");
   return nullptr;
 }
 
 nsStyleContext*
 nsFrame::DoGetParentStyleContext(nsIFrame** aProviderFrame) const
 {
   *aProviderFrame = nullptr;
@@ -9462,21 +9440,19 @@ nsIFrame::IsFocusable(int32_t *aTabIndex
       StyleContext()->GetPseudo() != nsCSSAnonBoxes::anonymousGridItem) {
     const nsStyleUserInterface* ui = StyleUserInterface();
     if (ui->mUserFocus != StyleUserFocus::Ignore &&
         ui->mUserFocus != StyleUserFocus::None) {
       // Pass in default tabindex of -1 for nonfocusable and 0 for focusable
       tabIndex = 0;
     }
     isFocusable = mContent->IsFocusable(&tabIndex, aWithMouse);
-    if (!isFocusable && !aWithMouse &&
-        GetType() == nsGkAtoms::scrollFrame &&
+    if (!isFocusable && !aWithMouse && IsScrollFrame() &&
         mContent->IsHTMLElement() &&
-        !mContent->IsRootOfNativeAnonymousSubtree() &&
-        mContent->GetParent() &&
+        !mContent->IsRootOfNativeAnonymousSubtree() && mContent->GetParent() &&
         !mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
       // Elements with scrollable view are focusable with script & tabbable
       // Otherwise you couldn't scroll them with keyboard, which is
       // an accessibility issue (e.g. Section 508 rules)
       // However, we don't make them to be focusable with the mouse,
       // because the extra focus outlines are considered unnecessarily ugly.
       // When clicked on, the selection position within the element 
       // will be enough to make them keyboard scrollable.
@@ -9541,17 +9517,17 @@ ConvertSVGDominantBaselineToVerticalAlig
 uint8_t
 nsIFrame::VerticalAlignEnum() const
 {
   if (nsSVGUtils::IsInSVGTextSubtree(this)) {
     uint8_t dominantBaseline;
     for (const nsIFrame* frame = this; frame; frame = frame->GetParent()) {
       dominantBaseline = frame->StyleSVGReset()->mDominantBaseline;
       if (dominantBaseline != NS_STYLE_DOMINANT_BASELINE_AUTO ||
-          frame->GetType() == nsGkAtoms::svgTextFrame) {
+          frame->IsSVGTextFrame()) {
         break;
       }
     }
     return ConvertSVGDominantBaselineToVerticalAlign(dominantBaseline);
   }
 
   const nsStyleCoord& verticalAlign = StyleDisplay()->mVerticalAlign;
   if (verticalAlign.GetUnit() == eStyleUnit_Enumerated) {
@@ -10717,20 +10693,20 @@ struct DR_FrameTypeInfo;
 struct DR_FrameTreeNode;
 struct DR_Rule;
 
 struct DR_State
 {
   DR_State();
   ~DR_State();
   void Init();
-  void AddFrameTypeInfo(nsIAtom* aFrameType,
+  void AddFrameTypeInfo(FrameType aFrameType,
                         const char* aFrameNameAbbrev,
                         const char* aFrameName);
-  DR_FrameTypeInfo* GetFrameTypeInfo(nsIAtom* aFrameType);
+  DR_FrameTypeInfo* GetFrameTypeInfo(FrameType aFrameType);
   DR_FrameTypeInfo* GetFrameTypeInfo(char* aFrameName);
   void InitFrameTypeTable();
   DR_FrameTreeNode* CreateTreeNode(nsIFrame*                aFrame,
                                    const ReflowInput* aReflowInput);
   void FindMatchingRule(DR_FrameTreeNode& aNode);
   bool RuleMatches(DR_Rule&          aRule,
                      DR_FrameTreeNode& aNode);
   bool GetToken(FILE* aFile,
@@ -10761,78 +10737,85 @@ struct DR_State
   nsTArray<DR_Rule*>          mWildRules;
   nsTArray<DR_FrameTypeInfo>  mFrameTypeTable;
   // reflow specific state
   nsTArray<DR_FrameTreeNode*> mFrameTreeLeaves;
 };
 
 static DR_State *DR_state; // the one and only DR_State
 
-struct DR_RulePart 
-{
-  explicit DR_RulePart(nsIAtom* aFrameType) : mFrameType(aFrameType), mNext(0) {}
+struct DR_RulePart
+{
+  explicit DR_RulePart(FrameType aFrameType)
+    : mFrameType(aFrameType)
+    , mNext(0)
+  {}
+
   void Destroy();
 
-  nsIAtom*     mFrameType;
+  FrameType mFrameType;
   DR_RulePart* mNext;
 };
 
 void DR_RulePart::Destroy()
 {
   if (mNext) {
     mNext->Destroy();
   }
   delete this;
 }
 
-struct DR_Rule 
+struct DR_Rule
 {
   DR_Rule() : mLength(0), mTarget(nullptr), mDisplay(false) {
     MOZ_COUNT_CTOR(DR_Rule);
   }
   ~DR_Rule() {
     if (mTarget) mTarget->Destroy();
     MOZ_COUNT_DTOR(DR_Rule);
   }
-  void AddPart(nsIAtom* aFrameType);
+  void AddPart(FrameType aFrameType);
 
   uint32_t      mLength;
   DR_RulePart*  mTarget;
   bool          mDisplay;
 };
 
-void DR_Rule::AddPart(nsIAtom* aFrameType)
+void
+DR_Rule::AddPart(FrameType aFrameType)
 {
   DR_RulePart* newPart = new DR_RulePart(aFrameType);
   newPart->mNext = mTarget;
   mTarget = newPart;
   mLength++;
 }
 
 struct DR_FrameTypeInfo
 {
-  DR_FrameTypeInfo(nsIAtom* aFrmeType, const char* aFrameNameAbbrev, const char* aFrameName);
-  ~DR_FrameTypeInfo() { 
+  DR_FrameTypeInfo(FrameType aFrameType,
+                   const char* aFrameNameAbbrev,
+                   const char* aFrameName);
+  ~DR_FrameTypeInfo() {
       int32_t numElements;
       numElements = mRules.Length();
       for (int32_t i = numElements - 1; i >= 0; i--) {
         delete mRules.ElementAt(i);
       }
    }
 
-  nsIAtom*    mType;
+  FrameType   mType;
   char        mNameAbbrev[16];
   char        mName[32];
   nsTArray<DR_Rule*> mRules;
 private:
   DR_FrameTypeInfo& operator=(const DR_FrameTypeInfo&) = delete;
 };
 
-DR_FrameTypeInfo::DR_FrameTypeInfo(nsIAtom* aFrameType, 
-                                   const char* aFrameNameAbbrev, 
+DR_FrameTypeInfo::DR_FrameTypeInfo(FrameType aFrameType,
+                                   const char* aFrameNameAbbrev,
                                    const char* aFrameName)
 {
   mType = aFrameType;
   PL_strncpyz(mNameAbbrev, aFrameNameAbbrev, sizeof(mNameAbbrev));
   PL_strncpyz(mName, aFrameName, sizeof(mName));
 }
 
 struct DR_FrameTreeNode
@@ -10967,30 +10950,30 @@ bool DR_State::GetToken(FILE* aFile,
 
 DR_Rule* DR_State::ParseRule(FILE* aFile)
 {
   char buf[128];
   int32_t doDisplay;
   DR_Rule* rule = nullptr;
   while (GetToken(aFile, buf, sizeof(buf))) {
     if (GetNumber(buf, doDisplay)) {
-      if (rule) { 
+      if (rule) {
         rule->mDisplay = !!doDisplay;
         break;
       }
       else {
         printf("unexpected token - %s \n", buf);
       }
     }
     else {
       if (!rule) {
         rule = new DR_Rule;
       }
       if (strcmp(buf, "*") == 0) {
-        rule->AddPart(nullptr);
+        rule->AddPart(FrameType::None);
       }
       else {
         DR_FrameTypeInfo* info = GetFrameTypeInfo(buf);
         if (info) {
           rule->AddPart(info->mType);
         }
         else {
           printf("invalid frame type - %s \n", buf);
@@ -11019,44 +11002,43 @@ void DR_State::AddRule(nsTArray<DR_Rule*
 void DR_State::ParseRulesFile()
 {
   char* path = PR_GetEnv("GECKO_DISPLAY_REFLOW_RULES_FILE");
   if (path) {
     FILE* inFile = fopen(path, "r");
     if (inFile) {
       for (DR_Rule* rule = ParseRule(inFile); rule; rule = ParseRule(inFile)) {
         if (rule->mTarget) {
-          nsIAtom* fType = rule->mTarget->mFrameType;
-          if (fType) {
-            DR_FrameTypeInfo* info = GetFrameTypeInfo(fType);
-            if (info) {
-              AddRule(info->mRules, *rule);
-            }
+          FrameType fType = rule->mTarget->mFrameType;
+          DR_FrameTypeInfo* info = GetFrameTypeInfo(fType);
+          if (info) {
+            AddRule(info->mRules, *rule);
           }
           else {
             AddRule(mWildRules, *rule);
           }
           mActive = true;
         }
       }
 
       fclose(inFile);
     }
   }
 }
 
-
-void DR_State::AddFrameTypeInfo(nsIAtom* aFrameType,
-                                const char* aFrameNameAbbrev,
-                                const char* aFrameName)
+void
+DR_State::AddFrameTypeInfo(FrameType aFrameType,
+                           const char* aFrameNameAbbrev,
+                           const char* aFrameName)
 {
   mFrameTypeTable.AppendElement(DR_FrameTypeInfo(aFrameType, aFrameNameAbbrev, aFrameName));
 }
 
-DR_FrameTypeInfo* DR_State::GetFrameTypeInfo(nsIAtom* aFrameType)
+DR_FrameTypeInfo*
+DR_State::GetFrameTypeInfo(FrameType aFrameType)
 {
   int32_t numEntries = mFrameTypeTable.Length();
   NS_ASSERTION(numEntries != 0, "empty FrameTypeTable");
   for (int32_t i = 0; i < numEntries; i++) {
     DR_FrameTypeInfo& info = mFrameTypeTable.ElementAt(i);
     if (info.mType == aFrameType) {
       return &info;
     }
@@ -11073,61 +11055,61 @@ DR_FrameTypeInfo* DR_State::GetFrameType
     if ((strcmp(aFrameName, info.mName) == 0) || (strcmp(aFrameName, info.mNameAbbrev) == 0)) {
       return &info;
     }
   }
   return &mFrameTypeTable.ElementAt(numEntries - 1); // return unknown frame type
 }
 
 void DR_State::InitFrameTypeTable()
-{  
-  AddFrameTypeInfo(nsGkAtoms::blockFrame,            "block",     "block");
-  AddFrameTypeInfo(nsGkAtoms::brFrame,               "br",        "br");
-  AddFrameTypeInfo(nsGkAtoms::bulletFrame,           "bullet",    "bullet");
-  AddFrameTypeInfo(nsGkAtoms::colorControlFrame,     "color",     "colorControl");
-  AddFrameTypeInfo(nsGkAtoms::gfxButtonControlFrame, "button",    "gfxButtonControl");
-  AddFrameTypeInfo(nsGkAtoms::HTMLButtonControlFrame, "HTMLbutton",    "HTMLButtonControl");
-  AddFrameTypeInfo(nsGkAtoms::HTMLCanvasFrame,       "HTMLCanvas","HTMLCanvas");
-  AddFrameTypeInfo(nsGkAtoms::subDocumentFrame,      "subdoc",    "subDocument");
-  AddFrameTypeInfo(nsGkAtoms::imageFrame,            "img",       "image");
-  AddFrameTypeInfo(nsGkAtoms::inlineFrame,           "inline",    "inline");
-  AddFrameTypeInfo(nsGkAtoms::letterFrame,           "letter",    "letter");
-  AddFrameTypeInfo(nsGkAtoms::lineFrame,             "line",      "line");
-  AddFrameTypeInfo(nsGkAtoms::listControlFrame,      "select",    "select");
-  AddFrameTypeInfo(nsGkAtoms::objectFrame,           "obj",       "object");
-  AddFrameTypeInfo(nsGkAtoms::pageFrame,             "page",      "page");
-  AddFrameTypeInfo(nsGkAtoms::placeholderFrame,      "place",     "placeholder");
-  AddFrameTypeInfo(nsGkAtoms::canvasFrame,           "canvas",    "canvas");
-  AddFrameTypeInfo(nsGkAtoms::rootFrame,             "root",      "root");
-  AddFrameTypeInfo(nsGkAtoms::scrollFrame,           "scroll",    "scroll");
-  AddFrameTypeInfo(nsGkAtoms::tableCellFrame,        "cell",      "tableCell");
-  AddFrameTypeInfo(nsGkAtoms::bcTableCellFrame,      "bcCell",    "bcTableCell");
-  AddFrameTypeInfo(nsGkAtoms::tableColFrame,         "col",       "tableCol");
-  AddFrameTypeInfo(nsGkAtoms::tableColGroupFrame,    "colG",      "tableColGroup");
-  AddFrameTypeInfo(nsGkAtoms::tableFrame,            "tbl",       "table");
-  AddFrameTypeInfo(nsGkAtoms::tableWrapperFrame,     "tblW",      "tableWrapper");
-  AddFrameTypeInfo(nsGkAtoms::tableRowGroupFrame,    "rowG",      "tableRowGroup");
-  AddFrameTypeInfo(nsGkAtoms::tableRowFrame,         "row",       "tableRow");
-  AddFrameTypeInfo(nsGkAtoms::textInputFrame,        "textCtl",   "textInput");
-  AddFrameTypeInfo(nsGkAtoms::textFrame,             "text",      "text");
-  AddFrameTypeInfo(nsGkAtoms::viewportFrame,         "VP",        "viewport");
+{
+  AddFrameTypeInfo(FrameType::Block,            "block",     "block");
+  AddFrameTypeInfo(FrameType::Br,               "br",        "br");
+  AddFrameTypeInfo(FrameType::Bullet,           "bullet",    "bullet");
+  AddFrameTypeInfo(FrameType::ColorControl,     "color",     "colorControl");
+  AddFrameTypeInfo(FrameType::GfxButtonControl, "button",    "gfxButtonControl");
+  AddFrameTypeInfo(FrameType::HTMLButtonControl, "HTMLbutton",    "HTMLButtonControl");
+  AddFrameTypeInfo(FrameType::HTMLCanvas,       "HTMLCanvas","HTMLCanvas");
+  AddFrameTypeInfo(FrameType::SubDocument,      "subdoc",    "subDocument");
+  AddFrameTypeInfo(FrameType::Image,            "img",       "image");
+  AddFrameTypeInfo(FrameType::Inline,           "inline",    "inline");
+  AddFrameTypeInfo(FrameType::Letter,           "letter",    "letter");
+  AddFrameTypeInfo(FrameType::Line,             "line",      "line");
+  AddFrameTypeInfo(FrameType::ListControl,      "select",    "select");
+  AddFrameTypeInfo(FrameType::Object,           "obj",       "object");
+  AddFrameTypeInfo(FrameType::Page,             "page",      "page");
+  AddFrameTypeInfo(FrameType::Placeholder,      "place",     "placeholder");
+  AddFrameTypeInfo(FrameType::Canvas,           "canvas",    "canvas");
+  AddFrameTypeInfo(FrameType::Root,             "root",      "root");
+  AddFrameTypeInfo(FrameType::Scroll,           "scroll",    "scroll");
+  AddFrameTypeInfo(FrameType::TableCell,        "cell",      "tableCell");
+  AddFrameTypeInfo(FrameType::BCTableCell,      "bcCell",    "bcTableCell");
+  AddFrameTypeInfo(FrameType::TableCol,         "col",       "tableCol");
+  AddFrameTypeInfo(FrameType::TableColGroup,    "colG",      "tableColGroup");
+  AddFrameTypeInfo(FrameType::Table,            "tbl",       "table");
+  AddFrameTypeInfo(FrameType::TableWrapper,     "tblW",      "tableWrapper");
+  AddFrameTypeInfo(FrameType::TableRowGroup,    "rowG",      "tableRowGroup");
+  AddFrameTypeInfo(FrameType::TableRow,         "row",       "tableRow");
+  AddFrameTypeInfo(FrameType::TextInput,        "textCtl",   "textInput");
+  AddFrameTypeInfo(FrameType::Text,             "text",      "text");
+  AddFrameTypeInfo(FrameType::Viewport,         "VP",        "viewport");
 #ifdef MOZ_XUL
-  AddFrameTypeInfo(nsGkAtoms::XULLabelFrame,         "XULLabel",  "XULLabel");
-  AddFrameTypeInfo(nsGkAtoms::boxFrame,              "Box",       "Box");
-  AddFrameTypeInfo(nsGkAtoms::sliderFrame,           "Slider",    "Slider");
-  AddFrameTypeInfo(nsGkAtoms::popupSetFrame,         "PopupSet",  "PopupSet");
+  AddFrameTypeInfo(FrameType::XULLabel,         "XULLabel",  "XULLabel");
+  AddFrameTypeInfo(FrameType::Box,              "Box",       "Box");
+  AddFrameTypeInfo(FrameType::Slider,           "Slider",    "Slider");
+  AddFrameTypeInfo(FrameType::PopupSet,         "PopupSet",  "PopupSet");
 #endif
-  AddFrameTypeInfo(nullptr,                          "unknown",   "unknown");
+  AddFrameTypeInfo(FrameType::None,             "unknown",   "unknown");
 }
 
 
 void DR_State::DisplayFrameTypeInfo(nsIFrame* aFrame,
                                     int32_t   aIndent)
-{ 
-  DR_FrameTypeInfo* frameTypeInfo = GetFrameTypeInfo(aFrame->GetType());
+{
+  DR_FrameTypeInfo* frameTypeInfo = GetFrameTypeInfo(aFrame->Type());
   if (frameTypeInfo) {
     for (int32_t i = 0; i < aIndent; i++) {
       printf(" ");
     }
     if(!strcmp(frameTypeInfo->mNameAbbrev, "unknown")) {
       if (aFrame) {
        nsAutoString  name;
        aFrame->GetFrameName(name);
@@ -11138,49 +11120,48 @@ void DR_State::DisplayFrameTypeInfo(nsIF
       }
     }
     else {
       printf("%s %p ", frameTypeInfo->mNameAbbrev, (void*)aFrame);
     }
   }
 }
 
-bool DR_State::RuleMatches(DR_Rule&          aRule,
-                             DR_FrameTreeNode& aNode)
+bool
+DR_State::RuleMatches(DR_Rule& aRule, DR_FrameTreeNode& aNode)
 {
   NS_ASSERTION(aRule.mTarget, "program error");
 
   DR_RulePart* rulePart;
   DR_FrameTreeNode* parentNode;
   for (rulePart = aRule.mTarget->mNext, parentNode = aNode.mParent;
        rulePart && parentNode;
        rulePart = rulePart->mNext, parentNode = parentNode->mParent) {
-    if (rulePart->mFrameType) {
+    if (rulePart->mFrameType != FrameType::None) {
       if (parentNode->mFrame) {
-        if (rulePart->mFrameType != parentNode->mFrame->GetType()) {
+        if (rulePart->mFrameType != parentNode->mFrame->Type()) {
           return false;
         }
-      }
-      else NS_ASSERTION(false, "program error");
+      } else NS_ASSERTION(false, "program error");
     }
     // else wild card match
   }
   return true;
 }
 
 void DR_State::FindMatchingRule(DR_FrameTreeNode& aNode)
 {
   if (!aNode.mFrame) {
     NS_ASSERTION(false, "invalid DR_FrameTreeNode \n");
     return;
   }
 
   bool matchingRule = false;
 
-  DR_FrameTypeInfo* info = GetFrameTypeInfo(aNode.mFrame->GetType());
+  DR_FrameTypeInfo* info = GetFrameTypeInfo(aNode.mFrame->Type());
   NS_ASSERTION(info, "program error");
   int32_t numRules = info->mRules.Length();
   for (int32_t ruleX = 0; ruleX < numRules; ruleX++) {
     DR_Rule* rule = info->mRules.ElementAt(ruleX);
     if (rule && RuleMatches(*rule, aNode)) {
       aNode.mDisplay = rule->mDisplay;
       matchingRule = true;
       break;
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -195,17 +195,16 @@ public:
   nsIFrame* GetPrevContinuation() const override;
   void SetPrevContinuation(nsIFrame*) override;
   nsIFrame* GetNextContinuation() const override;
   void SetNextContinuation(nsIFrame*) override;
   nsIFrame* GetPrevInFlowVirtual() const override;
   void SetPrevInFlow(nsIFrame*) override;
   nsIFrame* GetNextInFlowVirtual() const override;
   void SetNextInFlow(nsIFrame*) override;
-  nsIAtom* GetType() const override;
 
   nsresult GetSelectionController(nsPresContext *aPresContext,
                                   nsISelectionController **aSelCon) override;
 
   FrameSearchResult PeekOffsetNoAmount(bool aForward,
                                        int32_t* aOffset) override;
   FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
                                         bool aRespectClusters = true) override;
@@ -575,17 +574,17 @@ public:
    *                           Must not be null.
    * @param aChildPseudo the child's pseudo type, if any.
    */
   static nsIFrame*
   CorrectStyleParentFrame(nsIFrame* aProspectiveParent, nsIAtom* aChildPseudo);
 
 protected:
   // Protected constructor and destructor
-  explicit nsFrame(nsStyleContext* aContext);
+  explicit nsFrame(nsStyleContext* aContext, mozilla::FrameType aType);
   virtual ~nsFrame();
 
   /**
    * To be called by |BuildDisplayLists| of this class or derived classes to add
    * a translucent overlay if this frame's content is selected.
    * @param aContentType an nsISelectionDisplay DISPLAY_ constant identifying
    * which kind of content this is for
    */
@@ -621,52 +620,50 @@ public:
    * Returns true if aFrame should apply overflow clipping.
    */
   static bool ShouldApplyOverflowClipping(const nsIFrame* aFrame,
                                           const nsStyleDisplay* aDisp)
   {
     // clip overflow:-moz-hidden-unscrollable, except for nsListControlFrame,
     // which is an nsHTMLScrollFrame.
     if (MOZ_UNLIKELY(aDisp->mOverflowX == NS_STYLE_OVERFLOW_CLIP &&
-                     aFrame->GetType() != nsGkAtoms::listControlFrame)) {
+                     !aFrame->IsListControlFrame())) {
       return true;
     }
 
     // and overflow:hidden that we should interpret as -moz-hidden-unscrollable
     if (aDisp->mOverflowX == NS_STYLE_OVERFLOW_HIDDEN &&
         aDisp->mOverflowY == NS_STYLE_OVERFLOW_HIDDEN) {
       // REVIEW: these are the frame types that set up clipping.
-      nsIAtom* type = aFrame->GetType();
-      if (type == nsGkAtoms::tableFrame ||
-          type == nsGkAtoms::tableCellFrame ||
-          type == nsGkAtoms::bcTableCellFrame ||
-          type == nsGkAtoms::svgOuterSVGFrame ||
-          type == nsGkAtoms::svgInnerSVGFrame ||
-          type == nsGkAtoms::svgForeignObjectFrame) {
+      mozilla::FrameType type = aFrame->Type();
+      if (type == mozilla::FrameType::Table ||
+          type == mozilla::FrameType::TableCell ||
+          type == mozilla::FrameType::BCTableCell ||
+          type == mozilla::FrameType::SVGOuterSVG ||
+          type == mozilla::FrameType::SVGInnerSVG ||
+          type == mozilla::FrameType::SVGForeignObject) {
         return true;
       }
       if (aFrame->IsFrameOfType(nsIFrame::eReplacedContainsBlock)) {
-        if (type == nsGkAtoms::textInputFrame) {
+        if (type == mozilla::FrameType::TextInput) {
           // It always has an anonymous scroll frame that handles any overflow.
           return false;
         }
         return true;
       }
     }
 
     if ((aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
       return false;
     }
 
     // If we're paginated and a block, and have NS_BLOCK_CLIP_PAGINATED_OVERFLOW
     // set, then we want to clip our overflow.
-    return
-      (aFrame->GetStateBits() & NS_BLOCK_CLIP_PAGINATED_OVERFLOW) != 0 &&
-      aFrame->PresContext()->IsPaginated() &&
-      aFrame->GetType() == nsGkAtoms::blockFrame;
+    return (aFrame->GetStateBits() & NS_BLOCK_CLIP_PAGINATED_OVERFLOW) != 0 &&
+           aFrame->PresContext()->IsPaginated() && aFrame->IsBlockFrame();
   }
 
   nsILineIterator* GetLineIterator() override;
 
 protected:
 
   // Test if we are selecting a table object:
   //  Most table/cell selection requires that Ctrl (Cmd on Mac) key is down 
--- a/layout/generic/nsFrameList.cpp
+++ b/layout/generic/nsFrameList.cpp
@@ -355,17 +355,17 @@ nsFrameList::GetPrevVisualFor(nsIFrame* 
   if (!parent)
     return aFrame ? aFrame->GetPrevSibling() : LastChild();
 
   nsBidiDirection paraDir = nsBidiPresUtils::ParagraphDirection(mFirstChild);
 
   nsAutoLineIterator iter = parent->GetLineIterator();
   if (!iter) {
     // Parent is not a block Frame
-    if (parent->GetType() == nsGkAtoms::lineFrame) {
+    if (parent->IsLineFrame()) {
       // Line frames are not bidi-splittable, so need to consider bidi reordering
       if (paraDir == NSBIDI_LTR) {
         return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1);
       } else { // RTL
         return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1);
       }
     } else {
       // Just get the next or prev sibling, depending on block and frame direction.
@@ -427,17 +427,17 @@ nsFrameList::GetNextVisualFor(nsIFrame* 
   if (!parent)
     return aFrame ? aFrame->GetPrevSibling() : mFirstChild;
 
   nsBidiDirection paraDir = nsBidiPresUtils::ParagraphDirection(mFirstChild);
 
   nsAutoLineIterator iter = parent->GetLineIterator();
   if (!iter) { 
     // Parent is not a block Frame
-    if (parent->GetType() == nsGkAtoms::lineFrame) {
+    if (parent->IsLineFrame()) {
       // Line frames are not bidi-splittable, so need to consider bidi reordering
       if (paraDir == NSBIDI_LTR) {
         return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1);
       } else { // RTL
         return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1);
       }
     } else {
       // Just get the next or prev sibling, depending on block and frame direction.
--- a/layout/generic/nsFrameSetFrame.cpp
+++ b/layout/generic/nsFrameSetFrame.cpp
@@ -78,17 +78,17 @@ void nsFramesetDrag::UnSet()
   mIndex    = -1;
   mChange   = 0;
   mSource   = nullptr;
 }
 
 /*******************************************************************************
  * nsHTMLFramesetBorderFrame
  ******************************************************************************/
-class nsHTMLFramesetBorderFrame : public nsLeafFrame
+class nsHTMLFramesetBorderFrame final : public nsLeafFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
@@ -129,17 +129,17 @@ protected:
   bool mVertical;
   bool mVisibility;
   bool mCanResize;
   friend class nsHTMLFramesetFrame;
 };
 /*******************************************************************************
  * nsHTMLFramesetBlankFrame
  ******************************************************************************/
-class nsHTMLFramesetBlankFrame : public nsLeafFrame
+class nsHTMLFramesetBlankFrame final : public nsLeafFrame
 {
 public:
   NS_DECL_QUERYFRAME_TARGET(nsHTMLFramesetBlankFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
@@ -153,33 +153,36 @@ public:
                                 const nsDisplayListSet& aLists) override;
 
   virtual void Reflow(nsPresContext*           aPresContext,
                           ReflowOutput&     aDesiredSize,
                           const ReflowInput& aReflowInput,
                           nsReflowStatus&          aStatus) override;
 
 protected:
-  explicit nsHTMLFramesetBlankFrame(nsStyleContext* aContext) : nsLeafFrame(aContext) {}
+  explicit nsHTMLFramesetBlankFrame(nsStyleContext* aContext)
+    : nsLeafFrame(aContext, FrameType::None)
+  {}
+
   virtual ~nsHTMLFramesetBlankFrame();
   virtual nscoord GetIntrinsicISize() override;
   virtual nscoord GetIntrinsicBSize() override;
 
   friend class nsHTMLFramesetFrame;
   friend class nsHTMLFrameset;
 };
 
 /*******************************************************************************
  * nsHTMLFramesetFrame
  ******************************************************************************/
 bool    nsHTMLFramesetFrame::gDragInProgress = false;
 #define DEFAULT_BORDER_WIDTH_PX 6
 
 nsHTMLFramesetFrame::nsHTMLFramesetFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::FrameSet)
 {
   mNumRows             = 0;
   mNumCols             = 0;
   mEdgeVisibility      = 0;
   mParentFrameborder   = eFrameborder_Yes; // default
   mParentBorderWidth   = -1; // default not set
   mParentBorderColor   = NO_COLOR; // default not set
   mFirstDragPoint.x     = mFirstDragPoint.y = 0;
@@ -1086,22 +1089,16 @@ nsHTMLFramesetFrame::Reflow(nsPresContex
   mDrag.UnSet();
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
   FinishAndStoreOverflow(&aDesiredSize);
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
-nsIAtom*
-nsHTMLFramesetFrame::GetType() const
-{
-  return nsGkAtoms::frameSetFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsHTMLFramesetFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Frameset"), aResult);
 }
 #endif
 
@@ -1333,19 +1330,22 @@ NS_NewHTMLFramesetFrame(nsIPresShell* aP
 
 NS_IMPL_FRAMEARENA_HELPERS(nsHTMLFramesetFrame)
 
 /*******************************************************************************
  * nsHTMLFramesetBorderFrame
  ******************************************************************************/
 nsHTMLFramesetBorderFrame::nsHTMLFramesetBorderFrame(nsStyleContext* aContext,
                                                      int32_t aWidth,
-                                                     bool    aVertical,
-                                                     bool    aVisibility)
-  : nsLeafFrame(aContext), mWidth(aWidth), mVertical(aVertical), mVisibility(aVisibility)
+                                                     bool aVertical,
+                                                     bool aVisibility)
+  : nsLeafFrame(aContext, FrameType::None)
+  , mWidth(aWidth)
+  , mVertical(aVertical)
+  , mVisibility(aVisibility)
 {
    mCanResize    = true;
    mColor        = NO_COLOR;
    mPrevNeighbor = 0;
    mNextNeighbor = 0;
 }
 
 nsHTMLFramesetBorderFrame::~nsHTMLFramesetBorderFrame()
--- a/layout/generic/nsFrameSetFrame.h
+++ b/layout/generic/nsFrameSetFrame.h
@@ -100,17 +100,16 @@ public:
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
   virtual void Reflow(nsPresContext*           aPresContext,
                       ReflowOutput&     aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus&          aStatus) override;
 
-  virtual nsIAtom* GetType() const override;
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   virtual bool IsLeaf() const override;
   
   void StartMouseDrag(nsPresContext* aPresContext,
                       nsHTMLFramesetBorderFrame* aBorder,
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -104,19 +104,21 @@ GetOverflowChange(const nsRect& aCurScro
 nsHTMLScrollFrame*
 NS_NewHTMLScrollFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, bool aIsRoot)
 {
   return new (aPresShell) nsHTMLScrollFrame(aContext, aIsRoot);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsHTMLScrollFrame)
 
-nsHTMLScrollFrame::nsHTMLScrollFrame(nsStyleContext* aContext, bool aIsRoot)
-  : nsContainerFrame(aContext),
-    mHelper(ALLOW_THIS_IN_INITIALIZER_LIST(this), aIsRoot)
+nsHTMLScrollFrame::nsHTMLScrollFrame(nsStyleContext* aContext,
+                                     FrameType aType,
+                                     bool aIsRoot)
+  : nsContainerFrame(aContext, aType)
+  , mHelper(ALLOW_THIS_IN_INITIALIZER_LIST(this), aIsRoot)
 {
 }
 
 void
 nsHTMLScrollFrame::ScrollbarActivityStarted() const
 {
   if (mHelper.mScrollbarActivity) {
     mHelper.mScrollbarActivity->ActivityStarted();
@@ -192,22 +194,16 @@ nsHTMLScrollFrame::RemoveFrame(ChildList
 }
 
 nsSplittableType
 nsHTMLScrollFrame::GetSplittableType() const
 {
   return NS_FRAME_NOT_SPLITTABLE;
 }
 
-nsIAtom*
-nsHTMLScrollFrame::GetType() const
-{
-  return nsGkAtoms::scrollFrame;
-}
-
 /**
  HTML scrolling implementation
 
  All other things being equal, we prefer layouts with fewer scrollbars showing.
 */
 
 namespace mozilla {
 
@@ -621,17 +617,17 @@ nsHTMLScrollFrame::GuessVScrollbarNeeded
 
   // If this is the initial reflow, guess false because usually
   // we have very little content by then.
   if (InInitialReflow())
     return false;
 
   if (mHelper.mIsRoot) {
     nsIFrame *f = mHelper.mScrolledFrame->PrincipalChildList().FirstChild();
-    if (f && f->GetType() == nsGkAtoms::svgOuterSVGFrame &&
+    if (f && f->IsSVGOuterSVGFrame() &&
         static_cast<nsSVGOuterSVGFrame*>(f)->VerticalScrollbarNotNeeded()) {
       // Common SVG case - avoid a bad guess.
       return false;
     }
     // Assume that there will be a scrollbar; it seems to me
     // that 'most pages' do have a scrollbar, and anyway, it's cheaper
     // to do an extra reflow for the pages that *don't* need a
     // scrollbar (because on average they will have less content).
@@ -1158,19 +1154,20 @@ NS_NewXULScrollFrame(nsIPresShell* aPres
 {
   return new (aPresShell) nsXULScrollFrame(aContext, aIsRoot,
                                            aClipAllDescendants);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsXULScrollFrame)
 
 nsXULScrollFrame::nsXULScrollFrame(nsStyleContext* aContext,
-                                   bool aIsRoot, bool aClipAllDescendants)
-  : nsBoxFrame(aContext, aIsRoot),
-    mHelper(ALLOW_THIS_IN_INITIALIZER_LIST(this), aIsRoot)
+                                   bool aIsRoot,
+                                   bool aClipAllDescendants)
+  : nsBoxFrame(aContext, FrameType::Scroll, aIsRoot)
+  , mHelper(ALLOW_THIS_IN_INITIALIZER_LIST(this), aIsRoot)
 {
   SetXULLayoutManager(nullptr);
   mHelper.mClipAllDescendants = aClipAllDescendants;
 }
 
 void
 nsXULScrollFrame::ScrollbarActivityStarted() const
 {
@@ -1528,22 +1525,16 @@ nsXULScrollFrame::GetSplittableType() co
 
 nsresult
 nsXULScrollFrame::GetXULPadding(nsMargin& aMargin)
 {
   aMargin.SizeTo(0,0,0,0);
   return NS_OK;
 }
 
-nsIAtom*
-nsXULScrollFrame::GetType() const
-{
-  return nsGkAtoms::scrollFrame;
-}
-
 nscoord
 nsXULScrollFrame::GetXULBoxAscent(nsBoxLayoutState& aState)
 {
   if (!mHelper.mScrolledFrame)
     return 0;
 
   nscoord ascent = mHelper.mScrolledFrame->GetXULBoxAscent(aState);
   nsMargin m(0,0,0,0);
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -966,23 +966,16 @@ public:
     return NS_OK;
   }
   NS_IMETHOD RestoreState(nsPresState* aState) override {
     NS_ENSURE_ARG_POINTER(aState);
     mHelper.RestoreState(aState);
     return NS_OK;
   }
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::scrollFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   // nsIScrollbarMediator
   virtual void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection,
                             nsIScrollbarMediator::ScrollSnapMode aSnap
                               = nsIScrollbarMediator::DISABLE_SNAP) override {
     mHelper.ScrollByPage(aScrollbar, aDirection, aSnap);
   }
   virtual void ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection,
                              nsIScrollbarMediator::ScrollSnapMode aSnap
@@ -1061,17 +1054,23 @@ public:
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() override;
 #endif
 
 protected:
-  nsHTMLScrollFrame(nsStyleContext* aContext, bool aIsRoot);
+  nsHTMLScrollFrame(nsStyleContext* aContext, bool aIsRoot)
+    : nsHTMLScrollFrame(aContext, mozilla::FrameType::Scroll, aIsRoot)
+  {}
+
+  nsHTMLScrollFrame(nsStyleContext* aContext,
+                    mozilla::FrameType aType,
+                    bool aIsRoot);
   void SetSuppressScrollbarUpdate(bool aSuppress) {
     mHelper.mSupppressScrollbarUpdate = aSuppress;
   }
   bool GuessHScrollbarNeeded(const ScrollReflowInput& aState);
   bool GuessVScrollbarNeeded(const ScrollReflowInput& aState);
 
   bool IsScrollbarUpdateSuppressed() const {
     return mHelper.mSupppressScrollbarUpdate;
@@ -1387,23 +1386,16 @@ public:
     return NS_OK;
   }
   NS_IMETHOD RestoreState(nsPresState* aState) override {
     NS_ENSURE_ARG_POINTER(aState);
     mHelper.RestoreState(aState);
     return NS_OK;
   }
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::scrollFrame
-   */
-  virtual nsIAtom* GetType() const override;
-  
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     // Override bogus IsFrameOfType in nsBoxFrame.
     if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced))
       return false;
     return nsBoxFrame::IsFrameOfType(aFlags);
   }
 
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -4866,20 +4866,19 @@ nsGridContainerFrame::GetNearestFragment
   for ( ; cbRI; cbRI = cbRI->mCBReflowInput) {
     nsIScrollableFrame* sf = do_QueryFrame(cbRI->mFrame);
     if (sf) {
       break;
     }
     if (wm.IsOrthogonalTo(cbRI->GetWritingMode())) {
       break;
     }
-    nsIAtom* frameType = cbRI->mFrame->GetType();
-    if ((frameType == nsGkAtoms::canvasFrame &&
-         PresContext()->IsPaginated()) ||
-        frameType == nsGkAtoms::columnSetFrame) {
+    FrameType frameType = cbRI->mFrame->Type();
+    if ((frameType == FrameType::Canvas && PresContext()->IsPaginated()) ||
+        frameType == FrameType::ColumnSet) {
       data.emplace();
       data->mIsTopOfPage = gridRI->mFlags.mIsTopOfPage;
       data->mToFragmentainerEnd = aState.mFragBStart +
         gridRI->AvailableBSize() - aState.mBorderPadding.BStart(wm);
       const auto numRows = aState.mRows.mSizes.Length();
       data->mCanBreakAtStart =
         numRows > 0 && aState.mRows.mSizes[0].mPosition > 0;
       nscoord bSize = gridRI->ComputedBSize();
@@ -4913,18 +4912,17 @@ nsGridContainerFrame::ReflowInFlowChild(
                                         nsReflowStatus&        aStatus)
 {
   nsPresContext* pc = PresContext();
   nsStyleContext* containerSC = StyleContext();
   WritingMode wm = aState.mReflowInput->GetWritingMode();
   LogicalMargin pad(aState.mReflowInput->ComputedLogicalPadding());
   const LogicalPoint padStart(wm, pad.IStart(wm), pad.BStart(wm));
   const bool isGridItem = !!aGridItemInfo;
-  auto childType = aChild->GetType();
-  MOZ_ASSERT(isGridItem == (childType != nsGkAtoms::placeholderFrame));
+  MOZ_ASSERT(isGridItem == !aChild->IsPlaceholderFrame());
   LogicalRect cb(wm);
   WritingMode childWM = aChild->GetWritingMode();
   bool isConstrainedBSize = false;
   nscoord toFragmentainerEnd;
   // The part of the child's grid area that's in previous container fragments.
   nscoord consumedGridAreaBSize = 0;
   const bool isOrthogonal = wm.IsOrthogonalTo(childWM);
   if (MOZ_LIKELY(isGridItem)) {
@@ -5031,17 +5029,17 @@ nsGridContainerFrame::ReflowInFlowChild(
   // FIXME (perf): It would be faster to do this only if the previous
   // reflow of the child was a measuring reflow, and only if the child
   // does some of the things that are affected by
   // ReflowInput::COMPUTE_SIZE_USE_AUTO_BSIZE.
   childRI.SetBResize(true);
 
   // A table-wrapper needs to propagate the CB size we give it to its
   // inner table frame later.  @see nsTableWrapperFrame::InitChildReflowInput.
-  if (childType == nsGkAtoms::tableWrapperFrame) {
+  if (aChild->IsTableWrapperFrame()) {
     const auto& props = aChild->Properties();
     LogicalSize* cb = props.Get(nsTableWrapperFrame::GridItemCBSizeProperty());
     if (!cb) {
       cb = new LogicalSize(childWM);
       props.Set(nsTableWrapperFrame::GridItemCBSizeProperty(), cb);
     }
     *cb = percentBasis;
   }
@@ -5119,17 +5117,17 @@ nsGridContainerFrame::ReflowInFragmentai
 
   // Collect our grid items and sort them in row order.  Collect placeholders
   // and put them in a separate array.
   nsTArray<const GridItemInfo*> sortedItems(aState.mGridItems.Length());
   nsTArray<nsIFrame*> placeholders(aState.mAbsPosItems.Length());
   aState.mIter.Reset(CSSOrderAwareFrameIterator::eIncludeAll);
   for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
     nsIFrame* child = *aState.mIter;
-    if (child->GetType() != nsGkAtoms::placeholderFrame) {
+    if (!child->IsPlaceholderFrame()) {
       const GridItemInfo* info = &aState.mGridItems[aState.mIter.ItemIndex()];
       sortedItems.AppendElement(info);
     } else {
       placeholders.AppendElement(child);
     }
   }
   // NOTE: no need to use stable_sort here, there are no dependencies on
   // having content order between items on the same row in the code below.
@@ -5636,17 +5634,17 @@ nsGridContainerFrame::ReflowChildren(Gri
     aState.mInFragmentainer = true;
     bSize = ReflowInFragmentainer(aState, aContentArea, aDesiredSize, aStatus,
                                   *fragmentainer, containerSize);
   } else {
     aState.mIter.Reset(CSSOrderAwareFrameIterator::eIncludeAll);
     for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
       nsIFrame* child = *aState.mIter;
       const GridItemInfo* info = nullptr;
-      if (child->GetType() != nsGkAtoms::placeholderFrame) {
+      if (!child->IsPlaceholderFrame()) {
         info = &aState.mGridItems[aState.mIter.ItemIndex()];
       }
       ReflowInFlowChild(*aState.mIter, info, containerSize, Nothing(), nullptr,
                         aState, aContentArea, aDesiredSize, aStatus);
       MOZ_ASSERT(aStatus.IsComplete(), "child should be complete "
                  "in unconstrained reflow");
     }
   }
@@ -6350,22 +6348,16 @@ nsGridContainerFrame::MarkIntrinsicISize
   mCachedPrefISize = NS_INTRINSIC_WIDTH_UNKNOWN;
   mBaseline[0][0] = NS_INTRINSIC_WIDTH_UNKNOWN;
   mBaseline[0][1] = NS_INTRINSIC_WIDTH_UNKNOWN;
   mBaseline[1][0] = NS_INTRINSIC_WIDTH_UNKNOWN;
   mBaseline[1][1] = NS_INTRINSIC_WIDTH_UNKNOWN;
   nsContainerFrame::MarkIntrinsicISizesDirty();
 }
 
-nsIAtom*
-nsGridContainerFrame::GetType() const
-{
-  return nsGkAtoms::gridContainerFrame;
-}
-
 void
 nsGridContainerFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                        const nsRect&           aDirtyRect,
                                        const nsDisplayListSet& aLists)
 {
   DisplayBorderBackgroundOutline(aBuilder, aLists);
   if (GetPrevInFlow()) {
     DisplayOverflowContainers(aBuilder, aDirtyRect, aLists);
@@ -6850,18 +6842,17 @@ nsGridContainerFrame::GetGridFrameWithCo
   // Prepare a lambda function that we may need to call multiple times.
   auto GetGridContainerFrame = [](nsIFrame *aFrame) {
     // Return the aFrame's content insertion frame, iff it is
     // a grid container.
     nsGridContainerFrame* gridFrame = nullptr;
 
     if (aFrame) {
       nsIFrame* contentFrame = aFrame->GetContentInsertionFrame();
-      if (contentFrame &&
-          (contentFrame->GetType() == nsGkAtoms::gridContainerFrame)) {
+      if (contentFrame && (contentFrame->IsGridContainerFrame())) {
         gridFrame = static_cast<nsGridContainerFrame*>(contentFrame);
       }
     }
     return gridFrame;
   };
 
   nsGridContainerFrame* gridFrame = GetGridContainerFrame(aFrame);
   if (gridFrame) {
--- a/layout/generic/nsGridContainerFrame.h
+++ b/layout/generic/nsGridContainerFrame.h
@@ -93,17 +93,16 @@ public:
   // nsIFrame overrides
   void Reflow(nsPresContext*           aPresContext,
               ReflowOutput&     aDesiredSize,
               const ReflowInput& aReflowInput,
               nsReflowStatus&          aStatus) override;
   nscoord GetMinISize(nsRenderingContext* aRenderingContext) override;
   nscoord GetPrefISize(nsRenderingContext* aRenderingContext) override;
   void MarkIntrinsicISizesDirty() override;
-  nsIAtom* GetType() const override;
   bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsContainerFrame::IsFrameOfType(aFlags &
              ~nsIFrame::eCanContainOverflowContainers);
   }
 
   void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                         const nsRect&           aDirtyRect,
@@ -254,17 +253,17 @@ protected:
   struct LineRange;
   struct SharedGridData;
   struct TrackSizingFunctions;
   struct Tracks;
   struct TranslatedLineRange;
   friend nsContainerFrame* NS_NewGridContainerFrame(nsIPresShell* aPresShell,
                                                     nsStyleContext* aContext);
   explicit nsGridContainerFrame(nsStyleContext* aContext)
-    : nsContainerFrame(aContext)
+    : nsContainerFrame(aContext, mozilla::FrameType::GridContainer)
     , mCachedMinISize(NS_INTRINSIC_WIDTH_UNKNOWN)
     , mCachedPrefISize(NS_INTRINSIC_WIDTH_UNKNOWN)
   {
     mBaseline[0][0] = NS_INTRINSIC_WIDTH_UNKNOWN;
     mBaseline[0][1] = NS_INTRINSIC_WIDTH_UNKNOWN;
     mBaseline[1][0] = NS_INTRINSIC_WIDTH_UNKNOWN;
     mBaseline[1][1] = NS_INTRINSIC_WIDTH_UNKNOWN;
   }
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -384,25 +384,19 @@ nsHTMLCanvasFrame::BuildDisplayList(nsDi
 
   aLists.Content()->AppendNewToTop(
     new (aBuilder) nsDisplayCanvas(aBuilder, this));
 
   DisplaySelectionOverlay(aBuilder, aLists.Content(),
                           nsISelectionDisplay::DISPLAY_IMAGES);
 }
 
-nsIAtom*
-nsHTMLCanvasFrame::GetType() const
-{
-  return nsGkAtoms::HTMLCanvasFrame;
-}
-
 // get the offset into the content area of the image where aImg starts if it is a continuation.
 // from nsImageFrame
-nscoord 
+nscoord
 nsHTMLCanvasFrame::GetContinuationOffset(nscoord* aWidth) const
 {
   nscoord offset = 0;
   if (aWidth) {
     *aWidth = 0;
   }
 
   if (GetPrevInFlow()) {
--- a/layout/generic/nsHTMLCanvasFrame.h
+++ b/layout/generic/nsHTMLCanvasFrame.h
@@ -20,30 +20,31 @@ class LayerManager;
 } // namespace mozilla
 
 class nsPresContext;
 class nsDisplayItem;
 class nsAString;
 
 nsIFrame* NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
 
-class nsHTMLCanvasFrame : public nsContainerFrame
+class nsHTMLCanvasFrame final : public nsContainerFrame
 {
 public:
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
   typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
 
   NS_DECL_QUERYFRAME_TARGET(nsHTMLCanvasFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   explicit nsHTMLCanvasFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
-    , mBorderPadding(GetWritingMode()) {}
+    : nsContainerFrame(aContext, mozilla::FrameType::HTMLCanvas)
+    , mBorderPadding(GetWritingMode())
+  {}
 
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
@@ -77,18 +78,16 @@ public:
                       nsReflowStatus&          aStatus) override;
 
   nsRect GetInnerArea() const;
 
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() override;
 #endif
 
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsSplittableFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing));
   }
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -160,16 +160,26 @@ typedef uint32_t nsSplittableType;
 // 1 million CSS pixels less than our max app unit measure.
 // For reflowing with an "infinite" available inline space per [css-sizing].
 // (reflowing with an NS_UNCONSTRAINEDSIZE available inline size isn't allowed
 //  and leads to assertions)
 #define INFINITE_ISIZE_COORD nscoord(NS_MAXSIZE - (1000000*60))
 
 //----------------------------------------------------------------------
 
+namespace mozilla {
+
+enum class FrameType : uint8_t {
+#define FRAME_TYPE(ty_) ty_,
+#include "mozilla/FrameTypeList.h"
+#undef FRAME_TYPE
+};
+
+} // namespace mozilla
+
 enum nsSelectionAmount {
   eSelectCharacter = 0, // a single Unicode character;
                         // do not use this (prefer Cluster) unless you
                         // are really sure it's what you want
   eSelectCluster   = 1, // a grapheme cluster: this is usually the right
                         // choice for movement or selection by "character"
                         // as perceived by the user
   eSelectWord      = 2,
@@ -587,23 +597,24 @@ public:
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::Matrix Matrix;
   typedef mozilla::gfx::Matrix4x4 Matrix4x4;
   typedef mozilla::Sides Sides;
   typedef mozilla::LogicalSides LogicalSides;
 
   NS_DECL_QUERYFRAME_TARGET(nsIFrame)
 
-  nsIFrame()
+  explicit nsIFrame(mozilla::FrameType aType)
     : mRect()
     , mContent(nullptr)
     , mStyleContext(nullptr)
     , mParent(nullptr)
     , mNextSibling(nullptr)
     , mPrevSibling(nullptr)
+    , mType(aType)
   {
     mozilla::PodZero(&mOverflow);
   }
 
   nsPresContext* PresContext() const {
     return StyleContext()->PresContext();
   }
 
@@ -2618,21 +2629,26 @@ public:
   /**
    * Same as GetNearestWidget() above but uses an outparam to return the offset
    * of this frame to the returned widget expressed in appunits of |this| (the
    * widget might be in a different document with a different zoom).
    */
   nsIWidget* GetNearestWidget(nsPoint& aOffset) const;
 
   /**
-   * Get the "type" of the frame. May return nullptr.
+   * Get the "type" of the frame.
    *
-   * @see nsGkAtoms
+   * @see mozilla::FrameType
    */
-  virtual nsIAtom* GetType() const = 0;
+  mozilla::FrameType Type() const { return mType; }
+
+#define FRAME_TYPE(name_)                                                      \
+  bool Is##name_##Frame() const { return mType == mozilla::FrameType::name_; }
+#include "mozilla/FrameTypeList.h"
+#undef FRAME_TYPE
 
   /**
    * Returns a transformation matrix that converts points in this frame's
    * coordinate space to points in some ancestor frame's coordinate space.
    * The frame decides which ancestor it will use as a reference point.
    * If this frame has no ancestor, aOutAncestor will be set to null.
    *
    * @param aStopAtAncestor don't look further than aStopAtAncestor. If null,
@@ -3783,16 +3799,19 @@ protected:
   union {
     uint32_t     mType;
     VisualDeltas mVisualDeltas;
   } mOverflow;
 
   /** @see GetWritingMode() */
   mozilla::WritingMode mWritingMode;
 
+  /** The type of the frame. */
+  mozilla::FrameType mType;
+
   // Helpers
   /**
    * Can we stop inside this frame when we're skipping non-rendered whitespace?
    * @param  aForward [in] Are we moving forward (or backward) in content order.
    * @param  aOffset [in/out] At what offset into the frame to start looking.
    *         on output - what offset was reached (whether or not we found a place to stop).
    * @return STOP: An appropriate offset was found within this frame,
    *         and is given by aOffset.
--- a/layout/generic/nsIFrameInlines.h
+++ b/layout/generic/nsIFrameInlines.h
@@ -11,27 +11,24 @@
 #include "nsPlaceholderFrame.h"
 #include "nsStyleStructInlines.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsFrameManager.h"
 
 bool
 nsIFrame::IsFlexItem() const
 {
-  return GetParent() &&
-    GetParent()->GetType() == nsGkAtoms::flexContainerFrame &&
-    !(GetStateBits() & NS_FRAME_OUT_OF_FLOW);
+  return GetParent() && GetParent()->IsFlexContainerFrame() &&
+         !(GetStateBits() & NS_FRAME_OUT_OF_FLOW);
 }
 
 bool
 nsIFrame::IsFlexOrGridContainer() const
 {
-  nsIAtom* t = GetType();
-  return t == nsGkAtoms::flexContainerFrame ||
-         t == nsGkAtoms::gridContainerFrame;
+  return IsFlexContainerFrame() || IsGridContainerFrame();
 }
 
 bool
 nsIFrame::IsFlexOrGridItem() const
 {
   return !(GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
          GetParent() &&
          GetParent()->IsFlexOrGridContainer();
@@ -160,17 +157,17 @@ nsIFrame::BaselineBOffset(mozilla::Writi
   }
   // XXX AlignmentContext::eTable should use content box?
   return SynthesizeBaselineBOffsetFromBorderBox(aWM, aBaselineGroup);
 }
 
 void
 nsIFrame::PropagateRootElementWritingMode(mozilla::WritingMode aRootElemWM)
 {
-  MOZ_ASSERT(GetType() == nsGkAtoms::canvasFrame);
+  MOZ_ASSERT(IsCanvasFrame());
   for (auto f = this; f; f = f->GetParent()) {
     f->mWritingMode = aRootElemWM;
   }
 }
 
 nsContainerFrame*
 nsIFrame::GetInFlowParent()
 {
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -130,25 +130,24 @@ inline bool HaveFixedSize(const ReflowIn
 nsIFrame*
 NS_NewImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsImageFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsImageFrame)
 
-
-nsImageFrame::nsImageFrame(nsStyleContext* aContext) :
-  nsAtomicContainerFrame(aContext),
-  mComputedSize(0, 0),
-  mIntrinsicRatio(0, 0),
-  mDisplayingIcon(false),
-  mFirstFrameComplete(false),
-  mReflowCallbackPosted(false),
-  mForceSyncDecoding(false)
+nsImageFrame::nsImageFrame(nsStyleContext* aContext, FrameType aType)
+  : nsAtomicContainerFrame(aContext, aType)
+  , mComputedSize(0, 0)
+  , mIntrinsicRatio(0, 0)
+  , mDisplayingIcon(false)
+  , mFirstFrameComplete(false)
+  , mReflowCallbackPosted(false)
+  , mForceSyncDecoding(false)
 {
   EnableVisibilityTracking();
 
   // We assume our size is not constrained and we haven't gotten an
   // initial reflow yet, so don't touch those flags.
   mIntrinsicSize.width.SetCoordValue(0);
   mIntrinsicSize.height.SetCoordValue(0);
 }
@@ -2124,22 +2123,16 @@ nsImageFrame::OnVisibilityChange(Visibil
 
   if (aNewVisibility == Visibility::APPROXIMATELY_VISIBLE) {
     MaybeDecodeForPredictedSize();
   }
 
   nsAtomicContainerFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
 }
 
-nsIAtom*
-nsImageFrame::GetType() const
-{
-  return nsGkAtoms::imageFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsImageFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("ImageFrame"), aResult);
 }
 
 void
--- a/layout/generic/nsImageFrame.h
+++ b/layout/generic/nsImageFrame.h
@@ -66,17 +66,19 @@ public:
 
   typedef mozilla::image::DrawResult DrawResult;
   typedef mozilla::layers::ImageContainer ImageContainer;
   typedef mozilla::layers::ImageLayer ImageLayer;
   typedef mozilla::layers::LayerManager LayerManager;
 
   NS_DECL_FRAMEARENA_HELPERS
 
-  explicit nsImageFrame(nsStyleContext* aContext);
+  explicit nsImageFrame(nsStyleContext* aContext)
+    : nsImageFrame(aContext, mozilla::FrameType::Image)
+  {}
 
   NS_DECL_QUERYFRAME_TARGET(nsImageFrame)
   NS_DECL_QUERYFRAME
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) override;
 
   virtual void Init(nsIContent*       aContent,
@@ -107,18 +109,16 @@ public:
 
   void OnVisibilityChange(Visibility aNewVisibility,
                           const Maybe<OnNonvisible>& aNonvisibleAction = Nothing()) override;
 
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() override;
 #endif
 
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsAtomicContainerFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing));
   }
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
@@ -178,16 +178,18 @@ public:
 
   void DisconnectMap();
 
   // nsIReflowCallback
   virtual bool ReflowFinished() override;
   virtual void ReflowCallbackCanceled() override;
 
 protected:
+  nsImageFrame(nsStyleContext* aContext, mozilla::FrameType aType);
+
   virtual ~nsImageFrame();
 
   void EnsureIntrinsicSizeAndRatio();
 
   virtual mozilla::LogicalSize
   ComputeSize(nsRenderingContext *aRenderingContext,
               mozilla::WritingMode aWritingMode,
               const mozilla::LogicalSize& aCBSize,
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -51,42 +51,34 @@ NS_QUERYFRAME_TAIL_INHERITING(nsContaine
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsInlineFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Inline"), aResult);
 }
 #endif
 
-nsIAtom*
-nsInlineFrame::GetType() const
-{
-  return nsGkAtoms::inlineFrame;
-}
-
 void
 nsInlineFrame::InvalidateFrame(uint32_t aDisplayItemKey)
 {
   if (nsSVGUtils::IsInSVGTextSubtree(this)) {
     nsIFrame* svgTextFrame =
-      nsLayoutUtils::GetClosestFrameOfType(GetParent(),
-                                           nsGkAtoms::svgTextFrame);
+      nsLayoutUtils::GetClosestFrameOfType(GetParent(), FrameType::SVGText);
     svgTextFrame->InvalidateFrame();
     return;
   }
   nsContainerFrame::InvalidateFrame(aDisplayItemKey);
 }
 
 void
 nsInlineFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
 {
   if (nsSVGUtils::IsInSVGTextSubtree(this)) {
     nsIFrame* svgTextFrame =
-      nsLayoutUtils::GetClosestFrameOfType(GetParent(),
-                                           nsGkAtoms::svgTextFrame);
+      nsLayoutUtils::GetClosestFrameOfType(GetParent(), FrameType::SVGText);
     svgTextFrame->InvalidateFrame();
     return;
   }
   nsContainerFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
 }
 
 static inline bool
 IsMarginZero(const nsStyleCoord &aCoord)
@@ -484,17 +476,17 @@ nsInlineFrame::AttributeChanged(int32_t 
     nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
 
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   if (nsSVGUtils::IsInSVGTextSubtree(this)) {
     SVGTextFrame* f = static_cast<SVGTextFrame*>(
-      nsLayoutUtils::GetClosestFrameOfType(this, nsGkAtoms::svgTextFrame));
+      nsLayoutUtils::GetClosestFrameOfType(this, FrameType::SVGText));
     f->HandleAttributeChangeInDescendant(mContent->AsElement(),
                                          aNameSpaceID, aAttribute);
   }
 
   return NS_OK;
 }
 
 bool
@@ -532,17 +524,17 @@ nsInlineFrame::DrainSelfOverflowListInte
 /* virtual */ bool
 nsInlineFrame::DrainSelfOverflowList()
 {
   nsIFrame* lineContainer = nsLayoutUtils::FindNearestBlockAncestor(this);
   // Add the eInFirstLine flag if we have a ::first-line ancestor frame.
   // No need to look further than the nearest line container though.
   DrainFlags flags = DrainFlags(0);
   for (nsIFrame* p = GetParent(); p != lineContainer; p = p->GetParent()) {
-    if (p->GetType() == nsGkAtoms::lineFrame) {
+    if (p->IsLineFrame()) {
       flags = DrainFlags(flags | eInFirstLine);
       break;
     }
   }
   return DrainSelfOverflowListInternal(flags, lineContainer);
 }
 
 /* virtual */ bool
@@ -648,25 +640,23 @@ nsInlineFrame::ReflowFrames(nsPresContex
           }
         }
         MOZ_ASSERT(!child || mFrames.ContainsFrame(child));
       } while (child);
 
       // Fix the parent pointer for ::first-letter child frame next-in-flows,
       // so nsFirstLetterFrame::Reflow can destroy them safely (bug 401042).
       nsIFrame* realFrame = nsPlaceholderFrame::GetRealFrameFor(frame);
-      if (realFrame->GetType() == nsGkAtoms::letterFrame) {
+      if (realFrame->IsLetterFrame()) {
         nsIFrame* child = realFrame->PrincipalChildList().FirstChild();
         if (child) {
-          NS_ASSERTION(child->GetType() == nsGkAtoms::textFrame,
-                       "unexpected frame type");
+          NS_ASSERTION(child->IsTextFrame(), "unexpected frame type");
           nsIFrame* nextInFlow = child->GetNextInFlow();
           for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) {
-            NS_ASSERTION(nextInFlow->GetType() == nsGkAtoms::textFrame,
-                         "unexpected frame type");
+            NS_ASSERTION(nextInFlow->IsTextFrame(), "unexpected frame type");
             if (mFrames.ContainsFrame(nextInFlow)) {
               nextInFlow->SetParent(this);
               if (inFirstLine) {
                 restyleManager->ReparentStyleContext(nextInFlow);
                 nsLayoutUtils::MarkDescendantsDirty(nextInFlow);
               }
             }
             else {
@@ -1129,22 +1119,16 @@ nsFirstLineFrame::Init(nsIContent*      
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsFirstLineFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Line"), aResult);
 }
 #endif
 
-nsIAtom*
-nsFirstLineFrame::GetType() const
-{
-  return nsGkAtoms::lineFrame;
-}
-
 nsIFrame*
 nsFirstLineFrame::PullOneFrame(nsPresContext* aPresContext, InlineReflowInput& irs,
                                bool* aIsComplete)
 {
   nsIFrame* frame = nsInlineFrame::PullOneFrame(aPresContext, irs, aIsComplete);
   if (frame && !GetPrevInFlow()) {
     // We are a first-line frame. Fixup the child frames
     // style-context that we just pulled.
--- a/layout/generic/nsInlineFrame.h
+++ b/layout/generic/nsInlineFrame.h
@@ -36,17 +36,16 @@ public:
 
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() override;
 #endif
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
-  virtual nsIAtom* GetType() const override;
 
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     if (aFlags & eSupportsCSSTransforms) {
       return false;
     }
     return nsContainerFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eBidiInlineContainer | nsIFrame::eLineParticipant));
@@ -137,17 +136,23 @@ protected:
       mPrevFrame = nullptr;
       mNextInFlow = nullptr;
       mLineContainer = nullptr;
       mLineLayout = nullptr;
       mSetParentPointer = false;
     }
   };
 
-  explicit nsInlineFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
+  nsInlineFrame(nsStyleContext* aContext, mozilla::FrameType aType)
+    : nsContainerFrame(aContext, aType)
+  {}
+
+  explicit nsInlineFrame(nsStyleContext* aContext)
+    : nsInlineFrame(aContext, mozilla::FrameType::Inline)
+  {}
 
   virtual LogicalSides GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const override;
 
   void ReflowFrames(nsPresContext* aPresContext,
                     const ReflowInput& aReflowInput,
                     InlineReflowInput& rs,
                     ReflowOutput& aMetrics,
                     nsReflowStatus& aStatus);
@@ -209,29 +214,30 @@ public:
   NS_DECL_FRAMEARENA_HELPERS
 
   friend nsFirstLineFrame* NS_NewFirstLineFrame(nsIPresShell* aPresShell,
                                                 nsStyleContext* aContext);
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
-  virtual nsIAtom* GetType() const override;
   virtual void Reflow(nsPresContext* aPresContext,
                       ReflowOutput& aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus& aStatus) override;
 
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
   virtual void PullOverflowsFromPrevInFlow() override;
   virtual bool DrainSelfOverflowList() override;
 
 protected:
-  explicit nsFirstLineFrame(nsStyleContext* aContext) : nsInlineFrame(aContext) {}
+  explicit nsFirstLineFrame(nsStyleContext* aContext)
+    : nsInlineFrame(aContext, mozilla::FrameType::Line)
+  {}
 
   virtual nsIFrame* PullOneFrame(nsPresContext* aPresContext,
                                  InlineReflowInput& rs,
                                  bool* aIsComplete) override;
 };
 
 #endif /* nsInlineFrame_h___ */
--- a/layout/generic/nsLeafFrame.h
+++ b/layout/generic/nsLeafFrame.h
@@ -72,17 +72,20 @@ public:
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     // We don't actually contain a block, but we do always want a
     // computed width, so tell a little white lie here.
     return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplacedContainsBlock));
   }
 
 protected:
-  explicit nsLeafFrame(nsStyleContext* aContext) : nsFrame(aContext) {}
+  nsLeafFrame(nsStyleContext* aContext, mozilla::FrameType aType)
+    : nsFrame(aContext, aType)
+  {}
+
   virtual ~nsLeafFrame();
 
   /**
    * Return the intrinsic isize of the frame's content area. Note that this
    * should not include borders or padding and should not depend on the applied
    * styles.
    */
   virtual nscoord GetIntrinsicISize() = 0;
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -74,22 +74,20 @@ nsLineLayout::nsLineLayout(nsPresContext
     mInFirstLetter(false),
     mHasBullet(false),
     mDirtyNextLine(false),
     mLineAtStart(false),
     mHasRuby(false),
     mSuppressLineWrap(nsSVGUtils::IsInSVGTextSubtree(aOuterReflowInput->mFrame))
 {
   MOZ_ASSERT(aOuterReflowInput, "aOuterReflowInput must not be null");
-  NS_ASSERTION(aFloatManager || aOuterReflowInput->mFrame->GetType() ==
-                                  nsGkAtoms::letterFrame,
+  NS_ASSERTION(aFloatManager || aOuterReflowInput->mFrame->IsLetterFrame(),
                "float manager should be present");
   MOZ_ASSERT((!!mBaseLineLayout) ==
-             (aOuterReflowInput->mFrame->GetType() ==
-              nsGkAtoms::rubyTextContainerFrame),
+              aOuterReflowInput->mFrame->IsRubyTextContainerFrame(),
              "Only ruby text container frames have "
              "a different base line layout");
   MOZ_COUNT_CTOR(nsLineLayout);
 
   // Stash away some style data that we need
   nsBlockFrame* blockFrame = do_QueryFrame(aOuterReflowInput->mFrame);
   if (blockFrame)
     mStyleText = blockFrame->StyleTextForLineLayout();
@@ -223,17 +221,17 @@ nsLineLayout::BeginLineReflow(nscoord aI
     psd->mICoord += indent;
   }
 
   PerFrameData* pfd = NewPerFrameData(mBlockReflowInput->mFrame);
   pfd->mAscent = 0;
   pfd->mSpan = psd;
   psd->mFrame = pfd;
   nsIFrame* frame = mBlockReflowInput->mFrame;
-  if (frame->GetType() == nsGkAtoms::rubyTextContainerFrame) {
+  if (frame->IsRubyTextContainerFrame()) {
     // Ruby text container won't be reflowed via ReflowFrame, hence the
     // relative positioning information should be recorded here.
     MOZ_ASSERT(mBaseLineLayout != this);
     pfd->mRelativePos =
       mBlockReflowInput->mStyleDisplay->IsRelativelyPositionedStyle();
     if (pfd->mRelativePos) {
       MOZ_ASSERT(
         mBlockReflowInput->GetWritingMode() == pfd->mWritingMode,
@@ -366,17 +364,17 @@ nsLineLayout::UpdateBand(WritingMode aWM
     for (PerFrameData* pfd = mRootSpan->mFirstFrame; pfd; pfd = pfd->mNext) {
       pfd->mBounds.IStart(lineWM) += deltaICoord;
     }
   }
 
   mBStartEdge = availSpace.BStart(lineWM);
   mImpactedByFloats = true;
 
-  mLastFloatWasLetterFrame = nsGkAtoms::letterFrame == aFloatFrame->GetType();
+  mLastFloatWasLetterFrame = aFloatFrame->IsLetterFrame();
 }
 
 nsLineLayout::PerSpanData*
 nsLineLayout::NewPerSpanData()
 {
   nsLineLayout* outerLineLayout = GetOutermostLineLayout();
   PerSpanData* psd = outerLineLayout->mSpanFreeList;
   if (!psd) {
@@ -463,22 +461,22 @@ nsLineLayout::AttachFrameToBaseLineLayou
   NS_PRECONDITION(mBaseLineLayout,
                   "This method must not be called in a base line layout.");
 
   PerFrameData* baseFrame = mBaseLineLayout->LastFrame();
   MOZ_ASSERT(aFrame && baseFrame);
   MOZ_ASSERT(!aFrame->mIsLinkedToBase,
              "The frame must not have been linked with the base");
 #ifdef DEBUG
-  nsIAtom* baseType = baseFrame->mFrame->GetType();
-  nsIAtom* annotationType = aFrame->mFrame->GetType();
-  MOZ_ASSERT((baseType == nsGkAtoms::rubyBaseContainerFrame &&
-              annotationType == nsGkAtoms::rubyTextContainerFrame) ||
-             (baseType == nsGkAtoms::rubyBaseFrame &&
-              annotationType == nsGkAtoms::rubyTextFrame));
+  FrameType baseType = baseFrame->mFrame->Type();
+  FrameType annotationType = aFrame->mFrame->Type();
+  MOZ_ASSERT((baseType == FrameType::RubyBaseContainer &&
+              annotationType == FrameType::RubyTextContainer) ||
+             (baseType == FrameType::RubyBase &&
+              annotationType == FrameType::RubyText));
 #endif
 
   aFrame->mNextAnnotation = baseFrame->mNextAnnotation;
   baseFrame->mNextAnnotation = aFrame;
   aFrame->mIsLinkedToBase = true;
 }
 
 int32_t
@@ -708,24 +706,24 @@ HasPercentageUnitSide(const nsStyleSides
   return false;
 }
 
 static bool
 IsPercentageAware(const nsIFrame* aFrame)
 {
   NS_ASSERTION(aFrame, "null frame is not allowed");
 
-  nsIAtom *fType = aFrame->GetType();
-  if (fType == nsGkAtoms::textFrame) {
+  FrameType fType = aFrame->Type();
+  if (fType == FrameType::Text) {
     // None of these things can ever be true for text frames.
     return false;
   }
 
   // Some of these things don't apply to non-replaced inline frames
-  // (that is, fType == nsGkAtoms::inlineFrame), but we won't bother making
+  // (that is, fType == FrameType::Inline), but we won't bother making
   // things unnecessarily complicated, since they'll probably be set
   // quite rarely.
 
   const nsStyleMargin* margin = aFrame->StyleMargin();
   if (HasPercentageUnitSide(margin->mMargin)) {
     return true;
   }
 
@@ -748,20 +746,20 @@ IsPercentageAware(const nsIFrame* aFrame
   }
 
   if (eStyleUnit_Auto == pos->mWidth.GetUnit()) {
     // We need to check for frames that shrink-wrap when they're auto
     // width.
     const nsStyleDisplay* disp = aFrame->StyleDisplay();
     if (disp->mDisplay == StyleDisplay::InlineBlock ||
         disp->mDisplay == StyleDisplay::InlineTable ||
-        fType == nsGkAtoms::HTMLButtonControlFrame ||
-        fType == nsGkAtoms::gfxButtonControlFrame ||
-        fType == nsGkAtoms::fieldSetFrame ||
-        fType == nsGkAtoms::comboboxDisplayFrame) {
+        fType == FrameType::HTMLButtonControl ||
+        fType == FrameType::GfxButtonControl ||
+        fType == FrameType::FieldSet ||
+        fType == FrameType::ComboboxDisplay) {
       return true;
     }
 
     // Per CSS 2.1, section 10.3.2:
     //   If 'height' and 'width' both have computed values of 'auto' and
     //   the element has an intrinsic ratio but no intrinsic height or
     //   width and the containing block's width does not itself depend
     //   on the replaced element's width, then the used value of 'width'
@@ -835,19 +833,19 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
   // we can move the line down below float(s).)
   //
   // Capture this state *before* we reflow the frame in case it clears
   // the state out. We need to know how to treat the current frame
   // when breaking.
   bool notSafeToBreak = LineIsEmpty() && !mImpactedByFloats;
 
   // Figure out whether we're talking about a textframe here
-  nsIAtom* frameType = aFrame->GetType();
-  bool isText = frameType == nsGkAtoms::textFrame;
-  
+  FrameType frameType = aFrame->Type();
+  bool isText = frameType == FrameType::Text;
+
   // Inline-ish and text-ish things don't compute their width;
   // everything else does.  We need to give them an available width that
   // reflects the space left on the line.
   LAYOUT_WARN_IF_FALSE(psd->mIEnd != NS_UNCONSTRAINEDSIZE,
                       "have unconstrained width; this should only result from "
                       "very large sizes, not attempts at intrinsic width "
                       "calculation");
   nscoord availableSpaceOnLine = psd->mIEnd - psd->mICoord;
@@ -931,20 +929,20 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
   pfd->mJustificationInfo = mJustificationInfo;
   mJustificationInfo = JustificationInfo();
 
   // See if the frame is a placeholderFrame and if it is process
   // the float. At the same time, check if the frame has any non-collapsed-away
   // content.
   bool placedFloat = false;
   bool isEmpty;
-  if (!frameType) {
+  if (frameType == FrameType::None) {
     isEmpty = pfd->mFrame->IsEmpty();
   } else {
-    if (nsGkAtoms::placeholderFrame == frameType) {
+    if (FrameType::Placeholder == frameType) {
       isEmpty = true;
       pfd->mSkipWhenTrimmingWhitespace = true;
       nsIFrame* outOfFlowFrame = nsLayoutUtils::GetFloatFromPlaceholder(aFrame);
       if (outOfFlowFrame) {
         // Add mTrimmableISize to the available width since if the line ends
         // here, the width of the inline content will be reduced by
         // mTrimmableISize.
         nscoord availableISize = psd->mIEnd - (psd->mICoord - mTrimmableISize);
@@ -957,17 +955,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
           // content where there's no break opportunity. This is incorrect
           // but hopefully rare. Fixing it will require significant
           // restructuring of line layout.
           // We might as well allow zero-width floats to be placed, though.
           availableISize = 0;
         }
         placedFloat = GetOutermostLineLayout()->
           AddFloat(outOfFlowFrame, availableISize);
-        NS_ASSERTION(!(outOfFlowFrame->GetType() == nsGkAtoms::letterFrame &&
+        NS_ASSERTION(!(outOfFlowFrame->IsLetterFrame() &&
                        GetFirstLetterStyleOK()),
                     "FirstLetterStyle set on line with floating first letter");
       }
     }
     else if (isText) {
       // Note non-empty text-frames for inline frame compatibility hackery
       pfd->mIsTextFrame = true;
       nsTextFrame* textFrame = static_cast<nsTextFrame*>(pfd->mFrame);
@@ -976,22 +974,21 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
         pfd->mIsNonEmptyTextFrame = true;
         nsIContent* content = textFrame->GetContent();
 
         const nsTextFragment* frag = content->GetText();
         if (frag) {
           pfd->mIsNonWhitespaceTextFrame = !content->TextIsOnlyWhitespace();
         }
       }
-    }
-    else if (nsGkAtoms::brFrame == frameType) {
+    } else if (FrameType::Br == frameType) {
       pfd->mSkipWhenTrimmingWhitespace = true;
       isEmpty = false;
     } else {
-      if (nsGkAtoms::letterFrame==frameType) {
+      if (FrameType::Letter == frameType) {
         pfd->mIsLetterFrame = true;
       }
       if (pfd->mSpan) {
         isEmpty = !pfd->mSpan->mHasNonemptyContent && pfd->mFrame->IsSelfEmpty();
       } else {
         isEmpty = pfd->mFrame->IsEmpty();
       }
     }
@@ -1088,17 +1085,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
                       aReflowStatus, &optionalBreakAfterFits)) {
       if (!isEmpty) {
         psd->mHasNonemptyContent = true;
         mLineIsEmpty = false;
         if (!pfd->mSpan) {
           // nonempty leaf content has been placed
           mLineAtStart = false;
         }
-        if (nsGkAtoms::rubyFrame == frameType) {
+        if (FrameType::Ruby == frameType) {
           mHasRuby = true;
           SyncAnnotationBounds(pfd);
         }
       }
 
       // Place the frame, updating aBounds with the final size and
       // location.  Then apply the bottom+right margins (as
       // appropriate) to the frame.
@@ -1204,17 +1201,17 @@ nsLineLayout::GetCurrentFrameInlineDista
  * Containers are not part of the line in their levels, which means
  * their bounds are not set properly before.
  * Ruby annotations' position may have been changed when reflowing
  * their containers.
  */
 void
 nsLineLayout::SyncAnnotationBounds(PerFrameData* aRubyFrame)
 {
-  MOZ_ASSERT(aRubyFrame->mFrame->GetType() == nsGkAtoms::rubyFrame);
+  MOZ_ASSERT(aRubyFrame->mFrame->IsRubyFrame());
   MOZ_ASSERT(aRubyFrame->mSpan);
 
   PerSpanData* span = aRubyFrame->mSpan;
   WritingMode lineWM = mRootSpan->mWritingMode;
   for (PerFrameData* pfd = span->mFirstFrame; pfd; pfd = pfd->mNext) {
     for (PerFrameData* rtc = pfd->mNextAnnotation;
          rtc; rtc = rtc->mNextAnnotation) {
       // When the annotation container is reflowed, the width of the
@@ -1329,17 +1326,17 @@ nsLineLayout::CanPlaceFrame(PerFrameData
 #ifdef NOISY_CAN_PLACE_FRAME
     printf("   ==> empty frame fits\n");
 #endif
     return true;
   }
 
 #ifdef FIX_BUG_50257
   // another special case:  always place a BR
-  if (nsGkAtoms::brFrame == pfd->mFrame->GetType()) {
+  if (pfd->mFrame->IsBrFrame()) {
 #ifdef NOISY_CAN_PLACE_FRAME
     printf("   ==> BR frame fits\n");
 #endif
     return true;
   }
 #endif
 
   if (aNotSafeToBreak) {
@@ -1427,17 +1424,17 @@ nsLineLayout::PlaceFrame(PerFrameData* p
     }
   }
 
   // Advance to next inline coordinate
   mCurrentSpan->mICoord = pfd->mBounds.IEnd(lineWM) +
                           pfd->mMargin.IEnd(lineWM);
 
   // Count the number of non-placeholder frames on the line...
-  if (pfd->mFrame->GetType() == nsGkAtoms::placeholderFrame) {
+  if (pfd->mFrame->IsPlaceholderFrame()) {
     NS_ASSERTION(pfd->mBounds.ISize(lineWM) == 0 &&
                  pfd->mBounds.BSize(lineWM) == 0,
                  "placeholders should have 0 width/height (checking "
                  "placeholders were never counted by the old code in "
                  "this function)");
   } else {
     mTotalPlacedFrames++;
   }
@@ -1666,17 +1663,17 @@ GetBSizeOfEmphasisMarks(nsIFrame* aSpanF
 void
 nsLineLayout::AdjustLeadings(nsIFrame* spanFrame, PerSpanData* psd,
                              const nsStyleText* aStyleText, float aInflation,
                              bool* aZeroEffectiveSpanBox)
 {
   MOZ_ASSERT(spanFrame == psd->mFrame->mFrame);
   nscoord requiredStartLeading = 0;
   nscoord requiredEndLeading = 0;
-  if (spanFrame->GetType() == nsGkAtoms::rubyFrame) {
+  if (spanFrame->IsRubyFrame()) {
     // We may need to extend leadings here for ruby annotations as
     // required by section Line Spacing in the CSS Ruby spec.
     // See http://dev.w3.org/csswg/css-ruby/#line-height
     auto rubyFrame = static_cast<nsRubyFrame*>(spanFrame);
     RubyBlockLeadings leadings = rubyFrame->GetBlockLeadings();
     requiredStartLeading += leadings.mStart;
     requiredEndLeading += leadings.mEnd;
   }
@@ -1721,17 +1718,17 @@ nsLineLayout::AdjustLeadings(nsIFrame* s
 }
 
 static float
 GetInflationForBlockDirAlignment(nsIFrame* aFrame,
                                  nscoord aInflationMinFontSize)
 {
   if (nsSVGUtils::IsInSVGTextSubtree(aFrame)) {
     const nsIFrame* container =
-      nsLayoutUtils::GetClosestFrameOfType(aFrame, nsGkAtoms::svgTextFrame);
+      nsLayoutUtils::GetClosestFrameOfType(aFrame, FrameType::SVGText);
     NS_ASSERTION(container, "expected to find an ancestor SVGTextFrame");
     return
       static_cast<const SVGTextFrame*>(container)->GetFontSizeScaleFactor();
   }
   return nsLayoutUtils::FontSizeInflationInner(aFrame, aInflationMinFontSize);
 }
 
 #define BLOCKDIR_ALIGN_FRAMES_NO_MINIMUM nscoord_MAX
@@ -2234,17 +2231,17 @@ nsLineLayout::VerticalAlignFrames(PerSpa
           blockEnd = blockStart + logicalBSize;
         }
         if (!preMode &&
             mPresContext->CompatibilityMode() != eCompatibility_FullStandards &&
             !logicalBSize) {
           // Check if it's a BR frame that is not alone on its line (it
           // is given a block size of zero to indicate this), and if so reset
           // blockStart and blockEnd so that BR frames don't influence the line.
-          if (nsGkAtoms::brFrame == frame->GetType()) {
+          if (frame->IsBrFrame()) {
             blockStart = BLOCKDIR_ALIGN_FRAMES_NO_MINIMUM;
             blockEnd = BLOCKDIR_ALIGN_FRAMES_NO_MAXIMUM;
           }
         }
         if (blockStart < minBCoord) minBCoord = blockStart;
         if (blockEnd > maxBCoord) maxBCoord = blockEnd;
 #ifdef NOISY_BLOCKDIR_ALIGN
         printf("     [frame]raw: a=%d h=%d bp=%d,%d logical: h=%d leading=%d y=%d minBCoord=%d maxBCoord=%d\n",
@@ -2750,17 +2747,17 @@ nsLineLayout::ComputeFrameJustification(
              "Justification info should not have been set yet.");
   int32_t outerOpportunities = 0;
 
   for (PerFrameData* pfd = aPSD->mFirstFrame; pfd; pfd = pfd->mNext) {
     if (!pfd->ParticipatesInJustification()) {
       continue;
     }
 
-    bool isRubyBase = pfd->mFrame->GetType() == nsGkAtoms::rubyBaseFrame;
+    bool isRubyBase = pfd->mFrame->IsRubyBaseFrame();
     PerFrameData* outerRubyBase = aState.mLastEnteredRubyBase;
     if (isRubyBase) {
       aState.mLastEnteredRubyBase = pfd;
     }
 
     int extraOpportunities = 0;
     if (pfd->mSpan) {
       PerSpanData* span = pfd->mSpan;
@@ -2808,40 +2805,40 @@ nsLineLayout::ComputeFrameJustification(
 
 void
 nsLineLayout::AdvanceAnnotationInlineBounds(PerFrameData* aPFD,
                                             const nsSize& aContainerSize,
                                             nscoord aDeltaICoord,
                                             nscoord aDeltaISize)
 {
   nsIFrame* frame = aPFD->mFrame;
-  nsIAtom* frameType = frame->GetType();
-  MOZ_ASSERT(frameType == nsGkAtoms::rubyTextFrame ||
-             frameType == nsGkAtoms::rubyTextContainerFrame);
+  FrameType frameType = frame->Type();
+  MOZ_ASSERT(frameType == FrameType::RubyText ||
+             frameType == FrameType::RubyTextContainer);
   MOZ_ASSERT(aPFD->mSpan, "rt and rtc should have span.");
 
   PerSpanData* psd = aPFD->mSpan;
   WritingMode lineWM = mRootSpan->mWritingMode;
   aPFD->mBounds.IStart(lineWM) += aDeltaICoord;
 
   // Check whether this expansion should be counted into the reserved
   // isize or not. When it is a ruby text container, and it has some
   // children linked to the base, it must not have reserved isize,
   // or its children won't align with their bases.  Otherwise, this
   // expansion should be reserved.  There are two cases a ruby text
   // container does not have children linked to the base:
   // 1. it is a container for span; 2. its children are collapsed.
   // See bug 1055674 for the second case.
-  if (frameType == nsGkAtoms::rubyTextFrame ||
+  if (frameType == FrameType::RubyText ||
       // This ruby text container is a span.
       (psd->mFirstFrame == psd->mLastFrame && psd->mFirstFrame &&
        !psd->mFirstFrame->mIsLinkedToBase)) {
     // For ruby text frames, only increase frames
     // which are not auto-hidden.
-    if (frameType != nsGkAtoms::rubyTextFrame ||
+    if (frameType != FrameType::RubyText ||
         !static_cast<nsRubyTextFrame*>(frame)->IsAutoHidden()) {
       nscoord reservedISize = RubyUtils::GetReservedISize(frame);
       RubyUtils::SetReservedISize(frame, reservedISize + aDeltaISize);
     }
   } else {
     // It is a normal ruby text container. Its children will expand
     // themselves properly. We only need to expand its own size here.
     aPFD->mBounds.ISize(lineWM) += aDeltaISize;
@@ -2938,17 +2935,17 @@ nsLineLayout::ApplyFrameJustification(Pe
   }
   return deltaICoord;
 }
 
 static nsIFrame*
 FindNearestRubyBaseAncestor(nsIFrame* aFrame)
 {
   MOZ_ASSERT(aFrame->StyleContext()->ShouldSuppressLineBreak());
-  while (aFrame && aFrame->GetType() != nsGkAtoms::rubyBaseFrame) {
+  while (aFrame && !aFrame->IsRubyBaseFrame()) {
     aFrame = aFrame->GetParent();
   }
   // XXX It is possible that no ruby base ancestor is found because of
   // some edge cases like form control or canvas inside ruby text.
   // See bug 1138092 comment 4.
   NS_WARNING_ASSERTION(aFrame, "no ruby base ancestor?");
   return aFrame;
 }
@@ -3012,23 +3009,22 @@ nsLineLayout::ExpandRubyBoxWithAnnotatio
                                            const nsSize& aContainerSize)
 {
   nscoord reservedISize = RubyUtils::GetReservedISize(aFrame->mFrame);
   if (reservedISize) {
     ExpandRubyBox(aFrame, reservedISize, aContainerSize);
   }
 
   WritingMode lineWM = mRootSpan->mWritingMode;
-  bool isLevelContainer =
-    aFrame->mFrame->GetType() == nsGkAtoms::rubyBaseContainerFrame;
+  bool isLevelContainer = aFrame->mFrame->IsRubyBaseContainerFrame();
   for (PerFrameData* annotation = aFrame->mNextAnnotation;
        annotation; annotation = annotation->mNextAnnotation) {
     if (isLevelContainer) {
       nsIFrame* rtcFrame = annotation->mFrame;
-      MOZ_ASSERT(rtcFrame->GetType() == nsGkAtoms::rubyTextContainerFrame);
+      MOZ_ASSERT(rtcFrame->IsRubyTextContainerFrame());
       // It is necessary to set the rect again because the container
       // width was unknown, and zero was used instead when we reflow
       // them. The corresponding base containers were repositioned in
       // VerticalAlignFrames and PlaceTopBottomFrames.
       MOZ_ASSERT(
         rtcFrame->GetLogicalSize(lineWM) == annotation->mBounds.Size(lineWM));
       rtcFrame->SetPosition(lineWM, annotation->mBounds.Origin(lineWM),
                             aContainerSize);
@@ -3048,17 +3044,17 @@ nsLineLayout::ExpandRubyBoxWithAnnotatio
     if (IsRubyAlignSpaceAround(annotation->mFrame)) {
       // Add one gap at each side of this annotation.
       computeState.mFirstParticipant->mJustificationAssignment.mGapsAtStart = 1;
       computeState.mLastParticipant->mJustificationAssignment.mGapsAtEnd = 1;
     }
     nsIFrame* parentFrame = annotation->mFrame->GetParent();
     nsSize containerSize = parentFrame->GetSize();
     MOZ_ASSERT(containerSize == aContainerSize ||
-               parentFrame->GetType() == nsGkAtoms::rubyTextContainerFrame,
+               parentFrame->IsRubyTextContainerFrame(),
                "Container width should only be different when the current "
                "annotation is a ruby text frame, whose parent is not same "
                "as its base frame.");
     ExpandRubyBox(annotation, reservedISize, containerSize);
     ExpandInlineRubyBoxes(annotation->mSpan);
   }
 }
 
@@ -3249,23 +3245,23 @@ nsLineLayout::ApplyRelativePositioning(P
   frame->SetPosition(frameWM, origin, ContainerSize());
 }
 
 // This method do relative positioning for ruby annotations.
 void
 nsLineLayout::RelativePositionAnnotations(PerSpanData* aRubyPSD,
                                           nsOverflowAreas& aOverflowAreas)
 {
-  MOZ_ASSERT(aRubyPSD->mFrame->mFrame->GetType() == nsGkAtoms::rubyFrame);
+  MOZ_ASSERT(aRubyPSD->mFrame->mFrame->IsRubyFrame());
   for (PerFrameData* pfd = aRubyPSD->mFirstFrame; pfd; pfd = pfd->mNext) {
-    MOZ_ASSERT(pfd->mFrame->GetType() == nsGkAtoms::rubyBaseContainerFrame);
+    MOZ_ASSERT(pfd->mFrame->IsRubyBaseContainerFrame());
     for (PerFrameData* rtc = pfd->mNextAnnotation;
          rtc; rtc = rtc->mNextAnnotation) {
       nsIFrame* rtcFrame = rtc->mFrame;
-      MOZ_ASSERT(rtcFrame->GetType() == nsGkAtoms::rubyTextContainerFrame);
+      MOZ_ASSERT(rtcFrame->IsRubyTextContainerFrame());
       ApplyRelativePositioning(rtc);
       nsOverflowAreas rtcOverflowAreas;
       RelativePositionFrames(rtc->mSpan, rtcOverflowAreas);
       aOverflowAreas.UnionWith(rtcOverflowAreas + rtcFrame->GetPosition());
     }
   }
 }
 
@@ -3364,17 +3360,17 @@ nsLineLayout::RelativePositionFrames(Per
                                                  frame->GetView(),
                                                  r.VisualOverflow(),
                                                  NS_FRAME_NO_MOVE_VIEW);
 
     overflowAreas.UnionWith(r + frame->GetPosition());
   }
 
   // Also compute relative position in the annotations.
-  if (psd->mFrame->mFrame->GetType() == nsGkAtoms::rubyFrame) {
+  if (psd->mFrame->mFrame->IsRubyFrame()) {
     RelativePositionAnnotations(psd, overflowAreas);
   }
 
   // If we just computed a spans combined area, we need to update its
   // overflow rect...
   if (psd != mRootSpan) {
     PerFrameData* spanPFD = psd->mFrame;
     nsIFrame* frame = spanPFD->mFrame;
--- a/layout/generic/nsPageContentFrame.cpp
+++ b/layout/generic/nsPageContentFrame.cpp
@@ -103,21 +103,15 @@ nsPageContentFrame::Reflow(nsPresContext
   if (aReflowInput.ComputedBSize() != NS_UNCONSTRAINEDSIZE) {
     aDesiredSize.BSize(wm) = aReflowInput.ComputedBSize();
   }
   FinishAndStoreOverflow(&aDesiredSize);
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
-nsIAtom*
-nsPageContentFrame::GetType() const
-{
-  return nsGkAtoms::pageContentFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsPageContentFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("PageContent"), aResult);
 }
 #endif
--- a/layout/generic/nsPageContentFrame.h
+++ b/layout/generic/nsPageContentFrame.h
@@ -7,18 +7,18 @@
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ViewportFrame.h"
 
 class nsPageFrame;
 class nsSharedPageData;
 
 // Page frame class used by the simple page sequence frame
-class nsPageContentFrame : public mozilla::ViewportFrame {
-
+class nsPageContentFrame final : public mozilla::ViewportFrame
+{
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   friend nsPageContentFrame* NS_NewPageContentFrame(nsIPresShell* aPresShell,
                                                     nsStyleContext* aContext);
   friend class nsPageFrame;
 
   // nsIFrame
@@ -32,28 +32,23 @@ public:
     return ViewportFrame::IsFrameOfType(aFlags &
              ~(nsIFrame::eCanContainOverflowContainers));
   }
 
   virtual void SetSharedPageData(nsSharedPageData* aPD) { mPD = aPD; }
 
   virtual bool HasTransformGetter() const override { return true; }
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::pageContentFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   // Debugging
   virtual nsresult  GetFrameName(nsAString& aResult) const override;
 #endif
 
 protected:
-  explicit nsPageContentFrame(nsStyleContext* aContext) : ViewportFrame(aContext) {}
+  explicit nsPageContentFrame(nsStyleContext* aContext)
+    : ViewportFrame(aContext, mozilla::FrameType::PageContent)
+  {}
 
   nsSharedPageData*         mPD;
 };
 
 #endif /* nsPageContentFrame_h___ */
 
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -36,17 +36,17 @@ NS_NewPageFrame(nsIPresShell* aPresShell
 
 NS_IMPL_FRAMEARENA_HELPERS(nsPageFrame)
 
 NS_QUERYFRAME_HEAD(nsPageFrame)
   NS_QUERYFRAME_ENTRY(nsPageFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
 
 nsPageFrame::nsPageFrame(nsStyleContext* aContext)
-: nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::Page)
 {
 }
 
 nsPageFrame::~nsPageFrame()
 {
 }
 
 void
@@ -56,17 +56,17 @@ nsPageFrame::Reflow(nsPresContext*      
                                   nsReflowStatus&          aStatus)
 {
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("nsPageFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
   aStatus.Reset();  // initialize out parameter
 
   NS_ASSERTION(mFrames.FirstChild() &&
-               nsGkAtoms::pageContentFrame == mFrames.FirstChild()->GetType(),
+               mFrames.FirstChild()->IsPageContentFrame(),
                "pageFrame must have a pageContentFrame child");
 
   // Resize our frame allowing it only to be as big as we are
   // XXX Pay attention to the page's border and padding...
   if (mFrames.NotEmpty()) {
     nsIFrame* frame = mFrames.FirstChild();
     // When the reflow size is NS_UNCONSTRAINEDSIZE it means we are reflowing
     // a single page to print selection. So this means we want to use
@@ -164,22 +164,16 @@ nsPageFrame::Reflow(nsPresContext*      
   FinishAndStoreOverflow(&aDesiredSize);
 
   PR_PL(("PageFrame::Reflow %p ", this));
   PR_PL(("[%d,%d]\n", aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
-nsIAtom*
-nsPageFrame::GetType() const
-{
-  return nsGkAtoms::pageFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsPageFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Page"), aResult);
 }
 #endif
 
@@ -454,26 +448,26 @@ BuildDisplayListForExtraPage(nsDisplayLi
   aList->AppendToTop(&list);
 }
 
 static nsIFrame*
 GetNextPage(nsIFrame* aPageContentFrame)
 {
   // XXX ugh
   nsIFrame* pageFrame = aPageContentFrame->GetParent();
-  NS_ASSERTION(pageFrame->GetType() == nsGkAtoms::pageFrame,
+  NS_ASSERTION(pageFrame->IsPageFrame(),
                "pageContentFrame has unexpected parent");
   nsIFrame* nextPageFrame = pageFrame->GetNextSibling();
   if (!nextPageFrame)
     return nullptr;
-  NS_ASSERTION(nextPageFrame->GetType() == nsGkAtoms::pageFrame,
+  NS_ASSERTION(nextPageFrame->IsPageFrame(),
                "pageFrame's sibling is not a page frame...");
   nsIFrame* f = nextPageFrame->PrincipalChildList().FirstChild();
   NS_ASSERTION(f, "pageFrame has no page content frame!");
-  NS_ASSERTION(f->GetType() == nsGkAtoms::pageContentFrame,
+  NS_ASSERTION(f->IsPageContentFrame(),
                "pageFrame's child is not page content!");
   return f;
 }
 
 static gfx::Matrix4x4 ComputePageTransform(nsIFrame* aFrame, float aAppUnitsPerPixel)
 {
   float scale = aFrame->PresContext()->GetPageScale();
   return gfx::Matrix4x4::Scaling(scale, scale, 1);
@@ -682,18 +676,19 @@ NS_NewPageBreakFrame(nsIPresShell* aPres
   //check that we are only creating page break frames when printing
   NS_ASSERTION(aPresShell->GetPresContext()->IsPaginated(), "created a page break frame while not printing");
 
   return new (aPresShell) nsPageBreakFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsPageBreakFrame)
 
-nsPageBreakFrame::nsPageBreakFrame(nsStyleContext* aContext) :
-  nsLeafFrame(aContext), mHaveReflowed(false)
+nsPageBreakFrame::nsPageBreakFrame(nsStyleContext* aContext)
+  : nsLeafFrame(aContext, FrameType::PageBreak)
+  , mHaveReflowed(false)
 {
 }
 
 nsPageBreakFrame::~nsPageBreakFrame()
 {
 }
 
 nscoord
@@ -729,21 +724,15 @@ nsPageBreakFrame::Reflow(nsPresContext* 
   aDesiredSize.SetSize(wm, finalSize);
 
   // Note: not using NS_FRAME_FIRST_REFLOW here, since it's not clear whether
   // DidReflow will always get called before the next Reflow() call.
   mHaveReflowed = true;
   aStatus.Reset(); 
 }
 
-nsIAtom*
-nsPageBreakFrame::GetType() const
-{
-  return nsGkAtoms::pageBreakFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsPageBreakFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("PageBreak"), aResult);
 }
 #endif
--- a/layout/generic/nsPageFrame.h
+++ b/layout/generic/nsPageFrame.h
@@ -27,23 +27,16 @@ public:
                       ReflowOutput& aDesiredSize,
                       const ReflowInput& aMaxSize,
                       nsReflowStatus&      aStatus) override;
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::pageFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult  GetFrameName(nsAString& aResult) const override;
 #endif
 
   //////////////////
   // For Printing
   //////////////////
 
@@ -106,31 +99,30 @@ protected:
 
 class nsPageBreakFrame : public nsLeafFrame
 {
   NS_DECL_FRAMEARENA_HELPERS
 
   explicit nsPageBreakFrame(nsStyleContext* aContext);
   ~nsPageBreakFrame();
 
-  virtual void Reflow(nsPresContext*          aPresContext,
-                          ReflowOutput&     aDesiredSize,
-                          const ReflowInput& aReflowInput,
-                          nsReflowStatus&          aStatus) override;
-
-  virtual nsIAtom* GetType() const override;
+  virtual void Reflow(nsPresContext* aPresContext,
+                      ReflowOutput& aDesiredSize,
+                      const ReflowInput& aReflowInput,
+                      nsReflowStatus& aStatus) override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult  GetFrameName(nsAString& aResult) const override;
 #endif
 
 protected:
 
   virtual nscoord GetIntrinsicISize() override;
   virtual nscoord GetIntrinsicBSize() override;
 
-    bool mHaveReflowed;
+  bool mHaveReflowed;
 
-    friend nsIFrame* NS_NewPageBreakFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+  friend nsIFrame* NS_NewPageBreakFrame(nsIPresShell* aPresShell,
+                                        nsStyleContext* aContext);
 };
 
 #endif /* nsPageFrame_h___ */
 
--- a/layout/generic/nsPlaceholderFrame.cpp
+++ b/layout/generic/nsPlaceholderFrame.cpp
@@ -169,22 +169,16 @@ nsPlaceholderFrame::DestroyFrom(nsIFrame
       fm->RemoveFrame(listId, oof);
     }
     // else oof will be destroyed by its parent
   }
 
   nsFrame::DestroyFrom(aDestructRoot);
 }
 
-nsIAtom*
-nsPlaceholderFrame::GetType() const
-{
-  return nsGkAtoms::placeholderFrame;
-}
-
 /* virtual */ bool
 nsPlaceholderFrame::CanContinueTextRun() const
 {
   if (!mOutOfFlowFrame) {
     return false;
   }
   // first-letter frames can continue text runs, and placeholders for floated
   // first-letter frames can too
@@ -208,18 +202,18 @@ nsPlaceholderFrame::GetParentStyleContex
 
   nsIFrame* parentFrame = GetParent();
   // Placeholder of backdrop frame is a child of the corresponding top
   // layer frame, and its style context inherits from that frame. In
   // case of table, the top layer frame is the table wrapper frame.
   // However, it will be skipped in CorrectStyleParentFrame below, so
   // we need to handle it specially here.
   if ((GetStateBits() & PLACEHOLDER_FOR_TOPLAYER) &&
-      parentFrame->GetType() == nsGkAtoms::tableWrapperFrame) {
-    MOZ_ASSERT(mOutOfFlowFrame->GetType() == nsGkAtoms::backdropFrame,
+      parentFrame->IsTableWrapperFrame()) {
+    MOZ_ASSERT(mOutOfFlowFrame->IsBackdropFrame(),
                "Only placeholder of backdrop frame can be put inside "
                "a table wrapper frame");
     *aProviderFrame = parentFrame;
     return parentFrame->StyleContext();
   }
 
   // Lie about our pseudo so we can step out of all anon boxes and
   // pseudo-elements.  The other option would be to reimplement the
--- a/layout/generic/nsPlaceholderFrame.h
+++ b/layout/generic/nsPlaceholderFrame.h
@@ -63,17 +63,17 @@ public:
   /**
    * Create a new placeholder frame.  aTypeBit must be one of the
    * PLACEHOLDER_FOR_* constants above.
    */
   friend nsIFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell,
                                           nsStyleContext* aContext,
                                           nsFrameState aTypeBit);
   nsPlaceholderFrame(nsStyleContext* aContext, nsFrameState aTypeBit)
-    : nsFrame(aContext)
+    : nsFrame(aContext, mozilla::FrameType::Placeholder)
   {
     NS_PRECONDITION(aTypeBit == PLACEHOLDER_FOR_FLOAT ||
                     aTypeBit == PLACEHOLDER_FOR_ABSPOS ||
                     aTypeBit == PLACEHOLDER_FOR_FIXEDPOS ||
                     aTypeBit == PLACEHOLDER_FOR_POPUP ||
                     aTypeBit == PLACEHOLDER_FOR_TOPLAYER,
                     "Unexpected type bit");
     AddStateBits(aTypeBit);
@@ -111,23 +111,16 @@ public:
                                 const nsDisplayListSet& aLists) override;
 #endif // DEBUG || (MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF)
   
 #ifdef DEBUG_FRAME_DUMP
   void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const override;
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif // DEBUG
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::placeholderFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsEmpty() override { return true; }
   virtual bool IsSelfEmpty() override { return true; }
 
   virtual bool CanContinueTextRun() const override;
 
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() override
   {
@@ -149,27 +142,27 @@ public:
   }
 
   /**
    * @return the out-of-flow for aFrame if aFrame is a placeholder; otherwise
    * aFrame
    */
   static nsIFrame* GetRealFrameFor(nsIFrame* aFrame) {
     NS_PRECONDITION(aFrame, "Must have a frame to work with");
-    if (aFrame->GetType() == nsGkAtoms::placeholderFrame) {
+    if (aFrame->IsPlaceholderFrame()) {
       return GetRealFrameForPlaceholder(aFrame);
     }
     return aFrame;
   }
 
   /**
    * @return the out-of-flow for aFrame, which is known to be a placeholder
    */
   static nsIFrame* GetRealFrameForPlaceholder(nsIFrame* aFrame) {
-    NS_PRECONDITION(aFrame->GetType() == nsGkAtoms::placeholderFrame,
+    NS_PRECONDITION(aFrame->IsPlaceholderFrame(),
                     "Must have placeholder frame as input");
     nsIFrame* outOfFlow =
       static_cast<nsPlaceholderFrame*>(aFrame)->GetOutOfFlowFrame();
     NS_ASSERTION(outOfFlow, "Null out-of-flow for placeholder?");
     return outOfFlow;
   }
 
 protected:
--- a/layout/generic/nsPluginFrame.cpp
+++ b/layout/generic/nsPluginFrame.cpp
@@ -140,17 +140,17 @@ protected:
     return false;
   }
 
   uint64_t mLastSequenceNumber;
   nsPluginFrame* mFrame;
 };
 
 nsPluginFrame::nsPluginFrame(nsStyleContext* aContext)
-  : nsFrame(aContext)
+  : nsFrame(aContext, FrameType::Object)
   , mInstanceOwner(nullptr)
   , mOuterView(nullptr)
   , mInnerView(nullptr)
   , mBackgroundSink(nullptr)
   , mReflowCallbackPosted(false)
 {
   MOZ_LOG(sPluginFrameLog, LogLevel::Debug,
          ("Created new nsPluginFrame %p\n", this));
@@ -235,22 +235,16 @@ nsPluginFrame::DidSetStyleContext(nsStyl
         IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow;
       vm->SetViewVisibility(view, visibility);
     }
   }
 
   nsFrame::DidSetStyleContext(aOldStyleContext);
 }
 
-nsIAtom*
-nsPluginFrame::GetType() const
-{
-  return nsGkAtoms::objectFrame; 
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsPluginFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("PluginFrame"), aResult);
 }
 #endif
 
--- a/layout/generic/nsPluginFrame.h
+++ b/layout/generic/nsPluginFrame.h
@@ -42,19 +42,20 @@ namespace layers {
 class ImageContainer;
 class Layer;
 class LayerManager;
 } // namespace layers
 } // namespace mozilla
 
 class PluginFrameDidCompositeObserver;
 
-class nsPluginFrame : public nsFrame
-                    , public nsIObjectFrame
-                    , public nsIReflowCallback
+class nsPluginFrame final
+  : public nsFrame
+  , public nsIObjectFrame
+  , public nsIReflowCallback
 {
 public:
   typedef mozilla::LayerState LayerState;
   typedef mozilla::LayoutDeviceIntPoint LayoutDeviceIntPoint;
   typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
   typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
@@ -83,18 +84,16 @@ public:
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
   virtual nsresult  HandleEvent(nsPresContext* aPresContext,
                                 mozilla::WidgetGUIEvent* aEvent,
                                 nsEventStatus* aEventStatus) override;
 
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing));
   }
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
--- a/layout/generic/nsRubyBaseContainerFrame.cpp
+++ b/layout/generic/nsRubyBaseContainerFrame.cpp
@@ -43,22 +43,16 @@ NS_NewRubyBaseContainerFrame(nsIPresShel
 }
 
 
 //----------------------------------------------------------------------
 
 // nsRubyBaseContainerFrame Method Implementations
 // ===============================================
 
-nsIAtom*
-nsRubyBaseContainerFrame::GetType() const
-{
-  return nsGkAtoms::rubyBaseContainerFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsRubyBaseContainerFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("RubyBaseContainer"), aResult);
 }
 #endif
 
@@ -69,17 +63,17 @@ LineBreakBefore(nsIFrame* aFrame,
                 const nsLineList::iterator* aLine)
 {
   for (nsIFrame* child = aFrame; child;
        child = child->PrincipalChildList().FirstChild()) {
     if (!child->CanContinueTextRun()) {
       // It is not an inline element. We can break before it.
       return gfxBreakPriority::eNormalBreak;
     }
-    if (child->GetType() != nsGkAtoms::textFrame) {
+    if (!child->IsTextFrame()) {
       continue;
     }
 
     auto textFrame = static_cast<nsTextFrame*>(child);
     gfxSkipCharsIterator iter =
       textFrame->EnsureTextRun(nsTextFrame::eInflated, aDrawTarget,
                                aLineContainerFrame, aLine);
     iter.SetOriginalOffset(textFrame->GetContentOffset());
@@ -721,27 +715,27 @@ nsRubyBaseContainerFrame::PullOneColumn(
                                         RubyColumn& aColumn,
                                         bool& aIsComplete)
 {
   const AutoRubyTextContainerArray& textContainers =
     aPullFrameState.mTextContainers;
   const uint32_t rtcCount = textContainers.Length();
 
   nsIFrame* nextBase = GetNextInFlowChild(aPullFrameState.mBase);
-  MOZ_ASSERT(!nextBase || nextBase->GetType() == nsGkAtoms::rubyBaseFrame);
+  MOZ_ASSERT(!nextBase || nextBase->IsRubyBaseFrame());
   aColumn.mBaseFrame = static_cast<nsRubyBaseFrame*>(nextBase);
   bool foundFrame = !!aColumn.mBaseFrame;
   bool pullingIntraLevelWhitespace =
     aColumn.mBaseFrame && aColumn.mBaseFrame->IsIntraLevelWhitespace();
 
   aColumn.mTextFrames.ClearAndRetainStorage();
   for (uint32_t i = 0; i < rtcCount; i++) {
     nsIFrame* nextText =
       textContainers[i]->GetNextInFlowChild(aPullFrameState.mTexts[i]);
-    MOZ_ASSERT(!nextText || nextText->GetType() == nsGkAtoms::rubyTextFrame);
+    MOZ_ASSERT(!nextText || nextText->IsRubyTextFrame());
     nsRubyTextFrame* textFrame = static_cast<nsRubyTextFrame*>(nextText);
     aColumn.mTextFrames.AppendElement(textFrame);
     foundFrame = foundFrame || nextText;
     if (nextText && !pullingIntraLevelWhitespace) {
       pullingIntraLevelWhitespace = textFrame->IsIntraLevelWhitespace();
     }
   }
   // If there exists any frame in continations, we haven't
--- a/layout/generic/nsRubyBaseContainerFrame.h
+++ b/layout/generic/nsRubyBaseContainerFrame.h
@@ -22,17 +22,16 @@ nsContainerFrame* NS_NewRubyBaseContaine
 class nsRubyBaseContainerFrame final : public nsContainerFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
   NS_DECL_QUERYFRAME_TARGET(nsRubyBaseContainerFrame)
   NS_DECL_QUERYFRAME
 
   // nsIFrame overrides
-  virtual nsIAtom* GetType() const override;
   virtual bool IsFrameOfType(uint32_t aFlags) const override;
   virtual bool CanContinueTextRun() const override;
   virtual void AddInlineMinISize(nsRenderingContext *aRenderingContext,
                                  InlineMinISizeData *aData) override;
   virtual void AddInlinePrefISize(nsRenderingContext *aRenderingContext,
                                   InlinePrefISizeData *aData) override;
   virtual mozilla::LogicalSize
     ComputeSize(nsRenderingContext *aRenderingContext,
@@ -61,17 +60,20 @@ public:
   mozilla::RubyBlockLeadings GetDescendantLeadings() const {
     return mDescendantLeadings;
   }
 
 protected:
   friend nsContainerFrame*
     NS_NewRubyBaseContainerFrame(nsIPresShell* aPresShell,
                                  nsStyleContext* aContext);
-  explicit nsRubyBaseContainerFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
+
+  explicit nsRubyBaseContainerFrame(nsStyleContext* aContext)
+    : nsContainerFrame(aContext, mozilla::FrameType::RubyBaseContainer)
+  {}
 
   struct RubyReflowInput;
   nscoord ReflowColumns(const RubyReflowInput& aReflowInput,
                         nsReflowStatus& aStatus);
   nscoord ReflowOneColumn(const RubyReflowInput& aReflowInput,
                           uint32_t aColumnIndex,
                           const mozilla::RubyColumn& aColumn,
                           nsReflowStatus& aStatus);
--- a/layout/generic/nsRubyBaseFrame.cpp
+++ b/layout/generic/nsRubyBaseFrame.cpp
@@ -34,21 +34,15 @@ NS_NewRubyBaseFrame(nsIPresShell* aPresS
 }
 
 
 //----------------------------------------------------------------------
 
 // nsRubyBaseFrame Method Implementations
 // ======================================
 
-nsIAtom*
-nsRubyBaseFrame::GetType() const
-{
-  return nsGkAtoms::rubyBaseFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsRubyBaseFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("RubyBase"), aResult);
 }
 #endif
--- a/layout/generic/nsRubyBaseFrame.h
+++ b/layout/generic/nsRubyBaseFrame.h
@@ -20,23 +20,21 @@ nsContainerFrame* NS_NewRubyBaseFrame(ns
 
 class nsRubyBaseFrame final : public nsRubyContentFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
   NS_DECL_QUERYFRAME_TARGET(nsRubyBaseFrame)
   NS_DECL_QUERYFRAME
 
-  // nsIFrame overrides
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
 protected:
   friend nsContainerFrame* NS_NewRubyBaseFrame(nsIPresShell* aPresShell,
                                                nsStyleContext* aContext);
   explicit nsRubyBaseFrame(nsStyleContext* aContext)
-    : nsRubyContentFrame(aContext) {}
+    : nsRubyContentFrame(aContext, mozilla::FrameType::RubyBase)
+  {}
 };
 
 #endif /* nsRubyBaseFrame_h___ */
--- a/layout/generic/nsRubyContentFrame.h
+++ b/layout/generic/nsRubyContentFrame.h
@@ -22,13 +22,15 @@ public:
   // Indicates whether this is an "intra-level whitespace" frame, i.e.
   // an anonymous frame that was created to contain non-droppable
   // whitespaces directly inside a ruby level container. This impacts
   // ruby pairing behavior.
   // See http://dev.w3.org/csswg/css-ruby/#anon-gen-interpret-space
   bool IsIntraLevelWhitespace() const;
 
 protected:
-  explicit nsRubyContentFrame(nsStyleContext* aContext)
-    : nsInlineFrame(aContext) {}
+  explicit nsRubyContentFrame(nsStyleContext* aContext,
+                              mozilla::FrameType aType)
+    : nsInlineFrame(aContext, aType)
+  {}
 };
 
 #endif /* nsRubyContentFrame_h___ */
--- a/layout/generic/nsRubyFrame.cpp
+++ b/layout/generic/nsRubyFrame.cpp
@@ -37,22 +37,16 @@ NS_NewRubyFrame(nsIPresShell* aPresShell
   return new (aPresShell) nsRubyFrame(aContext);
 }
 
 //----------------------------------------------------------------------
 
 // nsRubyFrame Method Implementations
 // ==================================
 
-nsIAtom*
-nsRubyFrame::GetType() const
-{
-  return nsGkAtoms::rubyFrame;
-}
-
 /* virtual */ bool
 nsRubyFrame::IsFrameOfType(uint32_t aFlags) const
 {
   if (aFlags & eBidiInlineContainer) {
     return false;
   }
   return nsInlineFrame::IsFrameOfType(aFlags);
 }
@@ -91,17 +85,17 @@ nsRubyFrame::AddInlinePrefISize(nsRender
 }
 
 static nsRubyBaseContainerFrame*
 FindRubyBaseContainerAncestor(nsIFrame* aFrame)
 {
   for (nsIFrame* ancestor = aFrame->GetParent();
        ancestor && ancestor->IsFrameOfType(nsIFrame::eLineParticipant);
        ancestor = ancestor->GetParent()) {
-    if (ancestor->GetType() == nsGkAtoms::rubyBaseContainerFrame) {
+    if (ancestor->IsRubyBaseContainerFrame()) {
       return static_cast<nsRubyBaseContainerFrame*>(ancestor);
     }
   }
   return nullptr;
 }
 
 /* virtual */ void
 nsRubyFrame::Reflow(nsPresContext* aPresContext,
@@ -376,27 +370,27 @@ nsRubyBaseContainerFrame*
 nsRubyFrame::PullOneSegment(const nsLineLayout* aLineLayout,
                             ContinuationTraversingState& aState)
 {
   // Pull a ruby base container
   nsIFrame* baseFrame = GetNextInFlowChild(aState);
   if (!baseFrame) {
     return nullptr;
   }
-  MOZ_ASSERT(baseFrame->GetType() == nsGkAtoms::rubyBaseContainerFrame);
+  MOZ_ASSERT(baseFrame->IsRubyBaseContainerFrame());
 
   // Get the float containing block of the base frame before we pull it.
   nsBlockFrame* oldFloatCB =
     nsLayoutUtils::GetFloatContainingBlock(baseFrame);
   PullNextInFlowChild(aState);
 
   // Pull all ruby text containers following the base container
   nsIFrame* nextFrame;
   while ((nextFrame = GetNextInFlowChild(aState)) != nullptr &&
-         nextFrame->GetType() == nsGkAtoms::rubyTextContainerFrame) {
+         nextFrame->IsRubyTextContainerFrame()) {
     PullNextInFlowChild(aState);
   }
 
   if (nsBlockFrame* newFloatCB =
       nsLayoutUtils::GetAsBlock(aLineLayout->LineContainerFrame())) {
     if (oldFloatCB && oldFloatCB != newFloatCB) {
       newFloatCB->ReparentFloats(baseFrame, oldFloatCB, true);
     }
--- a/layout/generic/nsRubyFrame.h
+++ b/layout/generic/nsRubyFrame.h
@@ -22,17 +22,16 @@ nsContainerFrame* NS_NewRubyFrame(nsIPre
 class nsRubyFrame final : public nsInlineFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
   NS_DECL_QUERYFRAME_TARGET(nsRubyFrame)
   NS_DECL_QUERYFRAME
 
   // nsIFrame overrides
-  virtual nsIAtom* GetType() const override;
   virtual bool IsFrameOfType(uint32_t aFlags) const override;
   virtual void AddInlineMinISize(nsRenderingContext *aRenderingContext,
                                  InlineMinISizeData *aData) override;
   virtual void AddInlinePrefISize(nsRenderingContext *aRenderingContext,
                                   InlinePrefISizeData *aData) override;
   virtual void Reflow(nsPresContext* aPresContext,
                       ReflowOutput& aDesiredSize,
                       const ReflowInput& aReflowInput,
@@ -45,17 +44,18 @@ public:
   mozilla::RubyBlockLeadings GetBlockLeadings() const {
     return mLeadings;
   }
 
 protected:
   friend nsContainerFrame* NS_NewRubyFrame(nsIPresShell* aPresShell,
                                            nsStyleContext* aContext);
   explicit nsRubyFrame(nsStyleContext* aContext)
-    : nsInlineFrame(aContext) {}
+    : nsInlineFrame(aContext, mozilla::FrameType::Ruby)
+  {}
 
   void ReflowSegment(nsPresContext* aPresContext,
                      const ReflowInput& aReflowInput,
                      nsRubyBaseContainerFrame* aBaseContainer,
                      nsReflowStatus& aStatus);
 
   nsRubyBaseContainerFrame* PullOneSegment(const nsLineLayout* aLineLayout,
                                            ContinuationTraversingState& aState);
--- a/layout/generic/nsRubyTextContainerFrame.cpp
+++ b/layout/generic/nsRubyTextContainerFrame.cpp
@@ -35,22 +35,16 @@ NS_NewRubyTextContainerFrame(nsIPresShel
 }
 
 
 //----------------------------------------------------------------------
 
 // nsRubyTextContainerFrame Method Implementations
 // ===============================================
 
-nsIAtom*
-nsRubyTextContainerFrame::GetType() const
-{
-  return nsGkAtoms::rubyTextContainerFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsRubyTextContainerFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("RubyTextContainer"), aResult);
 }
 #endif
 
@@ -139,17 +133,17 @@ nsRubyTextContainerFrame::Reflow(nsPresC
   nscoord minBCoord = nscoord_MAX;
   nscoord maxBCoord = nscoord_MIN;
   // The container size is not yet known, so we use a dummy (0, 0) size.
   // The block-dir position will be corrected below after containerSize
   // is finalized.
   const nsSize dummyContainerSize;
   for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
     nsIFrame* child = e.get();
-    MOZ_ASSERT(child->GetType() == nsGkAtoms::rubyTextFrame);
+    MOZ_ASSERT(child->IsRubyTextFrame());
     LogicalRect rect = child->GetLogicalRect(lineWM, dummyContainerSize);
     LogicalMargin margin = child->GetLogicalUsedMargin(lineWM);
     nscoord blockStart = rect.BStart(lineWM) - margin.BStart(lineWM);
     minBCoord = std::min(minBCoord, blockStart);
     nscoord blockEnd = rect.BEnd(lineWM) + margin.BEnd(lineWM);
     maxBCoord = std::max(maxBCoord, blockEnd);
   }
 
--- a/layout/generic/nsRubyTextContainerFrame.h
+++ b/layout/generic/nsRubyTextContainerFrame.h
@@ -21,17 +21,16 @@ nsContainerFrame* NS_NewRubyTextContaine
 class nsRubyTextContainerFrame final : public nsContainerFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
   NS_DECL_QUERYFRAME_TARGET(nsRubyTextContainerFrame)
   NS_DECL_QUERYFRAME
 
   // nsIFrame overrides
-  virtual nsIAtom* GetType() const override;
   virtual bool IsFrameOfType(uint32_t aFlags) const override;
   virtual void Reflow(nsPresContext* aPresContext,
                       ReflowOutput& aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus& aStatus) override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
@@ -51,19 +50,21 @@ public:
   {
     return GetStateBits() & NS_RUBY_TEXT_CONTAINER_IS_SPAN;
   }
 
 protected:
   friend nsContainerFrame*
     NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell,
                                  nsStyleContext* aContext);
+
   explicit nsRubyTextContainerFrame(nsStyleContext* aContext)
-    : nsContainerFrame(aContext)
-    , mISize(0) {}
+    : nsContainerFrame(aContext, mozilla::FrameType::RubyTextContainer)
+    , mISize(0)
+  {}
 
   void UpdateSpanFlag();
 
   friend class nsRubyBaseContainerFrame;
   void SetISize(nscoord aISize) { mISize = aISize; }
 
   // The intended inline size of the ruby text container. It is set by
   // the corresponding ruby base container when the segment is reflowed,
--- a/layout/generic/nsRubyTextFrame.cpp
+++ b/layout/generic/nsRubyTextFrame.cpp
@@ -34,22 +34,16 @@ NS_NewRubyTextFrame(nsIPresShell* aPresS
 }
 
 
 //----------------------------------------------------------------------
 
 // nsRubyTextFrame Method Implementations
 // ======================================
 
-nsIAtom*
-nsRubyTextFrame::GetType() const
-{
-  return nsGkAtoms::rubyTextFrame;
-}
-
 /* virtual */ bool
 nsRubyTextFrame::CanContinueTextRun() const
 {
   return false;
 }
 
 #ifdef DEBUG_FRAME_DUMP
 nsresult
--- a/layout/generic/nsRubyTextFrame.h
+++ b/layout/generic/nsRubyTextFrame.h
@@ -21,17 +21,16 @@ nsContainerFrame* NS_NewRubyTextFrame(ns
 class nsRubyTextFrame final : public nsRubyContentFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
   NS_DECL_QUERYFRAME_TARGET(nsRubyTextFrame)
   NS_DECL_QUERYFRAME
 
   // nsIFrame overrides
-  virtual nsIAtom* GetType() const override;
   virtual bool CanContinueTextRun() const override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
@@ -46,12 +45,13 @@ public:
   {
     return GetStateBits() & NS_RUBY_TEXT_FRAME_AUTOHIDE;
   }
 
 protected:
   friend nsContainerFrame* NS_NewRubyTextFrame(nsIPresShell* aPresShell,
                                                nsStyleContext* aContext);
   explicit nsRubyTextFrame(nsStyleContext* aContext)
-    : nsRubyContentFrame(aContext) {}
+    : nsRubyContentFrame(aContext, mozilla::FrameType::RubyText)
+  {}
 };
 
 #endif /* nsRubyTextFrame_h___ */
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -1165,17 +1165,17 @@ nsFrameSelection::MoveCaret(nsDirection 
     }
     result = TakeFocus(pos.mResultContent, pos.mContentOffset, pos.mContentOffset,
                        tHint, aContinueSelection, false);
   } else if (aAmount <= eSelectWordNoSpace && aDirection == eDirNext &&
              !aContinueSelection) {
     // Collapse selection if PeekOffset failed, we either
     //  1. bumped into the BRFrame, bug 207623
     //  2. had select-all in a text input (DIV range), bug 352759.
-    bool isBRFrame = frame->GetType() == nsGkAtoms::brFrame;
+    bool isBRFrame = frame->IsBrFrame();
     sel->Collapse(sel->GetFocusNode(), sel->FocusOffset());
     // Note: 'frame' might be dead here.
     if (!isBRFrame) {
       mHint = CARET_ASSOCIATE_BEFORE; // We're now at the end of the frame to the left.
     }
     result = NS_OK;
   }
   if (NS_SUCCEEDED(result))
@@ -1403,21 +1403,21 @@ nsFrameSelection::GetPrevNextBidiLevels(
   FrameBidiData currentBidi = currentFrame->GetBidiData();
   nsBidiLevel currentLevel = currentBidi.embeddingLevel;
   nsBidiLevel newLevel = newFrame ? newFrame->GetEmbeddingLevel()
                                   : currentBidi.baseLevel;
   
   // If not jumping lines, disregard br frames, since they might be positioned incorrectly.
   // XXX This could be removed once bug 339786 is fixed.
   if (!aJumpLines) {
-    if (currentFrame->GetType() == nsGkAtoms::brFrame) {
+    if (currentFrame->IsBrFrame()) {
       currentFrame = nullptr;
       currentLevel = currentBidi.baseLevel;
     }
-    if (newFrame && newFrame->GetType() == nsGkAtoms::brFrame) {
+    if (newFrame && newFrame->IsBrFrame()) {
       newFrame = nullptr;
       newLevel = currentBidi.baseLevel;
     }
   }
   
   if (direction == eDirNext)
     levels.SetData(currentFrame, newFrame, currentLevel, newLevel);
   else
@@ -2290,17 +2290,17 @@ nsFrameSelection::PhysicalMove(int16_t a
                                                     true))) {
     if (frame) {
       if (!frame->StyleContext()->IsTextCombined()) {
         wm = frame->GetWritingMode();
       } else {
         // Using different direction for horizontal-in-vertical would
         // make it hard to navigate via keyboard. Inherit the moving
         // direction from its parent.
-        MOZ_ASSERT(frame->GetType() == nsGkAtoms::textFrame);
+        MOZ_ASSERT(frame->IsTextFrame());
         wm = frame->GetParent()->GetWritingMode();
         MOZ_ASSERT(wm.IsVertical(), "Text combined "
                    "can only appear in vertical text");
       }
     }
   }
 
   const PhysicalToLogicalMapping& mapping =
@@ -4469,29 +4469,29 @@ Selection::SelectAllFramesForContent(nsI
                                      bool aSelected)
 {
   nsresult result = aInnerIter->Init(aContent);
   nsIFrame *frame;
   if (NS_SUCCEEDED(result))
   {
     // First select frame of content passed in
     frame = aContent->GetPrimaryFrame();
-    if (frame && frame->GetType() == nsGkAtoms::textFrame) {
+    if (frame && frame->IsTextFrame()) {
       nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
       textFrame->SetSelectedRange(0, aContent->GetText()->GetLength(),
                                   aSelected, mSelectionType);
     }
     // Now iterated through the child frames and set them
     while (!aInnerIter->IsDone()) {
       nsCOMPtr<nsIContent> innercontent =
         do_QueryInterface(aInnerIter->GetCurrentNode());
 
       frame = innercontent->GetPrimaryFrame();
       if (frame) {
-        if (frame->GetType() == nsGkAtoms::textFrame) {
+        if (frame->IsTextFrame()) {
           nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
           textFrame->SetSelectedRange(0, innercontent->GetText()->GetLength(),
                                       aSelected, mSelectionType);
         } else {
           frame->InvalidateFrameSubtree();  // frame continuations?
         }
       }
 
@@ -4538,17 +4538,17 @@ Selection::selectFrames(nsPresContext* a
     // Don't warn, bug 1055722
     return NS_ERROR_UNEXPECTED;
   }
 
   // We must call first one explicitly
   if (content->IsNodeOfType(nsINode::eTEXT)) {
     nsIFrame* frame = content->GetPrimaryFrame();
     // The frame could be an SVG text frame, in which case we'll ignore it.
-    if (frame && frame->GetType() == nsGkAtoms::textFrame) {
+    if (frame && frame->IsTextFrame()) {
       nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
       uint32_t startOffset = aRange->StartOffset();
       uint32_t endOffset;
       if (aRange->GetEndParent() == content) {
         endOffset = aRange->EndOffset();
       } else {
         endOffset = content->Length();
       }
@@ -4569,17 +4569,17 @@ Selection::selectFrames(nsPresContext* a
     nsresult res;
     content = do_QueryInterface(aRange->GetEndParent(), &res);
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_TRUE(content, res);
 
     if (content->IsNodeOfType(nsINode::eTEXT)) {
       nsIFrame* frame = content->GetPrimaryFrame();
       // The frame could be an SVG text frame, in which case we'll ignore it.
-      if (frame && frame->GetType() == nsGkAtoms::textFrame) {
+      if (frame && frame->IsTextFrame()) {
         nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
         textFrame->SetSelectedRange(0, aRange->EndOffset(), aSelect,
                                     mSelectionType);
       }
     }
   }
   return NS_OK;
 }
--- a/layout/generic/nsSimplePageSequenceFrame.cpp
+++ b/layout/generic/nsSimplePageSequenceFrame.cpp
@@ -39,23 +39,23 @@ mozilla::LazyLogModule gLayoutPrintingLo
 nsSimplePageSequenceFrame*
 NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsSimplePageSequenceFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsSimplePageSequenceFrame)
 
-nsSimplePageSequenceFrame::nsSimplePageSequenceFrame(nsStyleContext* aContext) :
-  nsContainerFrame(aContext),
-  mTotalPages(-1),
-  mSelectionHeight(-1),
-  mYSelOffset(0),
-  mCalledBeginPage(false),
-  mCurrentCanvasListSetup(false)
+nsSimplePageSequenceFrame::nsSimplePageSequenceFrame(nsStyleContext* aContext)
+  : nsContainerFrame(aContext, FrameType::Sequence)
+  , mTotalPages(-1)
+  , mSelectionHeight(-1)
+  , mYSelOffset(0)
+  , mCalledBeginPage(false)
+  , mCurrentCanvasListSetup(false)
 {
   nscoord halfInch = PresContext()->CSSTwipsToAppUnits(NS_INCHES_TO_TWIPS(0.5));
   mMargin.SizeTo(halfInch, halfInch, halfInch, halfInch);
 
   // XXX Unsafe to assume successful allocation
   mPageData = new nsSharedPageData();
   mPageData->mHeadFootFont =
     *PresContext()->GetDefaultFont(kGenericFont_serif,
@@ -298,17 +298,17 @@ nsSimplePageSequenceFrame::Reflow(nsPres
   // Get Total Page Count
   // XXXdholbert technically we could calculate this in the loop above,
   // instead of needing a separate walk.
   int32_t pageTot = mFrames.GetLength();
 
   // Set Page Number Info
   int32_t pageNum = 1;
   for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
-    MOZ_ASSERT(e.get()->GetType() == nsGkAtoms::pageFrame,
+    MOZ_ASSERT(e.get()->IsPageFrame(),
                "only expecting nsPageFrame children. Other children will make "
                "this static_cast bogus & probably violate other assumptions");
     nsPageFrame* pf = static_cast<nsPageFrame*>(e.get());
     pf->SetPageNumInfo(pageNum, pageTot);
     pageNum++;
   }
 
   nsAutoString formattedDateString;
@@ -731,17 +731,17 @@ nsSimplePageSequenceFrame::PrintNextPage
     nscoord pageContentHeight =
       PresContext()->GetPageSize().height - (mMargin.top + mMargin.bottom);
     nscoord selectionY = pageContentHeight;
     int32_t selectionCurrentPageNum = 1;
     bool haveUnfinishedSelectionToPrint = false;
 
     if (mSelectionHeight >= 0) {
       selectionContentFrame = currentPageFrame->PrincipalChildList().FirstChild();
-      MOZ_ASSERT(selectionContentFrame->GetType() == nsGkAtoms::pageContentFrame &&
+      MOZ_ASSERT(selectionContentFrame->IsPageContentFrame() &&
                  !selectionContentFrame->GetNextSibling(),
                  "Unexpected frame tree");
       // To print a selection we reposition the page content frame for each
       // page.  We can do this (and not have to bother resetting the position
       // after we're done) because we are printing from a static clone document
       // that is thrown away after we finish printing.
       selectionContentFrame->SetPosition(selectionContentFrame->GetPosition() +
                                          nsPoint(0, -mYSelOffset));
@@ -859,22 +859,16 @@ nsSimplePageSequenceFrame::BuildDisplayL
 
   content.AppendNewToTop(new (aBuilder)
       nsDisplayTransform(aBuilder, this, &content, content.GetVisibleRect(),
                          ::ComputePageSequenceTransform));
 
   aLists.Content()->AppendToTop(&content);
 }
 
-nsIAtom*
-nsSimplePageSequenceFrame::GetType() const
-{
-  return nsGkAtoms::sequenceFrame; 
-}
-
 //------------------------------------------------------------------------------
 void
 nsSimplePageSequenceFrame::SetPageNumberFormat(const nsAString& aFormatStr, bool aForPageNumOnly)
 { 
   NS_ASSERTION(mPageData != nullptr, "mPageData string cannot be null!");
 
   if (aForPageNumOnly) {
     mPageData->mPageNumFormat = aFormatStr;
--- a/layout/generic/nsSimplePageSequenceFrame.h
+++ b/layout/generic/nsSimplePageSequenceFrame.h
@@ -46,18 +46,20 @@ public:
 
   // The scaling ratio we need to apply to make all pages fit horizontally.  It's
   // the minimum "ComputedWidth / OverflowWidth" ratio of all page content frames
   // that overflowed.  It's 1.0 if none overflowed horizontally.
   float mShrinkToFitRatio;
 };
 
 // Simple page sequence frame class. Used when we're in paginated mode
-class nsSimplePageSequenceFrame : public nsContainerFrame,
-                                  public nsIPageSequenceFrame {
+class nsSimplePageSequenceFrame final
+  : public nsContainerFrame
+  , public nsIPageSequenceFrame
+{
 public:
   friend nsSimplePageSequenceFrame* NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell,
                                                                   nsStyleContext* aContext);
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsIFrame
@@ -93,23 +95,16 @@ public:
   NS_IMETHOD DoPageEnd() override;
 
   // We must allow Print Preview UI to have a background, no matter what the
   // user's settings
   bool HonorPrintBackgroundSettings() override { return false; }
 
   bool HasTransformGetter() const override { return true; }
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::sequenceFrame
-   */
-  nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
 protected:
   explicit nsSimplePageSequenceFrame(nsStyleContext* aContext);
   virtual ~nsSimplePageSequenceFrame();
 
--- a/layout/generic/nsSplittableFrame.cpp
+++ b/layout/generic/nsSplittableFrame.cpp
@@ -49,31 +49,34 @@ nsSplittableFrame::GetSplittableType() c
 nsIFrame* nsSplittableFrame::GetPrevContinuation() const
 {
   return mPrevContinuation;
 }
 
 void
 nsSplittableFrame::SetPrevContinuation(nsIFrame* aFrame)
 {
-  NS_ASSERTION (!aFrame || GetType() == aFrame->GetType(), "setting a prev continuation with incorrect type!");
-  NS_ASSERTION (!IsInPrevContinuationChain(aFrame, this), "creating a loop in continuation chain!");
+  NS_ASSERTION(!aFrame || Type() == aFrame->Type(),
+               "setting a prev continuation with incorrect type!");
+  NS_ASSERTION(!IsInPrevContinuationChain(aFrame, this),
+               "creating a loop in continuation chain!");
   mPrevContinuation = aFrame;
   RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
 }
 
 nsIFrame* nsSplittableFrame::GetNextContinuation() const
 {
   return mNextContinuation;
 }
 
 void
 nsSplittableFrame::SetNextContinuation(nsIFrame* aFrame)
 {
-  NS_ASSERTION (!aFrame || GetType() == aFrame->GetType(),  "setting a next continuation with incorrect type!");
+  NS_ASSERTION(!aFrame || Type() == aFrame->Type(),
+              "setting a next continuation with incorrect type!");
   NS_ASSERTION (!IsInNextContinuationChain(aFrame, this), "creating a loop in continuation chain!");
   mNextContinuation = aFrame;
   if (aFrame)
     aFrame->RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
 }
 
 nsIFrame*
 nsSplittableFrame::FirstContinuation() const
@@ -128,33 +131,37 @@ bool nsSplittableFrame::IsInNextContinua
 nsIFrame* nsSplittableFrame::GetPrevInFlow() const
 {
   return (GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? mPrevContinuation : nullptr;
 }
 
 void
 nsSplittableFrame::SetPrevInFlow(nsIFrame* aFrame)
 {
-  NS_ASSERTION (!aFrame || GetType() == aFrame->GetType(), "setting a prev in flow with incorrect type!");
-  NS_ASSERTION (!IsInPrevContinuationChain(aFrame, this), "creating a loop in continuation chain!");
+  NS_ASSERTION(!aFrame || Type() == aFrame->Type(),
+               "setting a prev in flow with incorrect type!");
+  NS_ASSERTION(!IsInPrevContinuationChain(aFrame, this),
+               "creating a loop in continuation chain!");
   mPrevContinuation = aFrame;
   AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
 }
 
 nsIFrame* nsSplittableFrame::GetNextInFlow() const
 {
   return mNextContinuation && (mNextContinuation->GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? 
     mNextContinuation : nullptr;
 }
 
 void
 nsSplittableFrame::SetNextInFlow(nsIFrame* aFrame)
 {
-  NS_ASSERTION (!aFrame || GetType() == aFrame->GetType(),  "setting a next in flow with incorrect type!");
-  NS_ASSERTION (!IsInNextContinuationChain(aFrame, this), "creating a loop in continuation chain!");
+  NS_ASSERTION(!aFrame || Type() == aFrame->Type(),
+               "setting a next in flow with incorrect type!");
+  NS_ASSERTION(!IsInNextContinuationChain(aFrame, this),
+               "creating a loop in continuation chain!");
   mNextContinuation = aFrame;
   if (aFrame)
     aFrame->AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
 }
 
 nsIFrame*
 nsSplittableFrame::FirstInFlow() const
 {
--- a/layout/generic/nsSplittableFrame.h
+++ b/layout/generic/nsSplittableFrame.h
@@ -69,18 +69,18 @@ public:
   virtual nsIFrame* FirstInFlow() const override;
   virtual nsIFrame* LastInFlow() const override;
 
   // Remove the frame from the flow. Connects the frame's prev-in-flow
   // and its next-in-flow. This should only be called in frame Destroy() methods.
   static void RemoveFromFlow(nsIFrame* aFrame);
 
 protected:
-  explicit nsSplittableFrame(nsStyleContext* aContext)
-    : nsFrame(aContext)
+  explicit nsSplittableFrame(nsStyleContext* aContext, mozilla::FrameType aType)
+    : nsFrame(aContext, aType)
     , mPrevContinuation(nullptr)
     , mNextContinuation(nullptr)
   {}
 
   /**
    * Return the sum of the block-axis content size of our prev-in-flows.
    * @param aWM a writing-mode to determine the block-axis
    *
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -54,17 +54,17 @@ GetDocumentFromView(nsView* aView)
   NS_PRECONDITION(aView, "");
 
   nsViewManager* vm = aView->GetViewManager();
   nsIPresShell* ps =  vm ? vm->GetPresShell() : nullptr;
   return ps ? ps->GetDocument() : nullptr;
 }
 
 nsSubDocumentFrame::nsSubDocumentFrame(nsStyleContext* aContext)
-  : nsAtomicContainerFrame(aContext)
+  : nsAtomicContainerFrame(aContext, FrameType::SubDocument)
   , mOuterView(nullptr)
   , mInnerView(nullptr)
   , mIsInline(false)
   , mPostedReflowCallback(false)
   , mDidCreateDoc(false)
   , mCallingShow(false)
 {
 }
@@ -615,22 +615,16 @@ nsSubDocumentFrame::List(FILE* out, cons
 }
 
 nsresult nsSubDocumentFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("FrameOuter"), aResult);
 }
 #endif
 
-nsIAtom*
-nsSubDocumentFrame::GetType() const
-{
-  return nsGkAtoms::subDocumentFrame;
-}
-
 /* virtual */ nscoord
 nsSubDocumentFrame::GetMinISize(nsRenderingContext *aRenderingContext)
 {
   nscoord result;
   DISPLAY_MIN_WIDTH(this, result);
 
   nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
   if (subDocRoot) {
@@ -1083,17 +1077,17 @@ InsertViewsInReverseOrder(nsView* aSibli
     vm->InsertChild(aParent, aSibling, nullptr, true);
     aSibling = next;
   }
 }
 
 nsresult
 nsSubDocumentFrame::BeginSwapDocShells(nsIFrame* aOther)
 {
-  if (!aOther || aOther->GetType() != nsGkAtoms::subDocumentFrame) {
+  if (!aOther || !aOther->IsSubDocumentFrame()) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   nsSubDocumentFrame* other = static_cast<nsSubDocumentFrame*>(aOther);
   if (!mFrameLoader || !mDidCreateDoc || mCallingShow ||
       !other->mFrameLoader || !other->mDidCreateDoc) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
--- a/layout/generic/nsSubDocumentFrame.h
+++ b/layout/generic/nsSubDocumentFrame.h
@@ -10,34 +10,33 @@
 #include "nsAtomicContainerFrame.h"
 #include "nsIReflowCallback.h"
 #include "nsFrameLoader.h"
 #include "Units.h"
 
 /******************************************************************************
  * nsSubDocumentFrame
  *****************************************************************************/
-class nsSubDocumentFrame : public nsAtomicContainerFrame,
-                           public nsIReflowCallback
+class nsSubDocumentFrame final
+  : public nsAtomicContainerFrame
+  , public nsIReflowCallback
 {
 public:
   NS_DECL_QUERYFRAME_TARGET(nsSubDocumentFrame)
   NS_DECL_FRAMEARENA_HELPERS
 
   explicit nsSubDocumentFrame(nsStyleContext* aContext);
 
 #ifdef DEBUG_FRAME_DUMP
   void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const override;
   nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   NS_DECL_QUERYFRAME
 
-  nsIAtom* GetType() const override;
-
   bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsAtomicContainerFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced |
         nsIFrame::eReplacedSizing |
         nsIFrame::eReplacedContainsBlock));
   }
 
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -582,23 +582,23 @@ ClearAllTextRunReferences(nsTextFrame* a
                   (!aStartContinuation->GetTextRun(nsTextFrame::eNotInflated) ||
                    aStartContinuation->GetTextRun(nsTextFrame::eNotInflated) == aTextRun),
                   "wrong aStartContinuation for this text run");
 
   if (!aStartContinuation || aStartContinuation == aFrame) {
     aFrame->RemoveStateBits(aWhichTextRunState);
   } else {
     do {
-      NS_ASSERTION(aFrame->GetType() == nsGkAtoms::textFrame, "Bad frame");
+      NS_ASSERTION(aFrame->IsTextFrame(), "Bad frame");
       aFrame = aFrame->GetNextContinuation();
     } while (aFrame && aFrame != aStartContinuation);
   }
   bool found = aStartContinuation == aFrame;
   while (aFrame) {
-    NS_ASSERTION(aFrame->GetType() == nsGkAtoms::textFrame, "Bad frame");
+    NS_ASSERTION(aFrame->IsTextFrame(), "Bad frame");
     if (!aFrame->RemoveTextRun(aTextRun)) {
       break;
     }
     aFrame = aFrame->GetNextContinuation();
   }
   NS_POSTCONDITION(!found || aStartContinuation, "how did we find null?");
   return found;
 }
@@ -681,18 +681,17 @@ InvalidateFrameDueToGlyphsChanged(nsIFra
 
     // If this is a non-display text frame within SVG <text>, we need
     // to reflow the SVGTextFrame. (This is similar to reflowing the
     // SVGTextFrame in response to style changes, in
     // SVGTextFrame::DidSetStyleContext.)
     if (nsSVGUtils::IsInSVGTextSubtree(f) &&
         f->GetStateBits() & NS_FRAME_IS_NONDISPLAY) {
       auto svgTextFrame = static_cast<SVGTextFrame*>(
-                            nsLayoutUtils::GetClosestFrameOfType(f,
-                            nsGkAtoms::svgTextFrame));
+        nsLayoutUtils::GetClosestFrameOfType(f, FrameType::SVGText));
       svgTextFrame->ScheduleReflowSVGNonDisplayText(nsIPresShell::eResize);
     } else {
       // Theoretically we could just update overflow areas, perhaps using
       // OverflowChangedTracker, but that would do a bunch of work eagerly that
       // we should probably do lazily here since there could be a lot
       // of text frames affected and we'd like to coalesce the work. So that's
       // not easy to do well.
       shell->FrameNeedsReflow(f, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
@@ -1233,24 +1232,22 @@ struct FrameTextTraversal {
     } else {
       f = nullptr;
     }
     return f;
   }
 };
 
 static FrameTextTraversal
-CanTextCrossFrameBoundary(nsIFrame* aFrame, nsIAtom* aType)
-{
-  NS_ASSERTION(aType == aFrame->GetType(), "Wrong type");
-
+CanTextCrossFrameBoundary(nsIFrame* aFrame)
+{
   FrameTextTraversal result;
 
   bool continuesTextRun = aFrame->CanContinueTextRun();
-  if (aType == nsGkAtoms::placeholderFrame) {
+  if (aFrame->IsPlaceholderFrame()) {
     // placeholders are "invisible", so a text run should be able to span
     // across one. But don't descend into the out-of-flow.
     result.mLineBreakerCanCrossFrameBoundary = true;
     result.mOverflowFrameToScan = nullptr;
     if (continuesTextRun) {
       // ... Except for first-letter floats, which are really in-flow
       // from the point of view of capitalization etc, so we'd better
       // descend into them. But we actually need to break the textrun for
@@ -1271,39 +1268,39 @@ CanTextCrossFrameBoundary(nsIFrame* aFra
         aFrame->GetChildList(nsIFrame::kOverflowList).FirstChild();
       NS_WARNING_ASSERTION(
         !result.mOverflowFrameToScan,
         "Scanning overflow inline frames is something we should avoid");
       result.mScanSiblings = true;
       result.mTextRunCanCrossFrameBoundary = true;
       result.mLineBreakerCanCrossFrameBoundary = true;
     } else {
-      MOZ_ASSERT(aType != nsGkAtoms::rubyTextContainerFrame,
+      MOZ_ASSERT(!aFrame->IsRubyTextContainerFrame(),
                  "Shouldn't call this method for ruby text container");
       result.mFrameToScan = nullptr;
       result.mOverflowFrameToScan = nullptr;
       result.mTextRunCanCrossFrameBoundary = false;
       result.mLineBreakerCanCrossFrameBoundary = false;
     }
   }
   return result;
 }
 
 BuildTextRunsScanner::FindBoundaryResult
 BuildTextRunsScanner::FindBoundaries(nsIFrame* aFrame, FindBoundaryState* aState)
 {
-  nsIAtom* frameType = aFrame->GetType();
-  if (frameType == nsGkAtoms::rubyTextContainerFrame) {
+  FrameType frameType = aFrame->Type();
+  if (frameType == FrameType::RubyTextContainer) {
     // Don't stop a text run for ruby text container. We want ruby text
     // containers to be skipped, but continue the text run across them.
     return FB_CONTINUE;
   }
 
-  nsTextFrame* textFrame = frameType == nsGkAtoms::textFrame
-    ? static_cast<nsTextFrame*>(aFrame) : nullptr;
+  nsTextFrame* textFrame =
+    frameType == FrameType::Text ? static_cast<nsTextFrame*>(aFrame) : nullptr;
   if (textFrame) {
     if (aState->mLastTextFrame &&
         textFrame != aState->mLastTextFrame->GetNextInFlow() &&
         !ContinueTextRunAcrossFrames(aState->mLastTextFrame, textFrame)) {
       aState->mSeenTextRunBoundaryOnThisLine = true;
       if (aState->mSeenSpaceForLineBreakingOnThisLine)
         return FB_FOUND_VALID_TEXTRUN_BOUNDARY;
     }
@@ -1328,18 +1325,17 @@ BuildTextRunsScanner::FindBoundaries(nsI
         aState->mSeenSpaceForLineBreakingOnThisLine = true;
         if (aState->mSeenTextRunBoundaryOnLaterLine)
           return FB_FOUND_VALID_TEXTRUN_BOUNDARY;
       }
     }
     return FB_CONTINUE;
   }
 
-  FrameTextTraversal traversal =
-    CanTextCrossFrameBoundary(aFrame, frameType);
+  FrameTextTraversal traversal = CanTextCrossFrameBoundary(aFrame);
   if (!traversal.mTextRunCanCrossFrameBoundary) {
     aState->mSeenTextRunBoundaryOnThisLine = true;
     if (aState->mSeenSpaceForLineBreakingOnThisLine)
       return FB_FOUND_VALID_TEXTRUN_BOUNDARY;
   }
 
   for (nsIFrame* f = traversal.NextFrameToScan(); f;
        f = traversal.NextFrameToScan()) {
@@ -1389,17 +1385,17 @@ BuildTextRuns(DrawTarget* aDrawTarget, n
   if (!aLineContainer) {
     if (aForFrame->IsFloatingFirstLetterChild()) {
       lineContainerChild = aForFrame->PresContext()->PresShell()->
         GetPlaceholderFrameFor(aForFrame->GetParent());
     }
     aLineContainer = FindLineContainer(lineContainerChild);
   } else {
     NS_ASSERTION((aLineContainer == FindLineContainer(aForFrame) ||
-                  (aLineContainer->GetType() == nsGkAtoms::letterFrame &&
+                  (aLineContainer->IsLetterFrame() &&
                    aLineContainer->IsFloating())),
                  "Wrong line container hint");
   }
 
   if (aForFrame->HasAnyStateBits(TEXT_IS_IN_TOKEN_MATHML)) {
     aLineContainer->AddStateBits(TEXT_IS_IN_TOKEN_MATHML);
     if (aForFrame->HasAnyStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI)) {
       aLineContainer->AddStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI);
@@ -1412,20 +1408,19 @@ BuildTextRuns(DrawTarget* aDrawTarget, n
   nsPresContext* presContext = aLineContainer->PresContext();
   BuildTextRunsScanner scanner(presContext, aDrawTarget,
                                aLineContainer, aWhichTextRun);
 
   nsBlockFrame* block = nsLayoutUtils::GetAsBlock(aLineContainer);
 
   if (!block) {
     nsIFrame* textRunContainer = aLineContainer;
-    if (aLineContainer->GetType() == nsGkAtoms::rubyTextContainerFrame) {
+    if (aLineContainer->IsRubyTextContainerFrame()) {
       textRunContainer = aForFrame;
-      while (textRunContainer &&
-             textRunContainer->GetType() != nsGkAtoms::rubyTextFrame) {
+      while (textRunContainer && !textRunContainer->IsRubyTextFrame()) {
         textRunContainer = textRunContainer->GetParent();
       }
       MOZ_ASSERT(textRunContainer &&
                  textRunContainer->GetParent() == aLineContainer);
     } else {
       NS_ASSERTION(
         !aLineContainer->GetPrevInFlow() && !aLineContainer->GetNextInFlow(),
         "Breakable non-block line containers other than "
@@ -1839,43 +1834,43 @@ BuildTextRunsScanner::ContinueTextRunAcr
     fontStyle1->mLanguage == fontStyle2->mLanguage &&
     textStyle1->mTextTransform == textStyle2->mTextTransform &&
     nsLayoutUtils::GetTextRunFlagsForStyle(sc1, fontStyle1, textStyle1, letterSpacing1) ==
       nsLayoutUtils::GetTextRunFlagsForStyle(sc2, fontStyle2, textStyle2, letterSpacing2);
 }
 
 void BuildTextRunsScanner::ScanFrame(nsIFrame* aFrame)
 {
-  nsIAtom* frameType = aFrame->GetType();
-  if (frameType == nsGkAtoms::rubyTextContainerFrame) {
+  FrameType frameType = aFrame->Type();
+  if (frameType == FrameType::RubyTextContainer) {
     // Don't include any ruby text container into the text run.
     return;
   }
 
   // First check if we can extend the current mapped frame block. This is common.
   if (mMappedFlows.Length() > 0) {
     MappedFlow* mappedFlow = &mMappedFlows[mMappedFlows.Length() - 1];
     if (mappedFlow->mEndFrame == aFrame &&
         (aFrame->GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION)) {
-      NS_ASSERTION(frameType == nsGkAtoms::textFrame,
+      NS_ASSERTION(frameType == FrameType::Text,
                    "Flow-sibling of a text frame is not a text frame?");
 
       // Don't do this optimization if mLastFrame has a terminal newline...
       // it's quite likely preformatted and we might want to end the textrun here.
       // This is almost always true:
       if (mLastFrame->StyleContext() == aFrame->StyleContext() &&
           !HasTerminalNewline(mLastFrame)) {
         AccumulateRunInfo(static_cast<nsTextFrame*>(aFrame));
         return;
       }
     }
   }
 
   // Now see if we can add a new set of frames to the current textrun
-  if (frameType == nsGkAtoms::textFrame) {
+  if (frameType == FrameType::Text) {
     nsTextFrame* frame = static_cast<nsTextFrame*>(aFrame);
 
     if (mLastFrame) {
       if (!ContinueTextRunAcrossFrames(mLastFrame, frame)) {
         FlushFrames(false, false);
       } else {
         if (mLastFrame->GetContent() == frame->GetContent()) {
           AccumulateRunInfo(frame);
@@ -1894,19 +1889,18 @@ void BuildTextRunsScanner::ScanFrame(nsI
     AccumulateRunInfo(frame);
     if (mMappedFlows.Length() == 1) {
       mCurrentFramesAllSameTextRun = frame->GetTextRun(mWhichTextRun);
       mCurrentRunContextInfo = mNextRunContextInfo;
     }
     return;
   }
 
-  FrameTextTraversal traversal =
-    CanTextCrossFrameBoundary(aFrame, frameType);
-  bool isBR = frameType == nsGkAtoms::brFrame;
+  FrameTextTraversal traversal = CanTextCrossFrameBoundary(aFrame);
+  bool isBR = frameType == FrameType::Br;
   if (!traversal.mLineBreakerCanCrossFrameBoundary) {
     // BR frames are special. We do not need or want to record a break opportunity
     // before a BR frame.
     FlushFrames(true, isBR);
     mCommonAncestorWithLastFrame = aFrame;
     mNextRunContextInfo &= ~nsTextFrameUtils::INCOMING_WHITESPACE;
     mStartOfLine = false;
   } else if (!traversal.mTextRunCanCrossFrameBoundary) {
@@ -4323,47 +4317,50 @@ public:
   void DestroyFrom(nsIFrame* aDestructRoot) override;
 
   nsTextFrame* GetPrevContinuation() const override
   {
     return mPrevContinuation;
   }
   void SetPrevContinuation(nsIFrame* aPrevContinuation) override
   {
-    NS_ASSERTION (!aPrevContinuation || GetType() == aPrevContinuation->GetType(),
-                  "setting a prev continuation with incorrect type!");
+    NS_ASSERTION(!aPrevContinuation || Type() == aPrevContinuation->Type(),
+                 "setting a prev continuation with incorrect type!");
     NS_ASSERTION (!nsSplittableFrame::IsInPrevContinuationChain(aPrevContinuation, this),
                   "creating a loop in continuation chain!");
     mPrevContinuation = static_cast<nsTextFrame*>(aPrevContinuation);
     RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
   }
   nsIFrame* GetPrevInFlowVirtual() const override { return GetPrevInFlow(); }
   nsTextFrame* GetPrevInFlow() const
   {
     return (GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? mPrevContinuation : nullptr;
   }
   void SetPrevInFlow(nsIFrame* aPrevInFlow) override
   {
-    NS_ASSERTION (!aPrevInFlow || GetType() == aPrevInFlow->GetType(),
-                  "setting a prev in flow with incorrect type!");
+    NS_ASSERTION(!aPrevInFlow || Type() == aPrevInFlow->Type(),
+                 "setting a prev in flow with incorrect type!");
     NS_ASSERTION (!nsSplittableFrame::IsInPrevContinuationChain(aPrevInFlow, this),
                   "creating a loop in continuation chain!");
     mPrevContinuation = static_cast<nsTextFrame*>(aPrevInFlow);
     AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
   }
   nsIFrame* FirstInFlow() const override;
   nsIFrame* FirstContinuation() const override;
 
   void AddInlineMinISize(nsRenderingContext* aRenderingContext,
                          InlineMinISizeData* aData) override;
   void AddInlinePrefISize(nsRenderingContext* aRenderingContext,
                           InlinePrefISizeData* aData) override;
 
 protected:
-  explicit nsContinuingTextFrame(nsStyleContext* aContext) : nsTextFrame(aContext) {}
+  explicit nsContinuingTextFrame(nsStyleContext* aContext)
+    : nsTextFrame(aContext)
+  {}
+
   nsTextFrame* mPrevContinuation;
 };
 
 void
 nsContinuingTextFrame::Init(nsIContent*       aContent,
                             nsContainerFrame* aParent,
                             nsIFrame*         aPrevInFlow)
 {
@@ -4602,31 +4599,29 @@ nsTextFrame::LastContinuation() const
   return lastContinuation;
 }
 
 void
 nsTextFrame::InvalidateFrame(uint32_t aDisplayItemKey)
 {
   if (nsSVGUtils::IsInSVGTextSubtree(this)) {
     nsIFrame* svgTextFrame =
-      nsLayoutUtils::GetClosestFrameOfType(GetParent(),
-                                           nsGkAtoms::svgTextFrame);
+      nsLayoutUtils::GetClosestFrameOfType(GetParent(), FrameType::SVGText);
     svgTextFrame->InvalidateFrame();
     return;
   }
   nsFrame::InvalidateFrame(aDisplayItemKey);
 }
 
 void
 nsTextFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
 {
   if (nsSVGUtils::IsInSVGTextSubtree(this)) {
     nsIFrame* svgTextFrame =
-      nsLayoutUtils::GetClosestFrameOfType(GetParent(),
-                                           nsGkAtoms::svgTextFrame);
+      nsLayoutUtils::GetClosestFrameOfType(GetParent(), FrameType::SVGText);
     svgTextFrame->InvalidateFrame();
     return;
   }
   nsFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
 }
 
 gfxTextRun*
 nsTextFrame::GetUninflatedTextRun()
@@ -5446,28 +5441,28 @@ nsTextFrame::GetTextDecorations(
     // If we're on an absolutely-positioned element or a floating
     // element, we're done.
     if (f->IsFloating() || f->IsAbsolutelyPositioned()) {
       break;
     }
 
     // If we're an outer <svg> element, which is classified as an atomic
     // inline-level element, we're done.
-    if (f->GetType() == nsGkAtoms::svgOuterSVGFrame) {
+    if (f->IsSVGOuterSVGFrame()) {
       break;
     }
   }
 }
 
 static float
 GetInflationForTextDecorations(nsIFrame* aFrame, nscoord aInflationMinFontSize)
 {
   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();
   }
   return nsLayoutUtils::FontSizeInflationInner(aFrame, aInflationMinFontSize);
 }
@@ -5502,17 +5497,17 @@ GenerateTextRunForEmphasisMarks(nsTextFr
 
 static nsRubyFrame*
 FindFurthestInlineRubyAncestor(nsTextFrame* aFrame)
 {
   nsRubyFrame* rubyFrame = nullptr;
   for (nsIFrame* frame = aFrame->GetParent();
        frame && frame->IsFrameOfType(nsIFrame::eLineParticipant);
        frame = frame->GetParent()) {
-    if (frame->GetType() == nsGkAtoms::rubyFrame) {
+    if (frame->IsRubyFrame()) {
       rubyFrame = static_cast<nsRubyFrame*>(frame);
     }
   }
   return rubyFrame;
 }
 
 nsRect
 nsTextFrame::UpdateTextEmphasis(WritingMode aWM, PropertyProvider& aProvider)
@@ -8870,19 +8865,18 @@ nsTextFrame::SetLength(int32_t aLength, 
   // and ChildIsDirty to handle a range of frames would be worse.
   if (aLineLayout &&
       (end != f->mContentOffset || (f->GetStateBits() & NS_FRAME_IS_DIRTY))) {
     aLineLayout->SetDirtyNextLine();
   }
 
   if (end < f->mContentOffset) {
     // Our frame is shrinking. Give the text to our next in flow.
-    if (aLineLayout &&
-        HasSignificantTerminalNewline() &&
-        GetParent()->GetType() != nsGkAtoms::letterFrame &&
+    if (aLineLayout && HasSignificantTerminalNewline() &&
+        !GetParent()->IsLetterFrame() &&
         (aSetLengthFlags & ALLOW_FRAME_CREATION_AND_DESTRUCTION)) {
       // Whatever text we hand to our next-in-flow will end up in a frame all of
       // its own, since it ends in a forced linebreak.  Might as well just put
       // it in a separate frame now.  This is important to prevent text run
       // churn; if we did not do that, then we'd likely end up rebuilding
       // textruns for all our following continuations.
       // We skip this optimization when the parent is a first-letter frame
       // because it doesn't deal well with more than one child frame.
@@ -8969,26 +8963,25 @@ nsTextFrame::SetLength(int32_t aLength, 
   }
 #endif
 }
 
 bool
 nsTextFrame::IsFloatingFirstLetterChild() const
 {
   nsIFrame* frame = GetParent();
-  return frame && frame->IsFloating() &&
-         frame->GetType() == nsGkAtoms::letterFrame;
+  return frame && frame->IsFloating() && frame->IsLetterFrame();
 }
 
 bool
 nsTextFrame::IsInitialLetterChild() const
 {
   nsIFrame* frame = GetParent();
   return frame && frame->StyleTextReset()->mInitialLetterSize != 0.0f &&
-         frame->GetType() == nsGkAtoms::letterFrame;
+         frame->IsLetterFrame();
 }
 
 struct NewlineProperty {
   int32_t mStartOffset;
   // The offset of the first \n after mStartOffset, or -1 if there is none
   int32_t mNewlineOffset;
 };
 
@@ -9972,22 +9965,16 @@ nsTextFrame::GetRenderedText(uint32_t aS
 
   if (!haveOffsets) {
     result.mOffsetWithinNodeText = textFrag->GetLength();
     result.mOffsetWithinNodeRenderedText = offsetInRenderedString;
   }
   return result;
 }
 
-nsIAtom*
-nsTextFrame::GetType() const
-{
-  return nsGkAtoms::textFrame;
-}
-
 /* virtual */ bool
 nsTextFrame::IsEmpty()
 {
   NS_ASSERTION(!(mState & TEXT_IS_ONLY_WHITESPACE) ||
                !(mState & TEXT_ISNOT_ONLY_WHITESPACE),
                "Invalid state");
 
   // XXXldb Should this check compatibility mode as well???
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -44,33 +44,27 @@ class nsTextFrame : public nsFrame
   typedef mozilla::TextRangeStyle TextRangeStyle;
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::Point Point;
   typedef mozilla::gfx::Rect Rect;
   typedef mozilla::gfx::Size Size;
   typedef gfxTextRun::Range Range;
 
 public:
+  explicit nsTextFrame(nsStyleContext* aContext)
+    : nsTextFrame(aContext, mozilla::FrameType::Text)
+  {}
+
   NS_DECL_QUERYFRAME_TARGET(nsTextFrame)
   NS_DECL_FRAMEARENA_HELPERS
 
   friend class nsContinuingTextFrame;
   friend class nsDisplayTextGeometry;
   friend class nsDisplayText;
 
-  explicit nsTextFrame(nsStyleContext* aContext)
-    : nsFrame(aContext)
-    , mNextContinuation(nullptr)
-    , mContentOffset(0)
-    , mContentLengthHint(0)
-    , mAscent(0)
-  {
-    NS_ASSERTION(mContentOffset == 0, "Bogus content offset");
-  }
-
   // nsQueryFrame
   NS_DECL_QUERYFRAME
 
   // nsIFrame
   void BuildDisplayList(nsDisplayListBuilder* aBuilder,
                         const nsRect& aDirtyRect,
                         const nsDisplayListSet& aLists) override;
 
@@ -83,18 +77,17 @@ public:
   nsresult GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor) override;
 
   nsresult CharacterDataChanged(CharacterDataChangeInfo* aInfo) final;
 
   nsTextFrame* GetPrevContinuation() const override { return nullptr; }
   nsTextFrame* GetNextContinuation() const final { return mNextContinuation; }
   void SetNextContinuation(nsIFrame* aNextContinuation) final
   {
-    NS_ASSERTION(!aNextContinuation ||
-                   GetType() == aNextContinuation->GetType(),
+    NS_ASSERTION(!aNextContinuation || Type() == aNextContinuation->Type(),
                  "setting a next continuation with incorrect type!");
     NS_ASSERTION(
       !nsSplittableFrame::IsInNextContinuationChain(aNextContinuation, this),
       "creating a loop in continuation chain!");
     mNextContinuation = static_cast<nsTextFrame*>(aNextContinuation);
     if (aNextContinuation)
       aNextContinuation->RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
     // Setting a non-fluid continuation might affect our flow length (they're
@@ -107,17 +100,17 @@ public:
     return mNextContinuation &&
                (mNextContinuation->GetStateBits() &
                 NS_FRAME_IS_FLUID_CONTINUATION)
              ? mNextContinuation
              : nullptr;
   }
   void SetNextInFlow(nsIFrame* aNextInFlow) final
   {
-    NS_ASSERTION(!aNextInFlow || GetType() == aNextInFlow->GetType(),
+    NS_ASSERTION(!aNextInFlow || Type() == aNextInFlow->Type(),
                  "setting a next in flow with incorrect type!");
     NS_ASSERTION(
       !nsSplittableFrame::IsInNextContinuationChain(aNextInFlow, this),
       "creating a loop in continuation chain!");
     mNextContinuation = static_cast<nsTextFrame*>(aNextInFlow);
     if (mNextContinuation &&
         !mNextContinuation->HasAnyStateBits(NS_FRAME_IS_FLUID_CONTINUATION)) {
       // Changing from non-fluid to fluid continuation might affect our flow
@@ -131,38 +124,31 @@ public:
   nsTextFrame* LastInFlow() const final;
   nsTextFrame* LastContinuation() const final;
 
   nsSplittableType GetSplittableType() const final
   {
     return NS_FRAME_SPLITTABLE;
   }
 
-  /**
-    * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::textFrame
-   */
-  nsIAtom* GetType() const final;
-
   bool IsFrameOfType(uint32_t aFlags) const final
   {
     // Set the frame state bit for text frames to mark them as replaced.
     // XXX kipp: temporary
     return nsFrame::IsFrameOfType(
       aFlags & ~(nsIFrame::eReplaced | nsIFrame::eLineParticipant));
   }
 
   bool ShouldSuppressLineBreak() const
   {
     // If the parent frame of the text frame is ruby content box, it must
     // suppress line break inside. This check is necessary, because when
     // a whitespace is only contained by pseudo ruby frames, its style
     // context won't have SuppressLineBreak bit set.
-    if (mozilla::RubyUtils::IsRubyContentBox(GetParent()->GetType())) {
+    if (mozilla::RubyUtils::IsRubyContentBox(GetParent()->Type())) {
       return true;
     }
     return StyleContext()->ShouldSuppressLineBreak();
   }
 
   void InvalidateFrame(uint32_t aDisplayItemKey = 0) override;
   void InvalidateFrameWithRect(const nsRect& aRect,
                                uint32_t aDisplayItemKey = 0) override;
@@ -657,16 +643,26 @@ public:
   bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override;
 
   void AssignJustificationGaps(const mozilla::JustificationAssignment& aAssign);
   mozilla::JustificationAssignment GetJustificationAssignment() const;
 
   uint32_t CountGraphemeClusters() const;
 
 protected:
+  nsTextFrame(nsStyleContext* aContext, mozilla::FrameType aType)
+    : nsFrame(aContext, aType)
+    , mNextContinuation(nullptr)
+    , mContentOffset(0)
+    , mContentLengthHint(0)
+    , mAscent(0)
+  {
+    NS_ASSERTION(mContentOffset == 0, "Bogus content offset");
+  }
+
   virtual ~nsTextFrame();
 
   RefPtr<gfxTextRun> mTextRun;
   nsTextFrame* mNextContinuation;
   // The key invariant here is that mContentOffset never decreases along
   // a next-continuation chain. And of course mContentOffset is always <= the
   // the text node's content length, and the mContentOffset for the first frame
   // is always 0. Furthermore the text mapped by a frame is determined by
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -70,17 +70,17 @@ SwapScaleWidthHeightForRotation(IntSize&
       aDegrees == VideoInfo::Rotation::kDegree_270) {
     int32_t tmpWidth = aSize.width;
     aSize.width = aSize.height;
     aSize.height = tmpWidth;
   }
 }
 
 nsVideoFrame::nsVideoFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::HTMLVideo)
 {
   EnableVisibilityTracking();
 }
 
 nsVideoFrame::~nsVideoFrame()
 {
 }
 
@@ -513,30 +513,24 @@ nsVideoFrame::BuildDisplayList(nsDisplay
   // Add child frames to display list. We expect various children,
   // but only want to draw mPosterImage conditionally. Others we
   // always add to the display list.
   for (nsIFrame* child : mFrames) {
     if (child->GetContent() != mPosterImage || shouldDisplayPoster) {
       child->BuildDisplayListForStackingContext(aBuilder,
                                                 aDirtyRect - child->GetOffsetTo(this),
                                                 aLists.Content());
-    } else if (child->GetType() == nsGkAtoms::boxFrame) {
+    } else if (child->IsBoxFrame()) {
       child->BuildDisplayListForStackingContext(aBuilder,
                                                 aDirtyRect - child->GetOffsetTo(this),
                                                 aLists.Content());
     }
   }
 }
 
-nsIAtom*
-nsVideoFrame::GetType() const
-{
-  return nsGkAtoms::HTMLVideoFrame;
-}
-
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsVideoFrame::AccessibleType()
 {
   return a11y::eHTMLMediaType;
 }
 #endif
 
--- a/layout/generic/nsVideoFrame.h
+++ b/layout/generic/nsVideoFrame.h
@@ -76,18 +76,16 @@ public:
               ReflowOutput&      aDesiredSize,
               const ReflowInput& aReflowInput,
               nsReflowStatus&    aStatus) override;
 
 #ifdef ACCESSIBILITY
   mozilla::a11y::AccType AccessibleType() override;
 #endif
 
-  nsIAtom* GetType() const override;
-
   bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsSplittableFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing));
   }
   
   nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
   void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -115,18 +115,17 @@ void nsDisplayMathMLError::Paint(nsDispl
  * =============================================================================
  */
 
 static bool
 IsForeignChild(const nsIFrame* aFrame)
 {
   // This counts nsMathMLmathBlockFrame as a foreign child, because it
   // uses block reflow
-  return !(aFrame->IsFrameOfType(nsIFrame::eMathML)) ||
-    aFrame->GetType() == nsGkAtoms::blockFrame;
+  return !(aFrame->IsFrameOfType(nsIFrame::eMathML)) || aFrame->IsBlockFrame();
 }
 
 NS_DECLARE_FRAME_PROPERTY_DELETABLE(HTMLReflowOutputProperty,
                                     ReflowOutput)
 
 /* static */ void
 nsMathMLContainerFrame::SaveReflowAndBoundingMetricsFor(nsIFrame*                  aFrame,
                                                         const ReflowOutput& aReflowOutput,
--- a/layout/mathml/nsMathMLContainerFrame.h
+++ b/layout/mathml/nsMathMLContainerFrame.h
@@ -26,18 +26,18 @@
 // Options for the preferred size at which to stretch our stretchy children 
 #define STRETCH_CONSIDER_ACTUAL_SIZE    0x00000001 // just use our current size
 #define STRETCH_CONSIDER_EMBELLISHMENTS 0x00000002 // size calculations include embellishments
 
 class nsMathMLContainerFrame : public nsContainerFrame,
                                public nsMathMLFrame {
   friend class nsMathMLmfencedFrame;
 public:
-  explicit nsMathMLContainerFrame(nsStyleContext* aContext)
-    : nsContainerFrame(aContext)
+  nsMathMLContainerFrame(nsStyleContext* aContext)
+    : nsContainerFrame(aContext, mozilla::FrameType::None)
     , mIntrinsicWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
     , mBlockStartAscent(0)
   {}
 
   NS_DECL_QUERYFRAME_TARGET(nsMathMLContainerFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_ABSTRACT_FRAME(nsMathMLContainerFrame)
 
@@ -553,13 +553,16 @@ public:
 
   bool
   IsMrowLike() override {
     return mFrames.FirstChild() != mFrames.LastChild() ||
            !mFrames.FirstChild();
   }
 
 protected:
-  explicit nsMathMLmathInlineFrame(nsStyleContext* aContext) : nsInlineFrame(aContext) {}
+  explicit nsMathMLmathInlineFrame(nsStyleContext* aContext)
+    : nsInlineFrame(aContext)
+  {}
+
   virtual ~nsMathMLmathInlineFrame() {}
 };
 
 #endif /* nsMathMLContainerFrame_h___ */
--- a/layout/mathml/nsMathMLTokenFrame.cpp
+++ b/layout/mathml/nsMathMLTokenFrame.cpp
@@ -63,17 +63,17 @@ nsMathMLTokenFrame::MarkTextFramesAsToke
   // Set flags on child text frames
   // - to force them to trim their leading and trailing whitespaces.
   // - Indicate which frames are suitable for mathvariant
   // - flag single character <mi> frames for special italic treatment
   for (nsIFrame* childFrame = PrincipalChildList().FirstChild(); childFrame;
        childFrame = childFrame->GetNextSibling()) {
     for (nsIFrame* childFrame2 = childFrame->PrincipalChildList().FirstChild();
          childFrame2; childFrame2 = childFrame2->GetNextSibling()) {
-      if (childFrame2->GetType() == nsGkAtoms::textFrame) {
+      if (childFrame2->IsTextFrame()) {
         childFrame2->AddStateBits(TEXT_IS_IN_TOKEN_MATHML);
         child = childFrame2;
         childCount++;
       }
     }
   }
   if (mContent->IsMathMLElement(nsGkAtoms::mi_) && childCount == 1) {
     nsAutoString data;
--- a/layout/mathml/nsMathMLmrowFrame.cpp
+++ b/layout/mathml/nsMathMLmrowFrame.cpp
@@ -40,17 +40,17 @@ nsMathMLmrowFrame::AttributeChanged(int3
 {
   // Special for <mtable>: In the frame construction code, we also use
   // this frame class as a wrapper for mtable. Hence, we should pass the
   // notification to the real mtable
   if (mContent->IsMathMLElement(nsGkAtoms::mtable_)) {
     nsIFrame* frame = mFrames.FirstChild();
     for ( ; frame; frame = frame->PrincipalChildList().FirstChild()) {
       // drill down to the real mtable
-      if (frame->GetType() == nsGkAtoms::tableWrapperFrame)
+      if (frame->IsTableWrapperFrame())
         return frame->AttributeChanged(aNameSpaceID, aAttribute, aModType);
     }
     NS_NOTREACHED("mtable wrapper without the real table frame");
   }
 
   return nsMathMLContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
 
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -164,17 +164,17 @@ FindCellProperty(const nsIFrame* aCellFr
                  const FramePropertyDescriptor<nsTArray<int8_t>>* aFrameProperty)
 {
   const nsIFrame* currentFrame = aCellFrame;
   nsTArray<int8_t>* propertyData = nullptr;
 
   while (currentFrame) {
     ConstFrameProperties props = currentFrame->Properties();
     propertyData = props.Get(aFrameProperty);
-    bool frameIsTable = (currentFrame->GetType() == nsGkAtoms::tableFrame);
+    bool frameIsTable = (currentFrame->IsTableFrame());
 
     if (propertyData || frameIsTable)
       currentFrame = nullptr; // A null frame pointer exits the loop
     else
       currentFrame = currentFrame->GetParent(); // Go to the parent frame
   }
 
   return propertyData;
@@ -580,30 +580,30 @@ MapAllAttributesIntoCSS(nsMathMLmtableFr
   ParseFrameAttribute(aTableFrame, nsGkAtoms::columnalign_, true);
   ParseFrameAttribute(aTableFrame, nsGkAtoms::columnlines_, true);
 
   // Map mtable rowspacing, columnspacing & framespacing
   ParseSpacingAttributes(aTableFrame);
 
   // mtable is simple and only has one (pseudo) row-group
   nsIFrame* rgFrame = aTableFrame->PrincipalChildList().FirstChild();
-  if (!rgFrame || rgFrame->GetType() != nsGkAtoms::tableRowGroupFrame)
+  if (!rgFrame || !rgFrame->IsTableRowGroupFrame())
     return;
 
   for (nsIFrame* rowFrame : rgFrame->PrincipalChildList()) {
     DEBUG_VERIFY_THAT_FRAME_IS(rowFrame, TableRow);
-    if (rowFrame->GetType() == nsGkAtoms::tableRowFrame) {
+    if (rowFrame->IsTableRowFrame()) {
       // Map row rowalign.
       ParseFrameAttribute(rowFrame, nsGkAtoms::rowalign_, false);
       // Map row columnalign.
       ParseFrameAttribute(rowFrame, nsGkAtoms::columnalign_, true);
 
       for (nsIFrame* cellFrame : rowFrame->PrincipalChildList()) {
         DEBUG_VERIFY_THAT_FRAME_IS(cellFrame, TableCell);
-        if (IS_TABLE_CELL(cellFrame->GetType())) {
+        if (IS_TABLE_CELL(cellFrame->Type())) {
           // Map cell rowalign.
           ParseFrameAttribute(cellFrame, nsGkAtoms::rowalign_, false);
           // Map row columnalign.
           ParseFrameAttribute(cellFrame, nsGkAtoms::columnalign_, false);
         }
       }
     }
   }
@@ -723,20 +723,20 @@ nsMathMLmtableWrapperFrame::AttributeCha
   // rowlines      : here 
   // rowspacing    : here
   // columnalign   : here 
   // columnlines   : here 
   // columnspacing : here
 
   // mtable is simple and only has one (pseudo) row-group inside our inner-table
   nsIFrame* tableFrame = mFrames.FirstChild();
-  NS_ASSERTION(tableFrame && tableFrame->GetType() == nsGkAtoms::tableFrame,
+  NS_ASSERTION(tableFrame && tableFrame->IsTableFrame(),
                "should always have an inner table frame");
   nsIFrame* rgFrame = tableFrame->PrincipalChildList().FirstChild();
-  if (!rgFrame || rgFrame->GetType() != nsGkAtoms::tableRowGroupFrame)
+  if (!rgFrame || !rgFrame->IsTableRowGroupFrame())
     return NS_OK;
 
   // align - just need to issue a dirty (resize) reflow command
   if (aAttribute == nsGkAtoms::align) {
     PresContext()->PresShell()->
       FrameNeedsReflow(this, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
     return NS_OK;
   }
@@ -796,25 +796,25 @@ nsMathMLmtableWrapperFrame::GetRowFrameA
   } else {
     // aRowIndex is 1-based, so convert it to a 0-based index
     --aRowIndex;
   }
 
   // if our inner table says that the index is valid, find the row now
   if (0 <= aRowIndex && aRowIndex <= rowCount) {
     nsIFrame* tableFrame = mFrames.FirstChild();
-    NS_ASSERTION(tableFrame && tableFrame->GetType() == nsGkAtoms::tableFrame,
+    NS_ASSERTION(tableFrame && tableFrame->IsTableFrame(),
                  "should always have an inner table frame");
     nsIFrame* rgFrame = tableFrame->PrincipalChildList().FirstChild();
-    if (!rgFrame || rgFrame->GetType() != nsGkAtoms::tableRowGroupFrame)
+    if (!rgFrame || !rgFrame->IsTableRowGroupFrame())
       return nullptr;
     for (nsIFrame* rowFrame : rgFrame->PrincipalChildList()) {
       if (aRowIndex == 0) {
         DEBUG_VERIFY_THAT_FRAME_IS(rowFrame, TableRow);
-        if (rowFrame->GetType() != nsGkAtoms::tableRowFrame)
+        if (!rowFrame->IsTableRowFrame())
           return nullptr;
 
         return rowFrame;
       }
       --aRowIndex;
     }
   }
   return nullptr;
--- a/layout/mathml/nsMathMLmtableFrame.h
+++ b/layout/mathml/nsMathMLmtableFrame.h
@@ -12,18 +12,19 @@
 #include "nsTableWrapperFrame.h"
 #include "nsTableRowFrame.h"
 #include "nsTableCellFrame.h"
 
 //
 // <mtable> -- table or matrix
 //
 
-class nsMathMLmtableWrapperFrame : public nsTableWrapperFrame,
-                                   public nsMathMLFrame
+class nsMathMLmtableWrapperFrame final
+  : public nsTableWrapperFrame
+  , public nsMathMLFrame
 {
 public:
   friend nsContainerFrame*
   NS_NewMathMLmtableOuterFrame(nsIPresShell*   aPresShell,
                                nsStyleContext* aContext);
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
@@ -43,29 +44,31 @@ public:
 
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsTableWrapperFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML));
   }
 
 protected:
   explicit nsMathMLmtableWrapperFrame(nsStyleContext* aContext)
-    : nsTableWrapperFrame(aContext) {}
+    : nsTableWrapperFrame(aContext)
+  {}
+
   virtual ~nsMathMLmtableWrapperFrame();
 
   // helper to find the row frame at a given index, positive or negative, e.g.,
   // 1..n means the first row down to the last row, -1..-n means the last row
   // up to the first row. Used for alignments that are relative to a given row
   nsIFrame*
   GetRowFrameAt(int32_t aRowIndex);
 }; // class nsMathMLmtableWrapperFrame
 
 // --------------
 
-class nsMathMLmtableFrame : public nsTableFrame
+class nsMathMLmtableFrame final : public nsTableFrame
 {
 public:
   NS_DECL_QUERYFRAME_TARGET(nsMathMLmtableFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   friend nsContainerFrame*
   NS_NewMathMLmtableFrame(nsIPresShell*   aPresShell,
@@ -150,30 +153,32 @@ public:
    * rowspacing, columnspacing and framespacing attributes.  The second
    * approach is used if the user specifies at least one of those attributes.
    */
   void SetUseCSSSpacing();
   bool GetUseCSSSpacing() { return mUseCSSSpacing; }
 
 protected:
   explicit nsMathMLmtableFrame(nsStyleContext* aContext)
-    : nsTableFrame(aContext) {}
+    : nsTableFrame(aContext)
+  {}
+
   virtual ~nsMathMLmtableFrame();
 
 private:
   nsTArray<nscoord> mColSpacing;
   nsTArray<nscoord> mRowSpacing;
   nscoord mFrameSpacingX;
   nscoord mFrameSpacingY;
   bool mUseCSSSpacing;
 }; // class nsMathMLmtableFrame
 
 // --------------
 
-class nsMathMLmtrFrame : public nsTableRowFrame
+class nsMathMLmtrFrame final : public nsTableRowFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   friend nsContainerFrame*
   NS_NewMathMLmtrFrame(nsIPresShell*   aPresShell,
                        nsStyleContext* aContext);
 
@@ -220,17 +225,19 @@ public:
     if (tableFrame && tableFrame->IsFrameOfType(nsIFrame::eMathML)) {
       // relayout the table
       ((nsMathMLmtableFrame*)tableFrame)->RestyleTable();
     }
   }
 
 protected:
   explicit nsMathMLmtrFrame(nsStyleContext* aContext)
-    : nsTableRowFrame(aContext) {}
+    : nsTableRowFrame(aContext)
+  {}
+
   virtual ~nsMathMLmtrFrame();
 }; // class nsMathMLmtrFrame
 
 // --------------
 
 class nsMathMLmtdFrame : public nsTableCellFrame
 {
 public:
@@ -265,24 +272,28 @@ public:
   }
 
   virtual LogicalMargin GetBorderWidth(WritingMode aWM) const override;
 
   virtual nsMargin GetBorderOverflow() override;
 
 protected:
   nsMathMLmtdFrame(nsStyleContext* aContext, nsTableFrame* aTableFrame)
-    : nsTableCellFrame(aContext, aTableFrame) {}
+    : nsTableCellFrame(aContext, aTableFrame)
+  {
+  }
+
   virtual ~nsMathMLmtdFrame();
 }; // class nsMathMLmtdFrame
 
 // --------------
 
-class nsMathMLmtdInnerFrame : public nsBlockFrame,
-                              public nsMathMLFrame
+class nsMathMLmtdInnerFrame final
+  : public nsBlockFrame
+  , public nsMathMLFrame
 {
 public:
   friend nsContainerFrame*
   NS_NewMathMLmtdInnerFrame(nsIPresShell*   aPresShell,
                             nsStyleContext* aContext);
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -1230,21 +1230,21 @@ nsCSSRendering::FindNonTransparentBackgr
 
 // Returns true if aFrame is a canvas frame.
 // We need to treat the viewport as canvas because, even though
 // it does not actually paint a background, we need to get the right
 // background style so we correctly detect transparent documents.
 bool
 nsCSSRendering::IsCanvasFrame(nsIFrame* aFrame)
 {
-  nsIAtom* frameType = aFrame->GetType();
-  return frameType == nsGkAtoms::canvasFrame ||
-         frameType == nsGkAtoms::rootFrame ||
-         frameType == nsGkAtoms::pageContentFrame ||
-         frameType == nsGkAtoms::viewportFrame;
+  FrameType frameType = aFrame->Type();
+  return frameType == FrameType::Canvas ||
+         frameType == FrameType::Root ||
+         frameType == FrameType::PageContent ||
+         frameType == FrameType::Viewport;
 }
 
 nsIFrame*
 nsCSSRendering::FindBackgroundStyleFrame(nsIFrame* aForFrame)
 {
   const nsStyleBackground* result = aForFrame->StyleBackground();
 
   // Check if we need to do propagation from BODY rather than HTML.
@@ -1748,17 +1748,17 @@ nsCSSRendering::PaintBoxShadowInner(nsPr
                                     nsIFrame* aForFrame,
                                     const nsRect& aFrameArea)
 {
   if (!ShouldPaintBoxShadowInner(aForFrame)) {
     return;
   }
 
   nsCSSShadowArray* shadows = aForFrame->StyleEffects()->mBoxShadow;
-  NS_ASSERTION(aForFrame->GetType() == nsGkAtoms::fieldSetFrame ||
+  NS_ASSERTION(aForFrame->IsFieldSetFrame() ||
                aFrameArea.Size() == aForFrame->GetSize(), "unexpected size");
 
   nsRect paddingRect = GetBoxShadowInnerPaddingRect(aForFrame, aFrameArea);
 
   RectCornerRadii innerRadii;
   bool hasBorderRadius = GetShadowInnerRadii(aForFrame,
                                              aFrameArea,
                                              innerRadii);
@@ -2130,17 +2130,17 @@ nsCSSRendering::GetImageLayerClip(const 
   aClipState->mHasRoundedCorners = false;
   aClipState->mHasAdditionalBGClipArea = false;
   aClipState->mAdditionalBGClipArea.SetEmpty();
   aClipState->mCustomClip = false;
 
   StyleGeometryBox layerClip = ComputeBoxValue(aForFrame, aLayer.mClip);
   if (IsSVGStyleGeometryBox(layerClip)) {
     MOZ_ASSERT(aForFrame->IsFrameOfType(nsIFrame::eSVG) &&
-               (aForFrame->GetType() != nsGkAtoms::svgOuterSVGFrame));
+               !aForFrame->IsSVGOuterSVGFrame());
 
     // The coordinate space of clipArea is svg user space.
     nsRect clipArea =
       nsLayoutUtils::ComputeGeometryBox(aForFrame, layerClip);
 
     nsRect strokeBox = (layerClip == StyleGeometryBox::StrokeBox)
       ? clipArea
       : nsLayoutUtils::ComputeGeometryBox(aForFrame, StyleGeometryBox::StrokeBox);
@@ -2170,17 +2170,17 @@ nsCSSRendering::GetImageLayerClip(const 
     SetupDirtyRects(aClipState->mBGClipArea, aCallerDirtyRect,
                     aAppUnitsPerPixel, &aClipState->mDirtyRectInAppUnits,
                     &aClipState->mDirtyRectInDevPx);
     MOZ_ASSERT(aClipState->IsValid());
     return;
   }
 
   MOZ_ASSERT(!aForFrame->IsFrameOfType(nsIFrame::eSVG) ||
-             aForFrame->GetType() == nsGkAtoms::svgOuterSVGFrame);
+             aForFrame->IsSVGOuterSVGFrame());
 
   // Compute the outermost boundary of the area that might be painted.
   // Same coordinate space as aBorderArea.
   Sides skipSides = aForFrame->GetSkipSides();
   nsRect clipBorderArea =
     ::BoxDecorationRectForBorder(aForFrame, aBorderArea, skipSides, &aBorder);
 
   bool haveRoundedCorners = GetRadii(aForFrame, aBorder, aBorderArea,
@@ -2194,17 +2194,17 @@ nsCSSRendering::GetImageLayerClip(const 
     // background.
     layerClip = haveRoundedCorners
                      ? StyleGeometryBox::MozAlmostPadding
                      : StyleGeometryBox::PaddingBox;
   }
 
   aClipState->mBGClipArea = clipBorderArea;
 
-  if (aForFrame->GetType() == nsGkAtoms::scrollFrame &&
+  if (aForFrame->IsScrollFrame() &&
       NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL == aLayer.mAttachment) {
     // As of this writing, this is still in discussion in the CSS Working Group
     // http://lists.w3.org/Archives/Public/www-style/2013Jul/0250.html
 
     // The rectangle for 'background-clip' scrolls with the content,
     // but the background is also clipped at a non-scrolling 'padding-box'
     // like the content. (See below.)
     // Therefore, only 'content-box' makes a difference here.
@@ -2783,17 +2783,17 @@ nsCSSRendering::ComputeImageLayerPositio
   // may need  it to compute the effective image size for a CSS gradient.
   nsRect positionArea;
 
   StyleGeometryBox layerOrigin =
     ComputeBoxValue(aForFrame, aLayer.mOrigin);
 
   if (IsSVGStyleGeometryBox(layerOrigin)) {
     MOZ_ASSERT(aForFrame->IsFrameOfType(nsIFrame::eSVG) &&
-               (aForFrame->GetType() != nsGkAtoms::svgOuterSVGFrame));
+               !aForFrame->IsSVGOuterSVGFrame());
     *aAttachedToFrame = aForFrame;
 
     positionArea =
       nsLayoutUtils::ComputeGeometryBox(aForFrame, layerOrigin);
 
     nsPoint toStrokeBoxOffset = nsPoint(0, 0);
     if (layerOrigin != StyleGeometryBox::StrokeBox) {
       nsRect strokeBox =
@@ -2802,21 +2802,21 @@ nsCSSRendering::ComputeImageLayerPositio
       toStrokeBoxOffset = positionArea.TopLeft() - strokeBox.TopLeft();
     }
 
     // For SVG frames, the return value is relative to the stroke box
     return nsRect(toStrokeBoxOffset, positionArea.Size());
   }
 
   MOZ_ASSERT(!aForFrame->IsFrameOfType(nsIFrame::eSVG) ||
-             aForFrame->GetType() == nsGkAtoms::svgOuterSVGFrame);
-
-  nsIAtom* frameType = aForFrame->GetType();
+             aForFrame->IsSVGOuterSVGFrame());
+
+  FrameType frameType = aForFrame->Type();
   nsIFrame* geometryFrame = aForFrame;
-  if (MOZ_UNLIKELY(frameType == nsGkAtoms::scrollFrame &&
+  if (MOZ_UNLIKELY(frameType == FrameType::Scroll &&
                    NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL == aLayer.mAttachment)) {
     nsIScrollableFrame* scrollableFrame = do_QueryFrame(aForFrame);
     positionArea = nsRect(
       scrollableFrame->GetScrolledFrame()->GetPosition()
         // For the dir=rtl case:
         + scrollableFrame->GetScrollRange().TopLeft(),
       scrollableFrame->GetScrolledRect().Size());
     // The ScrolledRect’s size does not include the borders or scrollbars,
@@ -2833,17 +2833,17 @@ nsCSSRendering::ComputeImageLayerPositio
       positionArea.Deflate(padding);
       NS_ASSERTION(layerOrigin == StyleGeometryBox::ContentBox,
                    "unknown background-origin value");
     }
     *aAttachedToFrame = aForFrame;
     return positionArea;
   }
 
-  if (MOZ_UNLIKELY(frameType == nsGkAtoms::canvasFrame)) {
+  if (MOZ_UNLIKELY(frameType == FrameType::Canvas)) {
     geometryFrame = aForFrame->PrincipalChildList().FirstChild();
     // geometryFrame might be null if this canvas is a page created
     // as an overflow container (e.g. the in-flow content has already
     // finished and this page only displays the continuations of
     // absolutely positioned content).
     if (geometryFrame) {
       positionArea = geometryFrame->GetRect();
     }
@@ -2877,17 +2877,17 @@ nsCSSRendering::ComputeImageLayerPositio
     // If it's a fixed background attachment, then the image is placed
     // relative to the viewport, which is the area of the root frame
     // in a screen context or the page content frame in a print context.
     attachedToFrame = aPresContext->PresShell()->FrameManager()->GetRootFrame();
     NS_ASSERTION(attachedToFrame, "no root frame");
     nsIFrame* pageContentFrame = nullptr;
     if (aPresContext->IsPaginated()) {
       pageContentFrame =
-        nsLayoutUtils::GetClosestFrameOfType(aForFrame, nsGkAtoms::pageContentFrame);
+        nsLayoutUtils::GetClosestFrameOfType(aForFrame, FrameType::PageContent);
       if (pageContentFrame) {
         attachedToFrame = pageContentFrame;
       }
       // else this is an embedded shell and its root frame is what we want
     }
 
     // If the background is affected by a transform, treat is as if it
     // wasn't fixed.
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -1018,17 +1018,17 @@ AnimatedGeometryRoot*
 nsDisplayListBuilder::FindAnimatedGeometryRootFor(nsDisplayItem* aItem)
 {
   if (aItem->ShouldFixToViewport(this)) {
     // Make its active scrolled root be the active scrolled root of
     // the enclosing viewport, since it shouldn't be scrolled by scrolled
     // frames in its document. InvalidateFixedBackgroundFramesFromList in
     // nsGfxScrollFrame will not repaint this item when scrolling occurs.
     nsIFrame* viewportFrame =
-      nsLayoutUtils::GetClosestFrameOfType(aItem->Frame(), nsGkAtoms::viewportFrame, RootReferenceFrame());
+      nsLayoutUtils::GetClosestFrameOfType(aItem->Frame(), FrameType::Viewport, RootReferenceFrame());
     if (viewportFrame) {
       return FindAnimatedGeometryRootFor(viewportFrame);
     }
   }
   return FindAnimatedGeometryRootFor(aItem->Frame());
 }
 
 
@@ -1208,17 +1208,17 @@ DisplayListIsNonBlank(nsDisplayList* aLi
     switch (i->GetType()) {
       case nsDisplayItem::TYPE_LAYER_EVENT_REGIONS:
       case nsDisplayItem::TYPE_CANVAS_BACKGROUND_COLOR:
       case nsDisplayItem::TYPE_CANVAS_BACKGROUND_IMAGE:
         continue;
       case nsDisplayItem::TYPE_SOLID_COLOR:
       case nsDisplayItem::TYPE_BACKGROUND:
       case nsDisplayItem::TYPE_BACKGROUND_COLOR:
-        if (i->Frame()->GetType() == nsGkAtoms::canvasFrame) {
+        if (i->Frame()->IsCanvasFrame()) {
           continue;
         }
         return true;
       default:
         return true;
     }
   }
   return false;
@@ -1452,17 +1452,17 @@ IsStickyFrameActive(nsDisplayListBuilder
   MOZ_ASSERT(aFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY);
 
   // Find the nearest scrollframe.
   nsIFrame* cursor = aFrame;
   nsIFrame* parent = aParent;
   if (!parent) {
     parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
   }
-  while (parent->GetType() != nsGkAtoms::scrollFrame) {
+  while (!parent->IsScrollFrame()) {
     cursor = parent;
     if ((parent = nsLayoutUtils::GetCrossDocParentFrame(cursor)) == nullptr) {
       return false;
     }
   }
 
   nsIScrollableFrame* sf = do_QueryFrame(parent);
   return sf->IsScrollingActive(aBuilder) && sf->GetScrolledFrame() == cursor;
@@ -1498,30 +1498,31 @@ nsDisplayListBuilder::IsAnimatedGeometry
   if (aFrame->IsTransformed()) {
     return true;
   }
 
   nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
   if (!parent)
     return true;
 
-  nsIAtom* parentType = parent->GetType();
+  FrameType parentType = parent->Type();
   // Treat the slider thumb as being as an active scrolled root when it wants
   // its own layer so that it can move without repainting.
-  if (parentType == nsGkAtoms::sliderFrame && nsLayoutUtils::IsScrollbarThumbLayerized(aFrame)) {
+  if (parentType == FrameType::Slider &&
+      nsLayoutUtils::IsScrollbarThumbLayerized(aFrame)) {
     return true;
   }
 
   if (aFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY &&
       IsStickyFrameActive(this, aFrame, parent))
   {
     return true;
   }
 
-  if (parentType == nsGkAtoms::scrollFrame || parentType == nsGkAtoms::listControlFrame) {
+  if (parentType == FrameType::Scroll || parentType == FrameType::ListControl) {
     nsIScrollableFrame* sf = do_QueryFrame(parent);
     if (sf->IsScrollingActive(this) && sf->GetScrolledFrame() == aFrame) {
       return true;
     }
   }
 
   // Fixed-pos frames are parented by the viewport frame, which has no parent.
   if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame)) {
@@ -3475,17 +3476,17 @@ nsDisplayBackgroundImage::GetInsideClipR
 {
   nsRegion result;
   if (aRect.IsEmpty())
     return result;
 
   nsIFrame *frame = aItem->Frame();
 
   nsRect clipRect = aBackgroundRect;
-  if (frame->GetType() == nsGkAtoms::canvasFrame) {
+  if (frame->IsCanvasFrame()) {
     nsCanvasFrame* canvasFrame = static_cast<nsCanvasFrame*>(frame);
     clipRect = canvasFrame->CanvasArea() + aItem->ToReferenceFrame();
   } else if (aClip == StyleGeometryBox::PaddingBox ||
              aClip == StyleGeometryBox::ContentBox) {
     nsMargin border = frame->GetUsedBorder();
     if (aClip == StyleGeometryBox::ContentBox) {
       border += frame->GetUsedPadding();
     }
@@ -3682,17 +3683,17 @@ nsRect
 nsDisplayBackgroundImage::GetBoundsInternal(nsDisplayListBuilder* aBuilder) {
   nsPresContext* presContext = mFrame->PresContext();
 
   if (!mBackgroundStyle) {
     return nsRect();
   }
 
   nsRect clipRect = mBackgroundRect;
-  if (mFrame->GetType() == nsGkAtoms::canvasFrame) {
+  if (mFrame->IsCanvasFrame()) {
     nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
     clipRect = frame->CanvasArea() + ToReferenceFrame();
   }
   const nsStyleImageLayers::Layer& layer = mBackgroundStyle->mImage.mLayers[mLayer];
   return nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
                                                 mBackgroundRect, clipRect, layer,
                                                 aBuilder->GetBackgroundPaintFlags());
 }
@@ -4274,17 +4275,17 @@ nsDisplayLayerEventRegions::AddFrame(nsD
   NS_ASSERTION(aBuilder->FindReferenceFrameFor(aFrame) == aBuilder->FindReferenceFrameFor(mFrame),
                "Reference frame mismatch");
   if (aBuilder->IsInsidePointerEventsNoneDoc()) {
     // Somewhere up the parent document chain is a subdocument with pointer-
     // events:none set on it.
     return;
   }
   if (!aFrame->GetParent()) {
-    MOZ_ASSERT(aFrame->GetType() == nsGkAtoms::viewportFrame);
+    MOZ_ASSERT(aFrame->IsViewportFrame());
     // Viewport frames are never event targets, other frames, like canvas frames,
     // are the event targets for any regions viewport frames may cover.
     return;
   }
 
   uint8_t pointerEvents =
     aFrame->StyleUserInterface()->GetEffectivePointerEvents(aFrame);
   if (pointerEvents == NS_STYLE_POINTER_EVENTS_NONE) {
@@ -4343,17 +4344,17 @@ nsDisplayLayerEventRegions::AddFrame(nsD
       aBuilder->GetAncestorHasApzAwareEventHandler())
   {
     // Scrollbars may be painted into a layer below the actual layer they will
     // scroll, and therefore wheel events may be dispatched to the outer frame
     // instead of the intended scrollframe. To address this, we force a d-t-c
     // region on scrollbar frames that won't be placed in their own layer. See
     // bug 1213324 for details.
     mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, borderBox);
-  } else if (aFrame->GetType() == nsGkAtoms::objectFrame) {
+  } else if (aFrame->IsObjectFrame()) {
     // If the frame is a plugin frame and wants to handle wheel events as
     // default action, we should add the frame to dispatch-to-content region.
     nsPluginFrame* pluginFrame = do_QueryFrame(aFrame);
     if (pluginFrame && pluginFrame->WantsToHandleWheelEventAsDefaultAction()) {
       mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, borderBox);
     }
   }
 
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -2060,17 +2060,17 @@ nsPrintEngine::SetRootView(
     //XXX If printing supported printing document hierarchies with non-constant
     // zoom this would be wrong as we use the same mPrt->mPrintDC for all
     // subdocuments.
     adjSize = frame->GetContentRect().Size();
     documentIsTopLevel = false;
     // presshell exists because parent is printable
 
     // the top nsPrintObject's widget will always have scrollbars
-    if (frame && frame->GetType() == nsGkAtoms::subDocumentFrame) {
+    if (frame && frame->IsSubDocumentFrame()) {
       nsView* view = frame->GetView();
       NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
       view = view->GetFirstChild();
       NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
       parentView = view;
       canCreateScrollbars = false;
     }
   } else {
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -804,18 +804,18 @@ nsComputedDOMStyle::UpdateCurrentStyleSo
                             : nsGkAtoms::afterPseudoProperty;
 
       auto* pseudo = static_cast<Element*>(mContent->GetProperty(property));
       mOuterFrame = pseudo ? pseudo->GetPrimaryFrame() : nullptr;
     }
 
     mInnerFrame = mOuterFrame;
     if (mOuterFrame) {
-      nsIAtom* type = mOuterFrame->GetType();
-      if (type == nsGkAtoms::tableWrapperFrame) {
+      FrameType type = mOuterFrame->Type();
+      if (type == FrameType::TableWrapper) {
         // If the frame is a table wrapper frame then we should get the style
         // from the inner table frame.
         mInnerFrame = mOuterFrame->PrincipalChildList().FirstChild();
         NS_ASSERTION(mInnerFrame, "table wrapper must have an inner");
         NS_ASSERTION(!mInnerFrame->GetNextSibling(),
                      "table wrapper frames should have just one child, "
                      "the inner table");
       }
@@ -4978,17 +4978,17 @@ nsComputedDOMStyle::DoGetHeight()
 
   if (mInnerFrame) {
     calcHeight = true;
 
     const nsStyleDisplay* displayData = StyleDisplay();
     if (displayData->mDisplay == mozilla::StyleDisplay::Inline &&
         !(mInnerFrame->IsFrameOfType(nsIFrame::eReplaced)) &&
         // An outer SVG frame should behave the same as eReplaced in this case
-        mInnerFrame->GetType() != nsGkAtoms::svgOuterSVGFrame) {
+        !mInnerFrame->IsSVGOuterSVGFrame()) {
 
       calcHeight = false;
     }
   }
 
   if (calcHeight) {
     AssertFlushedPendingReflows();
     nsMargin adjustedValues = GetAdjustedValuesForBoxSizing();
@@ -5022,17 +5022,17 @@ nsComputedDOMStyle::DoGetWidth()
 
   if (mInnerFrame) {
     calcWidth = true;
 
     const nsStyleDisplay *displayData = StyleDisplay();
     if (displayData->mDisplay == mozilla::StyleDisplay::Inline &&
         !(mInnerFrame->IsFrameOfType(nsIFrame::eReplaced)) &&
         // An outer SVG frame should behave the same as eReplaced in this case
-        mInnerFrame->GetType() != nsGkAtoms::svgOuterSVGFrame) {
+        !mInnerFrame->IsSVGOuterSVGFrame()) {
 
       calcWidth = false;
     }
   }
 
   if (calcWidth) {
     AssertFlushedPendingReflows();
     nsMargin adjustedValues = GetAdjustedValuesForBoxSizing();
@@ -5089,23 +5089,22 @@ nsComputedDOMStyle::ShouldHonorMinSizeAu
   // Note: We only need to bother checking one "overflow" subproperty for
   // "visible", because a non-"visible" value in either axis would force the
   // other axis to also be non-"visible" as well.
 
   if (mOuterFrame) {
     nsIFrame* containerFrame = mOuterFrame->GetParent();
     if (containerFrame &&
         StyleDisplay()->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE) {
-      auto containerType = containerFrame->GetType();
-      if (containerType == nsGkAtoms::flexContainerFrame &&
+      if (containerFrame->IsFlexContainerFrame() &&
           (static_cast<nsFlexContainerFrame*>(containerFrame)->IsHorizontal() ==
            (aAxis == eAxisHorizontal))) {
         return true;
       }
-      if (containerType == nsGkAtoms::gridContainerFrame) {
+      if (containerFrame->IsGridContainerFrame()) {
         return true;
       }
     }
   }
   return false;
 }
 
 already_AddRefed<CSSValue>
@@ -5230,17 +5229,17 @@ nsComputedDOMStyle::GetAbsoluteOffset(mo
 
   nsIFrame* container = mOuterFrame->GetContainingBlock();
   nsMargin margin = mOuterFrame->GetUsedMargin();
   nsMargin border = container->GetUsedBorder();
   nsMargin scrollbarSizes(0, 0, 0, 0);
   nsRect rect = mOuterFrame->GetRect();
   nsRect containerRect = container->GetRect();
 
-  if (container->GetType() == nsGkAtoms::viewportFrame) {
+  if (container->IsViewportFrame()) {
     // For absolutely positioned frames scrollbars are taken into
     // account by virtue of getting a containing block that does
     // _not_ include the scrollbars.  For fixed positioned frames,
     // the containing block is the viewport, which _does_ include
     // scrollbars.  We have to do some extra work.
     // the first child in the default frame list is what we want
     nsIFrame* scrollingChild = container->PrincipalChildList().FirstChild();
     nsIScrollableFrame *scrollFrame = do_QueryFrame(scrollingChild);
--- a/layout/style/nsFontFaceUtils.cpp
+++ b/layout/style/nsFontFaceUtils.cpp
@@ -126,17 +126,17 @@ nsFontFaceUtils::MarkDirtyForFontChange(
       nsIFrame* f = stack.ElementAt(stack.Length() - 1);
       stack.RemoveElementAt(stack.Length() - 1);
 
       // if this frame uses the font, mark its descendants dirty
       // and skip checking its children
       if (FrameUsesFont(f, aFont)) {
         ScheduleReflow(ps, f);
       } else {
-        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);
--- a/layout/style/nsStyleStructInlines.h
+++ b/layout/style/nsStyleStructInlines.h
@@ -77,59 +77,59 @@ nsStyleText::WordCanWrap(const nsIFrame*
   return WordCanWrapStyle() && !nsSVGUtils::IsInSVGTextSubtree(aContextFrame);
 }
 
 bool
 nsStyleDisplay::IsBlockInside(const nsIFrame* aContextFrame) const
 {
   NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
   if (nsSVGUtils::IsInSVGTextSubtree(aContextFrame)) {
-    return aContextFrame->GetType() == nsGkAtoms::blockFrame;
+    return aContextFrame->IsBlockFrame();
   }
   return IsBlockInsideStyle();
 }
 
 bool
 nsStyleDisplay::IsBlockOutside(const nsIFrame* aContextFrame) const
 {
   NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
   if (nsSVGUtils::IsInSVGTextSubtree(aContextFrame)) {
-    return aContextFrame->GetType() == nsGkAtoms::blockFrame;
+    return aContextFrame->IsBlockFrame();
   }
   return IsBlockOutsideStyle();
 }
 
 bool
 nsStyleDisplay::IsInlineOutside(const nsIFrame* aContextFrame) const
 {
   NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
   if (nsSVGUtils::IsInSVGTextSubtree(aContextFrame)) {
-    return aContextFrame->GetType() != nsGkAtoms::blockFrame;
+    return !aContextFrame->IsBlockFrame();
   }
   return IsInlineOutsideStyle();
 }
 
 bool
 nsStyleDisplay::IsOriginalDisplayInlineOutside(const nsIFrame* aContextFrame) const
 {
   NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
   if (nsSVGUtils::IsInSVGTextSubtree(aContextFrame)) {
-    return aContextFrame->GetType() != nsGkAtoms::blockFrame;
+    return !aContextFrame->IsBlockFrame();
   }
   return IsOriginalDisplayInlineOutsideStyle();
 }
 
 mozilla::StyleDisplay
 nsStyleDisplay::GetDisplay(const nsIFrame* aContextFrame) const
 {
   NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
   if (nsSVGUtils::IsInSVGTextSubtree(aContextFrame) &&
       mDisplay != mozilla::StyleDisplay::None) {
-    return aContextFrame->GetType() == nsGkAtoms::blockFrame ?
-             mozilla::StyleDisplay::Block : mozilla::StyleDisplay::Inline;
+    return aContextFrame->IsBlockFrame() ? mozilla::StyleDisplay::Block
+                                         : mozilla::StyleDisplay::Inline;
   }
   return mDisplay;
 }
 
 bool
 nsStyleDisplay::IsFloating(const nsIFrame* aContextFrame) const
 {
   NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
--- a/layout/svg/SVGFEContainerFrame.cpp
+++ b/layout/svg/SVGFEContainerFrame.cpp
@@ -16,17 +16,17 @@
  * have special child elements that provide parameters.
  */
 class SVGFEContainerFrame : public nsContainerFrame
 {
   friend nsIFrame*
   NS_NewSVGFEContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   explicit SVGFEContainerFrame(nsStyleContext* aContext)
-    : nsContainerFrame(aContext)
+    : nsContainerFrame(aContext, mozilla::FrameType::SVGFEContainer)
   {
     AddStateBits(NS_FRAME_SVG_LAYOUT | NS_FRAME_IS_NONDISPLAY);
   }
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   virtual bool IsFrameOfType(uint32_t aFlags) const override
@@ -42,22 +42,16 @@ public:
   }
 #endif
 
 #ifdef DEBUG
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 #endif
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgFEContainerFrame
-   */
-  virtual nsIAtom* GetType() const override;
 
   virtual nsresult AttributeChanged(int32_t  aNameSpaceID,
                                     nsIAtom* aAttribute,
                                     int32_t  aModType) override;
 
   virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override {
     // We don't maintain a visual overflow rect
     return false;
@@ -81,28 +75,22 @@ SVGFEContainerFrame::Init(nsIContent*   
   NS_ASSERTION(aContent->IsNodeOfType(nsINode::eFILTER),
                "Trying to construct an SVGFEContainerFrame for a "
                "content element that doesn't support the right interfaces");
 
   nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
-nsIAtom *
-SVGFEContainerFrame::GetType() const
-{
-  return nsGkAtoms::svgFEContainerFrame;
-}
-
 nsresult
 SVGFEContainerFrame::AttributeChanged(int32_t  aNameSpaceID,
                                       nsIAtom* aAttribute,
                                       int32_t  aModType)
 {
   nsSVGFE *element = static_cast<nsSVGFE*>(mContent);
   if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) {
-    MOZ_ASSERT(GetParent()->GetType() == nsGkAtoms::svgFilterFrame,
+    MOZ_ASSERT(GetParent()->IsSVGFilterFrame(),
                "Observers observe the filter, so that's what we must invalidate");
     nsSVGEffects::InvalidateDirectRenderingObservers(GetParent());
   }
 
   return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
--- a/layout/svg/SVGFEImageFrame.cpp
+++ b/layout/svg/SVGFEImageFrame.cpp
@@ -11,23 +11,23 @@
 #include "nsLiteralString.h"
 #include "nsSVGEffects.h"
 #include "nsSVGFilters.h"
 #include "mozilla/dom/SVGFEImageElement.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
-class SVGFEImageFrame : public nsFrame
+class SVGFEImageFrame final : public nsFrame
 {
   friend nsIFrame*
   NS_NewSVGFEImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   explicit SVGFEImageFrame(nsStyleContext* aContext)
-    : nsFrame(aContext)
+    : nsFrame(aContext, FrameType::SVGFEImage)
   {
     AddStateBits(NS_FRAME_SVG_LAYOUT | NS_FRAME_IS_NONDISPLAY);
 
     // This frame isn't actually displayed, but it contains an image and we want
     // to use the nsImageLoadingContent machinery for managing images, which
     // requires visibility tracking, so we enable visibility tracking and
     // forcibly mark it visible below.
     EnableVisibilityTracking();
@@ -48,23 +48,16 @@ public:
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGFEImage"), aResult);
   }
 #endif
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgFEImageFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   virtual nsresult AttributeChanged(int32_t  aNameSpaceID,
                                     nsIAtom* aAttribute,
                                     int32_t  aModType) override;
 
   void OnVisibilityChange(Visibility aNewVisibility,
                           const Maybe<OnNonvisible>& aNonvisibleAction = Nothing()) override;
 
   virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override {
@@ -117,30 +110,24 @@ SVGFEImageFrame::Init(nsIContent*       
 
   nsCOMPtr<nsIImageLoadingContent> imageLoader =
     do_QueryInterface(nsFrame::mContent);
   if (imageLoader) {
     imageLoader->FrameCreated(this);
   }
 }
 
-nsIAtom *
-SVGFEImageFrame::GetType() const
-{
-  return nsGkAtoms::svgFEImageFrame;
-}
-
 nsresult
 SVGFEImageFrame::AttributeChanged(int32_t  aNameSpaceID,
                                   nsIAtom* aAttribute,
                                   int32_t  aModType)
 {
   SVGFEImageElement *element = static_cast<SVGFEImageElement*>(mContent);
   if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) {
-    MOZ_ASSERT(GetParent()->GetType() == nsGkAtoms::svgFilterFrame,
+    MOZ_ASSERT(GetParent()->IsSVGFilterFrame(),
                "Observers observe the filter, so that's what we must invalidate");
     nsSVGEffects::InvalidateDirectRenderingObservers(GetParent());
   }
   if ((aNameSpaceID == kNameSpaceID_XLink ||
        aNameSpaceID == kNameSpaceID_None) &&
       aAttribute == nsGkAtoms::href) {
     bool hrefIsSet =
       element->mStringAttributes[SVGFEImageElement::HREF].IsExplicitlySet() ||
--- a/layout/svg/SVGFELeafFrame.cpp
+++ b/layout/svg/SVGFELeafFrame.cpp
@@ -9,23 +9,23 @@
 #include "nsGkAtoms.h"
 #include "nsSVGEffects.h"
 #include "nsSVGFilters.h"
 
 /*
  * This frame is used by filter primitive elements that don't
  * have special child elements that provide parameters.
  */
-class SVGFELeafFrame : public nsFrame
+class SVGFELeafFrame final : public nsFrame
 {
   friend nsIFrame*
   NS_NewSVGFELeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   explicit SVGFELeafFrame(nsStyleContext* aContext)
-    : nsFrame(aContext)
+    : nsFrame(aContext, FrameType::SVGFELeaf)
   {
     AddStateBits(NS_FRAME_SVG_LAYOUT | NS_FRAME_IS_NONDISPLAY);
   }
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
 #ifdef DEBUG
@@ -41,23 +41,16 @@ public:
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGFELeaf"), aResult);
   }
 #endif
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgFELeafFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   virtual nsresult AttributeChanged(int32_t  aNameSpaceID,
                                     nsIAtom* aAttribute,
                                     int32_t  aModType) override;
 
   virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override {
     // We don't maintain a visual overflow rect
     return false;
   }
@@ -80,28 +73,22 @@ SVGFELeafFrame::Init(nsIContent*       a
   NS_ASSERTION(aContent->IsNodeOfType(nsINode::eFILTER),
                "Trying to construct an SVGFELeafFrame for a "
                "content element that doesn't support the right interfaces");
 
   nsFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
-nsIAtom *
-SVGFELeafFrame::GetType() const
-{
-  return nsGkAtoms::svgFELeafFrame;
-}
-
 nsresult
 SVGFELeafFrame::AttributeChanged(int32_t  aNameSpaceID,
                                  nsIAtom* aAttribute,
                                  int32_t  aModType)
 {
   nsSVGFE *element = static_cast<nsSVGFE*>(mContent);
   if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) {
-    MOZ_ASSERT(GetParent()->GetType() == nsGkAtoms::svgFilterFrame,
+    MOZ_ASSERT(GetParent()->IsSVGFilterFrame(),
                "Observers observe the filter, so that's what we must invalidate");
     nsSVGEffects::InvalidateDirectRenderingObservers(GetParent());
   }
 
   return nsFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
--- a/layout/svg/SVGFEUnstyledLeafFrame.cpp
+++ b/layout/svg/SVGFEUnstyledLeafFrame.cpp
@@ -11,17 +11,17 @@
 #include "nsSVGFilters.h"
 
 class SVGFEUnstyledLeafFrame : public nsFrame
 {
   friend nsIFrame*
   NS_NewSVGFEUnstyledLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   explicit SVGFEUnstyledLeafFrame(nsStyleContext* aContext)
-    : nsFrame(aContext)
+    : nsFrame(aContext, FrameType::SVGFEUnstyledLeaf)
   {
     AddStateBits(NS_FRAME_SVG_LAYOUT | NS_FRAME_IS_NONDISPLAY);
   }
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
@@ -35,23 +35,16 @@ public:
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGFEUnstyledLeaf"), aResult);
   }
 #endif
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgFEUnstyledLeafFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   virtual nsresult AttributeChanged(int32_t  aNameSpaceID,
                                     nsIAtom* aAttribute,
                                     int32_t  aModType) override;
 
   virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override {
     // We don't maintain a visual overflow rect
     return false;
   }
@@ -60,28 +53,22 @@ public:
 nsIFrame*
 NS_NewSVGFEUnstyledLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) SVGFEUnstyledLeafFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(SVGFEUnstyledLeafFrame)
 
-nsIAtom *
-SVGFEUnstyledLeafFrame::GetType() const
-{
-  return nsGkAtoms::svgFEUnstyledLeafFrame;
-}
-
 nsresult
 SVGFEUnstyledLeafFrame::AttributeChanged(int32_t  aNameSpaceID,
                                          nsIAtom* aAttribute,
                                          int32_t  aModType)
 {
   SVGFEUnstyledElement *element = static_cast<SVGFEUnstyledElement*>(mContent);
   if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) {
-    MOZ_ASSERT(GetParent()->GetParent()->GetType() == nsGkAtoms::svgFilterFrame,
+    MOZ_ASSERT(GetParent()->GetParent()->IsSVGFilterFrame(),
                "Observers observe the filter, so that's what we must invalidate");
     nsSVGEffects::InvalidateDirectRenderingObservers(GetParent()->GetParent());
   }
 
   return nsFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
--- a/layout/svg/SVGGeometryFrame.cpp
+++ b/layout/svg/SVGGeometryFrame.cpp
@@ -225,22 +225,16 @@ SVGGeometryFrame::DidSetStyleContext(nsS
           // Moz2D Path objects are fill-rule specific.
           element->ClearAnyCachedPath();
         }
       }
     }
   }
 }
 
-nsIAtom *
-SVGGeometryFrame::GetType() const
-{
-  return nsGkAtoms::svgGeometryFrame;
-}
-
 bool
 SVGGeometryFrame::IsSVGTransformed(gfx::Matrix *aOwnTransform,
                                    gfx::Matrix *aFromParentTransform) const
 {
   bool foundTransform = false;
 
   // Check if our parent has children-only transforms:
   nsIFrame *parent = GetParent();
@@ -731,36 +725,36 @@ SVGGeometryFrame::GetMarkerProperties(SV
   return result;
 }
 
 nsSVGMarkerFrame *
 SVGGeometryFrame::MarkerProperties::GetMarkerStartFrame()
 {
   if (!mMarkerStart)
     return nullptr;
-  return static_cast<nsSVGMarkerFrame *>
-    (mMarkerStart->GetReferencedFrame(nsGkAtoms::svgMarkerFrame, nullptr));
+  return static_cast<nsSVGMarkerFrame*>(
+    mMarkerStart->GetReferencedFrame(FrameType::SVGMarker, nullptr));
 }
 
 nsSVGMarkerFrame *
 SVGGeometryFrame::MarkerProperties::GetMarkerMidFrame()
 {
   if (!mMarkerMid)
     return nullptr;
-  return static_cast<nsSVGMarkerFrame *>
-    (mMarkerMid->GetReferencedFrame(nsGkAtoms::svgMarkerFrame, nullptr));
+  return static_cast<nsSVGMarkerFrame*>(
+    mMarkerMid->GetReferencedFrame(FrameType::SVGMarker, nullptr));
 }
 
 nsSVGMarkerFrame *
 SVGGeometryFrame::MarkerProperties::GetMarkerEndFrame()
 {
   if (!mMarkerEnd)
     return nullptr;
-  return static_cast<nsSVGMarkerFrame *>
-    (mMarkerEnd->GetReferencedFrame(nsGkAtoms::svgMarkerFrame, nullptr));
+  return static_cast<nsSVGMarkerFrame*>(
+    mMarkerEnd->GetReferencedFrame(FrameType::SVGMarker, nullptr));
 }
 
 DrawResult
 SVGGeometryFrame::Render(gfxContext* aContext,
                          uint32_t aRenderComponents,
                          const gfxMatrix& aNewTransform,
                          uint32_t aFlags)
 {
--- a/layout/svg/SVGGeometryFrame.h
+++ b/layout/svg/SVGGeometryFrame.h
@@ -44,22 +44,26 @@ class SVGGeometryFrame : public nsFrame
   typedef mozilla::gfx::DrawTarget DrawTarget;
 
   friend nsIFrame*
   ::NS_NewSVGGeometryFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   friend class ::nsDisplaySVGGeometry;
 
 protected:
-  explicit SVGGeometryFrame(nsStyleContext* aContext)
-    : nsFrame(aContext)
+  SVGGeometryFrame(nsStyleContext* aContext, mozilla::FrameType aType)
+    : nsFrame(aContext, aType)
   {
      AddStateBits(NS_FRAME_SVG_LAYOUT | NS_FRAME_MAY_BE_TRANSFORMED);
   }
 
+  explicit SVGGeometryFrame(nsStyleContext* aContext)
+    : SVGGeometryFrame(aContext, mozilla::FrameType::SVGGeometry)
+  {}
+
 public:
   NS_DECL_QUERYFRAME_TARGET(SVGGeometryFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsIFrame interface:
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
@@ -71,23 +75,16 @@ public:
   }
 
   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
                                      nsIAtom*        aAttribute,
                                      int32_t         aModType) override;
 
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgGeometryFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsSVGTransformed(Matrix *aOwnTransforms = nullptr,
                                 Matrix *aFromParentTransforms = nullptr) const override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGGeometry"), aResult);
   }
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -2764,17 +2764,17 @@ public:
   void NotifyGlyphPathEmitted() override;
   void NotifyAfterText() override;
 
 private:
   void SetupContext();
 
   bool IsClipPathChild() const {
     return nsLayoutUtils::GetClosestFrameOfType
-             (mFrame->GetParent(), nsGkAtoms::svgTextFrame)->GetStateBits() &
+             (mFrame->GetParent(), FrameType::SVGText)->GetStateBits() &
              NS_STATE_SVG_CLIPPATH_CHILD;
   }
 
   /**
    * Paints a piece of text geometry.  This is called when glyphs
    * or text decorations have been emitted to the gfxContext.
    */
   void HandleTextGeometry();
@@ -3205,22 +3205,16 @@ SVGTextFrame::AttributeChanged(int32_t a
              aAttribute == nsGkAtoms::textLength ||
              aAttribute == nsGkAtoms::lengthAdjust) {
     NotifyGlyphMetricsChange();
   }
 
   return NS_OK;
 }
 
-nsIAtom *
-SVGTextFrame::GetType() const
-{
-  return nsGkAtoms::svgTextFrame;
-}
-
 void
 SVGTextFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   if (mState & NS_FRAME_IS_NONDISPLAY) {
     // We need this DidSetStyleContext override to handle cases like this:
     //
     //   <defs>
     //     <g>
@@ -5447,17 +5441,17 @@ SVGTextFrame::GetFontSizeScaleFactor() c
  * which rendered run the point hits.
  */
 Point
 SVGTextFrame::TransformFramePointToTextChild(const Point& aPoint,
                                              nsIFrame* aChildFrame)
 {
   NS_ASSERTION(aChildFrame &&
                nsLayoutUtils::GetClosestFrameOfType
-                 (aChildFrame->GetParent(), nsGkAtoms::svgTextFrame) == this,
+                 (aChildFrame->GetParent(), FrameType::SVGText) == this,
                "aChildFrame must be a descendant of this frame");
 
   UpdateGlyphPositioning();
 
   nsPresContext* presContext = PresContext();
 
   // Add in the mRect offset to aPoint, as that will have been taken into
   // account when transforming the point from the ancestor frame down
@@ -5526,17 +5520,17 @@ SVGTextFrame::TransformFramePointToTextC
  * and union them all together.
  */
 gfxRect
 SVGTextFrame::TransformFrameRectToTextChild(const gfxRect& aRect,
                                             nsIFrame* aChildFrame)
 {
   NS_ASSERTION(aChildFrame &&
                nsLayoutUtils::GetClosestFrameOfType
-                 (aChildFrame->GetParent(), nsGkAtoms::svgTextFrame) == this,
+                 (aChildFrame->GetParent(), FrameType::SVGText) == this,
                "aChildFrame must be a descendant of this frame");
 
   UpdateGlyphPositioning();
 
   nsPresContext* presContext = PresContext();
 
   // Add in the mRect offset to aRect, as that will have been taken into
   // account when transforming the rect from the ancestor frame down
@@ -5607,17 +5601,17 @@ SVGTextFrame::TransformFrameRectToTextCh
  * The result is the union of all of these.
  */
 gfxRect
 SVGTextFrame::TransformFrameRectFromTextChild(const nsRect& aRect,
                                               nsIFrame* aChildFrame)
 {
   NS_ASSERTION(aChildFrame &&
                nsLayoutUtils::GetClosestFrameOfType
-                 (aChildFrame->GetParent(), nsGkAtoms::svgTextFrame) == this,
+                 (aChildFrame->GetParent(), FrameType::SVGText) == this,
                "aChildFrame must be a descendant of this frame");
 
   UpdateGlyphPositioning();
 
   nsPresContext* presContext = PresContext();
 
   gfxRect result;
   TextRenderedRunIterator it(this, TextRenderedRunIterator::eAllFrames,
--- a/layout/svg/SVGTextFrame.h
+++ b/layout/svg/SVGTextFrame.h
@@ -189,17 +189,17 @@ class SVGTextFrame final : public nsSVGD
   typedef gfxTextRun::Range Range;
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::Path Path;
   typedef mozilla::gfx::Point Point;
   typedef mozilla::image::DrawResult DrawResult;
 
 protected:
   explicit SVGTextFrame(nsStyleContext* aContext)
-    : nsSVGDisplayContainerFrame(aContext)
+    : nsSVGDisplayContainerFrame(aContext, mozilla::FrameType::SVGText)
     , mTrailingUndisplayedCharacters(0)
     , mFontSizeScaleFactor(1.0f)
     , mLastContextScale(1.0f)
     , mLengthAdjustScaleFactor(1.0f)
   {
     AddStateBits(NS_STATE_SVG_POSITIONING_DIRTY);
   }
 
@@ -223,23 +223,16 @@ public:
   {
     return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   }
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgTextFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGText"), aResult);
   }
 #endif
 
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) override;
--- a/layout/svg/SVGViewFrame.cpp
+++ b/layout/svg/SVGViewFrame.cpp
@@ -19,17 +19,17 @@ using namespace mozilla::dom;
  * the view receives to the overridden <svg> element (if there is one).
  **/
 class SVGViewFrame : public nsFrame
 {
   friend nsIFrame*
   NS_NewSVGViewFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   explicit SVGViewFrame(nsStyleContext* aContext)
-    : nsFrame(aContext)
+    : nsFrame(aContext, FrameType::SVGView)
   {
     AddStateBits(NS_FRAME_IS_NONDISPLAY);
   }
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
 #ifdef DEBUG
@@ -45,23 +45,16 @@ public:
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGView"), aResult);
   }
 #endif
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgFELeafFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   virtual nsresult AttributeChanged(int32_t  aNameSpaceID,
                                     nsIAtom* aAttribute,
                                     int32_t  aModType) override;
 
   virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override {
     // We don't maintain a visual overflow rect
     return false;
   }
@@ -83,22 +76,16 @@ SVGViewFrame::Init(nsIContent*       aCo
 {
   NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::view),
                "Content is not an SVG view");
 
   nsFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
-nsIAtom *
-SVGViewFrame::GetType() const
-{
-  return nsGkAtoms::svgViewFrame;
-}
-
 nsresult
 SVGViewFrame::AttributeChanged(int32_t  aNameSpaceID,
                                nsIAtom* aAttribute,
                                int32_t  aModType)
 {
   // Ignore zoomAndPan as it does not cause the <svg> element to re-render
     
   if (aNameSpaceID == kNameSpaceID_None &&
--- a/layout/svg/nsSVGAFrame.cpp
+++ b/layout/svg/nsSVGAFrame.cpp
@@ -15,39 +15,33 @@
 using namespace mozilla;
 
 class nsSVGAFrame : public nsSVGDisplayContainerFrame
 {
   friend nsIFrame*
   NS_NewSVGAFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   explicit nsSVGAFrame(nsStyleContext* aContext)
-    : nsSVGDisplayContainerFrame(aContext) {}
+    : nsSVGDisplayContainerFrame(aContext, FrameType::SVGA)
+  {}
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
 #ifdef DEBUG
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 #endif
 
   // nsIFrame:
   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
                                      nsIAtom*        aAttribute,
                                      int32_t         aModType) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgAFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGA"), aResult);
   }
 #endif
   // nsSVGDisplayableFrame interface:
   virtual void NotifySVGChanged(uint32_t aFlags) override;
@@ -98,22 +92,16 @@ nsSVGAFrame::AttributeChanged(int32_t   
     // return nsChangeHint_UpdateOverflow for "transform" attribute changes
     // and cause DoApplyRenderingChangeToTree to make the SchedulePaint call.
     NotifySVGChanged(TRANSFORM_CHANGED);
   }
 
  return NS_OK;
 }
 
-nsIAtom *
-nsSVGAFrame::GetType() const
-{
-  return nsGkAtoms::svgAFrame;
-}
-
 //----------------------------------------------------------------------
 // nsSVGDisplayableFrame methods
 
 void
 nsSVGAFrame::NotifySVGChanged(uint32_t aFlags)
 {
   MOZ_ASSERT(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED),
              "Invalidation logic may need adjusting");
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -392,33 +392,32 @@ nsSVGClipPathFrame::IsValid()
 
   if (nsSVGEffects::GetEffectProperties(this).HasInvalidClipPath()) {
     return false;
   }
 
   for (nsIFrame* kid = mFrames.FirstChild(); kid;
        kid = kid->GetNextSibling()) {
 
-    nsIAtom* kidType = kid->GetType();
+    FrameType kidType = kid->Type();
 
-    if (kidType == nsGkAtoms::svgUseFrame) {
+    if (kidType == FrameType::SVGUse) {
       for (nsIFrame* grandKid : kid->PrincipalChildList()) {
 
-        nsIAtom* grandKidType = grandKid->GetType();
+        FrameType grandKidType = grandKid->Type();
 
-        if (grandKidType != nsGkAtoms::svgGeometryFrame &&
-            grandKidType != nsGkAtoms::svgTextFrame) {
+        if (grandKidType != FrameType::SVGGeometry &&
+            grandKidType != FrameType::SVGText) {
           return false;
         }
       }
       continue;
     }
 
-    if (kidType != nsGkAtoms::svgGeometryFrame &&
-        kidType != nsGkAtoms::svgTextFrame) {
+    if (kidType != FrameType::SVGGeometry && kidType != FrameType::SVGText) {
       return false;
     }
   }
 
   return true;
 }
 
 nsresult
@@ -448,22 +447,16 @@ nsSVGClipPathFrame::Init(nsIContent*    
 {
   NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::clipPath),
                "Content is not an SVG clipPath!");
 
   AddStateBits(NS_STATE_SVG_CLIPPATH_CHILD);
   nsSVGContainerFrame::Init(aContent, aParent, aPrevInFlow);
 }
 
-nsIAtom *
-nsSVGClipPathFrame::GetType() const
-{
-  return nsGkAtoms::svgClipPathFrame;
-}
-
 gfxMatrix
 nsSVGClipPathFrame::GetCanvasTM()
 {
   return mMatrixForChildren;
 }
 
 gfxMatrix
 nsSVGClipPathFrame::GetClipPathTransform(nsIFrame* aClippedFrame)
--- a/layout/svg/nsSVGClipPathFrame.h
+++ b/layout/svg/nsSVGClipPathFrame.h
@@ -9,28 +9,28 @@
 #include "gfxMatrix.h"
 #include "mozilla/Attributes.h"
 #include "nsSVGContainerFrame.h"
 #include "nsSVGUtils.h"
 
 class gfxContext;
 class nsSVGDisplayableFrame;
 
-class nsSVGClipPathFrame : public nsSVGContainerFrame
+class nsSVGClipPathFrame final : public nsSVGContainerFrame
 {
   friend nsIFrame*
   NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   typedef mozilla::gfx::Matrix Matrix;
   typedef mozilla::gfx::SourceSurface SourceSurface;
   typedef mozilla::image::DrawResult DrawResult;
 
 protected:
   explicit nsSVGClipPathFrame(nsStyleContext* aContext)
-    : nsSVGContainerFrame(aContext)
+    : nsSVGContainerFrame(aContext, mozilla::FrameType::SVGClipPath)
     , mIsBeingProcessed(false)
   {
     AddStateBits(NS_FRAME_IS_NONDISPLAY);
   }
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
@@ -119,32 +119,25 @@ public:
   virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
                                     nsIAtom*        aAttribute,
                                     int32_t         aModType) override;
 
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgClipPathFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGClipPath"), aResult);
   }
 #endif
 
-  SVGBBox 
-  GetBBoxForClipPathFrame(const SVGBBox &aBBox, const gfxMatrix &aMatrix);
+  SVGBBox GetBBoxForClipPathFrame(const SVGBBox& aBBox,
+                                  const gfxMatrix& aMatrix);
 
   /**
    * If the clipPath element transforms its children due to
    * clipPathUnits="objectBoundingBox" being set on it and/or due to the
    * 'transform' attribute being set on it, this function returns the resulting
    * transform.
    */
   gfxMatrix GetClipPathTransform(nsIFrame* aClippedFrame);
--- a/layout/svg/nsSVGContainerFrame.cpp
+++ b/layout/svg/nsSVGContainerFrame.cpp
@@ -28,17 +28,18 @@ NS_QUERYFRAME_HEAD(nsSVGDisplayContainer
   NS_QUERYFRAME_ENTRY(nsSVGDisplayContainerFrame)
   NS_QUERYFRAME_ENTRY(nsSVGDisplayableFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsSVGContainerFrame)
 
 nsIFrame*
 NS_NewSVGContainerFrame(nsIPresShell* aPresShell,
                         nsStyleContext* aContext)
 {
-  nsIFrame *frame = new (aPresShell) nsSVGContainerFrame(aContext);
+  nsIFrame* frame =
+    new (aPresShell) nsSVGContainerFrame(aContext, FrameType::None);
   // If we were called directly, then the frame is for a <defs> or
   // an unknown element type. In both cases we prevent the content
   // from displaying directly.
   frame->AddStateBits(NS_FRAME_IS_NONDISPLAY);
   return frame;
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsSVGContainerFrame)
@@ -111,22 +112,22 @@ nsSVGContainerFrame::ReflowSVGNonDisplay
 {
   NS_ASSERTION(aContainer->GetStateBits() & NS_FRAME_IS_DIRTY,
                "expected aContainer to be NS_FRAME_IS_DIRTY");
   NS_ASSERTION((aContainer->GetStateBits() & NS_FRAME_IS_NONDISPLAY) ||
                !aContainer->IsFrameOfType(nsIFrame::eSVG),
                "it is wasteful to call ReflowSVGNonDisplayText on a container "
                "frame that is not NS_FRAME_IS_NONDISPLAY");
   for (nsIFrame* kid : aContainer->PrincipalChildList()) {
-    nsIAtom* type = kid->GetType();
-    if (type == nsGkAtoms::svgTextFrame) {
+    FrameType type = kid->Type();
+    if (type == FrameType::SVGText) {
       static_cast<SVGTextFrame*>(kid)->ReflowSVGNonDisplayText();
     } else {
       if (kid->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer) ||
-          type == nsGkAtoms::svgForeignObjectFrame ||
+          type == FrameType::SVGForeignObject ||
           !kid->IsFrameOfType(nsIFrame::eSVG)) {
         ReflowSVGNonDisplayText(kid);
       }
     }
   }
 }
 
 void
@@ -317,18 +318,17 @@ void
 nsSVGDisplayContainerFrame::ReflowSVG()
 {
   NS_ASSERTION(nsSVGUtils::OuterSVGIsCallingReflowSVG(this),
                "This call is probably a wasteful mistake");
 
   MOZ_ASSERT(!(GetStateBits() & NS_FRAME_IS_NONDISPLAY),
              "ReflowSVG mechanism not designed for this");
 
-  MOZ_ASSERT(GetType() != nsGkAtoms::svgOuterSVGFrame,
-             "Do not call on outer-<svg>");
+  MOZ_ASSERT(!IsSVGOuterSVGFrame(), "Do not call on outer-<svg>");
 
   if (!nsSVGUtils::NeedsReflowSVG(this)) {
     return;
   }
 
   // If the NS_FRAME_FIRST_REFLOW bit has been removed from our parent frame,
   // then our outer-<svg> has previously had its initial reflow. In that case
   // we need to make sure that that bit has been removed from ourself _before_
--- a/layout/svg/nsSVGContainerFrame.h
+++ b/layout/svg/nsSVGContainerFrame.h
@@ -35,18 +35,18 @@ struct nsRect;
  * Do *not* blindly cast to SVG element types in this class's methods (see the
  * warning comment for nsSVGDisplayContainerFrame below). 
  */
 class nsSVGContainerFrame : public nsContainerFrame
 {
   friend nsIFrame* NS_NewSVGContainerFrame(nsIPresShell* aPresShell,
                                            nsStyleContext* aContext);
 protected:
-  explicit nsSVGContainerFrame(nsStyleContext* aContext)
-    : nsContainerFrame(aContext)
+  nsSVGContainerFrame(nsStyleContext* aContext, mozilla::FrameType aType)
+    : nsContainerFrame(aContext, aType)
   {
     AddStateBits(NS_FRAME_SVG_LAYOUT);
   }
 
 public:
   NS_DECL_QUERYFRAME_TARGET(nsSVGContainerFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
@@ -106,18 +106,18 @@ protected:
  * an SVG element class since this class is inherited by
  * nsSVGGenericContainerFrame which is used for unrecognized elements in the
  * SVG namespace. Do *not* blindly cast to SVG element types.
  */
 class nsSVGDisplayContainerFrame : public nsSVGContainerFrame,
                                    public nsSVGDisplayableFrame
 {
 protected:
-  explicit nsSVGDisplayContainerFrame(nsStyleContext* aContext)
-    : nsSVGContainerFrame(aContext)
+  nsSVGDisplayContainerFrame(nsStyleContext* aContext, mozilla::FrameType aType)
+    : nsSVGContainerFrame(aContext, aType)
   {
      AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED);
   }
 
 public:
   NS_DECL_QUERYFRAME_TARGET(nsSVGDisplayContainerFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
--- a/layout/svg/nsSVGEffects.cpp
+++ b/layout/svg/nsSVGEffects.cpp
@@ -77,21 +77,21 @@ nsSVGRenderingObserver::GetReferencedEle
 nsIFrame*
 nsSVGRenderingObserver::GetReferencedFrame()
 {
   Element* referencedElement = GetReferencedElement();
   return referencedElement ? referencedElement->GetPrimaryFrame() : nullptr;
 }
 
 nsIFrame*
-nsSVGRenderingObserver::GetReferencedFrame(nsIAtom* aFrameType, bool* aOK)
+nsSVGRenderingObserver::GetReferencedFrame(FrameType aFrameType, bool* aOK)
 {
   nsIFrame* frame = GetReferencedFrame();
   if (frame) {
-    if (frame->GetType() == aFrameType)
+    if (frame->Type() == aFrameType)
       return frame;
     if (aOK) {
       *aOK = false;
     }
   }
   return nullptr;
 }
 
@@ -254,18 +254,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsSVGIDRenderingObserver)
   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
   NS_INTERFACE_MAP_ENTRY(nsISVGFilterReference)
 NS_INTERFACE_MAP_END
 
 nsSVGFilterFrame *
 nsSVGFilterReference::GetFilterFrame()
 {
-  return static_cast<nsSVGFilterFrame *>
-    (GetReferencedFrame(nsGkAtoms::svgFilterFrame, nullptr));
+  return static_cast<nsSVGFilterFrame*>(
+    GetReferencedFrame(FrameType::SVGFilter, nullptr));
 }
 
 void
 nsSVGFilterReference::DoUpdate()
 {
   nsSVGIDRenderingObserver::DoUpdate();
 
   if (mFilterChainObserver) {
@@ -522,17 +522,17 @@ GetEffectProperty(nsIURI* aURI, nsIFrame
   props.Set(aProperty, prop);
   return prop;
 }
 
 nsSVGMarkerProperty*
 nsSVGEffects::GetMarkerProperty(nsIURI* aURI, nsIFrame* aFrame,
   const mozilla::FramePropertyDescriptor<nsSVGMarkerProperty>* aProperty)
 {
-  MOZ_ASSERT(aFrame->GetType() == nsGkAtoms::svgGeometryFrame &&
+  MOZ_ASSERT(aFrame->IsSVGGeometryFrame() &&
              static_cast<SVGGeometryElement*>(aFrame->GetContent())->IsMarkable(),
              "Bad frame");
   return GetEffectProperty(aURI, aFrame, aProperty);
 }
 
 nsSVGTextPathProperty*
 nsSVGEffects::GetTextPathProperty(nsIURI* aURI, nsIFrame* aFrame,
   const mozilla::FramePropertyDescriptor<nsSVGTextPathProperty>* aProperty)
@@ -607,64 +607,63 @@ nsSVGEffects::GetPaintServer(nsIFrame* a
   // If we're looking at a frame within SVG text, then we need to look up
   // to find the right frame to get the painting property off.  We should at
   // least look up past a text frame, and if the text frame's parent is the
   // anonymous block frame, then we look up to its parent (the SVGTextFrame).
   nsIFrame* frame = aTargetFrame;
   if (frame->GetContent()->IsNodeOfType(nsINode::eTEXT)) {
     frame = frame->GetParent();
     nsIFrame* grandparent = frame->GetParent();
-    if (grandparent && grandparent->GetType() == nsGkAtoms::svgTextFrame) {
+    if (grandparent && grandparent->IsSVGTextFrame()) {
       frame = grandparent;
     }
   }
 
   nsCOMPtr<nsIURI> paintServerURL = nsSVGEffects::GetPaintURI(frame, aPaint);
   nsSVGPaintingProperty *property =
     nsSVGEffects::GetPaintingProperty(paintServerURL, frame, aType);
   if (!property)
     return nullptr;
-  nsIFrame *result = property->GetReferencedFrame();
+  nsIFrame* result = property->GetReferencedFrame();
   if (!result)
     return nullptr;
 
-  nsIAtom *type = result->GetType();
-  if (type != nsGkAtoms::svgLinearGradientFrame &&
-      type != nsGkAtoms::svgRadialGradientFrame &&
-      type != nsGkAtoms::svgPatternFrame)
+  FrameType type = result->Type();
+  if (type != FrameType::SVGLinearGradient &&
+      type != FrameType::SVGRadialGradient &&
+      type != FrameType::SVGPattern)
     return nullptr;
 
   return static_cast<nsSVGPaintServerFrame*>(result);
 }
 
 nsSVGClipPathFrame *
 nsSVGEffects::EffectProperties::GetClipPathFrame()
 {
   if (!mClipPath)
     return nullptr;
 
-  nsSVGClipPathFrame *frame = static_cast<nsSVGClipPathFrame *>
-    (mClipPath->GetReferencedFrame(nsGkAtoms::svgClipPathFrame, nullptr));
+  nsSVGClipPathFrame* frame = static_cast<nsSVGClipPathFrame*>(
+    mClipPath->GetReferencedFrame(FrameType::SVGClipPath, nullptr));
 
   return frame;
 }
 
 nsTArray<nsSVGMaskFrame *>
 nsSVGEffects::EffectProperties::GetMaskFrames()
 {
   nsTArray<nsSVGMaskFrame *> result;
   if (!mMask)
     return result;
 
   bool ok = true;
   const nsTArray<RefPtr<nsSVGPaintingProperty>>& props = mMask->GetProps();
   for (size_t i = 0; i < props.Length(); i++) {
-    nsSVGMaskFrame* maskFrame =
-      static_cast<nsSVGMaskFrame *>(props[i]->GetReferencedFrame(
-                                                nsGkAtoms::svgMaskFrame, &ok));
+    nsSVGMaskFrame* maskFrame = static_cast<nsSVGMaskFrame*>(
+      props[i]->GetReferencedFrame(FrameType::SVGMask, &ok));
     MOZ_ASSERT_IF(maskFrame, ok);
     result.AppendElement(maskFrame);
   }
 
   return result;
 }
 
 bool
@@ -673,34 +672,34 @@ nsSVGEffects::EffectProperties::HasNoOrV
   return HasNoOrValidClipPath() && HasNoOrValidMask() && HasNoOrValidFilter();
 }
 
 bool
 nsSVGEffects::EffectProperties::HasNoOrValidClipPath()
 {
   if (mClipPath) {
     bool ok = true;
-    nsSVGClipPathFrame *frame = static_cast<nsSVGClipPathFrame *>
-      (mClipPath->GetReferencedFrame(nsGkAtoms::svgClipPathFrame, &ok));
+    nsSVGClipPathFrame* frame = static_cast<nsSVGClipPathFrame*>(
+      mClipPath->GetReferencedFrame(FrameType::SVGClipPath, &ok));
     if (!ok || (frame && !frame->IsValid())) {
       return false;
     }
   }
 
   return true;
 }
 
 bool
 nsSVGEffects::EffectProperties::HasNoOrValidMask()
 {
   if (mMask) {
     bool ok = true;
     const nsTArray<RefPtr<nsSVGPaintingProperty>>& props = mMask->GetProps();
     for (size_t i = 0; i < props.Length(); i++) {
-      props[i]->GetReferencedFrame(nsGkAtoms::svgMaskFrame, &ok);
+      props[i]->GetReferencedFrame(FrameType::SVGMask, &ok);
       if (!ok) {
         return false;
       }
     }
   }
 
   return true;
 }
@@ -721,17 +720,17 @@ nsSVGEffects::UpdateEffects(nsIFrame* aF
   props.Delete(FillProperty());
   props.Delete(StrokeProperty());
   props.Delete(BackgroundImageProperty());
 
   // Ensure that the filter is repainted correctly
   // We can't do that in DoUpdate as the referenced frame may not be valid
   GetOrCreateFilterProperty(aFrame);
 
-  if (aFrame->GetType() == nsGkAtoms::svgGeometryFrame &&
+  if (aFrame->IsSVGGeometryFrame() &&
       static_cast<SVGGeometryElement*>(aFrame->GetContent())->IsMarkable()) {
     // Set marker properties here to avoid reference loops
     nsCOMPtr<nsIURI> markerURL =
       GetMarkerURI(aFrame, &nsStyleSVG::mMarkerStart);
     GetMarkerProperty(markerURL, aFrame, MarkerBeginProperty());
     markerURL = GetMarkerURI(aFrame, &nsStyleSVG::mMarkerMid);
     GetMarkerProperty(markerURL, aFrame, MarkerMiddleProperty());
     markerURL = GetMarkerURI(aFrame, &nsStyleSVG::mMarkerEnd);
--- a/layout/svg/nsSVGEffects.h
+++ b/layout/svg/nsSVGEffects.h
@@ -71,17 +71,17 @@ public:
 
   bool IsInObserverList() const { return mInObserverList; }
 
   nsIFrame* GetReferencedFrame();
   /**
    * @param aOK this is only for the convenience of callers. We set *aOK to false
    * if the frame is the wrong type
    */
-  nsIFrame* GetReferencedFrame(nsIAtom* aFrameType, bool* aOK);
+  nsIFrame* GetReferencedFrame(mozilla::FrameType aFrameType, bool* aOK);
 
   Element* GetReferencedElement();
 
   virtual bool ObservesReflow() { return true; }
 
 protected:
   // Non-virtual protected methods
   void StartListening();
--- a/layout/svg/nsSVGFilterFrame.cpp
+++ b/layout/svg/nsSVGFilterFrame.cpp
@@ -148,18 +148,18 @@ nsSVGFilterFrame::GetReferencedFilter()
     if (!property)
       return nullptr;
   }
 
   nsIFrame *result = property->GetReferencedFrame();
   if (!result)
     return nullptr;
 
-  nsIAtom* frameType = result->GetType();
-  if (frameType != nsGkAtoms::svgFilterFrame)
+  FrameType frameType = result->Type();
+  if (frameType != FrameType::SVGFilter)
     return nullptr;
 
   return static_cast<nsSVGFilterFrame*>(result);
 }
 
 nsresult
 nsSVGFilterFrame::AttributeChanged(int32_t  aNameSpaceID,
                                    nsIAtom* aAttribute,
@@ -193,14 +193,8 @@ nsSVGFilterFrame::Init(nsIContent*      
                        nsIFrame*         aPrevInFlow)
 {
   NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::filter),
                "Content is not an SVG filter");
 
   nsSVGContainerFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
-
-nsIAtom *
-nsSVGFilterFrame::GetType() const
-{
-  return nsGkAtoms::svgFilterFrame;
-}
--- a/layout/svg/nsSVGFilterFrame.h
+++ b/layout/svg/nsSVGFilterFrame.h
@@ -28,17 +28,17 @@ class SVGFilterElement;
 } // namespace mozilla
 
 class nsSVGFilterFrame : public nsSVGContainerFrame
 {
   friend nsIFrame*
   NS_NewSVGFilterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   explicit nsSVGFilterFrame(nsStyleContext* aContext)
-    : nsSVGContainerFrame(aContext)
+    : nsSVGContainerFrame(aContext, mozilla::FrameType::SVGFilter)
     , mLoopFlag(false)
     , mNoHRefURI(false)
   {
     AddStateBits(NS_FRAME_IS_NONDISPLAY);
   }
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
@@ -53,23 +53,16 @@ public:
                                     int32_t         aModType) override;
 
 #ifdef DEBUG
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 #endif
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgFilterFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 private:
   // Parse our xlink:href and set up our nsSVGPaintingProperty if we
   // reference another filter and we don't have a property. Return
   // the referenced filter's frame if available, null otherwise.
   friend class nsSVGFilterInstance;
   nsSVGFilterFrame* GetReferencedFilter();
 
   // Accessors to lookup filter attributes
--- a/layout/svg/nsSVGFilterInstance.cpp
+++ b/layout/svg/nsSVGFilterInstance.cpp
@@ -141,17 +141,17 @@ nsSVGFilterInstance::GetFilterFrame(nsIF
   Element* element = filterElement.get();
   if (!element) {
     // The URL points to no element.
     return nullptr;
   }
 
   // Get the frame of the filter element.
   nsIFrame* frame = element->GetPrimaryFrame();
-  if (!frame || frame->GetType() != nsGkAtoms::svgFilterFrame) {
+  if (!frame || !frame->IsSVGFilterFrame()) {
     // The URL points to an element that's not an SVG filter element, or to an
     // element that hasn't had its frame constructed yet.
     return nullptr;
   }
 
   return static_cast<nsSVGFilterFrame*>(frame);
 }
 
--- a/layout/svg/nsSVGForeignObjectFrame.cpp
+++ b/layout/svg/nsSVGForeignObjectFrame.cpp
@@ -35,17 +35,17 @@ NS_NewSVGForeignObjectFrame(nsIPresShell
                             nsStyleContext *aContext)
 {
   return new (aPresShell) nsSVGForeignObjectFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsSVGForeignObjectFrame)
 
 nsSVGForeignObjectFrame::nsSVGForeignObjectFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::SVGForeignObject)
   , mInReflow(false)
 {
   AddStateBits(NS_FRAME_REFLOW_ROOT | NS_FRAME_MAY_BE_TRANSFORMED |
                NS_FRAME_SVG_LAYOUT);
 }
 
 //----------------------------------------------------------------------
 // nsIFrame methods
@@ -75,22 +75,16 @@ void nsSVGForeignObjectFrame::DestroyFro
 {
   // Only unregister if we registered in the first place:
   if (!(mState & NS_FRAME_IS_NONDISPLAY)) {
       nsSVGUtils::GetOuterSVGFrame(this)->UnregisterForeignObject(this);
   }
   nsContainerFrame::DestroyFrom(aDestructRoot);
 }
 
-nsIAtom *
-nsSVGForeignObjectFrame::GetType() const
-{
-  return nsGkAtoms::svgForeignObjectFrame;
-}
-
 nsresult
 nsSVGForeignObjectFrame::AttributeChanged(int32_t  aNameSpaceID,
                                           nsIAtom *aAttribute,
                                           int32_t  aModType)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::width ||
         aAttribute == nsGkAtoms::height) {
--- a/layout/svg/nsSVGForeignObjectFrame.h
+++ b/layout/svg/nsSVGForeignObjectFrame.h
@@ -45,23 +45,16 @@ public:
                       ReflowOutput&     aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus&          aStatus) override;
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgForeignObjectFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsContainerFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eSVG | nsIFrame::eSVGForeignObject));
   }
 
   virtual bool IsSVGTransformed(Matrix *aOwnTransform,
                                 Matrix *aFromParentTransform) const override;
--- a/layout/svg/nsSVGGFrame.cpp
+++ b/layout/svg/nsSVGGFrame.cpp
@@ -36,22 +36,16 @@ nsSVGGFrame::Init(nsIContent*       aCon
   NS_ASSERTION(aContent->IsSVGElement() &&
                static_cast<nsSVGElement*>(aContent)->IsTransformable(),
                "The element doesn't support nsIDOMSVGTransformable");
 
   nsSVGDisplayContainerFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
-nsIAtom *
-nsSVGGFrame::GetType() const
-{
-  return nsGkAtoms::svgGFrame;
-}
-
 //----------------------------------------------------------------------
 // nsSVGDisplayableFrame methods
 
 void
 nsSVGGFrame::NotifySVGChanged(uint32_t aFlags)
 {
   MOZ_ASSERT(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED),
              "Invalidation logic may need adjusting");
--- a/layout/svg/nsSVGGFrame.h
+++ b/layout/svg/nsSVGGFrame.h
@@ -11,35 +11,33 @@
 #include "nsAutoPtr.h"
 #include "nsSVGContainerFrame.h"
 
 class nsSVGGFrame : public nsSVGDisplayContainerFrame
 {
   friend nsIFrame*
   NS_NewSVGGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
+  nsSVGGFrame(nsStyleContext* aContext, mozilla::FrameType aType)
+    : nsSVGDisplayContainerFrame(aContext, aType)
+  {}
+
   explicit nsSVGGFrame(nsStyleContext* aContext)
-    : nsSVGDisplayContainerFrame(aContext) {}
+    : nsSVGGFrame(aContext, mozilla::FrameType::SVGG)
+  {}
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
 #ifdef DEBUG
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 #endif
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgGFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGG"), aResult);
   }
 #endif
 
   // nsIFrame interface:
--- a/layout/svg/nsSVGGenericContainerFrame.cpp
+++ b/layout/svg/nsSVGGenericContainerFrame.cpp
@@ -31,22 +31,16 @@ nsSVGGenericContainerFrame::AttributeCha
     aAttribute->ToString(str);
     printf("** nsSVGGenericContainerFrame::AttributeChanged(%s)\n",
            NS_LossyConvertUTF16toASCII(str).get());
 #endif
 
   return NS_OK;
 }
 
-nsIAtom *
-nsSVGGenericContainerFrame::GetType() const
-{
-  return nsGkAtoms::svgGenericContainerFrame;
-}
-
 //----------------------------------------------------------------------
 // nsSVGContainerFrame methods:
 
 gfxMatrix
 nsSVGGenericContainerFrame::GetCanvasTM()
 {
   NS_ASSERTION(GetParent(), "null parent");
   
--- a/layout/svg/nsSVGGenericContainerFrame.h
+++ b/layout/svg/nsSVGGenericContainerFrame.h
@@ -13,38 +13,34 @@
 #include "nsQueryFrame.h"
 #include "nsSVGContainerFrame.h"
 
 class nsIAtom;
 class nsIFrame;
 class nsIPresShell;
 class nsStyleContext;
 
-class nsSVGGenericContainerFrame : public nsSVGDisplayContainerFrame
+class nsSVGGenericContainerFrame final : public nsSVGDisplayContainerFrame
 {
   friend nsIFrame*
   NS_NewSVGGenericContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
 protected:
   explicit nsSVGGenericContainerFrame(nsStyleContext* aContext)
-    : nsSVGDisplayContainerFrame(aContext) {}
+    : nsSVGDisplayContainerFrame(aContext,
+                                 mozilla::FrameType::SVGGenericContainer)
+  {}
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsIFrame:
   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
                                      nsIAtom*        aAttribute,
                                      int32_t         aModType) override;
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgGenericContainerFrame
-   */
-  virtual nsIAtom* GetType() const override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGGenericContainer"), aResult);
   }
 #endif
 
--- a/layout/svg/nsSVGGradientFrame.cpp
+++ b/layout/svg/nsSVGGradientFrame.cpp
@@ -20,18 +20,19 @@
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 
 //----------------------------------------------------------------------
 // Implementation
 
-nsSVGGradientFrame::nsSVGGradientFrame(nsStyleContext* aContext)
-  : nsSVGPaintServerFrame(aContext)
+nsSVGGradientFrame::nsSVGGradientFrame(nsStyleContext* aContext,
+                                       FrameType aType)
+  : nsSVGPaintServerFrame(aContext, aType)
   , mLoopFlag(false)
   , mNoHRefURI(false)
 {
 }
 
 //----------------------------------------------------------------------
 // nsIFrame methods:
 
@@ -367,31 +368,31 @@ nsSVGGradientFrame::GetReferencedGradien
     if (!property)
       return nullptr;
   }
 
   nsIFrame *result = property->GetReferencedFrame();
   if (!result)
     return nullptr;
 
-  nsIAtom* frameType = result->GetType();
-  if (frameType != nsGkAtoms::svgLinearGradientFrame &&
-      frameType != nsGkAtoms::svgRadialGradientFrame)
+  FrameType frameType = result->Type();
+  if (frameType != FrameType::SVGLinearGradient &&
+      frameType != FrameType::SVGRadialGradient)
     return nullptr;
 
   return static_cast<nsSVGGradientFrame*>(result);
 }
 
 void
 nsSVGGradientFrame::GetStopFrames(nsTArray<nsIFrame*>* aStopFrames)
 {
   nsIFrame *stopFrame = nullptr;
   for (stopFrame = mFrames.FirstChild(); stopFrame;
        stopFrame = stopFrame->GetNextSibling()) {
-    if (stopFrame->GetType() == nsGkAtoms::svgStopFrame) {
+    if (stopFrame->IsSVGStopFrame()) {
       aStopFrames->AppendElement(stopFrame);
     }
   }
   if (aStopFrames->Length() > 0) {
     return;
   }
 
   // Our gradient element doesn't have stops - try to "inherit" them
@@ -424,22 +425,16 @@ nsSVGLinearGradientFrame::Init(nsIConten
 {
   NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::linearGradient),
                "Content is not an SVG linearGradient");
 
   nsSVGGradientFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
-nsIAtom*
-nsSVGLinearGradientFrame::GetType() const
-{
-  return nsGkAtoms::svgLinearGradientFrame;
-}
-
 nsresult
 nsSVGLinearGradientFrame::AttributeChanged(int32_t         aNameSpaceID,
                                            nsIAtom*        aAttribute,
                                            int32_t         aModType)
 {
   if (aNameSpaceID == kNameSpaceID_None &&
       (aAttribute == nsGkAtoms::x1 ||
        aAttribute == nsGkAtoms::y1 ||
@@ -532,22 +527,16 @@ nsSVGRadialGradientFrame::Init(nsIConten
 {
   NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::radialGradient),
                "Content is not an SVG radialGradient");
 
   nsSVGGradientFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
-nsIAtom*
-nsSVGRadialGradientFrame::GetType() const
-{
-  return nsGkAtoms::svgRadialGradientFrame;
-}
-
 nsresult
 nsSVGRadialGradientFrame::AttributeChanged(int32_t         aNameSpaceID,
                                            nsIAtom*        aAttribute,
                                            int32_t         aModType)
 {
   if (aNameSpaceID == kNameSpaceID_None &&
       (aAttribute == nsGkAtoms::r ||
        aAttribute == nsGkAtoms::cx ||
--- a/layout/svg/nsSVGGradientFrame.h
+++ b/layout/svg/nsSVGGradientFrame.h
@@ -35,17 +35,17 @@ class SVGRadialGradientElement;
  * Gradients can refer to other gradients. We create an nsSVGPaintingProperty
  * with property type nsGkAtoms::href to track the referenced gradient.
  */
 class nsSVGGradientFrame : public nsSVGPaintServerFrame
 {
   typedef mozilla::gfx::ExtendMode ExtendMode;
 
 protected:
-  explicit nsSVGGradientFrame(nsStyleContext* aContext);
+  nsSVGGradientFrame(nsStyleContext* aContext, mozilla::FrameType aType);
 
 public:
   NS_DECL_ABSTRACT_FRAME(nsSVGGradientFrame)
 
   // nsSVGPaintServerFrame methods:
   virtual mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
     GetPaintServerPattern(nsIFrame* aSource,
                           const DrawTarget* aDrawTarget,
@@ -122,30 +122,29 @@ private:
 // -------------------------------------------------------------------------
 
 class nsSVGLinearGradientFrame : public nsSVGGradientFrame
 {
   friend nsIFrame* NS_NewSVGLinearGradientFrame(nsIPresShell* aPresShell,
                                                 nsStyleContext* aContext);
 protected:
   explicit nsSVGLinearGradientFrame(nsStyleContext* aContext)
-    : nsSVGGradientFrame(aContext) {}
+    : nsSVGGradientFrame(aContext, mozilla::FrameType::SVGLinearGradient)
+  {}
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsIFrame interface:
 #ifdef DEBUG
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 #endif
 
-  virtual nsIAtom* GetType() const override;  // frame type: nsGkAtoms::svgLinearGradientFrame
-
   virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
                                     nsIAtom*        aAttribute,
                                     int32_t         aModType) override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGLinearGradient"), aResult);
@@ -165,30 +164,29 @@ protected:
 // -------------------------------------------------------------------------
 
 class nsSVGRadialGradientFrame : public nsSVGGradientFrame
 {
   friend nsIFrame* NS_NewSVGRadialGradientFrame(nsIPresShell* aPresShell,
                                                 nsStyleContext* aContext);
 protected:
   explicit nsSVGRadialGradientFrame(nsStyleContext* aContext)
-    : nsSVGGradientFrame(aContext) {}
+    : nsSVGGradientFrame(aContext, mozilla::FrameType::SVGRadialGradient)
+  {}
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsIFrame interface:
 #ifdef DEBUG
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 #endif
 
-  virtual nsIAtom* GetType() const override;  // frame type: nsGkAtoms::svgRadialGradientFrame
-
   virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
                                     nsIAtom*        aAttribute,
                                     int32_t         aModType) override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGRadialGradient"), aResult);
--- a/layout/svg/nsSVGImageFrame.cpp
+++ b/layout/svg/nsSVGImageFrame.cpp
@@ -41,25 +41,26 @@ public:
   void SetFrame(nsSVGImageFrame *frame) { mFrame = frame; }
 
 private:
   ~nsSVGImageListener() {}
 
   nsSVGImageFrame *mFrame;
 };
 
-class nsSVGImageFrame : public SVGGeometryFrame
-                      , public nsIReflowCallback
+class nsSVGImageFrame final
+  : public SVGGeometryFrame
+  , public nsIReflowCallback
 {
   friend nsIFrame*
   NS_NewSVGImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
 protected:
   explicit nsSVGImageFrame(nsStyleContext* aContext)
-    : SVGGeometryFrame(aContext)
+    : SVGGeometryFrame(aContext, FrameType::SVGImage)
     , mReflowCallbackPosted(false)
   {
     EnableVisibilityTracking();
   }
 
   virtual ~nsSVGImageFrame();
 
 public:
@@ -84,23 +85,16 @@ public:
   void OnVisibilityChange(Visibility aNewVisibility,
                           const Maybe<OnNonvisible>& aNonvisibleAction = Nothing()) override;
 
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgImageFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGImage"), aResult);
   }
 #endif
 
   // nsIReflowCallback
@@ -489,22 +483,16 @@ nsSVGImageFrame::GetFrameForPoint(const 
         return nullptr;
       }
     }
   }
 
   return this;
 }
 
-nsIAtom *
-nsSVGImageFrame::GetType() const
-{
-  return nsGkAtoms::svgImageFrame;
-}
-
 //----------------------------------------------------------------------
 // SVGGeometryFrame methods:
 
 // Lie about our fill/stroke so that covered region and hit detection work properly
 
 void
 nsSVGImageFrame::ReflowSVG()
 {
--- a/layout/svg/nsSVGInnerSVGFrame.cpp
+++ b/layout/svg/nsSVGInnerSVGFrame.cpp
@@ -44,22 +44,16 @@ nsSVGInnerSVGFrame::Init(nsIContent*    
 {
   NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::svg),
                "Content is not an SVG 'svg' element!");
 
   nsSVGDisplayContainerFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
-nsIAtom *
-nsSVGInnerSVGFrame::GetType() const
-{
-  return nsGkAtoms::svgInnerSVGFrame;
-}
-
 //----------------------------------------------------------------------
 // nsSVGDisplayableFrame methods
 
 DrawResult
 nsSVGInnerSVGFrame::PaintSVG(gfxContext& aContext,
                              const gfxMatrix& aTransform,
                              const nsIntRect *aDirtyRect,
                              uint32_t aFlags)
--- a/layout/svg/nsSVGInnerSVGFrame.h
+++ b/layout/svg/nsSVGInnerSVGFrame.h
@@ -8,43 +8,39 @@
 
 #include "mozilla/Attributes.h"
 #include "nsAutoPtr.h"
 #include "nsSVGContainerFrame.h"
 #include "nsISVGSVGFrame.h"
 
 class gfxContext;
 
-class nsSVGInnerSVGFrame : public nsSVGDisplayContainerFrame
-                         , public nsISVGSVGFrame
+class nsSVGInnerSVGFrame final
+  : public nsSVGDisplayContainerFrame
+  , public nsISVGSVGFrame
 {
   friend nsIFrame*
   NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   explicit nsSVGInnerSVGFrame(nsStyleContext* aContext)
-    : nsSVGDisplayContainerFrame(aContext) {}
+    : nsSVGDisplayContainerFrame(aContext, mozilla::FrameType::SVGInnerSVG)
+  {
+  }
 
 public:
   NS_DECL_QUERYFRAME_TARGET(nsSVGInnerSVGFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
 #ifdef DEBUG
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 #endif
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgInnerSVGFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGInnerSVG"), aResult);
   }
 #endif
 
   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -191,17 +191,17 @@ gfxRect
 nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame)
 {
   // Except for nsSVGOuterSVGFrame, we shouldn't be getting here with SVG
   // frames at all. This function is for elements that are laid out using the
   // CSS box model rules.
   NS_ASSERTION(!(aNonSVGFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT),
                "Frames with SVG layout should not get here");
   MOZ_ASSERT_IF(aNonSVGFrame->IsFrameOfType(nsIFrame::eSVG),
-                aNonSVGFrame->GetType() == nsGkAtoms::svgOuterSVGFrame);
+                aNonSVGFrame->IsSVGOuterSVGFrame());
 
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(aNonSVGFrame);
   // 'r' is in "user space":
   nsRect r = GetPreEffectsVisualOverflowUnion(firstFrame, nullptr, nsRect(),
                                               GetOffsetToBoundingBox(firstFrame));
   return nsLayoutUtils::RectToGfxRect(r,
            aNonSVGFrame->PresContext()->AppUnitsPerCSSPixel());
--- a/layout/svg/nsSVGMarkerFrame.cpp
+++ b/layout/svg/nsSVGMarkerFrame.cpp
@@ -56,22 +56,16 @@ nsSVGMarkerFrame::Init(nsIContent*      
                        nsIFrame*         aPrevInFlow)
 {
   NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::marker), "Content is not an SVG marker");
 
   nsSVGContainerFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
-nsIAtom *
-nsSVGMarkerFrame::GetType() const
-{
-  return nsGkAtoms::svgMarkerFrame;
-}
-
 //----------------------------------------------------------------------
 // nsSVGContainerFrame methods:
 
 gfxMatrix
 nsSVGMarkerFrame::GetCanvasTM()
 {
   NS_ASSERTION(mMarkedFrame, "null SVGGeometry frame");
 
@@ -92,17 +86,17 @@ nsSVGMarkerFrame::GetCanvasTM()
 
   return ThebesMatrix(viewBoxTM * markerTM) * markedTM;
 }
 
 static nsIFrame*
 GetAnonymousChildFrame(nsIFrame* aFrame)
 {
   nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
-  MOZ_ASSERT(kid && kid->GetType() == nsGkAtoms::svgMarkerAnonChildFrame,
+  MOZ_ASSERT(kid && kid->IsSVGMarkerAnonChildFrame(),
              "expected to find anonymous child of marker frame");
   return kid;
 }
 
 DrawResult
 nsSVGMarkerFrame::PaintMark(gfxContext& aContext,
                             const gfxMatrix& aToMarkedFrameUserSpace,
                             SVGGeometryFrame *aMarkedFrame,
@@ -274,19 +268,12 @@ NS_NewSVGMarkerAnonChildFrame(nsIPresShe
 NS_IMPL_FRAMEARENA_HELPERS(nsSVGMarkerAnonChildFrame)
 
 #ifdef DEBUG
 void
 nsSVGMarkerAnonChildFrame::Init(nsIContent*       aContent,
                                 nsContainerFrame* aParent,
                                 nsIFrame*         aPrevInFlow)
 {
-  MOZ_ASSERT(aParent->GetType() == nsGkAtoms::svgMarkerFrame,
-             "Unexpected parent");
+  MOZ_ASSERT(aParent->IsSVGMarkerFrame(), "Unexpected parent");
   nsSVGDisplayContainerFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif
-
-nsIAtom *
-nsSVGMarkerAnonChildFrame::GetType() const
-{
-  return nsGkAtoms::svgMarkerAnonChildFrame;
-}
--- a/layout/svg/nsSVGMarkerFrame.h
+++ b/layout/svg/nsSVGMarkerFrame.h
@@ -21,24 +21,24 @@ namespace mozilla {
 class SVGGeometryFrame;
 namespace dom {
 class SVGSVGElement;
 } // namespace dom
 } // namespace mozilla
 
 struct nsSVGMark;
 
-class nsSVGMarkerFrame : public nsSVGContainerFrame
+class nsSVGMarkerFrame final : public nsSVGContainerFrame
 {
   friend class nsSVGMarkerAnonChildFrame;
   friend nsContainerFrame*
   NS_NewSVGMarkerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   explicit nsSVGMarkerFrame(nsStyleContext* aContext)
-    : nsSVGContainerFrame(aContext)
+    : nsSVGContainerFrame(aContext, mozilla::FrameType::SVGMarker)
     , mMarkedFrame(nullptr)
     , mInUse(false)
     , mInUse2(false)
   {
     AddStateBits(NS_FRAME_IS_NONDISPLAY);
   }
 
 public:
@@ -53,35 +53,28 @@ public:
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override {}
 
   virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
                                     nsIAtom*        aAttribute,
                                     int32_t         aModType) override;
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgMarkerFrame
-   */
-  virtual nsIAtom* GetType() const override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGMarker"), aResult);
   }
 #endif
 
   virtual nsContainerFrame* GetContentInsertionFrame() override {
     // Any children must be added to our single anonymous inner frame kid.
     MOZ_ASSERT(PrincipalChildList().FirstChild() &&
-               PrincipalChildList().FirstChild()->GetType() ==
-                 nsGkAtoms::svgMarkerAnonChildFrame,
+               PrincipalChildList().FirstChild()->IsSVGMarkerAnonChildFrame(),
                "Where is our anonymous child?");
     return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   }
 
   // nsSVGMarkerFrame methods:
   DrawResult PaintMark(gfxContext& aContext,
                       const gfxMatrix& aToMarkedFrameUserSpace,
                       mozilla::SVGGeometryFrame *aMarkedFrame,
@@ -134,24 +127,25 @@ private:
 
   // second recursion prevention flag, for GetCanvasTM()
   bool mInUse2;
 };
 
 ////////////////////////////////////////////////////////////////////////
 // nsMarkerAnonChildFrame class
 
-class nsSVGMarkerAnonChildFrame : public nsSVGDisplayContainerFrame
+class nsSVGMarkerAnonChildFrame final : public nsSVGDisplayContainerFrame
 {
   friend nsContainerFrame*
   NS_NewSVGMarkerAnonChildFrame(nsIPresShell* aPresShell,
                                 nsStyleContext* aContext);
 
   explicit nsSVGMarkerAnonChildFrame(nsStyleContext* aContext)
-    : nsSVGDisplayContainerFrame(aContext)
+    : nsSVGDisplayContainerFrame(aContext,
+                                 mozilla::FrameType::SVGMarkerAnonChild)
   {}
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
 #ifdef DEBUG
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
@@ -159,22 +153,15 @@ public:
 #endif
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("SVGMarkerAnonChild"), aResult);
   }
 #endif
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgMarkerAnonChildFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   // nsSVGContainerFrame methods:
   virtual gfxMatrix GetCanvasTM() override
   {
     return static_cast<nsSVGMarkerFrame*>(GetParent())->GetCanvasTM();
   }
 };
 #endif
--- a/layout/svg/nsSVGMaskFrame.cpp
+++ b/layout/svg/nsSVGMaskFrame.cpp
@@ -381,22 +381,16 @@ nsSVGMaskFrame::Init(nsIContent*       a
 {
   NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::mask),
                "Content is not an SVG mask");
 
   nsSVGContainerFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
-nsIAtom *
-nsSVGMaskFrame::GetType() const
-{
-  return nsGkAtoms::svgMaskFrame;
-}
-
 gfxMatrix
 nsSVGMaskFrame::GetCanvasTM()
 {
   return mMatrixForChildren;
 }
 
 gfxMatrix
 nsSVGMaskFrame::GetMaskTransform(nsIFrame* aMaskedFrame)
--- a/layout/svg/nsSVGMaskFrame.h
+++ b/layout/svg/nsSVGMaskFrame.h
@@ -38,17 +38,17 @@ class nsSVGMaskFrame final : public nsSV
   NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   typedef mozilla::gfx::Matrix Matrix;
   typedef mozilla::gfx::SourceSurface SourceSurface;
   typedef mozilla::image::DrawResult DrawResult;
 
 protected:
   explicit nsSVGMaskFrame(nsStyleContext* aContext)
-    : nsSVGContainerFrame(aContext)
+    : nsSVGContainerFrame(aContext, mozilla::FrameType::SVGMask)
     , mInUse(false)
   {
     AddStateBits(NS_FRAME_IS_NONDISPLAY);
   }
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
@@ -87,23 +87,16 @@ public:
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 #endif
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override {}
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgMaskFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGMask"), aResult);
   }
 #endif
 
 private:
--- a/layout/svg/nsSVGOuterSVGFrame.cpp
+++ b/layout/svg/nsSVGOuterSVGFrame.cpp
@@ -60,21 +60,21 @@ nsContainerFrame*
 NS_NewSVGOuterSVGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsSVGOuterSVGFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsSVGOuterSVGFrame)
 
 nsSVGOuterSVGFrame::nsSVGOuterSVGFrame(nsStyleContext* aContext)
-    : nsSVGDisplayContainerFrame(aContext)
-    , mCallingReflowSVG(false)
-    , mFullZoom(aContext->PresContext()->GetFullZoom())
-    , mViewportInitialized(false)
-    , mIsRootContent(false)
+  : nsSVGDisplayContainerFrame(aContext, FrameType::SVGOuterSVG)
+  , mCallingReflowSVG(false)
+  , mFullZoom(aContext->PresContext()->GetFullZoom())
+  , mViewportInitialized(false)
+  , mIsRootContent(false)
 {
   // Outer-<svg> has CSS layout, so remove this bit:
   RemoveStateBits(NS_FRAME_SVG_LAYOUT);
 }
 
 // helper
 static inline bool
 DependsOnIntrinsicSize(const nsIFrame* aEmbeddingFrame)
@@ -793,22 +793,16 @@ nsSVGOuterSVGFrame::BuildDisplayList(nsD
 }
 
 nsSplittableType
 nsSVGOuterSVGFrame::GetSplittableType() const
 {
   return NS_FRAME_NOT_SPLITTABLE;
 }
 
-nsIAtom *
-nsSVGOuterSVGFrame::GetType() const
-{
-  return nsGkAtoms::svgOuterSVGFrame;
-}
-
 //----------------------------------------------------------------------
 // nsISVGSVGFrame methods:
 
 void
 nsSVGOuterSVGFrame::NotifyViewportOrTransformChanged(uint32_t aFlags)
 {
   MOZ_ASSERT(aFlags &&
              !(aFlags & ~(COORD_CONTEXT_CHANGED | TRANSFORM_CHANGED |
@@ -870,31 +864,29 @@ nsSVGOuterSVGFrame::NotifyViewportOrTran
 // nsSVGDisplayableFrame methods:
 
 DrawResult
 nsSVGOuterSVGFrame::PaintSVG(gfxContext& aContext,
                              const gfxMatrix& aTransform,
                              const nsIntRect* aDirtyRect,
                              uint32_t aFlags)
 {
-  NS_ASSERTION(PrincipalChildList().FirstChild()->GetType() ==
-                 nsGkAtoms::svgOuterSVGAnonChildFrame &&
+  NS_ASSERTION(PrincipalChildList().FirstChild()->IsSVGOuterSVGAnonChildFrame() &&
                !PrincipalChildList().FirstChild()->GetNextSibling(),
                "We should have a single, anonymous, child");
   nsSVGOuterSVGAnonChildFrame *anonKid =
     static_cast<nsSVGOuterSVGAnonChildFrame*>(PrincipalChildList().FirstChild());
   return anonKid->PaintSVG(aContext, aTransform, aDirtyRect, aFlags);
 }
 
 SVGBBox
 nsSVGOuterSVGFrame::GetBBoxContribution(const gfx::Matrix &aToBBoxUserspace,
                                         uint32_t aFlags)
 {
-  NS_ASSERTION(PrincipalChildList().FirstChild()->GetType() ==
-                 nsGkAtoms::svgOuterSVGAnonChildFrame &&
+  NS_ASSERTION(PrincipalChildList().FirstChild()->IsSVGOuterSVGAnonChildFrame() &&
                !PrincipalChildList().FirstChild()->GetNextSibling(),
                "We should have a single, anonymous, child");
   // We must defer to our child so that we don't include our
   // content->PrependLocalTransformsTo() transforms.
   nsSVGOuterSVGAnonChildFrame *anonKid =
     static_cast<nsSVGOuterSVGAnonChildFrame*>(PrincipalChildList().FirstChild());
   return anonKid->GetBBoxContribution(aToBBoxUserspace, aFlags);
 }
@@ -981,17 +973,17 @@ nsSVGOuterSVGFrame::VerticalScrollbarNot
 
 void
 nsSVGOuterSVGFrame::DoUpdateStyleOfOwnedAnonBoxes(
   mozilla::ServoStyleSet& aStyleSet,
   nsStyleChangeList& aChangeList,
   nsChangeHint aHintForThisFrame)
 {
   nsIFrame* anonKid = PrincipalChildList().FirstChild();
-  MOZ_ASSERT(anonKid->GetType() == nsGkAtoms::svgOuterSVGAnonChildFrame);
+  MOZ_ASSERT(anonKid->IsSVGOuterSVGAnonChildFrame());
   UpdateStyleOfChildAnonBox(anonKid, aStyleSet, aChangeList, aHintForThisFrame);
 }
 
 //----------------------------------------------------------------------
 // Implementation of nsSVGOuterSVGAnonChildFrame
 
 nsContainerFrame*
 NS_NewSVGOuterSVGAnonChildFrame(nsIPresShell* aPresShell,
@@ -1003,28 +995,21 @@ NS_NewSVGOuterSVGAnonChildFrame(nsIPresS
 NS_IMPL_FRAMEARENA_HELPERS(nsSVGOuterSVGAnonChildFrame)
 
 #ifdef DEBUG
 void
 nsSVGOuterSVGAnonChildFrame::Init(nsIContent*       aContent,
                                   nsContainerFrame* aParent,
                                   nsIFrame*         aPrevInFlow)
 {
-  MOZ_ASSERT(aParent->GetType() == nsGkAtoms::svgOuterSVGFrame,
-             "Unexpected parent");
+  MOZ_ASSERT(aParent->IsSVGOuterSVGFrame(), "Unexpected parent");
   nsSVGDisplayContainerFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif
 
-nsIAtom *
-nsSVGOuterSVGAnonChildFrame::GetType() const
-{
-  return nsGkAtoms::svgOuterSVGAnonChildFrame;
-}
-
 bool
 nsSVGOuterSVGAnonChildFrame::IsSVGTransformed(Matrix* aOwnTransform,
                                               Matrix* aFromParentTransform) const
 {
   // Our elements 'transform' attribute is applied to our nsSVGOuterSVGFrame
   // parent, and the element's children-only transforms are applied to us, the
   // anonymous child frame. Since we are the child frame, we apply the
   // children-only transforms as if they are our own transform.
--- a/layout/svg/nsSVGOuterSVGFrame.h
+++ b/layout/svg/nsSVGOuterSVGFrame.h
@@ -70,39 +70,31 @@ public:
                                 const nsDisplayListSet& aLists) override;
 
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 
   virtual nsSplittableType GetSplittableType() const override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgOuterSVGFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGOuterSVG"), aResult);
   }
 #endif
 
   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
                                      nsIAtom*        aAttribute,
                                      int32_t         aModType) override;
 
   virtual nsContainerFrame* GetContentInsertionFrame() override {
     // Any children must be added to our single anonymous inner frame kid.
     MOZ_ASSERT(PrincipalChildList().FirstChild() &&
-               PrincipalChildList().FirstChild()->GetType() ==
-                 nsGkAtoms::svgOuterSVGAnonChildFrame,
+               PrincipalChildList().FirstChild()->IsSVGOuterSVGAnonChildFrame(),
                "Where is our anonymous child?");
     return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   }
 
   bool IsSVGTransformed(Matrix* aOwnTransform,
                         Matrix* aFromParentTransform) const override;
 
   // Update the style on our anonymous box child.
@@ -227,24 +219,25 @@ protected:
  * keeps both nsDisplayTransform and nsIFrame::GetOffsetTo happy.
  *
  * The reason that this class inherit from nsSVGDisplayContainerFrame rather
  * than simply from nsContainerFrame is so that we can avoid having special
  * handling for these inner wrappers in multiple parts of the SVG code. For
  * example, the implementations of IsSVGTransformed and GetCanvasTM assume
  * nsSVGContainerFrame instances all the way up to the nsSVGOuterSVGFrame.
  */
-class nsSVGOuterSVGAnonChildFrame : public nsSVGDisplayContainerFrame
+class nsSVGOuterSVGAnonChildFrame final : public nsSVGDisplayContainerFrame
 {
   friend nsContainerFrame*
   NS_NewSVGOuterSVGAnonChildFrame(nsIPresShell* aPresShell,
                                   nsStyleContext* aContext);
 
   explicit nsSVGOuterSVGAnonChildFrame(nsStyleContext* aContext)
-    : nsSVGDisplayContainerFrame(aContext)
+    : nsSVGDisplayContainerFrame(aContext,
+                                 mozilla::FrameType::SVGOuterSVGAnonChild)
   {}
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
 #ifdef DEBUG
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
@@ -252,23 +245,16 @@ public:
 #endif
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("SVGOuterSVGAnonChild"), aResult);
   }
 #endif
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgOuterSVGAnonChildFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   bool IsSVGTransformed(Matrix *aOwnTransform,
                         Matrix *aFromParentTransform) const override;
 
   // nsSVGContainerFrame methods:
   virtual gfxMatrix GetCanvasTM() override {
     // GetCanvasTM returns the transform from an SVG frame to the frame's
     // nsSVGOuterSVGFrame's content box, so we do not include any x/y offset
     // set on us for any CSS border or padding on our nsSVGOuterSVGFrame.
--- a/layout/svg/nsSVGPaintServerFrame.h
+++ b/layout/svg/nsSVGPaintServerFrame.h
@@ -53,18 +53,19 @@ private:
 };
 
 class nsSVGPaintServerFrame : public nsSVGContainerFrame
 {
 protected:
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::image::DrawResult DrawResult;
 
-  explicit nsSVGPaintServerFrame(nsStyleContext* aContext)
-    : nsSVGContainerFrame(aContext)
+  explicit nsSVGPaintServerFrame(nsStyleContext* aContext,
+                                 mozilla::FrameType aType)
+    : nsSVGContainerFrame(aContext, aType)
   {
     AddStateBits(NS_FRAME_IS_NONDISPLAY);
   }
 
 public:
   NS_DECL_ABSTRACT_FRAME(nsSVGPaintServerFrame)
 
   /**
--- a/layout/svg/nsSVGPatternFrame.cpp
+++ b/layout/svg/nsSVGPatternFrame.cpp
@@ -29,17 +29,17 @@ using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 using namespace mozilla::image;
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGPatternFrame::nsSVGPatternFrame(nsStyleContext* aContext)
-  : nsSVGPaintServerFrame(aContext)
+  : nsSVGPaintServerFrame(aContext, FrameType::SVGPattern)
   , mLoopFlag(false)
   , mNoHRefURI(false)
 {
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsSVGPatternFrame)
 
 //----------------------------------------------------------------------
@@ -84,22 +84,16 @@ nsSVGPatternFrame::Init(nsIContent*     
                         nsIFrame*         aPrevInFlow)
 {
   NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::pattern), "Content is not an SVG pattern");
 
   nsSVGPaintServerFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
-nsIAtom*
-nsSVGPatternFrame::GetType() const
-{
-  return nsGkAtoms::svgPatternFrame;
-}
-
 //----------------------------------------------------------------------
 // nsSVGContainerFrame methods:
 
 // If our GetCanvasTM is getting called, we
 // need to return *our current* transformation
 // matrix, which depends on our units parameters
 // and X, Y, Width, and Height
 gfxMatrix
@@ -616,18 +610,18 @@ nsSVGPatternFrame::GetReferencedPattern(
     if (!property)
       return nullptr;
   }
 
   nsIFrame *result = property->GetReferencedFrame();
   if (!result)
     return nullptr;
 
-  nsIAtom* frameType = result->GetType();
-  if (frameType != nsGkAtoms::svgPatternFrame)
+  FrameType frameType = result->Type();
+  if (frameType != FrameType::SVGPattern)
     return nullptr;
 
   return static_cast<nsSVGPatternFrame*>(result);
 }
 
 gfxRect
 nsSVGPatternFrame::GetPatternRect(uint16_t aPatternUnits,
                                   const gfxRect &aTargetBBox,
--- a/layout/svg/nsSVGPatternFrame.h
+++ b/layout/svg/nsSVGPatternFrame.h
@@ -22,17 +22,17 @@ class SVGAnimatedPreserveAspectRatio;
 class SVGGeometryFrame;
 class nsSVGAnimatedTransformList;
 } // namespace mozilla
 
 /**
  * Patterns can refer to other patterns. We create an nsSVGPaintingProperty
  * with property type nsGkAtoms::href to track the referenced pattern.
  */
-class nsSVGPatternFrame : public nsSVGPaintServerFrame
+class nsSVGPatternFrame final : public nsSVGPaintServerFrame
 {
   typedef mozilla::gfx::SourceSurface SourceSurface;
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   friend nsIFrame* NS_NewSVGPatternFrame(nsIPresShell* aPresShell,
                                          nsStyleContext* aContext);
@@ -61,23 +61,16 @@ public:
                                     int32_t         aModType) override;
 
 #ifdef DEBUG
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 #endif
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgPatternFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGPattern"), aResult);
   }
 #endif // DEBUG
 
 protected:
--- a/layout/svg/nsSVGStopFrame.cpp
+++ b/layout/svg/nsSVGStopFrame.cpp
@@ -15,17 +15,17 @@
 // within the nsSVGGradientFrame, which is the parent for this frame
 
 class nsSVGStopFrame : public nsFrame
 {
   friend nsIFrame*
   NS_NewSVGStopFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   explicit nsSVGStopFrame(nsStyleContext* aContext)
-    : nsFrame(aContext)
+    : nsFrame(aContext, FrameType::SVGStop)
   {
     AddStateBits(NS_FRAME_IS_NONDISPLAY);
   }
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsIFrame interface:
@@ -38,23 +38,16 @@ public:
   void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                         const nsRect&           aDirtyRect,
                         const nsDisplayListSet& aLists) override {}
 
   virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
                                     nsIAtom*        aAttribute,
                                     int32_t         aModType) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgStopFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eSVG));
   }
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
@@ -78,31 +71,25 @@ nsSVGStopFrame::Init(nsIContent*       a
                      nsIFrame*         aPrevInFlow)
 {
   NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::stop), "Content is not a stop element");
 
   nsFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
-nsIAtom *
-nsSVGStopFrame::GetType() const
-{
-  return nsGkAtoms::svgStopFrame;
-}
-
 nsresult
 nsSVGStopFrame::AttributeChanged(int32_t         aNameSpaceID,
                                  nsIAtom*        aAttribute,
                                  int32_t         aModType)
 {
   if (aNameSpaceID == kNameSpaceID_None &&
       aAttribute == nsGkAtoms::offset) {
-    MOZ_ASSERT(GetParent()->GetType() == nsGkAtoms::svgLinearGradientFrame ||
-               GetParent()->GetType() == nsGkAtoms::svgRadialGradientFrame,
+    MOZ_ASSERT(GetParent()->IsSVGLinearGradientFrame() ||
+               GetParent()->IsSVGRadialGradientFrame(),
                "Observers observe the gradient, so that's what we must invalidate");
     nsSVGEffects::InvalidateDirectRenderingObservers(GetParent());
   }
 
   return nsFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
 
 // -------------------------------------------------------------------------
--- a/layout/svg/nsSVGSwitchFrame.cpp
+++ b/layout/svg/nsSVGSwitchFrame.cpp
@@ -8,40 +8,34 @@
 #include "nsSVGEffects.h"
 #include "nsSVGGFrame.h"
 #include "mozilla/dom/SVGSwitchElement.h"
 #include "nsSVGUtils.h"
 
 using namespace mozilla::gfx;
 using namespace mozilla::image;
 
-class nsSVGSwitchFrame : public nsSVGGFrame
+class nsSVGSwitchFrame final : public nsSVGGFrame
 {
   friend nsIFrame*
   NS_NewSVGSwitchFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   explicit nsSVGSwitchFrame(nsStyleContext* aContext)
-    : nsSVGGFrame(aContext) {}
+    : nsSVGGFrame(aContext, FrameType::SVGSwitch)
+  {}
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
 #ifdef DEBUG
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 #endif
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgSwitchFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGSwitch"), aResult);
   }
 #endif
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
@@ -81,22 +75,16 @@ nsSVGSwitchFrame::Init(nsIContent*      
 {
   NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::svgSwitch),
                "Content is not an SVG switch");
 
   nsSVGGFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
-nsIAtom *
-nsSVGSwitchFrame::GetType() const
-{
-  return nsGkAtoms::svgSwitchFrame;
-}
-
 void
 nsSVGSwitchFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                    const nsRect&           aDirtyRect,
                                    const nsDisplayListSet& aLists)
 {
   nsIFrame* kid = GetActiveChildFrame();
   if (kid) {
     BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
--- a/layout/svg/nsSVGUseFrame.cpp
+++ b/layout/svg/nsSVGUseFrame.cpp
@@ -7,25 +7,26 @@
 #include "nsIAnonymousContentCreator.h"
 #include "nsSVGEffects.h"
 #include "nsSVGGFrame.h"
 #include "mozilla/dom/SVGUseElement.h"
 #include "nsContentList.h"
 
 using namespace mozilla::dom;
 
-class nsSVGUseFrame : public nsSVGGFrame
-                    , public nsIAnonymousContentCreator
+class nsSVGUseFrame final
+  : public nsSVGGFrame
+  , public nsIAnonymousContentCreator
 {
   friend nsIFrame*
   NS_NewSVGUseFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
 protected:
   explicit nsSVGUseFrame(nsStyleContext* aContext)
-    : nsSVGGFrame(aContext)
+    : nsSVGGFrame(aContext, FrameType::SVGUse)
     , mHasValidDimensions(true)
   {}
 
 public:
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsIFrame interface:
@@ -34,23 +35,16 @@ public:
                     nsIFrame*         aPrevInFlow) override;
 
   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
                                      nsIAtom*        aAttribute,
                                      int32_t         aModType) override;
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::svgUseFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsLeaf() const override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGUse"), aResult);
   }
 #endif
@@ -74,22 +68,16 @@ private:
 nsIFrame*
 NS_NewSVGUseFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsSVGUseFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsSVGUseFrame)
 
-nsIAtom *
-nsSVGUseFrame::GetType() const
-{
-  return nsGkAtoms::svgUseFrame;
-}
-
 //----------------------------------------------------------------------
 // nsQueryFrame methods
 
 NS_QUERYFRAME_HEAD(nsSVGUseFrame)
   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
 NS_QUERYFRAME_TAIL_INHERITING(nsSVGGFrame)
 
 //----------------------------------------------------------------------
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -151,18 +151,17 @@ nsSVGUtils::Init()
 nsIFrame*
 nsSVGUtils::GetNearestSVGViewport(nsIFrame *aFrame)
 {
   NS_ASSERTION(aFrame->IsFrameOfType(nsIFrame::eSVG), "SVG frame expected");
 
   for (; aFrame &&  aFrame->IsFrameOfType(nsIFrame::eSVG);
        aFrame = aFrame->GetParent()) {
     NS_ASSERTION(aFrame->IsFrameOfType(nsIFrame::eSVG), "SVG frame expected");
-    if (aFrame->GetType() == nsGkAtoms::svgInnerSVGFrame ||
-        aFrame->GetType() == nsGkAtoms::svgOuterSVGFrame) {
+    if (aFrame->IsSVGInnerSVGFrame() || aFrame->IsSVGOuterSVGFrame()) {
       return aFrame;
     }
   }
 
   return nullptr;
 }
 
 nsRect
@@ -245,18 +244,17 @@ nsSVGUtils::ScheduleReflowSVG(nsIFrame *
       f->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
       f = f->GetParent();
       MOZ_ASSERT(f->IsFrameOfType(nsIFrame::eSVG),
                  "NS_STATE_IS_OUTER_SVG check above not valid!");
     }
 
     outerSVGFrame = static_cast<nsSVGOuterSVGFrame*>(f);
 
-    MOZ_ASSERT(outerSVGFrame &&
-               outerSVGFrame->GetType() == nsGkAtoms::svgOuterSVGFrame,
+    MOZ_ASSERT(outerSVGFrame && outerSVGFrame->IsSVGOuterSVGFrame(),
                "Did not find nsSVGOuterSVGFrame!");
   }
 
   if (outerSVGFrame->GetStateBits() & NS_FRAME_IN_REFLOW) {
     // We're currently under an nsSVGOuterSVGFrame::Reflow call so there is no
     // need to call PresShell::FrameNeedsReflow, since we have an
     // nsSVGOuterSVGFrame::DidReflow call pending.
     return;
@@ -409,21 +407,21 @@ gfxMatrix
 nsSVGUtils::GetCanvasTM(nsIFrame *aFrame)
 {
   // XXX yuck, we really need a common interface for GetCanvasTM
 
   if (!aFrame->IsFrameOfType(nsIFrame::eSVG)) {
     return GetCSSPxToDevPxMatrix(aFrame);
   }
 
-  nsIAtom* type = aFrame->GetType();
-  if (type == nsGkAtoms::svgForeignObjectFrame) {
+  FrameType type = aFrame->Type();
+  if (type == FrameType::SVGForeignObject) {
     return static_cast<nsSVGForeignObjectFrame*>(aFrame)->GetCanvasTM();
   }
-  if (type == nsGkAtoms::svgOuterSVGFrame) {
+  if (type == FrameType::SVGOuterSVG) {
     return GetCSSPxToDevPxMatrix(aFrame);
   }
 
   nsSVGContainerFrame *containerFrame = do_QueryFrame(aFrame);
   if (containerFrame) {
     return containerFrame->GetCanvasTM();
   }
 
@@ -1106,33 +1104,33 @@ nsSVGUtils::GetBBox(nsIFrame* aFrame, ui
 
   if (nsSVGUtils::IsInSVGTextSubtree(aFrame)) {
     // It is possible to apply a gradient, pattern, clipping path, mask or
     // filter to text. When one of these facilities is applied to text
     // the bounding box is the entire text element in all
     // cases.
     nsIFrame* ancestor = GetFirstNonAAncestorFrame(aFrame);
     if (ancestor && nsSVGUtils::IsInSVGTextSubtree(ancestor)) {
-      while (ancestor->GetType() != nsGkAtoms::svgTextFrame) {
+      while (!ancestor->IsSVGTextFrame()) {
         ancestor = ancestor->GetParent();
       }
     }
     aFrame = ancestor;
   }
 
   nsSVGDisplayableFrame* svg = do_QueryFrame(aFrame);
   const bool hasSVGLayout = aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT;
   if (hasSVGLayout && !svg) {
     // An SVG frame, but not one that can be displayed directly (for
     // example, nsGradientFrame). These can't contribute to the bbox.
     return gfxRect();
   }
 
   const bool isOuterSVG = svg && !hasSVGLayout;
-  MOZ_ASSERT_IF(isOuterSVG, aFrame->GetType() == nsGkAtoms::svgOuterSVGFrame);
+  MOZ_ASSERT_IF(isOuterSVG, aFrame->IsSVGOuterSVGFrame());
   if (!svg ||
       (isOuterSVG && (aFlags & eUseFrameBoundsForOuterSVG))) {
     // An HTML element or an SVG outer frame.
     MOZ_ASSERT(!hasSVGLayout);
     return nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(aFrame);
   }
 
   MOZ_ASSERT(svg);
@@ -1154,17 +1152,17 @@ nsSVGUtils::GetBBox(nsIFrame* aFrame, ui
     }
   }
 
   gfxMatrix matrix;
   if (aToBoundsSpace) {
     matrix = *aToBoundsSpace;
   }
 
-  if (aFrame->GetType() == nsGkAtoms::svgForeignObjectFrame) {
+  if (aFrame->IsSVGForeignObjectFrame()) {
     // The spec says getBBox "Returns the tight bounding box in *current user
     // space*". So we should really be doing this for all elements, but that
     // needs investigation to check that we won't break too much content.
     // NOTE: When changing this to apply to other frame types, make sure to
     // also update nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset.
     MOZ_ASSERT(content->IsSVGElement(), "bad cast");
     nsSVGElement *element = static_cast<nsSVGElement*>(content);
     matrix = element->PrependLocalTransformsTo(matrix, eChildToUserSpace);
@@ -1182,36 +1180,35 @@ nsSVGUtils::GetBBox(nsIFrame* aFrame, ui
     x = fillBBox.x;
     y = fillBBox.y;
     width = fillBBox.width;
     height = fillBBox.height;
     bool hasClip = aFrame->StyleDisplay()->IsScrollableOverflow();
     if (hasClip) {
       clipRect =
         nsSVGUtils::GetClipRectForFrame(aFrame, x, y, width, height);
-        if (aFrame->GetType() == nsGkAtoms::svgForeignObjectFrame ||
-            aFrame->GetType() == nsGkAtoms::svgUseFrame) {
-          clipRect = matrix.TransformBounds(clipRect);
-        }
+      if (aFrame->IsSVGForeignObjectFrame() || aFrame->IsSVGUseFrame()) {
+        clipRect = matrix.TransformBounds(clipRect);
+      }
     }
     nsSVGEffects::EffectProperties effectProperties =
       nsSVGEffects::GetEffectProperties(aFrame);
     if (effectProperties.HasInvalidClipPath()) {
       bbox = gfxRect(0, 0, 0, 0);
     } else {
       nsSVGClipPathFrame *clipPathFrame =
         effectProperties.GetClipPathFrame();
       if (clipPathFrame) {
         SVGClipPathElement *clipContent =
           static_cast<SVGClipPathElement*>(clipPathFrame->GetContent());
         RefPtr<SVGAnimatedEnumeration> units = clipContent->ClipPathUnits();
         if (units->AnimVal() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
           matrix.Translate(gfxPoint(x, y));
           matrix.Scale(width, height);
-        } else if (aFrame->GetType() == nsGkAtoms::svgForeignObjectFrame) {
+        } else if (aFrame->IsSVGForeignObjectFrame()) {
           matrix.Reset();
         }
         bbox =
           clipPathFrame->GetBBoxForClipPathFrame(bbox, matrix).ToThebesRect();
       }
 
       if (hasClip) {
         bbox = bbox.Intersect(clipRect);
@@ -1247,17 +1244,17 @@ nsSVGUtils::FrameSpaceInCSSPxToUserSpace
   if (aFrame->IsFrameOfType(nsIFrame::eSVGGeometry) ||
       nsSVGUtils::IsInSVGTextSubtree(aFrame)) {
     return nsLayoutUtils::RectToGfxRect(aFrame->GetRect(),
                                          nsPresContext::AppUnitsPerCSSPixel()).TopLeft();
   }
 
   // For foreignObject frames, nsSVGUtils::GetBBox applies their local
   // transform, so we need to do the same here.
-  if (aFrame->GetType() == nsGkAtoms::svgForeignObjectFrame) {
+  if (aFrame->IsSVGForeignObjectFrame()) {
     gfxMatrix transform = static_cast<nsSVGElement*>(aFrame->GetContent())->
         PrependLocalTransformsTo(gfxMatrix(), eChildToUserSpace);
     NS_ASSERTION(!transform.HasNonTranslation(), "we're relying on this being an offset-only transform");
     return transform.GetTranslation();
   }
 
   return gfxPoint();
 }
@@ -1302,26 +1299,25 @@ nsSVGUtils::GetRelativeRect(uint16_t aUn
 }
 
 bool
 nsSVGUtils::CanOptimizeOpacity(nsIFrame *aFrame)
 {
   if (!(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
     return false;
   }
-  nsIAtom *type = aFrame->GetType();
-  if (type != nsGkAtoms::svgImageFrame &&
-      type != nsGkAtoms::svgGeometryFrame) {
+  FrameType type = aFrame->Type();
+  if (type != FrameType::SVGImage && type != FrameType::SVGGeometry) {
     return false;
   }
   if (aFrame->StyleEffects()->HasFilters()) {
     return false;
   }
   // XXX The SVG WG is intending to allow fill, stroke and markers on <image>
-  if (type == nsGkAtoms::svgImageFrame) {
+  if (type == FrameType::SVGImage) {
     return true;
   }
   const nsStyleSVG *style = aFrame->StyleSVG();
   if (style->HasMarker()) {
     return false;
   }
   if (!style->HasFill() || !HasStroke(aFrame)) {
     return true;
@@ -1345,17 +1341,17 @@ nsSVGUtils::AdjustMatrixForUnits(const g
   return aMatrix;
 }
 
 nsIFrame*
 nsSVGUtils::GetFirstNonAAncestorFrame(nsIFrame* aStartFrame)
 {
   for (nsIFrame *ancestorFrame = aStartFrame; ancestorFrame;
        ancestorFrame = ancestorFrame->GetParent()) {
-    if (ancestorFrame->GetType() != nsGkAtoms::svgAFrame) {
+    if (!ancestorFrame->IsSVGAFrame()) {
       return ancestorFrame;
     }
   }
   return nullptr;
 }
 
 bool
 nsSVGUtils::GetNonScalingStrokeTransform(nsIFrame *aFrame,
--- a/layout/tables/BasicTableLayoutStrategy.cpp
+++ b/layout/tables/BasicTableLayoutStrategy.cpp
@@ -288,24 +288,23 @@ BasicTableLayoutStrategy::ComputeColumnI
 
         // Consider the isizes on the column-group.  Note that we follow
         // what the HTML spec says here, and make the isize apply to
         // each column in the group, not the group as a whole.
 
         // If column has isize, column-group doesn't override isize.
         if (colInfo.minCoord == 0 && colInfo.prefCoord == 0 &&
             colInfo.prefPercent == 0.0f) {
-            NS_ASSERTION(colFrame->GetParent()->GetType() ==
-                             nsGkAtoms::tableColGroupFrame,
-                         "expected a column-group");
-            colInfo = GetColISizeInfo(aRenderingContext,
-                                      colFrame->GetParent(), wm);
-            colFrame->AddCoords(colInfo.minCoord, colInfo.prefCoord,
-                                colInfo.hasSpecifiedISize);
-            colFrame->AddPrefPercent(colInfo.prefPercent);
+          NS_ASSERTION(colFrame->GetParent()->IsTableColGroupFrame(),
+                       "expected a column-group");
+          colInfo =
+            GetColISizeInfo(aRenderingContext, colFrame->GetParent(), wm);
+          colFrame->AddCoords(
+            colInfo.minCoord, colInfo.prefCoord, colInfo.hasSpecifiedISize);
+          colFrame->AddPrefPercent(colInfo.prefPercent);
         }
 
         // Consider the contents of and the isizes on the cells without
         // colspans.
         nsCellMapColumnIterator columnIter(cellMap, col);
         int32_t row, colSpan;
         nsTableCellFrame* cellFrame;
         while ((cellFrame = columnIter.GetNextFrame(&row, &colSpan))) {
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -38,18 +38,19 @@
 #include "nsFrameSelection.h"
 #include "mozilla/LookAndFeel.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::image;
 
 nsTableCellFrame::nsTableCellFrame(nsStyleContext* aContext,
-                                   nsTableFrame* aTableFrame)
-  : nsContainerFrame(aContext)
+                                   nsTableFrame* aTableFrame,
+                                   FrameType aType)
+  : nsContainerFrame(aContext, aType)
   , mDesiredSize(aTableFrame->GetWritingMode())
 {
   mColIndex = 0;
   mPriorAvailISize = 0;
 
   SetContentEmpty(false);
   SetHasPctOverBSize(false);
 }
@@ -169,30 +170,30 @@ nsTableCellFrame::NeedsToObserve(const R
   }
   rs = rs->mParentReflowInput;
   if (!rs) {
     return false;
   }
 
   // We always need to let the percent bsize observer be propagated
   // from a table wrapper frame to an inner table frame.
-  nsIAtom *fType = aReflowInput.mFrame->GetType();
-  if (fType == nsGkAtoms::tableFrame) {
+  FrameType fType = aReflowInput.mFrame->Type();
+  if (fType == FrameType::Table) {
     return true;
   }
 
   // We need the observer to be propagated to all children of the cell
   // (i.e., children of the child block) in quirks mode, but only to
   // tables in standards mode.
   // XXX This may not be true in the case of orthogonal flows within
   // the cell (bug 1174711 comment 8); we may need to observe isizes
   // instead of bsizes for orthogonal children.
   return rs->mFrame == this &&
          (PresContext()->CompatibilityMode() == eCompatibility_NavQuirks ||
-          fType == nsGkAtoms::tableWrapperFrame);
+          fType == FrameType::TableWrapper);
 }
 
 nsresult
 nsTableCellFrame::GetRowIndex(int32_t &aRowIndex) const
 {
   nsresult result;
   nsTableRowFrame* row = static_cast<nsTableRowFrame*>(GetParent());
   if (row) {
@@ -706,23 +707,22 @@ nsTableCellFrame::CellHasVisibleContent(
                                         nsIFrame*     kidFrame)
 {
   // see  http://www.w3.org/TR/CSS21/tables.html#empty-cells
   if (height > 0)
     return true;
   if (tableFrame->IsBorderCollapse())
     return true;
   for (nsIFrame* innerFrame : kidFrame->PrincipalChildList()) {
-    nsIAtom* frameType = innerFrame->GetType();
-    if (nsGkAtoms::textFrame == frameType) {
-       nsTextFrame* textFrame = static_cast<nsTextFrame*>(innerFrame);
-       if (textFrame->HasNoncollapsedCharacters())
-         return true;
-    }
-    else if (nsGkAtoms::placeholderFrame != frameType) {
+    FrameType frameType = innerFrame->Type();
+    if (FrameType::Text == frameType) {
+      nsTextFrame* textFrame = static_cast<nsTextFrame*>(innerFrame);
+      if (textFrame->HasNoncollapsedCharacters())
+        return true;
+    } else if (FrameType::Placeholder != frameType) {
       return true;
     }
     else {
       nsIFrame *floatFrame = nsLayoutUtils::GetFloatFromPlaceholder(innerFrame);
       if (floatFrame)
         return true;
     }
   }
@@ -1092,22 +1092,16 @@ NS_NewTableCellFrame(nsIPresShell*   aPr
 NS_IMPL_FRAMEARENA_HELPERS(nsBCTableCellFrame)
 
 LogicalMargin
 nsTableCellFrame::GetBorderWidth(WritingMode aWM) const
 {
   return LogicalMargin(aWM, StyleBorder()->GetComputedBorder());
 }
 
-nsIAtom*
-nsTableCellFrame::GetType() const
-{
-  return nsGkAtoms::tableCellFrame;
-}
-
 void
 nsTableCellFrame::DoUpdateStyleOfOwnedAnonBoxes(ServoStyleSet& aStyleSet,
                                                 nsStyleChangeList& aChangeList,
                                                 nsChangeHint aHintForThisFrame)
 {
   nsIFrame* kid = mFrames.FirstChild();
   MOZ_ASSERT(kid && !kid->GetNextSibling(),
              "Table cells should have just one child");
@@ -1121,31 +1115,25 @@ nsTableCellFrame::GetFrameName(nsAString
   return MakeFrameName(NS_LITERAL_STRING("TableCell"), aResult);
 }
 #endif
 
 // nsBCTableCellFrame
 
 nsBCTableCellFrame::nsBCTableCellFrame(nsStyleContext* aContext,
                                        nsTableFrame* aTableFrame)
-  : nsTableCellFrame(aContext, aTableFrame)
+  : nsTableCellFrame(aContext, aTableFrame, FrameType::BCTableCell)
 {
   mBStartBorder = mIEndBorder = mBEndBorder = mIStartBorder = 0;
 }
 
 nsBCTableCellFrame::~nsBCTableCellFrame()
 {
 }
 
-nsIAtom*
-nsBCTableCellFrame::GetType() const
-{
-  return nsGkAtoms::bcTableCellFrame;
-}
-
 /* virtual */ nsMargin
 nsBCTableCellFrame::GetUsedBorder() const
 {
   WritingMode wm = GetWritingMode();
   return GetBorderWidth(wm).GetPhysicalMargin(wm);
 }
 
 /* virtual */ bool
--- a/layout/tables/nsTableCellFrame.h
+++ b/layout/tables/nsTableCellFrame.h
@@ -44,23 +44,26 @@ protected:
 
 public:
   NS_DECL_QUERYFRAME_TARGET(nsTableCellFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   // default constructor supplied by the compiler
 
-  nsTableCellFrame(nsStyleContext* aContext, nsTableFrame* aTableFrame);
+  nsTableCellFrame(nsStyleContext* aContext, nsTableFrame* aTableFrame)
+    : nsTableCellFrame(aContext, aTableFrame, mozilla::FrameType::TableCell)
+  {}
+
   ~nsTableCellFrame();
 
   nsTableRowFrame* GetTableRowFrame() const
   {
     nsIFrame* parent = GetParent();
-    MOZ_ASSERT(parent && parent->GetType() == nsGkAtoms::tableRowFrame);
+    MOZ_ASSERT(parent && parent->IsTableRowFrame());
     return static_cast<nsTableRowFrame*>(parent);
   }
 
   nsTableFrame* GetTableFrame() const
   {
     return GetTableRowFrame()->GetTableFrame();
   }
 
@@ -120,23 +123,16 @@ public:
   virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
   virtual IntrinsicISizeOffsetData IntrinsicISizeOffsets() override;
 
   virtual void Reflow(nsPresContext*      aPresContext,
                       ReflowOutput& aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus&      aStatus) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsLayoutAtoms::tableCellFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   void BlockDirAlignChild(mozilla::WritingMode aWM, nscoord aMaxAscent);
 
   /*
    * Get the value of vertical-align adjusted for CSS 2's rules for a
@@ -235,16 +231,20 @@ public:
     return nsContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eTablePart));
   }
   
   virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) override;
   virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) override;
   virtual void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); }
 
 protected:
+  nsTableCellFrame(nsStyleContext* aContext,
+                   nsTableFrame* aTableFrame,
+                   mozilla::FrameType aType);
+
   virtual LogicalSides
   GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const override;
 
   /**
    * GetBorderOverflow says how far the cell's own borders extend
    * outside its own bounds.  In the separated borders model this should
    * just be zero (as it is for most frames), but in the collapsed
    * borders model (for which nsBCTableCellFrame overrides this virtual
@@ -309,18 +309,16 @@ class nsBCTableCellFrame final : public 
   typedef mozilla::image::DrawResult DrawResult;
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   nsBCTableCellFrame(nsStyleContext* aContext, nsTableFrame* aTableFrame);
 
   ~nsBCTableCellFrame();
 
-  virtual nsIAtom* GetType() const override;
-
   virtual nsMargin GetUsedBorder() const override;
   virtual bool GetBorderRadii(const nsSize& aFrameSize,
                               const nsSize& aBorderArea,
                               Sides aSkipSides,
                               nscoord aRadii[8]) const override;
 
   // Get the *inner half of the border only*, in twips.
   virtual LogicalMargin GetBorderWidth(WritingMode aWM) const override;
--- a/layout/tables/nsTableColFrame.cpp
+++ b/layout/tables/nsTableColFrame.cpp
@@ -19,17 +19,17 @@ using namespace mozilla;
                                        NS_FRAME_STATE_BIT(29) | \
                                        NS_FRAME_STATE_BIT(30) | \
                                        NS_FRAME_STATE_BIT(31))
 #define COL_TYPE_OFFSET               28
 
 using namespace mozilla;
 
 nsTableColFrame::nsTableColFrame(nsStyleContext* aContext)
-  : nsSplittableFrame(aContext)
+  : nsSplittableFrame(aContext, FrameType::TableCol)
   , mMinCoord(0)
   , mPrefCoord(0)
   , mSpanMinCoord(0)
   , mSpanPrefCoord(0)
   , mPrefPercent(0.0f)
   , mSpanPrefPercent(0.0f)
   , mFinalISize(0)
   , mColIndex(0)
@@ -174,30 +174,24 @@ NS_NewTableColFrame(nsIPresShell* aPresS
 
 NS_IMPL_FRAMEARENA_HELPERS(nsTableColFrame)
 
 nsTableColFrame*
 nsTableColFrame::GetNextCol() const
 {
   nsIFrame* childFrame = GetNextSibling();
   while (childFrame) {
-    if (nsGkAtoms::tableColFrame == childFrame->GetType()) {
+    if (childFrame->IsTableColFrame()) {
       return (nsTableColFrame*)childFrame;
     }
     childFrame = childFrame->GetNextSibling();
   }
   return nullptr;
 }
 
-nsIAtom*
-nsTableColFrame::GetType() const
-{
-  return nsGkAtoms::tableColFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsTableColFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("TableCol"), aResult);
 }
 #endif
 
--- a/layout/tables/nsTableColFrame.h
+++ b/layout/tables/nsTableColFrame.h
@@ -8,17 +8,18 @@
 #include "mozilla/Attributes.h"
 #include "celldata.h"
 #include "nscore.h"
 #include "nsContainerFrame.h"
 #include "nsTArray.h"
 #include "nsTableColGroupFrame.h"
 #include "mozilla/WritingModes.h"
 
-class nsTableColFrame : public nsSplittableFrame {
+class nsTableColFrame final : public nsSplittableFrame
+{
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   enum {eWIDTH_SOURCE_NONE          =0,   // no cell has contributed to the width style
         eWIDTH_SOURCE_CELL          =1,   // a cell specified a width
         eWIDTH_SOURCE_CELL_WITH_SPAN=2    // a cell implicitly specified a width via colspan
   };
 
@@ -54,33 +55,26 @@ public:
 
   /**
    * Table columns never paint anything, nor receive events.
    */
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override {}
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::tableColFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   virtual nsSplittableType GetSplittableType() const override;
 
   nsTableColGroupFrame* GetTableColGroupFrame() const
   {
     nsIFrame* parent = GetParent();
-    MOZ_ASSERT(parent && parent->GetType() == nsGkAtoms::tableColGroupFrame);
+    MOZ_ASSERT(parent && parent->IsTableColGroupFrame());
     return static_cast<nsTableColGroupFrame*>(parent);
   }
 
   nsTableFrame* GetTableFrame() const
   {
     return GetTableColGroupFrame()->GetTableFrame();
   }
 
--- a/layout/tables/nsTableColGroupFrame.cpp
+++ b/layout/tables/nsTableColGroupFrame.cpp
@@ -38,31 +38,31 @@ void nsTableColGroupFrame::SetColType(ns
 
 void nsTableColGroupFrame::ResetColIndices(nsIFrame*       aFirstColGroup,
                                            int32_t         aFirstColIndex,
                                            nsIFrame*       aStartColFrame)
 {
   nsTableColGroupFrame* colGroupFrame = (nsTableColGroupFrame*)aFirstColGroup;
   int32_t colIndex = aFirstColIndex;
   while (colGroupFrame) {
-    if (nsGkAtoms::tableColGroupFrame == colGroupFrame->GetType()) {
+    if (colGroupFrame->IsTableColGroupFrame()) {
       // reset the starting col index for the first cg only if we should reset
       // the whole colgroup (aStartColFrame defaults to nullptr) or if
       // aFirstColIndex is smaller than the existing starting col index
       if ((colIndex != aFirstColIndex) ||
           (colIndex < colGroupFrame->GetStartColumnIndex()) ||
           !aStartColFrame) {
         colGroupFrame->SetStartColumnIndex(colIndex);
       }
       nsIFrame* colFrame = aStartColFrame; 
       if (!colFrame || (colIndex != aFirstColIndex)) {
         colFrame = colGroupFrame->PrincipalChildList().FirstChild();
       }
       while (colFrame) {
-        if (nsGkAtoms::tableColFrame == colFrame->GetType()) {
+        if (colFrame->IsTableColFrame()) {
           ((nsTableColFrame*)colFrame)->SetColIndex(colIndex);
           colIndex++;
         }
         colFrame = colFrame->GetNextSibling();
       }
     }
     colGroupFrame = static_cast<nsTableColGroupFrame*>
                                (colGroupFrame->GetNextSibling());
@@ -223,18 +223,18 @@ nsTableColGroupFrame::InsertFrames(Child
   NS_ASSERTION(!aPrevFrame || aPrevFrame == aPrevFrame->LastContinuation(),
                "Prev frame should be last in continuation chain");
   NS_ASSERTION(!aPrevFrame || !GetNextColumn(aPrevFrame) ||
                GetNextColumn(aPrevFrame)->GetColType() != eColAnonymousCol,
                "Shouldn't be inserting before a spanned colframe");
 
   const nsFrameList::Slice& newFrames =
     mFrames.InsertFrames(this, aPrevFrame, aFrameList);
-  nsIFrame* prevFrame = nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame,
-                                                         nsGkAtoms::tableColFrame);
+  nsIFrame* prevFrame =
+    nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame, FrameType::TableCol);
 
   int32_t colIndex = (prevFrame) ? ((nsTableColFrame*)prevFrame)->GetColIndex() + 1 : GetStartColumnIndex();
   InsertColsReflow(colIndex, newFrames);
 }
 
 void
 nsTableColGroupFrame::InsertColsReflow(int32_t                   aColIndex,
                                        const nsFrameList::Slice& aCols)
@@ -279,18 +279,18 @@ nsTableColGroupFrame::RemoveFrame(ChildL
                                   nsIFrame*       aOldFrame)
 {
   NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
 
   if (!aOldFrame) {
     return;
   }
   bool contentRemoval = false;
-  
-  if (nsGkAtoms::tableColFrame == aOldFrame->GetType()) {
+
+  if (aOldFrame->IsTableColFrame()) {
     nsTableColFrame* colFrame = (nsTableColFrame*)aOldFrame;
     if (colFrame->GetColType() == eColContent) {
       contentRemoval = true;
       // Remove any anonymous column frames this <col> produced via a colspan
       nsTableColFrame* col = colFrame->GetNextCol();
       nsTableColFrame* nextCol;
       while (col && col->GetColType() == eColAnonymousCol) {
 #ifdef DEBUG
@@ -452,31 +452,26 @@ void nsTableColGroupFrame::GetContinuous
 nsTableColGroupFrame*
 NS_NewTableColGroupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsTableColGroupFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsTableColGroupFrame)
 
-nsIAtom*
-nsTableColGroupFrame::GetType() const
-{
-  return nsGkAtoms::tableColGroupFrame;
-}
-  
-void 
+void
 nsTableColGroupFrame::InvalidateFrame(uint32_t aDisplayItemKey)
 {
   nsIFrame::InvalidateFrame(aDisplayItemKey);
   GetParent()->InvalidateFrameWithRect(GetVisualOverflowRect() + GetPosition(), aDisplayItemKey);
 }
 
-void 
-nsTableColGroupFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
+void
+nsTableColGroupFrame::InvalidateFrameWithRect(const nsRect& aRect,
+                                              uint32_t aDisplayItemKey)
 {
   nsIFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
   // If we have filters applied that would affects our bounds, then
   // we get an inactive layer created and this is computed
   // within FrameLayerBuilder
   GetParent()->InvalidateFrameWithRect(aRect + GetPosition(), aDisplayItemKey);
 }
 
--- a/layout/tables/nsTableColGroupFrame.h
+++ b/layout/tables/nsTableColGroupFrame.h
@@ -39,17 +39,17 @@ public:
     if (!aPrevInFlow) {
       mWritingMode = GetTableFrame()->GetWritingMode();
     }
   }
 
   nsTableFrame* GetTableFrame() const
   {
     nsIFrame* parent = GetParent();
-    MOZ_ASSERT(parent && parent->GetType() == nsGkAtoms::tableFrame);
+    MOZ_ASSERT(parent && parent->IsTableFrame());
     MOZ_ASSERT(!parent->GetPrevInFlow(),
                "Col group should always be in a first-in-flow table frame");
     return static_cast<nsTableFrame*>(parent);
   }
 
   /**
    * ColGroups never paint anything, nor receive events.
    */
@@ -106,27 +106,20 @@ public:
                    bool             aResetSubsequentColIndices);
 
   /** reflow of a column group is a trivial matter of reflowing
     * the col group's children (columns), and setting this frame
     * to 0-size.  Since tables are row-centric, column group frames
     * don't play directly in the rendering game.  They do however
     * maintain important state that effects table and cell layout.
     */
-  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::tableColGroupFrame
-   */
-  virtual nsIAtom* GetType() const override;
+                      nsReflowStatus& aStatus) override;
 
   /** Add column frames to the table storages: colframe cache and cellmap
     * this doesn't change the mFrames of the colgroup frame.
     * @param aFirstColIndex - the index at which aFirstFrame should be inserted
     *                         into the colframe cache.
     * @param aResetSubsequentColIndices - the indices of the col frames
     *                                     after the insertion might need
     *                                     an update
@@ -217,44 +210,46 @@ protected:
 
   void InsertColsReflow(int32_t                   aColIndex,
                         const nsFrameList::Slice& aCols);
 
   virtual LogicalSides GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const override;
 
   // data members
   int32_t mColCount;
-  // the starting column index this col group represents. Must be >= 0. 
+  // the starting column index this col group represents. Must be >= 0.
   int32_t mStartColIndex;
 
   // border width in pixels
   BCPixelSize mBStartContBorderWidth;
   BCPixelSize mBEndContBorderWidth;
 };
 
-inline nsTableColGroupFrame::nsTableColGroupFrame(nsStyleContext *aContext)
-: nsContainerFrame(aContext), mColCount(0), mStartColIndex(0)
-{ 
+inline nsTableColGroupFrame::nsTableColGroupFrame(nsStyleContext* aContext)
+  : nsContainerFrame(aContext, mozilla::FrameType::TableColGroup)
+  , mColCount(0)
+  , mStartColIndex(0)
+{
   SetColType(eColGroupContent);
 }
-  
+
 inline int32_t nsTableColGroupFrame::GetStartColumnIndex()
-{  
+{
   return mStartColIndex;
 }
 
 inline void nsTableColGroupFrame::SetStartColumnIndex (int32_t aIndex)
 {
   mStartColIndex = aIndex;
 }
 
 inline int32_t nsTableColGroupFrame::GetColCount() const
-{  
+{
   return mColCount;
 }
 
 inline nsFrameList& nsTableColGroupFrame::GetWritableChildList()
-{  
+{
   return mFrames;
 }
 
 #endif
 
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -74,17 +74,17 @@ struct TableReflowInput {
   // Running block-offset
   nscoord bCoord;
 
   TableReflowInput(const ReflowInput& aReflowInput,
                      const LogicalSize& aAvailSize)
     : reflowInput(aReflowInput)
     , availSize(aAvailSize)
   {
-    MOZ_ASSERT(reflowInput.mFrame->GetType() == nsGkAtoms::tableFrame,
+    MOZ_ASSERT(reflowInput.mFrame->IsTableFrame(),
                "TableReflowInput should only be created for nsTableFrame");
     nsTableFrame* table =
       static_cast<nsTableFrame*>(reflowInput.mFrame->FirstInFlow());
     WritingMode wm = aReflowInput.GetWritingMode();
     LogicalMargin borderPadding = table->GetChildAreaOffset(wm, &reflowInput);
 
     iCoord = borderPadding.IStart(wm) + table->GetColSpacing(-1);
     bCoord = borderPadding.BStart(wm); //cellspacing added during reflow
@@ -138,41 +138,32 @@ nsTableFrame::GetParentStyleContext(nsIF
     // We're the root.  We have no style context parent.
     *aProviderFrame = nullptr;
     return nullptr;
   }
 
   return GetParent()->DoGetParentStyleContext(aProviderFrame);
 }
 
-
-nsIAtom*
-nsTableFrame::GetType() const
-{
-  return nsGkAtoms::tableFrame;
-}
-
-
 nsTableFrame::nsTableFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext),
-    mCellMap(nullptr),
-    mTableLayoutStrategy(nullptr)
+  : nsContainerFrame(aContext, FrameType::Table)
+  , mCellMap(nullptr)
+  , mTableLayoutStrategy(nullptr)
 {
   memset(&mBits, 0, sizeof(mBits));
 }
 
 void
 nsTableFrame::Init(nsIContent*       aContent,
                    nsContainerFrame* aParent,
                    nsIFrame*         aPrevInFlow)
 {
   NS_PRECONDITION(!mCellMap, "Init called twice");
   NS_PRECONDITION(!mTableLayoutStrategy, "Init called twice");
-  NS_PRECONDITION(!aPrevInFlow ||
-                  aPrevInFlow->GetType() == nsGkAtoms::tableFrame,
+  NS_PRECONDITION(!aPrevInFlow || aPrevInFlow->IsTableFrame(),
                   "prev-in-flow must be of same type");
 
   // Let the base class do its processing
   nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
 
   // see if border collapse is on, if so set it
   const nsStyleTableBorder* tableStyle = StyleTableBorder();
   bool borderCollapse = (NS_STYLE_BORDER_COLLAPSE == tableStyle->mBorderCollapse);
@@ -214,19 +205,18 @@ nsTableFrame::RePositionViews(nsIFrame* 
 {
   nsContainerFrame::PositionFrameView(aFrame);
   nsContainerFrame::PositionChildViews(aFrame);
 }
 
 static bool
 IsRepeatedFrame(nsIFrame* kidFrame)
 {
-  return (kidFrame->GetType() == nsGkAtoms::tableRowFrame ||
-          kidFrame->GetType() == nsGkAtoms::tableRowGroupFrame) &&
-          kidFrame->HasAnyStateBits(NS_REPEATED_ROW_OR_ROWGROUP);
+  return (kidFrame->IsTableRowFrame() || kidFrame->IsTableRowGroupFrame()) &&
+         kidFrame->HasAnyStateBits(NS_REPEATED_ROW_OR_ROWGROUP);
 }
 
 bool
 nsTableFrame::PageBreakAfter(nsIFrame* aSourceFrame,
                              nsIFrame* aNextFrame)
 {
   const nsStyleDisplay* display = aSourceFrame->StyleDisplay();
   nsTableRowGroupFrame* prevRg = do_QueryFrame(aSourceFrame);
@@ -251,17 +241,17 @@ nsTableFrame::PageBreakAfter(nsIFrame* a
 
 /* static */ void
 nsTableFrame::RegisterPositionedTablePart(nsIFrame* aFrame)
 {
   // Supporting relative positioning for table parts other than table cells has
   // the potential to break sites that apply 'position: relative' to those
   // parts, expecting nothing to happen. We warn at the console to make tracking
   // down the issue easy.
-  if (!IS_TABLE_CELL(aFrame->GetType())) {
+  if (!IS_TABLE_CELL(aFrame->Type())) {
     nsIContent* content = aFrame->GetContent();
     nsPresContext* presContext = aFrame->PresContext();
     if (content && !presContext->HasWarnedAboutPositionedTableParts()) {
       presContext->SetHasWarnedAboutPositionedTableParts();
       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                       NS_LITERAL_CSTRING("Layout: Tables"),
                                       content->OwnerDoc(),
                                       nsContentUtils::eLAYOUT_PROPERTIES,
@@ -333,17 +323,17 @@ nsTableFrame::SetInitialChildList(ChildL
   // form for two reasons:
   // 1) Both rowgroups and column groups come in on the principal child list.
   while (aChildList.NotEmpty()) {
     nsIFrame* childFrame = aChildList.FirstChild();
     aChildList.RemoveFirstChild();
     const nsStyleDisplay* childDisplay = childFrame->StyleDisplay();
 
     if (mozilla::StyleDisplay::TableColumnGroup == childDisplay->mDisplay) {
-      NS_ASSERTION(nsGkAtoms::tableColGroupFrame == childFrame->GetType(),
+      NS_ASSERTION(childFrame->IsTableColGroupFrame(),
                    "This is not a colgroup");
       mColGroups.AppendFrame(nullptr, childFrame);
     }
     else { // row groups and unknown frames go on the main list for now
       mFrames.AppendFrame(nullptr, childFrame);
     }
   }
 
@@ -561,17 +551,17 @@ nsTableFrame::ResetRowIndices(const nsFr
 
 void
 nsTableFrame::InsertColGroups(int32_t                   aStartColIndex,
                               const nsFrameList::Slice& aColGroups)
 {
   int32_t colIndex = aStartColIndex;
   nsFrameList::Enumerator colGroups(aColGroups);
   for (; !colGroups.AtEnd(); colGroups.Next()) {
-    MOZ_ASSERT(colGroups.get()->GetType() == nsGkAtoms::tableColGroupFrame);
+    MOZ_ASSERT(colGroups.get()->IsTableColGroupFrame());
     nsTableColGroupFrame* cgFrame =
       static_cast<nsTableColGroupFrame*>(colGroups.get());
     cgFrame->SetStartColumnIndex(colIndex);
     // XXXbz this sucks.  AddColsToTable will actually remove colgroups from
     // the list we're traversing!  Need to fix things here.  :( I guess this is
     // why the old code used pointer-to-last-frame as opposed to
     // pointer-to-frame-after-last....
 
@@ -1264,25 +1254,25 @@ public:
 
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx) override;
   NS_DISPLAY_DECL_NAME("TableBorderBackground", TYPE_TABLE_BORDER_BACKGROUND)
 };
 
 #ifdef DEBUG
 static bool
-IsFrameAllowedInTable(nsIAtom* aType)
+IsFrameAllowedInTable(FrameType aType)
 {
   return IS_TABLE_CELL(aType) ||
-         nsGkAtoms::tableRowFrame == aType ||
-         nsGkAtoms::tableRowGroupFrame == aType ||
-         nsGkAtoms::scrollFrame == aType ||
-         nsGkAtoms::tableFrame == aType ||
-         nsGkAtoms::tableColFrame == aType ||
-         nsGkAtoms::tableColGroupFrame == aType;
+         FrameType::TableRow == aType ||
+         FrameType::TableRowGroup == aType ||
+         FrameType::Scroll == aType ||
+         FrameType::Table == aType ||
+         FrameType::TableCol == aType ||
+         FrameType::TableColGroup == aType;
 }
 #endif
 
 void
 nsDisplayTableBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
                                       nsRenderingContext* aCtx)
 {
   DrawResult result = static_cast<nsTableFrame*>(mFrame)->
@@ -1290,22 +1280,22 @@ nsDisplayTableBorderBackground::Paint(ns
                                ToReferenceFrame());
 
   nsDisplayTableItemGeometry::UpdateDrawResult(this, result);
 }
 
 static int32_t
 GetTablePartRank(nsDisplayItem* aItem)
 {
-  nsIAtom* type = aItem->Frame()->GetType();
-  if (type == nsGkAtoms::tableFrame)
+  FrameType type = aItem->Frame()->Type();
+  if (type == FrameType::Table)
     return 0;
-  if (type == nsGkAtoms::tableRowGroupFrame)
+  if (type == FrameType::TableRowGroup)
     return 1;
-  if (type == nsGkAtoms::tableRowFrame)
+  if (type == FrameType::TableRow)
     return 2;
   return 3;
 }
 
 struct TablePartRankComparator {
   bool operator()(nsDisplayItem* aItem1, nsDisplayItem* aItem2) const {
     return GetTablePartRank(aItem1) < GetTablePartRank(aItem2);
   }
@@ -1415,17 +1405,17 @@ static inline bool FrameHasBorderOrBackg
 }
 
 static bool
 AnyTablePartHasBorderOrBackground(nsTableFrame* aTableFrame,
                                   nsIFrame* aStart,
                                   nsIFrame* aEnd)
 {
   for (nsIFrame* f = aStart; f != aEnd; f = f->GetNextSibling()) {
-    NS_ASSERTION(IsFrameAllowedInTable(f->GetType()), "unexpected frame type");
+    NS_ASSERTION(IsFrameAllowedInTable(f->Type()), "unexpected frame type");
 
     if (FrameHasBorderOrBackground(aTableFrame, f))
       return true;
 
     nsTableCellFrame *cellFrame = do_QueryFrame(f);
     if (cellFrame)
       continue;
 
@@ -1583,17 +1573,17 @@ nsTableFrame::SetColumnDimensions(nscoor
   const nscoord colBSize = aBSize - (aBorderPadding.BStartEnd(aWM) +
                            GetRowSpacing(-1) + GetRowSpacing(GetRowCount()));
   int32_t colIdx = 0;
   LogicalPoint colGroupOrigin(aWM,
                               aBorderPadding.IStart(aWM) + GetColSpacing(-1),
                               aBorderPadding.BStart(aWM) + GetRowSpacing(-1));
   nsTableFrame* fif = static_cast<nsTableFrame*>(FirstInFlow());
   for (nsIFrame* colGroupFrame : mColGroups) {
-    MOZ_ASSERT(colGroupFrame->GetType() == nsGkAtoms::tableColGroupFrame);
+    MOZ_ASSERT(colGroupFrame->IsTableColGroupFrame());
     // first we need to figure out the size of the colgroup
     int32_t groupFirstCol = colIdx;
     nscoord colGroupISize = 0;
     nscoord cellSpacingI = 0;
     const nsFrameList& columnList = colGroupFrame->PrincipalChildList();
     for (nsIFrame* colFrame : columnList) {
       if (mozilla::StyleDisplay::TableColumn ==
           colFrame->StyleDisplay()->mDisplay) {
@@ -1814,44 +1804,43 @@ nsTableFrame::ComputeAutoSize(nsRenderin
 // Return true if aParentReflowInput.frame or any of its ancestors within
 // the containing table have non-auto bsize. (e.g. pct or fixed bsize)
 bool
 nsTableFrame::AncestorsHaveStyleBSize(const ReflowInput& aParentReflowInput)
 {
   WritingMode wm = aParentReflowInput.GetWritingMode();
   for (const ReflowInput* rs = &aParentReflowInput;
        rs && rs->mFrame; rs = rs->mParentReflowInput) {
-    nsIAtom* frameType = rs->mFrame->GetType();
-    if (IS_TABLE_CELL(frameType)                     ||
-        (nsGkAtoms::tableRowFrame      == frameType) ||
-        (nsGkAtoms::tableRowGroupFrame == frameType)) {
+    FrameType frameType = rs->mFrame->Type();
+    if (IS_TABLE_CELL(frameType) ||
+        (FrameType::TableRow      == frameType) ||
+        (FrameType::TableRowGroup == frameType)) {
       const nsStyleCoord &bsize = rs->mStylePosition->BSize(wm);
       // calc() with percentages treated like 'auto' on internal table elements
       if (bsize.GetUnit() != eStyleUnit_Auto &&
           (!bsize.IsCalcUnit() || !bsize.HasPercent())) {
         return true;
       }
-    }
-    else if (nsGkAtoms::tableFrame == frameType) {
+    } else if (FrameType::Table == frameType) {
       // we reached the containing table, so always return
       return rs->mStylePosition->BSize(wm).GetUnit() != eStyleUnit_Auto;
     }
   }
   return false;
 }
 
 // See if a special block-size reflow needs to occur and if so,
 // call RequestSpecialBSizeReflow
 void
 nsTableFrame::CheckRequestSpecialBSizeReflow(const ReflowInput& aReflowInput)
 {
-  NS_ASSERTION(IS_TABLE_CELL(aReflowInput.mFrame->GetType()) ||
-               aReflowInput.mFrame->GetType() == nsGkAtoms::tableRowFrame ||
-               aReflowInput.mFrame->GetType() == nsGkAtoms::tableRowGroupFrame ||
-               aReflowInput.mFrame->GetType() == nsGkAtoms::tableFrame,
+  NS_ASSERTION(IS_TABLE_CELL(aReflowInput.mFrame->Type()) ||
+               aReflowInput.mFrame->IsTableRowFrame() ||
+               aReflowInput.mFrame->IsTableRowGroupFrame() ||
+               aReflowInput.mFrame->IsTableFrame(),
                "unexpected frame type");
   WritingMode wm = aReflowInput.GetWritingMode();
   if (!aReflowInput.mFrame->GetPrevInFlow() &&  // 1st in flow
       (NS_UNCONSTRAINEDSIZE == aReflowInput.ComputedBSize() ||  // no computed bsize
        0                    == aReflowInput.ComputedBSize()) &&
       eStyleUnit_Percent == aReflowInput.mStylePosition->BSize(wm).GetUnit() && // pct bsize
       nsTableFrame::AncestorsHaveStyleBSize(*aReflowInput.mParentReflowInput)) {
     nsTableFrame::RequestSpecialBSizeReflow(aReflowInput);
@@ -1863,25 +1852,25 @@ nsTableFrame::CheckRequestSpecialBSizeRe
 // row, or cell returns the last size it was reflowed at. However, the table may
 // change the bsize of row groups, rows, cells in DistributeBSizeToRows after.
 // And the row group can change the bsize of rows, cells in CalculateRowBSizes.
 void
 nsTableFrame::RequestSpecialBSizeReflow(const ReflowInput& aReflowInput)
 {
   // notify the frame and its ancestors of the special reflow, stopping at the containing table
   for (const ReflowInput* rs = &aReflowInput; rs && rs->mFrame; rs = rs->mParentReflowInput) {
-    nsIAtom* frameType = rs->mFrame->GetType();
+    FrameType frameType = rs->mFrame->Type();
     NS_ASSERTION(IS_TABLE_CELL(frameType) ||
-                 nsGkAtoms::tableRowFrame == frameType ||
-                 nsGkAtoms::tableRowGroupFrame == frameType ||
-                 nsGkAtoms::tableFrame == frameType,
+                 FrameType::TableRow == frameType ||
+                 FrameType::TableRowGroup == frameType ||
+                 FrameType::Table == frameType,
                  "unexpected frame type");
 
     rs->mFrame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
-    if (nsGkAtoms::tableFrame == frameType) {
+    if (FrameType::Table == frameType) {
       NS_ASSERTION(rs != &aReflowInput,
                    "should not request special bsize reflow for table");
       // always stop when we reach a table
       break;
     }
   }
 }
 
@@ -2619,17 +2608,17 @@ nsTableFrame::HomogenousInsertFrames(Chi
     // Insert the column group frames
     const nsFrameList::Slice& newColgroups =
       mColGroups.InsertFrames(this, aPrevFrame, aFrameList);
     // find the starting col index for the first new col group
     int32_t startColIndex = 0;
     if (aPrevFrame) {
       nsTableColGroupFrame* prevColGroup =
         (nsTableColGroupFrame*)GetFrameAtOrBefore(this, aPrevFrame,
-                                                  nsGkAtoms::tableColGroupFrame);
+                                                  FrameType::TableColGroup);
       if (prevColGroup) {
         startColIndex = prevColGroup->GetStartColumnIndex() + prevColGroup->GetColCount();
       }
     }
     InsertColGroups(startColIndex, newColgroups);
   } else if (IsRowGroup(display->mDisplay)) {
     NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
     DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
@@ -3987,17 +3976,17 @@ NS_NewTableFrame(nsIPresShell* aPresShel
 
 NS_IMPL_FRAMEARENA_HELPERS(nsTableFrame)
 
 nsTableFrame*
 nsTableFrame::GetTableFrame(nsIFrame* aFrame)
 {
   for (nsIFrame* ancestor = aFrame->GetParent(); ancestor;
        ancestor = ancestor->GetParent()) {
-    if (nsGkAtoms::tableFrame == ancestor->GetType()) {
+    if (ancestor->IsTableFrame()) {
       return static_cast<nsTableFrame*>(ancestor);
     }
   }
   MOZ_CRASH("unable to find table parent");
   return nullptr;
 }
 
 nsTableFrame*
@@ -4012,17 +4001,17 @@ nsTableFrame::GetTableFramePassingThroug
   // Retrieve the table frame, and check if we hit aMustPassThrough on the
   // way.
   *aDidPassThrough = false;
   nsTableFrame* tableFrame = nullptr;
   for (nsIFrame* ancestor = aFrame; ancestor; ancestor = ancestor->GetParent()) {
     if (ancestor == aMustPassThrough) {
       *aDidPassThrough = true;
     }
-    if (nsGkAtoms::tableFrame == ancestor->GetType()) {
+    if (ancestor->IsTableFrame()) {
       tableFrame = static_cast<nsTableFrame*>(ancestor);
       break;
     }
   }
 
   MOZ_ASSERT(tableFrame, "Should have a table frame here");
   return tableFrame;
 }
@@ -4072,34 +4061,34 @@ nsTableFrame::GetFrameName(nsAString& aR
 {
   return MakeFrameName(NS_LITERAL_STRING("Table"), aResult);
 }
 #endif
 
 // Find the closet sibling before aPriorChildFrame (including aPriorChildFrame) that
 // is of type aChildType
 nsIFrame*
-nsTableFrame::GetFrameAtOrBefore(nsIFrame*       aParentFrame,
-                                 nsIFrame*       aPriorChildFrame,
-                                 nsIAtom*        aChildType)
+nsTableFrame::GetFrameAtOrBefore(nsIFrame* aParentFrame,
+                                 nsIFrame* aPriorChildFrame,
+                                 FrameType aChildType)
 {
   nsIFrame* result = nullptr;
   if (!aPriorChildFrame) {
     return result;
   }
-  if (aChildType == aPriorChildFrame->GetType()) {
+  if (aChildType == aPriorChildFrame->Type()) {
     return aPriorChildFrame;
   }
 
   // aPriorChildFrame is not of type aChildType, so we need start from
   // the beginnng and find the closest one
   nsIFrame* lastMatchingFrame = nullptr;
   nsIFrame* childFrame = aParentFrame->PrincipalChildList().FirstChild();
   while (childFrame && (childFrame != aPriorChildFrame)) {
-    if (aChildType == childFrame->GetType()) {
+    if (aChildType == childFrame->Type()) {
       lastMatchingFrame = childFrame;
     }
     childFrame = childFrame->GetNextSibling();
   }
   return lastMatchingFrame;
 }
 
 #ifdef DEBUG
@@ -4176,17 +4165,17 @@ nsTableFrame::Dump(bool            aDump
         break;
       case eColAnonymousCell:
         printf(" anonymous-cell ");
         break;
       }
     }
     printf("\n colgroups->");
     for (nsIFrame* childFrame : mColGroups) {
-      if (nsGkAtoms::tableColGroupFrame == childFrame->GetType()) {
+      if (FrameType::TableColGroup == childFrame->Type()) {
         nsTableColGroupFrame* colGroupFrame = (nsTableColGroupFrame *)childFrame;
         colGroupFrame->Dump(1);
       }
     }
     for (colIdx = 0; colIdx < numCols; colIdx++) {
       printf("\n");
       nsTableColFrame* colFrame = GetColFrame(colIdx);
       colFrame->Dump(1);
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -28,19 +28,21 @@ class nsStyleContext;
 namespace mozilla {
 class WritingMode;
 class LogicalMargin;
 struct TableReflowInput;
 } // namespace mozilla
 
 struct BCPropertyData;
 
-static inline bool IS_TABLE_CELL(nsIAtom* frameType) {
-  return nsGkAtoms::tableCellFrame == frameType ||
-    nsGkAtoms::bcTableCellFrame == frameType;
+static inline bool
+IS_TABLE_CELL(mozilla::FrameType frameType)
+{
+  return frameType == mozilla::FrameType::TableCell ||
+         frameType == mozilla::FrameType::BCTableCell;
 }
 
 class nsDisplayTableItem : public nsDisplayItem
 {
 public:
   nsDisplayTableItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                      bool aDrawsBackground = true) :
       nsDisplayItem(aBuilder, aFrame),
@@ -243,19 +245,19 @@ public:
                                       nsFrame* aFrame,
                                       const nsRect& aDirtyRect,
                                       const nsDisplayListSet& aLists,
                                       nsDisplayTableItem* aDisplayItem,
                                       DisplayGenericTablePartTraversal aTraversal = GenericTraversal);
 
   // Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
   // of type aChildType.
-  static nsIFrame* GetFrameAtOrBefore(nsIFrame*       aParentFrame,
-                                      nsIFrame*       aPriorChildFrame,
-                                      nsIAtom*        aChildType);
+  static nsIFrame* GetFrameAtOrBefore(nsIFrame* aParentFrame,
+                                      nsIFrame* aPriorChildFrame,
+                                      mozilla::FrameType aChildType);
   bool IsAutoBSize(mozilla::WritingMode aWM);
 
   /** @return true if aDisplayType represents a rowgroup of any sort
     * (header, footer, or body)
     */
   bool IsRowGroup(mozilla::StyleDisplay aDisplayType) const;
 
   virtual const nsFrameList& GetChildList(ChildListID aListID) const override;
@@ -372,23 +374,16 @@ public:
                    nsIFrame*&               aLastChildReflowed,
                    nsReflowStatus&          aStatus);
 
   nsFrameList& GetColGroups();
 
   virtual nsStyleContext*
   GetParentStyleContext(nsIFrame** aProviderFrame) const override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::tableFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     if (aFlags & eSupportsCSSTransforms) {
       return false;
     }
     return nsContainerFrame::IsFrameOfType(aFlags);
   }
 
--- a/layout/tables/nsTablePainter.cpp
+++ b/layout/tables/nsTablePainter.cpp
@@ -417,17 +417,17 @@ TableBackgroundPainter::PaintRowGroup(ns
   // Note that mDirtyRect  - mRenderPt is guaranteed to be in the row
   // group's coordinate system here, so passing its .y to
   // GetFirstRowContaining is ok.
   nscoord overflowAbove;
   nsIFrame* cursor = aFrame->GetFirstRowContaining(mDirtyRect.y - mRenderPt.y, &overflowAbove);
 
   // Sadly, it seems like there may be non-row frames in there... or something?
   // There are certainly null-checks in GetFirstRow() and GetNextRow().  :(
-  while (cursor && cursor->GetType() != nsGkAtoms::tableRowFrame) {
+  while (cursor && !cursor->IsTableRowFrame()) {
     cursor = cursor->GetNextSibling();
   }
 
   // It's OK if cursor is null here.
   nsTableRowFrame* row = static_cast<nsTableRowFrame*>(cursor);
   if (!row) {
     // No useful cursor; just start at the top.  Don't bother to set up a
     // cursor; if we've gotten this far then we've already built the display
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -125,17 +125,17 @@ nsTableRowFrame::SetPctBSize(float aPctV
 
 /* ----------- nsTableRowFrame ---------- */
 
 NS_QUERYFRAME_HEAD(nsTableRowFrame)
   NS_QUERYFRAME_ENTRY(nsTableRowFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
 
 nsTableRowFrame::nsTableRowFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::TableRow)
   , mContentBSize(0)
   , mStylePctBSize(0)
   , mStyleFixedBSize(0)
   , mMaxCellAscent(0)
   , mMaxCellDescent(0)
   , mBStartBorderWidth(0)
   , mBEndBorderWidth(0)
   , mIEndContBorderWidth(0)
@@ -208,17 +208,17 @@ nsTableRowFrame::AppendFrames(ChildListI
 
   DrainSelfOverflowList(); // ensure the last frame is in mFrames
   const nsFrameList::Slice& newCells = mFrames.AppendFrames(nullptr, aFrameList);
 
   // Add the new cell frames to the table
   nsTableFrame* tableFrame = GetTableFrame();
   for (nsFrameList::Enumerator e(newCells) ; !e.AtEnd(); e.Next()) {
     nsIFrame *childFrame = e.get();
-    NS_ASSERTION(IS_TABLE_CELL(childFrame->GetType()),
+    NS_ASSERTION(IS_TABLE_CELL(childFrame->Type()),
                  "Not a table cell frame/pseudo frame construction failure");
     tableFrame->AppendCell(static_cast<nsTableCellFrame&>(*childFrame), GetRowIndex());
   }
 
   PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                                                NS_FRAME_HAS_DIRTY_CHILDREN);
   tableFrame->SetGeometryDirty();
 }
@@ -233,22 +233,23 @@ nsTableRowFrame::InsertFrames(ChildListI
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                "inserting after sibling frame with different parent");
   DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
   //Insert Frames in the frame list
   const nsFrameList::Slice& newCells = mFrames.InsertFrames(nullptr, aPrevFrame, aFrameList);
 
   // Get the table frame
   nsTableFrame* tableFrame = GetTableFrame();
-  nsIAtom* cellFrameType = tableFrame->IsBorderCollapse() ? nsGkAtoms::bcTableCellFrame : nsGkAtoms::tableCellFrame;
+  FrameType cellFrameType = tableFrame->IsBorderCollapse()
+      ? FrameType::BCTableCell : FrameType::TableCell;
   nsTableCellFrame* prevCellFrame = (nsTableCellFrame *)nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame, cellFrameType);
   nsTArray<nsTableCellFrame*> cellChildren;
   for (nsFrameList::Enumerator e(newCells); !e.AtEnd(); e.Next()) {
     nsIFrame *childFrame = e.get();
-    NS_ASSERTION(IS_TABLE_CELL(childFrame->GetType()),
+    NS_ASSERTION(IS_TABLE_CELL(childFrame->Type()),
                  "Not a table cell frame/pseudo frame construction failure");
     cellChildren.AppendElement(static_cast<nsTableCellFrame*>(childFrame));
   }
   // insert the cells into the cell map
   int32_t colIndex = -1;
   if (prevCellFrame) {
     prevCellFrame->GetColIndex(colIndex);
   }
@@ -304,17 +305,17 @@ GetBSizeOfRowsSpannedBelowFirst(nsTableC
                                 nsTableFrame&     aTableFrame,
                                 const WritingMode aWM)
 {
   nscoord bsize = 0;
   int32_t rowSpan = aTableFrame.GetEffectiveRowSpan(aTableCellFrame);
   // add in bsize of rows spanned beyond the 1st one
   nsIFrame* nextRow = aTableCellFrame.GetParent()->GetNextSibling();
   for (int32_t rowX = 1; ((rowX < rowSpan) && nextRow);) {
-    if (nsGkAtoms::tableRowFrame == nextRow->GetType()) {
+    if (nextRow->IsTableRowFrame()) {
       bsize += nextRow->BSize(aWM);
       rowX++;
     }
     bsize += aTableFrame.GetRowSpacing(rowX);
     nextRow = nextRow->GetNextSibling();
   }
   return bsize;
 }
@@ -448,17 +449,17 @@ nscoord nsTableRowFrame::GetRowBaseline(
   // bp              pb
   // bp              pb
   // bppppppppppppppppb
   // bbbbbbbbbbbbbbbbbb
 
   nscoord ascent = 0;
   nsSize containerSize = GetSize();
   for (nsIFrame* childFrame : mFrames) {
-    if (IS_TABLE_CELL(childFrame->GetType())) {
+    if (IS_TABLE_CELL(childFrame->Type())) {
       nsIFrame* firstKid = childFrame->PrincipalChildList().FirstChild();
       ascent = std::max(ascent,
                         LogicalRect(aWM, firstKid->GetNormalRect(),
                                     containerSize).BEnd(aWM));
     }
   }
   return ascent;
 }
@@ -1400,22 +1401,16 @@ nsTableRowFrame::InsertCellFrame(nsTable
         priorCell = cellFrame;
       }
       else break;
     }
   }
   mFrames.InsertFrame(this, priorCell, aFrame);
 }
 
-nsIAtom*
-nsTableRowFrame::GetType() const
-{
-  return nsGkAtoms::tableRowFrame;
-}
-
 nsTableRowFrame*
 nsTableRowFrame::GetNextRow() const
 {
   nsIFrame* childFrame = GetNextSibling();
   while (childFrame) {
     nsTableRowFrame *rowFrame = do_QueryFrame(childFrame);
     if (rowFrame) {
 	  NS_ASSERTION(mozilla::StyleDisplay::TableRow == childFrame->StyleDisplay()->mDisplay,
--- a/layout/tables/nsTableRowFrame.h
+++ b/layout/tables/nsTableRowFrame.h
@@ -61,17 +61,17 @@ public:
     * @return           the frame that was created
     */
   friend nsTableRowFrame* NS_NewTableRowFrame(nsIPresShell* aPresShell,
                                               nsStyleContext* aContext);
 
   nsTableRowGroupFrame* GetTableRowGroupFrame() const
   {
     nsIFrame* parent = GetParent();
-    MOZ_ASSERT(parent && parent->GetType() == nsGkAtoms::tableRowGroupFrame);
+    MOZ_ASSERT(parent && parent->IsTableRowGroupFrame());
     return static_cast<nsTableRowGroupFrame*>(parent);
   }
 
   nsTableFrame* GetTableFrame() const
   {
     return GetTableRowGroupFrame()->GetTableFrame();
   }
 
@@ -100,23 +100,16 @@ public:
     */
   virtual void Reflow(nsPresContext*           aPresContext,
                       ReflowOutput&     aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus&          aStatus) override;
 
   void DidResize();
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::tableRowFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   void UpdateBSize(nscoord           aBSize,
                    nscoord           aAscent,
                    nscoord           aDescent,
                    nsTableFrame*     aTableFrame = nullptr,
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -48,18 +48,18 @@ struct TableRowGroupReflowInput {
   {
   }
 
   ~TableRowGroupReflowInput() {}
 };
 
 } // namespace mozilla
 
-nsTableRowGroupFrame::nsTableRowGroupFrame(nsStyleContext* aContext):
-  nsContainerFrame(aContext)
+nsTableRowGroupFrame::nsTableRowGroupFrame(nsStyleContext* aContext)
+  : nsContainerFrame(aContext, FrameType::TableRowGroup)
 {
   SetRepeatable(false);
 }
 
 nsTableRowGroupFrame::~nsTableRowGroupFrame()
 {
 }
 
@@ -80,29 +80,28 @@ NS_QUERYFRAME_TAIL_INHERITING(nsContaine
 int32_t
 nsTableRowGroupFrame::GetRowCount()
 {
 #ifdef DEBUG
   for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
     NS_ASSERTION(e.get()->StyleDisplay()->mDisplay ==
                  mozilla::StyleDisplay::TableRow,
                  "Unexpected display");
-    NS_ASSERTION(e.get()->GetType() == nsGkAtoms::tableRowFrame,
-                 "Unexpected frame type");
+    NS_ASSERTION(e.get()->IsTableRowFrame(), "Unexpected frame type");
   }
 #endif
 
   return mFrames.GetLength();
 }
 
 int32_t nsTableRowGroupFrame::GetStartRowIndex()
 {
   int32_t result = -1;
   if (mFrames.NotEmpty()) {
-    NS_ASSERTION(mFrames.FirstChild()->GetType() == nsGkAtoms::tableRowFrame,
+    NS_ASSERTION(mFrames.FirstChild()->IsTableRowFrame(),
                  "Unexpected frame type");
     result = static_cast<nsTableRowFrame*>(mFrames.FirstChild())->GetRowIndex();
   }
   // if the row group doesn't have any children, get it the hard way
   if (-1 == result) {
     return GetTableFrame()->GetStartRowIndex(this);
   }
 
@@ -1584,17 +1583,17 @@ nsTableRowGroupFrame::InsertFrames(Child
   }
 
   int32_t startRowIndex = GetStartRowIndex();
   // Insert the frames in the sibling chain
   mFrames.InsertFrames(nullptr, aPrevFrame, aFrameList);
 
   int32_t numRows = rows.Length();
   if (numRows > 0) {
-    nsTableRowFrame* prevRow = (nsTableRowFrame *)nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame, nsGkAtoms::tableRowFrame);
+    nsTableRowFrame* prevRow = (nsTableRowFrame *)nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame, FrameType::TableRow);
     int32_t rowIndex = (prevRow) ? prevRow->GetRowIndex() + 1 : startRowIndex;
     tableFrame->InsertRows(this, rows, rowIndex, true);
 
     PresContext()->PresShell()->
       FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                        NS_FRAME_HAS_DIRTY_CHILDREN);
     tableFrame->SetGeometryDirty();
   }
@@ -1680,22 +1679,16 @@ nsTableRowGroupFrame::IsSimpleRowFrame(n
   if (!aTableFrame->RowIsSpannedInto(rowIndex, numEffCols) &&
       !aTableFrame->RowHasSpanningCells(rowIndex, numEffCols)) {
     return true;
   }
 
   return false;
 }
 
-nsIAtom*
-nsTableRowGroupFrame::GetType() const
-{
-  return nsGkAtoms::tableRowGroupFrame;
-}
-
 /** find page break before the first row **/
 bool
 nsTableRowGroupFrame::HasInternalBreakBefore() const
 {
  nsIFrame* firstChild = mFrames.FirstChild();
   if (!firstChild)
     return false;
   return firstChild->StyleDisplay()->mBreakBefore;
--- a/layout/tables/nsTableRowGroupFrame.h
+++ b/layout/tables/nsTableRowGroupFrame.h
@@ -94,34 +94,27 @@ public:
     */
   virtual void Reflow(nsPresContext*           aPresContext,
                       ReflowOutput&     aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus&          aStatus) override;
 
   virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::tableRowGroupFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   nsTableRowFrame* GetFirstRow();
   nsTableRowFrame* GetLastRow();
 
   nsTableFrame* GetTableFrame() const
   {
     nsIFrame* parent = GetParent();
-    MOZ_ASSERT(parent && parent->GetType() == nsGkAtoms::tableFrame);
+    MOZ_ASSERT(parent && parent->IsTableFrame());
     return static_cast<nsTableFrame*>(parent);
   }
 
   /** return the number of child rows (not necessarily == number of child frames) */
   int32_t GetRowCount();
 
   /** return the table-relative row index of the first row in this rowgroup.
     * if there are no rows, -1 is returned.
--- a/layout/tables/nsTableWrapperFrame.cpp
+++ b/layout/tables/nsTableWrapperFrame.cpp
@@ -38,17 +38,17 @@ nsTableWrapperFrame::GetLogicalBaseline(
     return nsContainerFrame::GetLogicalBaseline(aWritingMode);
   }
 
   return kid->GetLogicalBaseline(aWritingMode) +
          kid->BStart(aWritingMode, mRect.Size());
 }
 
 nsTableWrapperFrame::nsTableWrapperFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext)
+  : nsContainerFrame(aContext, FrameType::TableWrapper)
 {
 }
 
 nsTableWrapperFrame::~nsTableWrapperFrame()
 {
 }
 
 NS_QUERYFRAME_HEAD(nsTableWrapperFrame)
@@ -96,17 +96,17 @@ nsTableWrapperFrame::SetInitialChildList
     // the frame constructor already checked for table-caption display type
     MOZ_ASSERT(mCaptionFrames.IsEmpty(),
                "already have child frames in CaptionList");
     mCaptionFrames.SetFrames(aChildList);
   } else {
     MOZ_ASSERT(kPrincipalList != aListID ||
                (aChildList.FirstChild() &&
                 aChildList.FirstChild() == aChildList.LastChild() &&
-                nsGkAtoms::tableFrame == aChildList.FirstChild()->GetType()),
+                aChildList.FirstChild()->IsTableFrame()),
                "expected a single table frame in principal child list");
     nsContainerFrame::SetInitialChildList(aListID, aChildList);
   }
 }
 
 void
 nsTableWrapperFrame::AppendFrames(ChildListID     aListID,
                                   nsFrameList&    aFrameList)
@@ -391,19 +391,18 @@ nsTableWrapperFrame::ChildShrinkWrapISiz
   LogicalSize paddingSize =
     offsets.ComputedLogicalPadding().Size(childWM).ConvertTo(aWM, childWM);
   LogicalSize bpSize =
     offsets.ComputedLogicalBorderPadding().Size(childWM).ConvertTo(aWM, childWM);
 
   // Shrink-wrap aChildFrame by default, except if we're a stretched grid item.
   auto flags = ComputeSizeFlags::eShrinkWrap;
   auto parent = GetParent();
-  nsIAtom* parentFrameType = parent ? parent->GetType() : nullptr;
-  bool isGridItem = (parentFrameType == nsGkAtoms::gridContainerFrame &&
-                     !HasAnyStateBits(NS_FRAME_OUT_OF_FLOW));
+  bool isGridItem = parent && parent->IsGridContainerFrame() &&
+                    !HasAnyStateBits(NS_FRAME_OUT_OF_FLOW);
   if (MOZ_UNLIKELY(isGridItem) &&
       !StyleMargin()->HasInlineAxisAuto(aWM)) {
     auto inlineAxisAlignment = aWM.IsOrthogonalTo(parent->GetWritingMode()) ?
                      StylePosition()->UsedAlignSelf(parent->StyleContext()) :
                      StylePosition()->UsedJustifySelf(parent->StyleContext());
     if (inlineAxisAlignment == NS_STYLE_ALIGN_NORMAL ||
         inlineAxisAlignment == NS_STYLE_ALIGN_STRETCH) {
       flags = nsIFrame::ComputeSizeFlags::eDefault;
@@ -1053,22 +1052,16 @@ nsTableWrapperFrame::Reflow(nsPresContex
 
   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aOuterRI, aStatus);
 
   // Return our desired rect
 
   NS_FRAME_SET_TRUNCATION(aStatus, aOuterRI, aDesiredSize);
 }
 
-nsIAtom*
-nsTableWrapperFrame::GetType() const
-{
-  return nsGkAtoms::tableWrapperFrame;
-}
-
 /* ----- global methods ----- */
 
 nsIContent*
 nsTableWrapperFrame::GetCellAt(uint32_t aRowIdx, uint32_t aColIdx) const
 {
   nsTableCellMap* cellMap = InnerTableFrame()->GetCellMap();
   if (!cellMap) {
     return nullptr;
--- a/layout/tables/nsTableWrapperFrame.h
+++ b/layout/tables/nsTableWrapperFrame.h
@@ -103,23 +103,16 @@ public:
   /** process a reflow command for the table.
     * This involves reflowing the caption and the inner table.
     * @see nsIFrame::Reflow */
   virtual void Reflow(nsPresContext*           aPresContext,
                       ReflowOutput&     aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus&          aStatus) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::tableWrapperFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   virtual nsStyleContext* GetParentStyleContext(nsIFrame** aProviderFrame) const override;
 
   /**
    * Return the content for the cell at the given row and column.
--- a/layout/xul/nsBox.cpp
+++ b/layout/xul/nsBox.cpp
@@ -171,17 +171,18 @@ nsBox::EndXULLayout(nsBoxLayoutState& aS
   #endif
 
   return SyncLayout(aState);
 }
 
 bool nsBox::gGotTheme = false;
 nsITheme* nsBox::gTheme = nullptr;
 
-nsBox::nsBox()
+nsBox::nsBox(FrameType aType)
+  : nsIFrame(aType)
 {
   MOZ_COUNT_CTOR(nsBox);
   //mX = 0;
   //mY = 0;
   if (!gGotTheme) {
     gGotTheme = true;
     CallGetService("@mozilla.org/chrome/chrome-native-theme;1", &gTheme);
   }
--- a/layout/xul/nsBox.h
+++ b/layout/xul/nsBox.h
@@ -45,17 +45,17 @@ public:
   NS_IMETHOD GetDebugBoxAt(const nsPoint& aPoint, nsIFrame** aBox);
   virtual nsresult GetXULDebug(bool& aDebug) override;
   virtual nsresult SetXULDebug(nsBoxLayoutState& aState, bool aDebug) override;
 
   virtual nsresult XULDumpBox(FILE* out) override;
   void PropagateDebug(nsBoxLayoutState& aState);
 #endif
 
-  nsBox();
+  explicit nsBox(mozilla::FrameType);
   virtual ~nsBox();
 
   /**
    * Returns true if this box clips its children, e.g., if this box is an sc
 rollbox.
   */
   virtual bool DoesClipChildren();
   virtual bool ComputesOwnOverflowArea() = 0;
--- a/layout/xul/nsBoxFrame.cpp
+++ b/layout/xul/nsBoxFrame.cpp
@@ -111,19 +111,20 @@ NS_IMPL_FRAMEARENA_HELPERS(nsBoxFrame)
 
 #ifdef DEBUG
 NS_QUERYFRAME_HEAD(nsBoxFrame)
   NS_QUERYFRAME_ENTRY(nsBoxFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
 #endif
 
 nsBoxFrame::nsBoxFrame(nsStyleContext* aContext,
+                       FrameType aType,
                        bool aIsRoot,
-                       nsBoxLayout* aLayoutManager) :
-  nsContainerFrame(aContext)
+                       nsBoxLayout* aLayoutManager)
+  : nsContainerFrame(aContext, aType)
 {
   mState |= NS_STATE_IS_HORIZONTAL;
   mState |= NS_STATE_AUTO_STRETCH;
 
   if (aIsRoot) 
      mState |= NS_STATE_IS_ROOT;
 
   mValign = vAlign_Top;
@@ -1538,22 +1539,16 @@ nsBoxFrame::GetBoxName(nsAutoString& aNa
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsBoxFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Box"), aResult);
 }
 #endif
 
-nsIAtom*
-nsBoxFrame::GetType() const
-{
-  return nsGkAtoms::boxFrame;
-}
-
 #ifdef DEBUG_LAYOUT
 nsresult
 nsBoxFrame::GetXULDebug(bool& aDebug)
 {
   aDebug = (mState & NS_STATE_CURRENTLY_IN_DEBUG);
   return NS_OK;
 }
 #endif
--- a/layout/xul/nsBoxFrame.h
+++ b/layout/xul/nsBoxFrame.h
@@ -107,18 +107,16 @@ public:
                             nsFrameList&    aFrameList) override;
   virtual void RemoveFrame(ChildListID     aListID,
                            nsIFrame*       aOldFrame) override;
 
   virtual nsContainerFrame* GetContentInsertionFrame() override;
 
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) override;
 
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     // record that children that are ignorable whitespace should be excluded 
     // (When content was loaded via the XUL content sink, it's already
     // been excluded, but we need this for when the XUL namespace is used
     // in other MIME types or when the XUL CSS display types are used with
     // non-XUL elements.)
 
@@ -137,18 +135,22 @@ public:
 
   virtual void DidReflow(nsPresContext*           aPresContext,
                          const ReflowInput* aReflowInput,
                          nsDidReflowStatus        aStatus) override;
 
   virtual bool HonorPrintBackgroundSettings() override;
 
   virtual ~nsBoxFrame();
-  
-  explicit nsBoxFrame(nsStyleContext* aContext, bool aIsRoot = false, nsBoxLayout* aLayoutManager = nullptr);
+
+  explicit nsBoxFrame(nsStyleContext* aContext,
+                      bool aIsRoot = false,
+                      nsBoxLayout* aLayoutManager = nullptr)
+    : nsBoxFrame(aContext, mozilla::FrameType::Box, aIsRoot, aLayoutManager)
+  {}
 
   // virtual so nsStackFrame, nsButtonBoxFrame, nsSliderFrame and nsMenuFrame
   // can override it
   virtual void BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
                                            const nsRect&           aDirtyRect,
                                            const nsDisplayListSet& aLists);
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
@@ -174,16 +176,21 @@ public:
 
   /**
    * This defaults to true, but some box frames (nsListBoxBodyFrame for
    * example) don't support ordinals in their children.
    */
   virtual bool SupportsOrdinalsInChildren();
 
 protected:
+  nsBoxFrame(nsStyleContext* aContext,
+             mozilla::FrameType aType,
+             bool aIsRoot = false,
+             nsBoxLayout* aLayoutManager = nullptr);
+
 #ifdef DEBUG_LAYOUT
     virtual void GetBoxName(nsAutoString& aName) override;
     void PaintXULDebugBackground(nsRenderingContext& aRenderingContext,
                                  nsPoint aPt);
     void PaintXULDebugOverlay(DrawTarget& aRenderingContext,
                               nsPoint aPt);
 #endif
 
--- a/layout/xul/nsDeckFrame.cpp
+++ b/layout/xul/nsDeckFrame.cpp
@@ -40,29 +40,24 @@ NS_NewDeckFrame(nsIPresShell* aPresShell
 NS_IMPL_FRAMEARENA_HELPERS(nsDeckFrame)
 
 NS_QUERYFRAME_HEAD(nsDeckFrame)
   NS_QUERYFRAME_ENTRY(nsDeckFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
 
 
 nsDeckFrame::nsDeckFrame(nsStyleContext* aContext)
-  : nsBoxFrame(aContext), mIndex(0)
+  : nsBoxFrame(aContext, FrameType::Deck)
+  , mIndex(0)
 {
   nsCOMPtr<nsBoxLayout> layout;
   NS_NewStackLayout(layout);
   SetXULLayoutManager(layout);
 }
 
-nsIAtom*
-nsDeckFrame::GetType() const
-{
-  return nsGkAtoms::deckFrame;
-}
-
 nsresult
 nsDeckFrame::AttributeChanged(int32_t         aNameSpaceID,
                               nsIAtom*        aAttribute,
                               int32_t         aModType)
 {
   nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
                                              aModType);
 
--- a/layout/xul/nsDeckFrame.h
+++ b/layout/xul/nsDeckFrame.h
@@ -38,23 +38,21 @@ public:
                                 const nsDisplayListSet& aLists) override;
 
   virtual void RemoveFrame(ChildListID aListID,
                            nsIFrame* aOldFrame) override;
 
   virtual void BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
                                            const nsRect&           aDirtyRect,
                                            const nsDisplayListSet& aLists) override;
-                                         
+
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
       return MakeFrameName(NS_LITERAL_STRING("Deck"), aResult);
   }
 #endif
 
   explicit nsDeckFrame(nsStyleContext* aContext);
--- a/layout/xul/nsImageBoxFrame.cpp
+++ b/layout/xul/nsImageBoxFrame.cpp
@@ -145,23 +145,23 @@ nsImageBoxFrame::AttributeChanged(int32_
       FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
   }
   else if (aAttribute == nsGkAtoms::validate)
     UpdateLoadFlags();
 
   return rv;
 }
 
-nsImageBoxFrame::nsImageBoxFrame(nsStyleContext* aContext):
-  nsLeafBoxFrame(aContext),
-  mIntrinsicSize(0,0),
-  mLoadFlags(nsIRequest::LOAD_NORMAL),
-  mRequestRegistered(false),
-  mUseSrcAttr(false),
-  mSuppressStyleCheck(false)
+nsImageBoxFrame::nsImageBoxFrame(nsStyleContext* aContext)
+  : nsLeafBoxFrame(aContext, FrameType::ImageBox)
+  , mIntrinsicSize(0, 0)
+  , mLoadFlags(nsIRequest::LOAD_NORMAL)
+  , mRequestRegistered(false)
+  , mUseSrcAttr(false)
+  , mSuppressStyleCheck(false)
 {
   MarkIntrinsicISizesDirty();
 }
 
 nsImageBoxFrame::~nsImageBoxFrame()
 {
 }
 
@@ -657,22 +657,16 @@ nsImageBoxFrame::GetXULMinSize(nsBoxLayo
 }
 
 nscoord
 nsImageBoxFrame::GetXULBoxAscent(nsBoxLayoutState& aState)
 {
   return GetXULPrefSize(aState).height;
 }
 
-nsIAtom*
-nsImageBoxFrame::GetType() const
-{
-  return nsGkAtoms::imageBoxFrame;
-}
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsImageBoxFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("ImageBox"), aResult);
 }
 #endif
 
--- a/layout/xul/nsImageBoxFrame.h
+++ b/layout/xul/nsImageBoxFrame.h
@@ -63,17 +63,16 @@ public:
   virtual nsresult AttributeChanged(int32_t aNameSpaceID,
                                     nsIAtom* aAttribute,
                                     int32_t aModType) override;
 
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) override;
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
-  virtual nsIAtom* GetType() const override;
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   /** 
    * Update mUseSrcAttr from appropriate content attributes or from
    * style, throw away the current image, and load the appropriate
    * image.
--- a/layout/xul/nsLeafBoxFrame.cpp
+++ b/layout/xul/nsLeafBoxFrame.cpp
@@ -35,18 +35,18 @@ using namespace mozilla;
 nsIFrame*
 NS_NewLeafBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsLeafBoxFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsLeafBoxFrame)
 
-nsLeafBoxFrame::nsLeafBoxFrame(nsStyleContext* aContext)
-    : nsLeafFrame(aContext)
+nsLeafBoxFrame::nsLeafBoxFrame(nsStyleContext* aContext, FrameType aType)
+  : nsLeafFrame(aContext, aType)
 {
 }
 
 #ifdef DEBUG_LAYOUT
 void
 nsLeafBoxFrame::GetBoxName(nsAutoString& aName)
 {
    GetFrameName(aName);
@@ -328,22 +328,16 @@ nsLeafBoxFrame::Reflow(nsPresContext*   
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsLeafBoxFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("LeafBox"), aResult);
 }
 #endif
 
-nsIAtom*
-nsLeafBoxFrame::GetType() const
-{
-  return nsGkAtoms::leafBoxFrame;
-}
-
 nsresult
 nsLeafBoxFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo)
 {
   MarkIntrinsicISizesDirty();
   return nsLeafFrame::CharacterDataChanged(aInfo);
 }
 
 /* virtual */ nsSize
--- a/layout/xul/nsLeafBoxFrame.h
+++ b/layout/xul/nsLeafBoxFrame.h
@@ -17,17 +17,16 @@ public:
   friend nsIFrame* NS_NewLeafBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   virtual nsSize GetXULPrefSize(nsBoxLayoutState& aState) override;
   virtual nsSize GetXULMinSize(nsBoxLayoutState& aState) override;
   virtual nsSize GetXULMaxSize(nsBoxLayoutState& aState) override;
   virtual nscoord GetXULFlex() override;
   virtual nscoord GetXULBoxAscent(nsBoxLayoutState& aState) override;
 
-  virtual nsIAtom* GetType() const override;
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     // This is bogus, but it's what we've always done.
     // Note that nsLeafFrame is also eReplacedContainsBlock.
     return nsLeafFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock | nsIFrame::eXULBox));
   }
 
@@ -78,17 +77,21 @@ protected:
   NS_IMETHOD DoXULLayout(nsBoxLayoutState& aState) override;
 
 #ifdef DEBUG_LAYOUT
   virtual void GetBoxName(nsAutoString& aName) override;
 #endif
 
   virtual nscoord GetIntrinsicISize() override;
 
- explicit nsLeafBoxFrame(nsStyleContext* aContext);
+  explicit nsLeafBoxFrame(nsStyleContext* aContext)
+    : nsLeafBoxFrame(aContext, mozilla::FrameType::LeafBox)
+  {}
+
+  nsLeafBoxFrame(nsStyleContext* aContext, mozilla::FrameType aType);
 
 private:
 
  void UpdateMouseThrough();
 
 
 }; // class nsLeafBoxFrame
 
--- a/layout/xul/nsMenuFrame.cpp
+++ b/layout/xul/nsMenuFrame.cpp
@@ -164,24 +164,24 @@ NS_NewMenuItemFrame(nsIPresShell* aPresS
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsMenuFrame)
 
 NS_QUERYFRAME_HEAD(nsMenuFrame)
   NS_QUERYFRAME_ENTRY(nsMenuFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
 
-nsMenuFrame::nsMenuFrame(nsStyleContext* aContext):
-  nsBoxFrame(aContext),
-    mIsMenu(false),
-    mChecked(false),
-    mIgnoreAccelTextChange(false),
-    mReflowCallbackPosted(false),
-    mType(eMenuType_Normal),
-    mBlinkState(0)
+nsMenuFrame::nsMenuFrame(nsStyleContext* aContext)
+  : nsBoxFrame(aContext, FrameType::Menu)
+  , mIsMenu(false)
+  , mChecked(false)
+  , mIgnoreAccelTextChange(false)
+  , mReflowCallbackPosted(false)
+  , mType(eMenuType_Normal)
+  , mBlinkState(0)
 {
 }
 
 nsMenuParent*
 nsMenuFrame::GetMenuParent() const
 {
   nsContainerFrame* parent = GetParent();
   for (; parent; parent = parent->GetParent()) {
@@ -260,17 +260,17 @@ nsMenuFrame::GetPopup()
 nsFrameList*
 nsMenuFrame::GetPopupList() const
 {
   if (!HasPopup()) {
     return nullptr;
   }
   nsFrameList* prop = Properties().Get(PopupListProperty());
   NS_ASSERTION(prop && prop->GetLength() == 1 &&
-               prop->FirstChild()->GetType() == nsGkAtoms::menuPopupFrame,
+               prop->FirstChild()->IsMenuPopupFrame(),
                "popup list should have exactly one nsMenuPopupFrame");
   return prop;
 }
 
 void
 nsMenuFrame::DestroyPopupList()
 {
   NS_ASSERTION(HasPopup(), "huh?");
--- a/layout/xul/nsMenuFrame.h
+++ b/layout/xul/nsMenuFrame.h
@@ -103,34 +103,32 @@ public:
   virtual const nsFrameList& GetChildList(ChildListID aList) const override;
   virtual void GetChildLists(nsTArray<ChildList>* aLists) const override;
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
   // Overridden to prevent events from going to children of the menu.
   virtual void BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
                                            const nsRect&           aDirtyRect,
                                            const nsDisplayListSet& aLists) override;
-                                         
+
   // this method can destroy the frame
   virtual nsresult HandleEvent(nsPresContext* aPresContext,
                                mozilla::WidgetGUIEvent* aEvent,
                                nsEventStatus* aEventStatus) override;
 
   virtual void SetInitialChildList(ChildListID  aListID,
                                    nsFrameList& aChildList) override;
   virtual void AppendFrames(ChildListID     aListID,
                             nsFrameList&    aFrameList) override;
   virtual void InsertFrames(ChildListID     aListID,
                             nsIFrame*       aPrevFrame,
                             nsFrameList&    aFrameList) override;
   virtual void RemoveFrame(ChildListID     aListID,
                            nsIFrame*       aOldFrame) override;
 
-  virtual nsIAtom* GetType() const override { return nsGkAtoms::menuFrame; }
-
   NS_IMETHOD SelectMenu(bool aActivateFlag);
 
   virtual nsIScrollableFrame* GetScrollTargetFrame() override;
 
   // Retrieve the element that the menu should be anchored to. By default this is
   // the menu itself. However, the anchor attribute may refer to the value of an
   // anonid within the menu's binding, or, if not found, the id of an element in
   // the document.
--- a/layout/xul/nsMenuPopupFrame.cpp
+++ b/layout/xul/nsMenuPopupFrame.cpp
@@ -90,40 +90,40 @@ NS_IMPL_FRAMEARENA_HELPERS(nsMenuPopupFr
 NS_QUERYFRAME_HEAD(nsMenuPopupFrame)
   NS_QUERYFRAME_ENTRY(nsMenuPopupFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
 
 //
 // nsMenuPopupFrame ctor
 //
 nsMenuPopupFrame::nsMenuPopupFrame(nsStyleContext* aContext)
-  :nsBoxFrame(aContext),
-  mCurrentMenu(nullptr),
-  mView(nullptr),
-  mPrefSize(-1, -1),
-  mLastClientOffset(0, 0),
-  mPopupType(ePopupTypePanel),
-  mPopupState(ePopupClosed),
-  mPopupAlignment(POPUPALIGNMENT_NONE),
-  mPopupAnchor(POPUPALIGNMENT_NONE),
-  mPosition(POPUPPOSITION_UNKNOWN),
-  mConsumeRollupEvent(PopupBoxObject::ROLLUP_DEFAULT),
-  mFlip(FlipType_Default),
-  mIsOpenChanged(false),
-  mIsContextMenu(false),
-  mAdjustOffsetForContextMenu(false),
-  mGeneratedChildren(false),
-  mMenuCanOverlapOSBar(false),
-  mShouldAutoPosition(true),
-  mInContentShell(true),
-  mIsMenuLocked(false),
-  mMouseTransparent(false),
-  mHFlip(false),
-  mVFlip(false),
-  mAnchorType(MenuPopupAnchorType_Node)
+  : nsBoxFrame(aContext, FrameType::MenuPopup)
+  , mCurrentMenu(nullptr)
+  , mView(nullptr)
+  , mPrefSize(-1, -1)
+  , mLastClientOffset(0, 0)
+  , mPopupType(ePopupTypePanel)
+  , mPopupState(ePopupClosed)
+  , mPopupAlignment(POPUPALIGNMENT_NONE)
+  , mPopupAnchor(POPUPALIGNMENT_NONE)
+  , mPosition(POPUPPOSITION_UNKNOWN)
+  , mConsumeRollupEvent(PopupBoxObject::ROLLUP_DEFAULT)
+  , mFlip(FlipType_Default)
+  , mIsOpenChanged(false)
+  , mIsContextMenu(false)
+  , mAdjustOffsetForContextMenu(false)
+  , mGeneratedChildren(false)
+  , mMenuCanOverlapOSBar(false)
+  , mShouldAutoPosition(true)
+  , mInContentShell(true)
+  , mIsMenuLocked(false)
+  , mMouseTransparent(false)
+  , mHFlip(false)
+  , mVFlip(false)
+  , mAnchorType(MenuPopupAnchorType_Node)
 {
   // the preference name is backwards here. True means that the 'top' level is
   // the default, and false means that the 'parent' level is the default.
   if (sDefaultLevelIsTop >= 0)
     return;
   sDefaultLevelIsTop =
     Preferences::GetBool("ui.panel.default_level_parent", false);
   Preferences::AddUintVarCache(&sTimeoutOfIncrementalSearch,
--- a/layout/xul/nsMenuPopupFrame.h
+++ b/layout/xul/nsMenuPopupFrame.h
@@ -332,18 +332,16 @@ public:
   // type the first few letters of an item/s name to select it.
   nsMenuFrame* FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent, bool& doAction);
 
   void ClearIncrementalString() { mIncrementalString.Truncate(); }
   static bool IsWithinIncrementalTime(DOMTimeStamp time) {
     return !sTimeoutOfIncrementalSearch || time - sLastKeyTime <= sTimeoutOfIncrementalSearch;
   }
 
-  virtual nsIAtom* GetType() const override { return nsGkAtoms::menuPopupFrame; }
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
       return MakeFrameName(NS_LITERAL_STRING("MenuPopup"), aResult);
   }
 #endif
 
   void EnsureMenuItemIsVisible(nsMenuFrame* aMenuFrame);
--- a/layout/xul/nsPopupSetFrame.cpp
+++ b/layout/xul/nsPopupSetFrame.cpp
@@ -32,22 +32,16 @@ nsPopupSetFrame::Init(nsIContent*       
   // Normally the root box is our grandparent, but in case of wrapping
   // it can be our great-grandparent.
   nsIRootBox *rootBox = nsIRootBox::GetRootBox(PresContext()->GetPresShell());
   if (rootBox) {
     rootBox->SetPopupSetFrame(this);
   }
 }
 
-nsIAtom*
-nsPopupSetFrame::GetType() const
-{
-  return nsGkAtoms::popupSetFrame;
-}
-
 void
 nsPopupSetFrame::AppendFrames(ChildListID     aListID,
                               nsFrameList&    aFrameList)
 {
   if (aListID == kPopupList) {
     AddPopupFrameList(aFrameList);
     return;
   }
@@ -135,26 +129,26 @@ nsPopupSetFrame::DoXULLayout(nsBoxLayout
 
   return rv;
 }
 
 void
 nsPopupSetFrame::RemovePopupFrame(nsIFrame* aPopup)
 {
   NS_PRECONDITION((aPopup->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
-                  aPopup->GetType() == nsGkAtoms::menuPopupFrame,
+                  aPopup->IsMenuPopupFrame(),
                   "removing wrong type of frame in popupset's ::popupList");
 
   mPopupList.DestroyFrame(aPopup);
 }
 
 void
 nsPopupSetFrame::AddPopupFrameList(nsFrameList& aPopupFrameList)
 {
 #ifdef DEBUG
   for (nsFrameList::Enumerator e(aPopupFrameList); !e.AtEnd(); e.Next()) {
     NS_ASSERTION((e.get()->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
-                 e.get()->GetType() == nsGkAtoms::menuPopupFrame,
+                 e.get()->IsMenuPopupFrame(),
                  "adding wrong type of frame in popupset's ::popupList");
   }
 #endif
   mPopupList.InsertFrames(nullptr, nullptr, aPopupFrameList);
 }
--- a/layout/xul/nsPopupSetFrame.h
+++ b/layout/xul/nsPopupSetFrame.h
@@ -8,26 +8,27 @@
 #define nsPopupSetFrame_h__
 
 #include "mozilla/Attributes.h"
 #include "nsIAtom.h"
 #include "nsBoxFrame.h"
 
 nsIFrame* NS_NewPopupSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
-class nsPopupSetFrame : public nsBoxFrame
+class nsPopupSetFrame final : public nsBoxFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
-  explicit nsPopupSetFrame(nsStyleContext* aContext):
-    nsBoxFrame(aContext) {}
+  explicit nsPopupSetFrame(nsStyleContext* aContext)
+    : nsBoxFrame(aContext, mozilla::FrameType::PopupSet)
+  {}
 
   ~nsPopupSetFrame() {}
-  
+
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 
   virtual void SetInitialChildList(ChildListID  aListID,
                                     nsFrameList& aChildList) override;
   virtual void AppendFrames(ChildListID     aListID,
                             nsFrameList&    aFrameList) override;
@@ -40,25 +41,23 @@ public:
   virtual const nsFrameList& GetChildList(ChildListID aList) const override;
   virtual void GetChildLists(nsTArray<ChildList>* aLists) const override;
 
   NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
 
   // Used to destroy our popup frames.
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
-  virtual nsIAtom* GetType() const override;
-
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
       return MakeFrameName(NS_LITERAL_STRING("PopupSet"), aResult);
   }
 #endif
 
 protected:
   void AddPopupFrameList(nsFrameList& aPopupFrameList);
   void RemovePopupFrame(nsIFrame* aPopup);
-  
+
   nsFrameList mPopupList;
 };
 
 #endif
--- a/layout/xul/nsProgressMeterFrame.h
+++ b/layout/xul/nsProgressMeterFrame.h
@@ -2,30 +2,30 @@
 /* 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/. */
 
 /**
 
   David Hyatt & Eric D Vaughan.
 
-  An XBL-based progress meter. 
+  An XBL-based progress meter.
 
   Attributes:
 
   value: A number between 0% and 100%
   align: horizontal or vertical
   mode: determined, undetermined (one shows progress other shows animated candy cane)
 
 **/
 
 #include "mozilla/Attributes.h"
 #include "nsBoxFrame.h"
 
-class nsProgressMeterFrame : public nsBoxFrame
+class nsProgressMeterFrame final : public nsBoxFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   friend nsIFrame* NS_NewProgressMeterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
 
--- a/layout/xul/nsRootBoxFrame.cpp
+++ b/layout/xul/nsRootBoxFrame.cpp
@@ -73,23 +73,16 @@ public:
   virtual nsresult HandleEvent(nsPresContext* aPresContext,
                                WidgetGUIEvent* aEvent,
                                nsEventStatus* aEventStatus) override;
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::rootFrame
-   */
-  virtual nsIAtom* GetType() const override;
-
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     // Override bogus IsFrameOfType in nsBoxFrame.
     if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced))
       return false;
     return nsBoxFrame::IsFrameOfType(aFlags);
   }
   
@@ -109,17 +102,17 @@ nsContainerFrame*
 NS_NewRootBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsRootBoxFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsRootBoxFrame)
 
 nsRootBoxFrame::nsRootBoxFrame(nsStyleContext* aContext)
-  : nsBoxFrame(aContext, true)
+  : nsBoxFrame(aContext, FrameType::Root, true)
   , mPopupSetFrame(nullptr)
   , mDefaultTooltip(nullptr)
 {
   nsCOMPtr<nsBoxLayout> layout;
   NS_NewStackLayout(layout);
   SetXULLayoutManager(layout);
 }
 
@@ -207,24 +200,16 @@ nsRootBoxFrame::HandleEvent(nsPresContex
 
   if (aEvent->mMessage == eMouseUp) {
     nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
   }
 
   return NS_OK;
 }
 
-// REVIEW: The override here was doing nothing since nsBoxFrame is our
-// parent class
-nsIAtom*
-nsRootBoxFrame::GetType() const
-{
-  return nsGkAtoms::rootFrame;
-}
-
 nsPopupSetFrame*
 nsRootBoxFrame::GetPopupSetFrame()
 {
   return mPopupSetFrame;
 }
 
 void
 nsRootBoxFrame::SetPopupSetFrame(nsPopupSetFrame* aPopupSet)
--- a/layout/xul/nsScrollbarFrame.cpp
+++ b/layout/xul/nsScrollbarFrame.cpp
@@ -67,22 +67,16 @@ nsScrollbarFrame::Reflow(nsPresContext* 
   if (aReflowInput.AvailableWidth() == 0) {
     aDesiredSize.Width() = 0;
   }
   if (aReflowInput.AvailableHeight() == 0) {
     aDesiredSize.Height() = 0;
   }
 }
 
-nsIAtom*
-nsScrollbarFrame::GetType() const
-{
-  return nsGkAtoms::scrollbarFrame;
-}
-
 nsresult
 nsScrollbarFrame::AttributeChanged(int32_t aNameSpaceID,
                                    nsIAtom* aAttribute,
                                    int32_t aModType)
 {
   nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
                                              aModType);
 
--- a/layout/xul/nsScrollbarFrame.h
+++ b/layout/xul/nsScrollbarFrame.h
@@ -15,18 +15,20 @@
 
 class nsIScrollbarMediator;
 
 nsIFrame* NS_NewScrollbarFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
 class nsScrollbarFrame : public nsBoxFrame
 {
 public:
-    explicit nsScrollbarFrame(nsStyleContext* aContext):
-      nsBoxFrame(aContext), mScrollbarMediator(nullptr) {}
+  explicit nsScrollbarFrame(nsStyleContext* aContext)
+    : nsBoxFrame(aContext, mozilla::FrameType::Scrollbar)
+    , mScrollbarMediator(nullptr)
+  {}
 
   NS_DECL_QUERYFRAME_TARGET(nsScrollbarFrame)
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("ScrollbarFrame"), aResult);
   }
 #endif
@@ -60,18 +62,16 @@ public:
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 
   virtual void Reflow(nsPresContext*           aPresContext,
                       ReflowOutput&     aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus&          aStatus) override;
 
-  virtual nsIAtom* GetType() const override;  
-
   void SetScrollbarMediatorContent(nsIContent* aMediator);
   nsIScrollbarMediator* GetScrollbarMediator();
 
   // nsBox methods
 
   /**
    * Treat scrollbars as clipping their children; overflowing children
    * will not be allowed to set an overflow rect on this
--- a/layout/xul/nsSliderFrame.cpp
+++ b/layout/xul/nsSliderFrame.cpp
@@ -76,25 +76,25 @@ NS_NewSliderFrame (nsIPresShell* aPresSh
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsSliderFrame)
 
 NS_QUERYFRAME_HEAD(nsSliderFrame)
   NS_QUERYFRAME_ENTRY(nsSliderFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
 
-nsSliderFrame::nsSliderFrame(nsStyleContext* aContext):
-  nsBoxFrame(aContext),
-  mRatio(0.0f),
-  mCurPos(0),
-  mChange(0),
-  mDragFinished(true),
-  mUserChanged(false),
-  mScrollingWithAPZ(false),
-  mSuppressionActive(false)
+nsSliderFrame::nsSliderFrame(nsStyleContext* aContext)
+  : nsBoxFrame(aContext, FrameType::Slider)
+  , mRatio(0.0f)
+  , mCurPos(0)
+  , mChange(0)
+  , mDragFinished(true)
+  , mUserChanged(false)
+  , mScrollingWithAPZ(false)
+  , mSuppressionActive(false)
 {
 }
 
 // stop timer
 nsSliderFrame::~nsSliderFrame()
 {
   if (mSuppressionActive) {
     APZCCallbackHelper::SuppressDisplayport(false, PresContext() ?
@@ -905,22 +905,16 @@ nsSliderFrame::SetCurrentPositionInterna
   mUserChanged = false;
 
 #ifdef DEBUG_SLIDER
   printf("Current Pos=%d\n",aNewPos);
 #endif
 
 }
 
-nsIAtom*
-nsSliderFrame::GetType() const
-{
-  return nsGkAtoms::sliderFrame;
-}
-
 void
 nsSliderFrame::SetInitialChildList(ChildListID     aListID,
                                    nsFrameList&    aChildList)
 {
   nsBoxFrame::SetInitialChildList(aListID, aChildList);
   if (aListID == kPrincipalList) {
     AddListener();
   }
--- a/layout/xul/nsSliderFrame.h
+++ b/layout/xul/nsSliderFrame.h
@@ -32,17 +32,17 @@ public:
   virtual void SetSlider(nsSliderFrame* aSlider) { mSlider = aSlider; }
 
   NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override;
 
 protected:
   virtual ~nsSliderMediator() {}
 };
 
-class nsSliderFrame : public nsBoxFrame
+class nsSliderFrame final : public nsBoxFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
   NS_DECL_QUERYFRAME_TARGET(nsSliderFrame)
   NS_DECL_QUERYFRAME
 
   friend class nsSliderMediator;
 
@@ -79,18 +79,16 @@ public:
                     nsContainerFrame* aParent,
                     nsIFrame*         asPrevInFlow) override;
 
 
   virtual nsresult HandleEvent(nsPresContext* aPresContext,
                                mozilla::WidgetGUIEvent* aEvent,
                                nsEventStatus* aEventStatus) override;
 
-  virtual nsIAtom* GetType() const override;
-
   // nsContainerFrame overrides
   virtual void SetInitialChildList(ChildListID     aListID,
                                    nsFrameList&    aChildList) override;
   virtual void AppendFrames(ChildListID     aListID,
                             nsFrameList&    aFrameList) override;
   virtual void InsertFrames(ChildListID     aListID,
                             nsIFrame*       aPrevFrame,
                             nsFrameList&    aFrameList) override;
--- a/layout/xul/nsXULLabelFrame.cpp
+++ b/layout/xul/nsXULLabelFrame.cpp
@@ -91,22 +91,16 @@ nsXULLabelFrame::AttributeChanged(int32_
   // If the accesskey changed, register for the new value
   // The old value has been unregistered in nsXULElement::SetAttr
   if (aAttribute == nsGkAtoms::accesskey || aAttribute == nsGkAtoms::control)
     RegUnregAccessKey(true);
 
   return rv;
 }
 
-nsIAtom*
-nsXULLabelFrame::GetType() const
-{
-  return nsGkAtoms::XULLabelFrame;
-}
-
 /////////////////////////////////////////////////////////////////////////////
 // Diagnostics
 
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsXULLabelFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("XULLabel"), aResult);
--- a/layout/xul/nsXULLabelFrame.h
+++ b/layout/xul/nsXULLabelFrame.h
@@ -29,29 +29,24 @@ public:
                     nsIFrame*         aPrevInFlow) override;
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
   virtual nsresult AttributeChanged(int32_t aNameSpaceID,
                                     nsIAtom* aAttribute,
                                     int32_t aModType) override;
 
-  /**
-   * Get the "type" of the frame
-   *
-   * @see nsGkAtoms::XULLabelFrame
-   */
-  virtual nsIAtom* GetType() const override;
-  
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
 protected:
-  explicit nsXULLabelFrame(nsStyleContext *aContext) : nsBlockFrame(aContext) {}
+  explicit nsXULLabelFrame(nsStyleContext* aContext)
+    : nsBlockFrame(aContext, mozilla::FrameType::XULLabel)
+  {}
 
   nsresult RegUnregAccessKey(bool aDoReg);
 };
 
 nsIFrame*
 NS_NewXULLabelFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
 #endif /* !defined(nsXULLabelFrame_h_) */
--- a/view/nsView.cpp
+++ b/view/nsView.cpp
@@ -1037,18 +1037,17 @@ nsView::WindowResized(nsIWidget* aWidget
   }
 
   return false;
 }
 
 bool
 nsView::RequestWindowClose(nsIWidget* aWidget)
 {
-  if (mFrame && IsPopupWidget(aWidget) &&
-      mFrame->GetType() == nsGkAtoms::menuPopupFrame) {
+  if (mFrame && IsPopupWidget(aWidget) && mFrame->IsMenuPopupFrame()) {
     nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
     if (pm) {
       pm->HidePopup(mFrame->GetContent(), false, true, false, false);
       return true;
     }
   }
 
   return false;
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -446,17 +446,17 @@ static ChildView* ChildViewForFrame(nsIF
   NSView* view = (NSView*)widget->GetNativeData(NS_NATIVE_WIDGET);
   return [view isKindOfClass:[ChildView class]] ? (ChildView*)view : nil;
 }
 
 static NSWindow* NativeWindowForFrame(nsIFrame* aFrame,
                                       nsIWidget** aTopLevelWidget = NULL)
 {
   if (!aFrame)
-    return nil;  
+    return nil;
 
   nsIWidget* widget = aFrame->GetNearestWidget();
   if (!widget)
     return nil;
 
   nsIWidget* topLevelWidget = widget->GetTopLevelWidget();
   if (aTopLevelWidget)
     *aTopLevelWidget = topLevelWidget;
@@ -534,17 +534,17 @@ nsNativeThemeCocoa::nsNativeThemeCocoa()
   // provide a local autorelease pool, as this is called during startup
   // before the main event-loop pool is in place
   nsAutoreleasePool pool;
 
   mDisclosureButtonCell = [[NSButtonCell alloc] initTextCell:@""];
   [mDisclosureButtonCell setBezelStyle:NSRoundedDisclosureBezelStyle];
   [mDisclosureButtonCell setButtonType:NSPushOnPushOffButton];
   [mDisclosureButtonCell setHighlightsBy:NSPushInCellMask];
-  
+
   mHelpButtonCell = [[NSButtonCell alloc] initTextCell:@""];
   [mHelpButtonCell setBezelStyle:NSHelpButtonBezelStyle];
   [mHelpButtonCell setButtonType:NSMomentaryPushInButton];
   [mHelpButtonCell setHighlightsBy:NSPushInCellMask];
 
   mPushButtonCell = [[NSButtonCell alloc] initTextCell:@""];
   [mPushButtonCell setButtonType:NSMomentaryPushInButton];
   [mPushButtonCell setHighlightsBy:NSPushInCellMask];
@@ -615,17 +615,17 @@ nsNativeThemeCocoa::~nsNativeThemeCocoa(
 
 static int
 GetBackingScaleFactorForRendering(CGContextRef cgContext)
 {
   CGAffineTransform ctm = CGContextGetUserSpaceToDeviceSpaceTransform(cgContext);
   CGRect transformedUserSpacePixel = CGRectApplyAffineTransform(CGRectMake(0, 0, 1, 1), ctm);
   float maxScale = std::max(fabs(transformedUserSpacePixel.size.width),
                           fabs(transformedUserSpacePixel.size.height));
-  return maxScale > 1.0 ? 2 : 1;  
+  return maxScale > 1.0 ? 2 : 1;
 }
 
 /*
  * Draw the given NSCell into the given cgContext.
  *
  * destRect - the size and position of the resulting control rectangle
  * controlSize - the NSControlSize which will be given to the NSCell before
  *  asking it to render
@@ -2052,47 +2052,47 @@ nsNativeThemeCocoa::DrawSegment(CGContex
             (isPressed ? @"pressed" : (isActive ? @"normal" : @"inactive")), @"state",
             [NSNumber numberWithBool:isFocused], @"focus",
             CUIControlSizeForCocoaSize(controlSize), @"size",
             [NSNumber numberWithBool:YES], @"is.flipped",
             @"up", @"direction",
             nil]);
 }
 
-void 
+void
 nsNativeThemeCocoa::GetScrollbarPressStates(nsIFrame* aFrame,
                                             EventStates aButtonStates[])
 {
   static nsIContent::AttrValuesArray attributeValues[] = {
     &nsGkAtoms::scrollbarUpTop,
     &nsGkAtoms::scrollbarDownTop,
     &nsGkAtoms::scrollbarUpBottom,
     &nsGkAtoms::scrollbarDownBottom,
     nullptr
   };
 
   // Get the state of any scrollbar buttons in our child frames
   for (nsIFrame *childFrame : aFrame->PrincipalChildList()) {
     nsIContent *childContent = childFrame->GetContent();
     if (!childContent) continue;
-    int32_t attrIndex = childContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::sbattr, 
+    int32_t attrIndex = childContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::sbattr,
                                                       attributeValues, eCaseMatters);
     if (attrIndex < 0) continue;
 
     aButtonStates[attrIndex] = GetContentState(childFrame, NS_THEME_BUTTON);
   }
 }
 
 nsIFrame*
 nsNativeThemeCocoa::GetParentScrollbarFrame(nsIFrame *aFrame)
 {
   // Walk our parents to find a scrollbar frame
-  nsIFrame *scrollbarFrame = aFrame;
+  nsIFrame* scrollbarFrame = aFrame;
   do {
-    if (scrollbarFrame->GetType() == nsGkAtoms::scrollbarFrame) break;
+    if (scrollbarFrame->IsScrollbarFrame()) break;
   } while ((scrollbarFrame = scrollbarFrame->GetParent()));
 
   // We return null if we can't find a parent scrollbar frame
   return scrollbarFrame;
 }
 
 static bool
 ToolbarCanBeUnified(CGContextRef cgContext, const HIRect& inBoxRect, NSWindow* aWindow)
@@ -2598,17 +2598,17 @@ nsNativeThemeCocoa::DrawWidgetBackground
       NSWindow* win = NativeWindowForFrame(aFrame);
       BOOL isMain = [win isMainWindow];
       float unifiedToolbarHeight = [win isKindOfClass:[ToolbarWindow class]] ?
         [(ToolbarWindow*)win unifiedToolbarHeight] : macRect.size.height;
       DrawNativeTitlebar(cgContext, macRect, unifiedToolbarHeight, isMain, YES);
     }
       break;
 
-    case NS_THEME_STATUSBAR: 
+    case NS_THEME_STATUSBAR:
       DrawStatusBar(cgContext, macRect, aFrame);
       break;
 
     case NS_THEME_MENULIST:
     case NS_THEME_MENULIST_TEXTFIELD:
       DrawDropdown(cgContext, macRect, eventState, aWidgetType, aFrame);
       break;
 
@@ -2636,17 +2636,17 @@ nsNativeThemeCocoa::DrawWidgetBackground
       // to check the window's focus ring state here
       if (aFrame->GetContent()->IsXULElement() && IsFocused(aFrame)) {
         eventState |= NS_EVENT_STATE_FOCUS;
       }
 
       DrawFrame(cgContext, kHIThemeFrameTextFieldSquare, macRect,
                 IsDisabled(aFrame, eventState) || IsReadOnly(aFrame), eventState);
       break;
-      
+
     case NS_THEME_SEARCHFIELD:
       DrawSearchField(cgContext, macRect, aFrame, eventState);
       break;
 
     case NS_THEME_PROGRESSBAR:
     {
       double value = GetProgressValue(aFrame);
       double maxValue = GetProgressMaxValue(aFrame);
@@ -2826,17 +2826,17 @@ nsNativeThemeCocoa::DrawWidgetBackground
                 true);
       }
     }
       break;
 
     case NS_THEME_TEXTFIELD_MULTILINE: {
       // we have to draw this by hand because there is no HITheme value for it
       CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
-      
+
       CGContextFillRect(cgContext, macRect);
 
       // #737373 for the top border, #999999 for the rest.
       float x = macRect.origin.x, y = macRect.origin.y;
       float w = macRect.size.width, h = macRect.size.height;
       CGContextSetRGBFillColor(cgContext, 0.4510, 0.4510, 0.4510, 1.0);
       CGContextFillRect(cgContext, CGRectMake(x, y, w, 1));
       CGContextSetRGBFillColor(cgContext, 0.6, 0.6, 0.6, 1.0);
@@ -2919,17 +2919,17 @@ nsNativeThemeCocoa::DrawWidgetBackground
             [NSNumber numberWithBool:YES], @"is.flipped",
             @"kCUIVariantGradientSideBarSelection", @"kCUIVariantKey",
             (FrameIsInActiveWindow(aFrame) ? @"normal" : @"inactive"), @"state",
             @"gradient", @"widget",
             nil]);
       }
     }
       break;
-    
+
     case NS_THEME_TAB:
       DrawSegment(cgContext, macRect, eventState, aFrame, tabRenderSettings);
       break;
 
     case NS_THEME_TABPANELS:
       DrawTabPanel(cgContext, macRect, aFrame);
       break;
 
@@ -2970,17 +2970,17 @@ nsNativeThemeCocoa::DirectionAwareMargin
   return nsIntMargin(m.top, m.right, m.bottom, m.left);
 }
 
 static const nsIntMargin kAquaDropdownBorder(1, 22, 2, 5);
 static const nsIntMargin kAquaComboboxBorder(3, 20, 3, 4);
 static const nsIntMargin kAquaSearchfieldBorder(3, 5, 2, 19);
 
 NS_IMETHODIMP
-nsNativeThemeCocoa::GetWidgetBorder(nsDeviceContext* aContext, 
+nsNativeThemeCocoa::GetWidgetBorder(nsDeviceContext* aContext,
                                     nsIFrame* aFrame,
                                     uint8_t aWidgetType,
                                     nsIntMargin* aResult)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   aResult->SizeTo(0, 0, 0, 0);
 
@@ -3094,17 +3094,17 @@ nsNativeThemeCocoa::GetWidgetBorder(nsDe
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 // Return false here to indicate that CSS padding values should be used. There is
 // no reason to make a distinction between padding and border values, just specify
 // whatever values you want in GetWidgetBorder and only use this to return true
 // if you want to override CSS padding values.
 bool
-nsNativeThemeCocoa::GetWidgetPadding(nsDeviceContext* aContext, 
+nsNativeThemeCocoa::GetWidgetPadding(nsDeviceContext* aContext,
                                      nsIFrame* aFrame,
                                      uint8_t aWidgetType,
                                      nsIntMargin* aResult)
 {
   // We don't want CSS padding being used for certain widgets.
   // See bug 381639 for an example of why.
   switch (aWidgetType) {
     // Radios and checkboxes return a fixed size in GetMinimumWidgetSize
@@ -3296,26 +3296,26 @@ nsNativeThemeCocoa::GetMinimumWidgetSize
     {
       SInt32 barHeight = 0;
       ::GetThemeMetric(kThemeMetricNormalProgressBarThickness, &barHeight);
       aResult->SizeTo(0, barHeight);
       break;
     }
 
     case NS_THEME_TREETWISTY:
-    case NS_THEME_TREETWISTYOPEN:   
+    case NS_THEME_TREETWISTYOPEN:
     {
       SInt32 twistyHeight = 0, twistyWidth = 0;
       ::GetThemeMetric(kThemeMetricDisclosureButtonWidth, &twistyWidth);
       ::GetThemeMetric(kThemeMetricDisclosureButtonHeight, &twistyHeight);
       aResult->SizeTo(twistyWidth, twistyHeight);
       *aIsOverridable = false;
       break;
     }
-    
+
     case NS_THEME_TREEHEADER:
     case NS_THEME_TREEHEADERCELL:
     {
       SInt32 headerHeight = 0;
       ::GetThemeMetric(kThemeMetricListHeaderHeight, &headerHeight);
       aResult->SizeTo(0, headerHeight - 1); // We don't need the top border.
       break;
     }
@@ -3464,17 +3464,17 @@ nsNativeThemeCocoa::GetMinimumWidgetSize
       SInt32 scrollbarWidth = 0;
       ::GetThemeMetric(themeMetric, &scrollbarWidth);
 
       // It seems that for both sizes of scrollbar, the buttons are one pixel "longer".
       if (aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT || aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT)
         aResult->SizeTo(scrollbarWidth+1, scrollbarWidth);
       else
         aResult->SizeTo(scrollbarWidth, scrollbarWidth+1);
- 
+
       *aIsOverridable = false;
       break;
     }
     case NS_THEME_RESIZER:
     {
       HIThemeGrowBoxDrawInfo drawInfo;
       drawInfo.version = 0;
       drawInfo.state = kThemeStateActive;
@@ -3494,17 +3494,17 @@ nsNativeThemeCocoa::GetMinimumWidgetSize
   }
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 NS_IMETHODIMP
-nsNativeThemeCocoa::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, 
+nsNativeThemeCocoa::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType,
                                        nsIAtom* aAttribute, bool* aShouldRepaint,
                                        const nsAttrValue* aOldValue)
 {
   // Some widget types just never change state.
   switch (aWidgetType) {
     case NS_THEME_WINDOW_TITLEBAR:
     case NS_THEME_TOOLBOX:
     case NS_THEME_TOOLBAR:
@@ -3531,17 +3531,17 @@ nsNativeThemeCocoa::WidgetStateChanged(n
 
   // XXXdwh Not sure what can really be done here.  Can at least guess for
   // specific widgets that they're highly unlikely to have certain states.
   // For example, a toolbar doesn't care about any states.
   if (!aAttribute) {
     // Hover/focus/active changed.  Always repaint.
     *aShouldRepaint = true;
   } else {
-    // Check the attribute to see if it's relevant.  
+    // Check the attribute to see if it's relevant.
     // disabled, checked, dlgtype, default, etc.
     *aShouldRepaint = false;
     if (aAttribute == nsGkAtoms::disabled ||
         aAttribute == nsGkAtoms::checked ||
         aAttribute == nsGkAtoms::selected ||
         aAttribute == nsGkAtoms::visuallyselected ||
         aAttribute == nsGkAtoms::menuactive ||
         aAttribute == nsGkAtoms::sortDirection ||
@@ -3558,30 +3558,30 @@ nsNativeThemeCocoa::WidgetStateChanged(n
 NS_IMETHODIMP
 nsNativeThemeCocoa::ThemeChanged()
 {
   // This is unimplemented because we don't care if gecko changes its theme
   // and Mac OS X doesn't have themes.
   return NS_OK;
 }
 
-bool 
+bool
 nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame,
                                       uint8_t aWidgetType)
 {
   // We don't have CSS set up to render non-native scrollbars on Mac OS X so we
   // render natively even if native theme support is disabled.
   if (aWidgetType != NS_THEME_SCROLLBAR &&
       aPresContext && !aPresContext->PresShell()->IsThemeSupportEnabled())
     return false;
 
   // if this is a dropdown button in a combobox the answer is always no
   if (aWidgetType == NS_THEME_MENULIST_BUTTON) {
     nsIFrame* parentFrame = aFrame->GetParent();
-    if (parentFrame && (parentFrame->GetType() == nsGkAtoms::comboboxControlFrame))
+    if (parentFrame && parentFrame->IsComboboxControlFrame())
       return false;
   }
 
   switch (aWidgetType) {
     // Combobox dropdowns don't support native theming in vertical mode.
     case NS_THEME_MENULIST:
     case NS_THEME_MENULIST_BUTTON:
     case NS_THEME_MENULIST_TEXT:
@@ -3599,17 +3599,17 @@ nsNativeThemeCocoa::ThemeSupportsWidget(
     case NS_THEME_WINDOW_TITLEBAR:
     case NS_THEME_CHECKMENUITEM:
     case NS_THEME_MENUPOPUP:
     case NS_THEME_MENUARROW:
     case NS_THEME_MENUITEM:
     case NS_THEME_MENUSEPARATOR:
     case NS_THEME_MAC_FULLSCREEN_BUTTON:
     case NS_THEME_TOOLTIP:
-    
+
     case NS_THEME_CHECKBOX:
     case NS_THEME_CHECKBOX_CONTAINER:
     case NS_THEME_RADIO:
     case NS_THEME_RADIO_CONTAINER:
     case NS_THEME_GROUPBOX:
     case NS_THEME_MAC_HELP_BUTTON:
     case NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN:
     case NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED:
@@ -3631,20 +3631,20 @@ nsNativeThemeCocoa::ThemeSupportsWidget(
     //case NS_THEME_TOOLBARBUTTON:
     case NS_THEME_PROGRESSBAR:
     case NS_THEME_PROGRESSBAR_VERTICAL:
     case NS_THEME_PROGRESSCHUNK:
     case NS_THEME_PROGRESSCHUNK_VERTICAL:
     case NS_THEME_METERBAR:
     case NS_THEME_METERCHUNK:
     case NS_THEME_SEPARATOR:
-    
+
     case NS_THEME_TABPANELS:
     case NS_THEME_TAB:
-    
+
     case NS_THEME_TREETWISTY:
     case NS_THEME_TREETWISTYOPEN:
     case NS_THEME_TREEVIEW:
     case NS_THEME_TREEHEADER:
     case NS_THEME_TREEHEADERCELL:
     case NS_THEME_TREEHEADERSORTARROW:
     case NS_THEME_TREEITEM:
     case NS_THEME_TREELINE:
@@ -3670,17 +3670,17 @@ nsNativeThemeCocoa::ThemeSupportsWidget(
     case NS_THEME_SCROLLBARTRACK_VERTICAL:
     case NS_THEME_SCROLLBARTRACK_HORIZONTAL:
     case NS_THEME_SCROLLBAR_NON_DISAPPEARING:
       return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
 
     case NS_THEME_RESIZER:
     {
       nsIFrame* parentFrame = aFrame->GetParent();
-      if (!parentFrame || parentFrame->GetType() != nsGkAtoms::scrollFrame)
+      if (!parentFrame || !parentFrame->IsScrollFrame())
         return true;
 
       // Note that IsWidgetStyled is not called for resizers on Mac. This is
       // because for scrollable containers, the native resizer looks better
       // when (non-overlay) scrollbars are present even when the style is
       // overriden, and the custom transparent resizer looks better when
       // scrollbars are not present.
       nsIScrollableFrame* scrollFrame = do_QueryFrame(parentFrame);
--- a/widget/nsBaseDragService.cpp
+++ b/widget/nsBaseDragService.cpp
@@ -496,17 +496,17 @@ nsBaseDragService::FireDragEventAtSource
  * used as a drag image during the drag. This isn't used on GTK as it manages
  * the drag popup itself.
  */
 NS_IMETHODIMP
 nsBaseDragService::DragMoved(int32_t aX, int32_t aY)
 {
   if (mDragPopup) {
     nsIFrame* frame = mDragPopup->GetPrimaryFrame();
-    if (frame && frame->GetType() == nsGkAtoms::menuPopupFrame) {
+    if (frame && frame->IsMenuPopupFrame()) {
       CSSIntPoint cssPos = RoundedToInt(LayoutDeviceIntPoint(aX, aY) /
           frame->PresContext()->CSSToDevPixelScale()) - mImageOffset;
       (static_cast<nsMenuPopupFrame *>(frame))->MoveTo(cssPos, true);
     }
   }
 
   return NS_OK;
 }
@@ -639,17 +639,17 @@ nsBaseDragService::DrawDrag(nsIDOMNode* 
     }
 
     // If the image is a popup, use that as the image. This allows custom drag
     // images that can change during the drag, but means that any platform
     // default image handling won't occur.
     // XXXndeakin this should be chrome-only
 
     nsIFrame* frame = content->GetPrimaryFrame();
-    if (frame && frame->GetType() == nsGkAtoms::menuPopupFrame) {
+    if (frame && frame->IsMenuPopupFrame()) {
       mDragPopup = content;
     }
   }
 
   if (!mDragPopup) {
     // otherwise, just draw the node
     nsIntRegion clipRegion;
     uint32_t renderFlags = mImage ? 0 : nsIPresShell::RENDER_AUTO_SCALE;
--- a/widget/nsNativeTheme.cpp
+++ b/widget/nsNativeTheme.cpp
@@ -276,17 +276,17 @@ nsNativeTheme::IsWidgetStyled(nsPresCont
 
   // Resizers have some special handling, dependent on whether in a scrollable
   // container or not. If so, use the scrollable container's to determine
   // whether the style is overriden instead of the resizer. This allows a
   // non-native transparent resizer to be used instead. Otherwise, we just
   // fall through and return false.
   if (aWidgetType == NS_THEME_RESIZER) {
     nsIFrame* parentFrame = aFrame->GetParent();
-    if (parentFrame && parentFrame->GetType() == nsGkAtoms::scrollFrame) {
+    if (parentFrame && parentFrame->IsScrollFrame()) {
       // if the parent is a scrollframe, the resizer should be native themed
       // only if the scrollable area doesn't override the widget style.
       parentFrame = parentFrame->GetParent();
       if (parentFrame) {
         return IsWidgetStyled(aPresContext, parentFrame,
                               parentFrame->StyleDisplay()->UsedAppearance());
       }
     }
@@ -707,21 +707,21 @@ nsNativeTheme::GetAdjacentSiblingFrameWi
     return nullptr;
   return sibling;
 }
 
 bool
 nsNativeTheme::IsRangeHorizontal(nsIFrame* aFrame)
 {
   nsIFrame* rangeFrame = aFrame;
-  if (rangeFrame->GetType() != nsGkAtoms::rangeFrame) {
+  if (!rangeFrame->IsRangeFrame()) {
     // If the thumb's frame is passed in, get its range parent:
     rangeFrame = aFrame->GetParent();
   }
-  if (rangeFrame->GetType() == nsGkAtoms::rangeFrame) {
+  if (rangeFrame->IsRangeFrame()) {
     return static_cast<nsRangeFrame*>(rangeFrame)->IsHorizontal();
   }
   // Not actually a range frame - just use the ratio of the frame's size to
   // decide:
   return aFrame->GetSize().width >= aFrame->GetSize().height;
 }
 
 static nsIFrame*
--- a/widget/windows/nsNativeThemeWin.cpp
+++ b/widget/windows/nsNativeThemeWin.cpp
@@ -1145,17 +1145,17 @@ nsNativeThemeWin::GetThemePartAndState(n
           aState = TS_NORMAL;
       }
 
       return NS_OK;
     }
     case NS_THEME_MENULIST_BUTTON: {
       bool isHTML = IsHTMLContent(aFrame);
       nsIFrame* parentFrame = aFrame->GetParent();
-      bool isMenulist = !isHTML && parentFrame->GetType() == nsGkAtoms::menuFrame;
+      bool isMenulist = !isHTML && parentFrame->IsMenuFrame();
       bool isOpen = false;
 
       // HTML select and XUL menulist dropdown buttons get state from the parent.
       if (isHTML || isMenulist)
         aFrame = parentFrame;
 
       EventStates eventState = GetContentState(aFrame, aWidgetType);
       aPart = CBP_DROPMARKER_VISTA;
@@ -2586,17 +2586,17 @@ nsNativeThemeWin::ClassicThemeSupportsWi
 {
   switch (aWidgetType) {
     case NS_THEME_RESIZER:
     {
       // The classic native resizer has an opaque grey background which doesn't
       // match the usually white background of the scrollable container, so
       // only support the native resizer if not in a scrollframe.
       nsIFrame* parentFrame = aFrame->GetParent();
-      return (!parentFrame || parentFrame->GetType() != nsGkAtoms::scrollFrame);
+      return !parentFrame || !parentFrame->IsScrollFrame();
     }
     case NS_THEME_MENUBAR:
     case NS_THEME_MENUPOPUP:
       // Classic non-flat menus are handled almost entirely through CSS.
       if (!nsUXThemeData::sFlatMenus)
         return false;
     case NS_THEME_BUTTON:
     case NS_THEME_NUMBER_INPUT:
@@ -3109,17 +3109,17 @@ nsresult nsNativeThemeWin::ClassicGetThe
       return NS_OK;
     case NS_THEME_MENULIST_BUTTON: {
 
       aPart = DFC_SCROLL;
       aState = DFCS_SCROLLCOMBOBOX;
 
       nsIFrame* parentFrame = aFrame->GetParent();
       bool isHTML = IsHTMLContent(aFrame);
-      bool isMenulist = !isHTML && parentFrame->GetType() == nsGkAtoms::menuFrame;
+      bool isMenulist = !isHTML && parentFrame->IsMenuFrame();
       bool isOpen = false;
 
       // HTML select and XUL menulist dropdown buttons get state from the parent.
       if (isHTML || isMenulist)
         aFrame = parentFrame;
 
       EventStates eventState = GetContentState(aFrame, aWidgetType);