Merge mozilla-central to autoland
authorarthur.iakab <aiakab@mozilla.com>
Tue, 03 Apr 2018 12:39:24 +0300
changeset 411525 801d1d90b2ffcca423d9cee10509169318890b8c
parent 411524 76f66b8cea9315e4dbd2535be368c27ab206b919 (current diff)
parent 411442 4a3275936ddf871103b53e00608e2b8d5aee7e69 (diff)
child 411526 4e884e689aada1cfec78a41e8d89bf0229f0d8fc
push id101686
push useraciure@mozilla.com
push dateTue, 03 Apr 2018 21:59:31 +0000
treeherdermozilla-inbound@8d846598d35d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to autoland
dom/interfaces/base/nsIDOMScreen.idl
--- a/devtools/client/framework/components/toolbox-tab.js
+++ b/devtools/client/framework/components/toolbox-tab.js
@@ -57,16 +57,21 @@ class ToolboxTab extends Component {
         id: `toolbox-tab-${id}`,
         "data-id": id,
         title: tooltip,
         type: "button",
         "aria-pressed": currentToolId === id ? "true" : "false",
         tabIndex: focusedButton === id ? "0" : "-1",
         onFocus: () => focusButton(id),
         onMouseDown: () => selectTool(id),
+        onKeyDown: (evt) => {
+          if (evt.key === "Enter" || evt.key === " ") {
+            selectTool(id);
+          }
+        },
       },
       span(
         {
           className: "devtools-tab-line"
         }
       ),
       ...this.renderIcon(panelDefinition, isHighlighted),
       iconOnly ?
--- a/devtools/client/framework/test/browser_toolbox_keyboard_navigation.js
+++ b/devtools/client/framework/test/browser_toolbox_keyboard_navigation.js
@@ -76,8 +76,49 @@ add_task(async function () {
   EventUtils.synthesizeKey("KEY_Tab");
   ok(!containsFocus(doc, toolbar), "Focus is outside of the toolbar");
 
   // Move the focus back to the toolbar, ensure we land on the last active
   // descendant control.
   EventUtils.synthesizeKey("KEY_Tab", {shiftKey: true});
   is(doc.activeElement.id, expectedFocusedControl.id, "New control is focused");
 });
+
+// Test that moving the focus of tab button and selecting it.
+add_task(async function () {
+  info("Create a test tab and open the toolbox");
+  let toolbox = await openNewTabAndToolbox(TEST_URL, "inspector");
+  let doc = toolbox.doc;
+
+  let toolbar = doc.querySelector(".toolbox-tabs");
+  let tabButtons = toolbar.querySelectorAll(".devtools-tab, button");
+  let win = tabButtons[0].ownerDocument.defaultView;
+
+  // Put the keyboard focus onto the first tab button.
+  tabButtons[0].focus();
+  ok(containsFocus(doc, toolbar), "Focus is within the toolbox");
+  is(doc.activeElement.id, tabButtons[0].id, "First tab button is focused.");
+
+  // Move the focused tab and select it by using enter key.
+  let onKeyEvent = once(win, "keydown");
+  EventUtils.synthesizeKey("KEY_ArrowRight");
+  await onKeyEvent;
+
+  let onceSelected = toolbox.once("webconsole-selected");
+  EventUtils.synthesizeKey("Enter");
+  await onceSelected;
+  ok(doc.activeElement.id, tabButtons[1].id, "Changed tab button is focused.");
+
+  // Webconsole steal the focus from button after sending "webconsole-selected"
+  // event.
+  tabButtons[1].focus();
+
+  // Return the focused tab with space key.
+  onKeyEvent = once(win, "keydown");
+  EventUtils.synthesizeKey("KEY_ArrowLeft");
+  await onKeyEvent;
+
+  onceSelected = toolbox.once("inspector-selected");
+  EventUtils.synthesizeKey(" ");
+  await onceSelected;
+
+  ok(doc.activeElement.id, tabButtons[0].id, "Changed tab button is focused.");
+});
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -2327,25 +2327,16 @@ nsGlobalWindowInner::GetScreen(ErrorResu
       aError.Throw(NS_ERROR_UNEXPECTED);
       return nullptr;
     }
   }
 
   return mScreen;
 }
 
-nsIDOMScreen*
-nsGlobalWindowInner::GetScreen()
-{
-  ErrorResult dummy;
-  nsIDOMScreen* screen = GetScreen(dummy);
-  dummy.SuppressException();
-  return screen;
-}
-
 nsHistory*
 nsGlobalWindowInner::GetHistory(ErrorResult& aError)
 {
   if (!mHistory) {
     mHistory = new nsHistory(this);
   }
 
   return mHistory;
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -774,17 +774,16 @@ public:
   already_AddRefed<nsICSSDeclaration>
     GetComputedStyle(mozilla::dom::Element& aElt, const nsAString& aPseudoElt,
                      mozilla::ErrorResult& aError) override;
   already_AddRefed<mozilla::dom::MediaQueryList> MatchMedia(
     const nsAString& aQuery,
     mozilla::dom::CallerType aCallerType,
     mozilla::ErrorResult& aError);
   nsScreen* GetScreen(mozilla::ErrorResult& aError);
-  nsIDOMScreen* GetScreen() override;
   void MoveTo(int32_t aXPos, int32_t aYPos,
               mozilla::dom::CallerType aCallerType,
               mozilla::ErrorResult& aError);
   void MoveBy(int32_t aXDif, int32_t aYDif,
               mozilla::dom::CallerType aCallerType,
               mozilla::ErrorResult& aError);
   void ResizeTo(int32_t aWidth, int32_t aHeight,
                 mozilla::dom::CallerType aCallerType,
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -2591,20 +2591,20 @@ nsPIDOMWindowOuter::SetFrameElementInter
 }
 
 Navigator*
 nsGlobalWindowOuter::GetNavigator()
 {
   FORWARD_TO_INNER(Navigator, (), nullptr);
 }
 
-nsIDOMScreen*
+nsScreen*
 nsGlobalWindowOuter::GetScreen()
 {
-  FORWARD_TO_INNER(GetScreen, (), nullptr);
+  FORWARD_TO_INNER(GetScreen, (IgnoreErrors()), nullptr);
 }
 
 void
 nsPIDOMWindowOuter::MaybeActiveMediaComponents()
 {
   if (mMediaSuspend != nsISuspendedTypes::SUSPENDED_BLOCK) {
     return;
   }
@@ -3703,48 +3703,47 @@ nsGlobalWindowOuter::CheckSecurityLeftAn
 #endif
 
     if (nsGlobalWindowOuter* rootWindow = nsGlobalWindowOuter::Cast(GetPrivateRoot())) {
       rootWindow->FlushPendingNotifications(FlushType::Layout);
     }
 
     nsCOMPtr<nsIBaseWindow> treeOwner = GetTreeOwnerWindow();
 
-    nsCOMPtr<nsIDOMScreen> screen = GetScreen();
+    RefPtr<nsScreen> screen = GetScreen();
 
     if (treeOwner && screen) {
-      int32_t screenLeft, screenTop, screenWidth, screenHeight;
       int32_t winLeft, winTop, winWidth, winHeight;
 
       // Get the window size
       treeOwner->GetPositionAndSize(&winLeft, &winTop, &winWidth, &winHeight);
 
       // convert those values to CSS pixels
       // XXX four separate retrievals of the prescontext
       winLeft   = DevToCSSIntPixels(winLeft);
       winTop    = DevToCSSIntPixels(winTop);
       winWidth  = DevToCSSIntPixels(winWidth);
       winHeight = DevToCSSIntPixels(winHeight);
 
       // Get the screen dimensions
       // XXX This should use nsIScreenManager once it's fully fleshed out.
-      screen->GetAvailLeft(&screenLeft);
-      screen->GetAvailWidth(&screenWidth);
-      screen->GetAvailHeight(&screenHeight);
+      int32_t screenLeft = screen->GetAvailLeft(IgnoreErrors());
+      int32_t screenWidth = screen->GetAvailWidth(IgnoreErrors());
+      int32_t screenHeight = screen->GetAvailHeight(IgnoreErrors());
 #if defined(XP_MACOSX)
       /* The mac's coordinate system is different from the assumed Windows'
          system. It offsets by the height of the menubar so that a window
          placed at (0,0) will be entirely visible. Unfortunately that
          correction is made elsewhere (in Widget) and the meaning of
          the Avail... coordinates is overloaded. Here we allow a window
          to be placed at (0,0) because it does make sense to do so.
       */
-      screen->GetTop(&screenTop);
+      int32_t screenTop = screen->GetTop(IgnoreErrors());
 #else
-      screen->GetAvailTop(&screenTop);
+      int32_t screenTop = screen->GetAvailTop(IgnoreErrors());
 #endif
 
       if (aLeft) {
         if (screenLeft+screenWidth < *aLeft+winWidth)
           *aLeft = screenLeft+screenWidth - winWidth;
         if (screenLeft > *aLeft)
           *aLeft = screenLeft;
       }
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -631,17 +631,17 @@ public:
                    nsIPrincipal& aSubjectPrincipal,
                    mozilla::ErrorResult& aError);
   void PrintOuter(mozilla::ErrorResult& aError);
   mozilla::dom::Selection* GetSelectionOuter();
   already_AddRefed<nsISelection> GetSelection() override;
   already_AddRefed<mozilla::dom::MediaQueryList> MatchMediaOuter(
     const nsAString& aQuery,
     mozilla::dom::CallerType aCallerType);
-  nsIDOMScreen* GetScreen() override;
+  nsScreen* GetScreen();
   void MoveToOuter(int32_t aXPos, int32_t aYPos,
                    mozilla::dom::CallerType aCallerType,
                    mozilla::ErrorResult& aError);
   void MoveByOuter(int32_t aXDif, int32_t aYDif,
                    mozilla::dom::CallerType aCallerType,
                    mozilla::ErrorResult& aError);
   nsresult MoveBy(int32_t aXDif, int32_t aYDif) override;
   void ResizeToOuter(int32_t aWidth, int32_t aHeight,
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -585,17 +585,16 @@ public:
     mMarkedCCGeneration = aGeneration;
   }
 
   uint32_t GetMarkedCCGeneration()
   {
     return mMarkedCCGeneration;
   }
 
-  virtual nsIDOMScreen* GetScreen() = 0;
   mozilla::dom::Navigator* Navigator();
   virtual mozilla::dom::Location* GetLocation() = 0;
 
   virtual nsresult GetControllers(nsIControllers** aControllers) = 0;
 
   virtual already_AddRefed<nsIDOMWindowCollection> GetFrames() = 0;
 
   virtual nsresult GetInnerWidth(int32_t* aWidth) = 0;
@@ -1089,17 +1088,16 @@ public:
 
   uint32_t GetMarkedCCGeneration()
   {
     return mMarkedCCGeneration;
   }
 
   // XXX(nika): These feel like they should be inner window only, but they're
   // called on the outer window.
-  virtual nsIDOMScreen* GetScreen() = 0;
   virtual mozilla::dom::Navigator* GetNavigator() = 0;
   virtual mozilla::dom::Location* GetLocation() = 0;
 
   virtual nsresult GetPrompter(nsIPrompt** aPrompt) = 0;
   virtual nsresult GetControllers(nsIControllers** aControllers) = 0;
   virtual already_AddRefed<nsISelection> GetSelection() = 0;
   virtual already_AddRefed<nsPIDOMWindowOuter> GetOpener() = 0;
 
--- a/dom/base/nsScreen.cpp
+++ b/dom/base/nsScreen.cpp
@@ -45,17 +45,16 @@ nsScreen::nsScreen(nsPIDOMWindowInner* a
 
 nsScreen::~nsScreen()
 {
 }
 
 
 // QueryInterface implementation for nsScreen
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsScreen)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMScreen)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(nsScreen, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(nsScreen, DOMEventTargetHelper)
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(nsScreen,
                                    DOMEventTargetHelper,
                                    mScreenOrientation)
@@ -75,32 +74,16 @@ nsScreen::GetPixelDepth(ErrorResult& aRv
     return -1;
   }
 
   uint32_t depth;
   context->GetDepth(depth);
   return depth;
 }
 
-#define FORWARD_LONG_GETTER(_name)                                              \
-  NS_IMETHODIMP                                                                 \
-  nsScreen::Get ## _name(int32_t* aOut)                                         \
-  {                                                                             \
-    ErrorResult rv;                                                             \
-    *aOut = Get ## _name(rv);                                                   \
-    return rv.StealNSResult();                                                  \
-  }
-
-FORWARD_LONG_GETTER(AvailWidth)
-FORWARD_LONG_GETTER(AvailHeight)
-
-FORWARD_LONG_GETTER(Top)
-FORWARD_LONG_GETTER(AvailTop)
-FORWARD_LONG_GETTER(AvailLeft)
-
 nsPIDOMWindowOuter*
 nsScreen::GetOuter() const
 {
   if (nsPIDOMWindowInner* inner = GetOwner()) {
     return inner->GetOuterWindow();
   }
 
   return nullptr;
--- a/dom/base/nsScreen.h
+++ b/dom/base/nsScreen.h
@@ -5,32 +5,29 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef nsScreen_h___
 #define nsScreen_h___
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/ScreenOrientation.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/ErrorResult.h"
-#include "nsIDOMScreen.h"
 #include "nsCOMPtr.h"
 #include "nsRect.h"
 
 class nsDeviceContext;
 
 // Script "screen" object
 class nsScreen : public mozilla::DOMEventTargetHelper
-               , public nsIDOMScreen
 {
   typedef mozilla::ErrorResult ErrorResult;
 public:
   static already_AddRefed<nsScreen> Create(nsPIDOMWindowInner* aWindow);
 
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIDOMSCREEN
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsScreen, mozilla::DOMEventTargetHelper)
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(mozilla::DOMEventTargetHelper)
 
   nsPIDOMWindowInner* GetParentObject() const
   {
     return GetOwner();
   }
 
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -2184,16 +2184,17 @@ class PropertyDefiner:
         lastCondition = getCondition(array[0], self.descriptor)
 
         specs = []
         disablers = []
         prefableSpecs = []
 
         disablersTemplate = dedent(
             """
+            // Can't be const because the pref-enabled boolean needs to be writable
             static PrefableDisablers %s_disablers%d = {
               true, %s, %s, %s
             };
             """)
         prefableWithDisablersTemplate = '  { &%s_disablers%d, &%s_specs[%d] }'
         prefableWithoutDisablersTemplate = '  { nullptr, &%s_specs[%d] }'
         prefCacheTemplate = '&%s[%d].disablers->enabled'
 
@@ -2252,18 +2253,17 @@ class PropertyDefiner:
             static ${specType} ${name}_specs[] = {
             ${specs}
             };
             #if defined(__clang__)
             #pragma clang diagnostic pop
             #endif
 
             ${disablers}
-            // Can't be const because the pref-enabled boolean needs to be writable
-            static Prefable<${specType}> ${name}[] = {
+            static const Prefable<${specType}> ${name}[] = {
             ${prefableSpecs}
             };
 
             """,
             specType=specType,
             name=name,
             disablers='\n'.join(disablers),
             specs=',\n'.join(specs),
--- a/dom/interfaces/base/domstubs.idl
+++ b/dom/interfaces/base/domstubs.idl
@@ -29,17 +29,16 @@ namespace dom {
 class DOMException;
 }
 }
 %}
 
 // Base
 interface nsIDOMWindow;
 interface nsIDOMWindowCollection;
-interface nsIDOMScreen;
 
 // Events
 interface nsIDOMEvent;
 interface nsIDOMEventTarget;
 interface nsIDOMEventListener;
 
 // HTML
 interface nsIDOMHTMLHeadElement;
--- a/dom/interfaces/base/moz.build
+++ b/dom/interfaces/base/moz.build
@@ -12,17 +12,16 @@ XPIDL_SOURCES += [
     'nsIBrowser.idl',
     'nsIBrowserDOMWindow.idl',
     'nsIContentPermissionPrompt.idl',
     'nsIContentPrefService2.idl',
     'nsIContentProcess.idl',
     'nsIContentURIGrouper.idl',
     'nsIDOMChromeWindow.idl',
     'nsIDOMGlobalPropertyInitializer.idl',
-    'nsIDOMScreen.idl',
     'nsIDOMWindow.idl',
     'nsIDOMWindowCollection.idl',
     'nsIDOMWindowUtils.idl',
     'nsIFocusManager.idl',
     'nsIIdleObserver.idl',
     'nsIQueryContentEventResult.idl',
     'nsIRemoteBrowser.idl',
     'nsIServiceWorkerManager.idl',
deleted file mode 100644
--- a/dom/interfaces/base/nsIDOMScreen.idl
+++ /dev/null
@@ -1,16 +0,0 @@
-/* -*- Mode: IDL; 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/. */
-
-#include "nsIDOMEventTarget.idl"
-
-[builtinclass, uuid(82c7924b-4b46-4e5a-a8d2-6edb5fc0a60d)]
-interface nsIDOMScreen : nsIDOMEventTarget
-{
-  readonly attribute long             top;
-  readonly attribute long             availWidth;
-  readonly attribute long             availHeight;
-  readonly attribute long             availLeft;
-  readonly attribute long             availTop;
-};
--- a/editor/spellchecker/TextServicesDocument.cpp
+++ b/editor/spellchecker/TextServicesDocument.cpp
@@ -26,17 +26,16 @@
 #include "nsIPlaintextEditor.h"         // for nsIPlaintextEditor
 #include "nsISelection.h"               // for nsISelection
 #include "nsISelectionController.h"     // for nsISelectionController, etc
 #include "nsISupportsBase.h"            // for nsISupports
 #include "nsISupportsUtils.h"           // for NS_IF_ADDREF, NS_ADDREF, etc
 #include "nsITextServicesFilter.h"      // for nsITextServicesFilter
 #include "mozilla/intl/WordBreaker.h"   // for WordRange, WordBreaker
 #include "nsRange.h"                    // for nsRange
-#include "nsStaticAtom.h"               // for NS_STATIC_ATOM_SETUP, etc
 #include "nsString.h"                   // for nsString, nsAutoString
 #include "nscore.h"                     // for nsresult, NS_IMETHODIMP, etc
 
 #define LOCK_DOC(doc)
 #define UNLOCK_DOC(doc)
 
 namespace mozilla {
 
--- a/layout/style/nsCSSAnonBoxes.cpp
+++ b/layout/style/nsCSSAnonBoxes.cpp
@@ -4,76 +4,73 @@
  * 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/. */
 
 /* atom list for CSS anonymous boxes */
 
 #include "mozilla/ArrayUtils.h"
 
 #include "nsCSSAnonBoxes.h"
-#include "nsStaticAtom.h"
 
 using namespace mozilla;
 
 namespace mozilla {
 namespace detail {
 
 MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
 extern constexpr CSSAnonBoxAtoms gCSSAnonBoxAtoms = {
   #define CSS_ANON_BOX(name_, value_) \
     NS_STATIC_ATOM_INIT_STRING(value_)
   #include "nsCSSAnonBoxList.h"
   #undef CSS_ANON_BOX
-
-  #define CSS_ANON_BOX(name_, value_) \
-    NS_STATIC_ATOM_INIT_ATOM(CSSAnonBoxAtoms, name_, value_)
-  #include "nsCSSAnonBoxList.h"
-  #undef CSS_ANON_BOX
+  {
+    #define CSS_ANON_BOX(name_, value_) \
+      NS_STATIC_ATOM_INIT_ATOM( \
+        nsICSSAnonBoxPseudo, CSSAnonBoxAtoms, name_, value_)
+    #include "nsCSSAnonBoxList.h"
+    #undef CSS_ANON_BOX
+  }
 };
 MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
 
 } // namespace detail
 } // namespace mozilla
 
+// Non-inheriting boxes must come first in nsCSSAnonBoxList.h so that
+// `NonInheriting` values can index into this array and other similar arrays.
+const nsStaticAtom* const nsCSSAnonBoxes::sAtoms =
+  mozilla::detail::gCSSAnonBoxAtoms.mAtoms;
+
 #define CSS_ANON_BOX(name_, value_) \
-  NS_STATIC_ATOM_SUBCLASS_DEFN_PTR(nsICSSAnonBoxPseudo, nsCSSAnonBoxes, name_)
+  NS_STATIC_ATOM_DEFN_PTR( \
+    nsICSSAnonBoxPseudo, mozilla::detail::CSSAnonBoxAtoms, \
+    mozilla::detail::gCSSAnonBoxAtoms, nsCSSAnonBoxes, name_)
 #include "nsCSSAnonBoxList.h"
 #undef CSS_ANON_BOX
 
-static const nsStaticAtomSetup sCSSAnonBoxAtomSetup[] = {
-  // Non-inheriting boxes must come first in nsCSSAnonBoxList.h so that
-  // `NonInheriting` values can index into this array and other similar arrays.
-  #define CSS_ANON_BOX(name_, value_) \
-    NS_STATIC_ATOM_SUBCLASS_SETUP( \
-      mozilla::detail::gCSSAnonBoxAtoms, nsCSSAnonBoxes, name_)
-  #include "nsCSSAnonBoxList.h"
-  #undef CSS_ANON_BOX
-};
-
 void nsCSSAnonBoxes::RegisterStaticAtoms()
 {
-  NS_RegisterStaticAtoms(sCSSAnonBoxAtomSetup);
+  NS_RegisterStaticAtoms(sAtoms, sAtomsLen);
 }
 
 bool nsCSSAnonBoxes::IsAnonBox(nsAtom *aAtom)
 {
-  return nsStaticAtomUtils::IsMember(aAtom, sCSSAnonBoxAtomSetup);
+  return nsStaticAtomUtils::IsMember(aAtom, sAtoms, sAtomsLen);
 }
 
 #ifdef MOZ_XUL
 /* static */ bool
 nsCSSAnonBoxes::IsTreePseudoElement(nsAtom* aPseudo)
 {
   MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(aPseudo));
   return StringBeginsWith(nsDependentAtomString(aPseudo),
                           NS_LITERAL_STRING(":-moz-tree-"));
 }
 #endif
 
 /* static*/ nsCSSAnonBoxes::NonInheriting
 nsCSSAnonBoxes::NonInheritingTypeForPseudoTag(nsAtom* aPseudo)
 {
   MOZ_ASSERT(IsNonInheritingAnonBox(aPseudo));
-  Maybe<uint32_t> index =
-    nsStaticAtomUtils::Lookup(aPseudo, sCSSAnonBoxAtomSetup);
+  Maybe<uint32_t> index = nsStaticAtomUtils::Lookup(aPseudo, sAtoms, sAtomsLen);
   MOZ_RELEASE_ASSERT(index.isSome());
   return static_cast<NonInheriting>(*index);
 }
--- a/layout/style/nsCSSAnonBoxes.h
+++ b/layout/style/nsCSSAnonBoxes.h
@@ -7,32 +7,45 @@
 /* atom list for CSS anonymous boxes */
 
 #ifndef nsCSSAnonBoxes_h___
 #define nsCSSAnonBoxes_h___
 
 #include "nsAtom.h"
 #include "nsStaticAtom.h"
 
-// Empty class derived from nsAtom so that function signatures can
-// require an atom from this atom list.
-class nsICSSAnonBoxPseudo : public nsAtom {};
+// Trivial subclass of nsStaticAtom so that function signatures can require an
+// atom from this atom list.
+class nsICSSAnonBoxPseudo : public nsStaticAtom
+{
+public:
+  constexpr nsICSSAnonBoxPseudo(const char16_t* aStr, uint32_t aLength,
+                                uint32_t aStringOffset)
+    : nsStaticAtom(aStr, aLength, aStringOffset)
+  {}
+};
 
 namespace mozilla {
 namespace detail {
 
 struct CSSAnonBoxAtoms
 {
   #define CSS_ANON_BOX(name_, value_) NS_STATIC_ATOM_DECL_STRING(name_, value_)
   #include "nsCSSAnonBoxList.h"
   #undef CSS_ANON_BOX
 
-  #define CSS_ANON_BOX(name_, value_) NS_STATIC_ATOM_DECL_ATOM(name_)
-  #include "nsCSSAnonBoxList.h"
-  #undef CSS_ANON_BOX
+  enum class Atoms {
+    #define CSS_ANON_BOX(name_, value_) \
+      NS_STATIC_ATOM_ENUM(name_)
+    #include "nsCSSAnonBoxList.h"
+    #undef CSS_ANON_BOX
+    AtomsCount
+  };
+
+  const nsICSSAnonBoxPseudo mAtoms[static_cast<size_t>(Atoms::AtomsCount)];
 };
 
 extern const CSSAnonBoxAtoms gCSSAnonBoxAtoms;
 
 } // namespace detail
 } // namespace mozilla
 
 class nsCSSAnonBoxes {
@@ -45,20 +58,26 @@ public:
   static bool IsTreePseudoElement(nsAtom* aPseudo);
 #endif
   static bool IsNonElement(nsAtom* aPseudo)
   {
     return aPseudo == mozText || aPseudo == oofPlaceholder ||
            aPseudo == firstLetterContinuation;
   }
 
-#define CSS_ANON_BOX(name_, value_) \
-  NS_STATIC_ATOM_SUBCLASS_DECL_PTR(nsICSSAnonBoxPseudo, name_)
-#include "nsCSSAnonBoxList.h"
-#undef CSS_ANON_BOX
+private:
+  static const nsStaticAtom* const sAtoms;
+  static constexpr size_t sAtomsLen =
+    mozilla::ArrayLength(mozilla::detail::gCSSAnonBoxAtoms.mAtoms);
+
+public:
+  #define CSS_ANON_BOX(name_, value_) \
+    NS_STATIC_ATOM_DECL_PTR(nsICSSAnonBoxPseudo, name_)
+  #include "nsCSSAnonBoxList.h"
+  #undef CSS_ANON_BOX
 
   typedef uint8_t NonInheritingBase;
   enum class NonInheriting : NonInheritingBase {
 #define CSS_ANON_BOX(_name, _value) /* nothing */
 #define CSS_NON_INHERITING_ANON_BOX(_name, _value) _name,
 #include "nsCSSAnonBoxList.h"
 #undef CSS_NON_INHERITING_ANON_BOX
 #undef CSS_ANON_BOX
--- a/layout/style/nsCSSPseudoElements.cpp
+++ b/layout/style/nsCSSPseudoElements.cpp
@@ -5,76 +5,70 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* atom list for CSS pseudo-elements */
 
 #include "nsCSSPseudoElements.h"
 
 #include "mozilla/ArrayUtils.h"
 
-#include "nsStaticAtom.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsDOMString.h"
 
 using namespace mozilla;
 
 namespace mozilla {
 namespace detail {
 
 MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
 extern constexpr CSSPseudoElementAtoms gCSSPseudoElementAtoms = {
   #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
     NS_STATIC_ATOM_INIT_STRING(value_)
   #include "nsCSSPseudoElementList.h"
   #undef CSS_PSEUDO_ELEMENT
-
-  #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
-    NS_STATIC_ATOM_INIT_ATOM(CSSPseudoElementAtoms, name_, value_)
-  #include "nsCSSPseudoElementList.h"
-  #undef CSS_PSEUDO_ELEMENT
+  {
+    #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
+      NS_STATIC_ATOM_INIT_ATOM( \
+        nsICSSPseudoElement, CSSPseudoElementAtoms, name_, value_)
+    #include "nsCSSPseudoElementList.h"
+    #undef CSS_PSEUDO_ELEMENT
+  }
 };
 MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
 
 } // namespace detail
 } // namespace mozilla
 
+const nsStaticAtom* const nsCSSPseudoElements::sAtoms =
+  mozilla::detail::gCSSPseudoElementAtoms.mAtoms;
+
 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
-  NS_STATIC_ATOM_SUBCLASS_DEFN_PTR( \
-    nsICSSPseudoElement, nsCSSPseudoElements, name_)
+  NS_STATIC_ATOM_DEFN_PTR( \
+    nsICSSPseudoElement, mozilla::detail::CSSPseudoElementAtoms, \
+    mozilla::detail::gCSSPseudoElementAtoms, nsCSSPseudoElements, name_);
 #include "nsCSSPseudoElementList.h"
 #undef CSS_PSEUDO_ELEMENT
 
-// Array of nsStaticAtomSetup for each of the pseudo-elements.
-static const nsStaticAtomSetup sCSSPseudoElementAtomSetup[] = {
-  #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
-    NS_STATIC_ATOM_SUBCLASS_SETUP( \
-      detail::gCSSPseudoElementAtoms, nsCSSPseudoElements, name_)
-  #include "nsCSSPseudoElementList.h"
-  #undef CSS_PSEUDO_ELEMENT
-};
-
-// Flags data for each of the pseudo-elements, which must be separate
-// from the previous array since there's no place for it in
-// nsStaticAtomSetup.
+// Flags data for each of the pseudo-elements.
 /* static */ const uint32_t
 nsCSSPseudoElements::kPseudoElementFlags[] = {
 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
   flags_,
 #include "nsCSSPseudoElementList.h"
 #undef CSS_PSEUDO_ELEMENT
 };
 
 void nsCSSPseudoElements::RegisterStaticAtoms()
 {
-  NS_RegisterStaticAtoms(sCSSPseudoElementAtomSetup);
+  NS_RegisterStaticAtoms(sAtoms, sAtomsLen);
 }
 
 bool nsCSSPseudoElements::IsPseudoElement(nsAtom *aAtom)
 {
-  return nsStaticAtomUtils::IsMember(aAtom, sCSSPseudoElementAtomSetup);
+  return nsStaticAtomUtils::IsMember(aAtom, sAtoms, sAtomsLen);
 }
 
 /* static */ bool
 nsCSSPseudoElements::IsCSS2PseudoElement(nsAtom *aAtom)
 {
   // We don't implement this using PseudoElementHasFlags because callers
   // want to pass things that could be anon boxes.
   NS_ASSERTION(nsCSSPseudoElements::IsPseudoElement(aAtom) ||
@@ -90,18 +84,17 @@ nsCSSPseudoElements::IsCSS2PseudoElement
                    CSS_PSEUDO_ELEMENT_IS_CSS2),
                "result doesn't match flags");
   return result;
 }
 
 /* static */ CSSPseudoElementType
 nsCSSPseudoElements::GetPseudoType(nsAtom *aAtom, EnabledState aEnabledState)
 {
-  Maybe<uint32_t> index =
-    nsStaticAtomUtils::Lookup(aAtom, sCSSPseudoElementAtomSetup);
+  Maybe<uint32_t> index = nsStaticAtomUtils::Lookup(aAtom, sAtoms, sAtomsLen);
   if (index.isSome()) {
     auto type = static_cast<Type>(*index);
     // ::moz-placeholder is an alias for ::placeholder
     if (type == CSSPseudoElementType::mozPlaceholder) {
       type = CSSPseudoElementType::placeholder;
     }
     return IsEnabled(type, aEnabledState) ? type : Type::NotPseudo;
   }
@@ -121,19 +114,19 @@ nsCSSPseudoElements::GetPseudoType(nsAto
   }
 
   return Type::NotPseudo;
 }
 
 /* static */ nsAtom*
 nsCSSPseudoElements::GetPseudoAtom(Type aType)
 {
-  NS_ASSERTION(aType < Type::Count, "Unexpected type");
-  return *sCSSPseudoElementAtomSetup[
-    static_cast<CSSPseudoElementTypeBase>(aType)].mAtomp;
+  MOZ_ASSERT(aType < Type::Count, "Unexpected type");
+  return const_cast<nsStaticAtom*>(
+    &sAtoms[static_cast<CSSPseudoElementTypeBase>(aType)]);
 }
 
 /* static */ already_AddRefed<nsAtom>
 nsCSSPseudoElements::GetPseudoAtom(const nsAString& aPseudoElement)
 {
   if (DOMStringIsNull(aPseudoElement) || aPseudoElement.IsEmpty() ||
       aPseudoElement.First() != char16_t(':')) {
     return nullptr;
--- a/layout/style/nsCSSPseudoElements.h
+++ b/layout/style/nsCSSPseudoElements.h
@@ -51,16 +51,27 @@
 // Can we use the ChromeOnly document.createElement(..., { pseudo: "::foo" })
 // API for creating pseudo-implementing native anonymous content in JS with this
 // pseudo-element?
 #define CSS_PSEUDO_ELEMENT_IS_JS_CREATED_NAC           (1<<6)
 // Does this pseudo-element act like an item for containers (such as flex and
 // grid containers) and thus needs parent display-based style fixup?
 #define CSS_PSEUDO_ELEMENT_IS_FLEX_OR_GRID_ITEM        (1<<7)
 
+// Trivial subclass of nsStaticAtom so that function signatures can require an
+// atom from this atom list.
+class nsICSSPseudoElement : public nsStaticAtom
+{
+public:
+  constexpr nsICSSPseudoElement(const char16_t* aStr, uint32_t aLength,
+                                uint32_t aStringOffset)
+    : nsStaticAtom(aStr, aLength, aStringOffset)
+  {}
+};
+
 namespace mozilla {
 
 // The total count of CSSPseudoElement is less than 256,
 // so use uint8_t as its underlying type.
 typedef uint8_t CSSPseudoElementTypeBase;
 enum class CSSPseudoElementType : CSSPseudoElementTypeBase {
   // If the actual pseudo-elements stop being first here, change
   // GetPseudoType.
@@ -83,32 +94,33 @@ namespace detail {
 
 struct CSSPseudoElementAtoms
 {
   #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
     NS_STATIC_ATOM_DECL_STRING(name_, value_)
   #include "nsCSSPseudoElementList.h"
   #undef CSS_PSEUDO_ELEMENT
 
-  #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
-    NS_STATIC_ATOM_DECL_ATOM(name_)
-  #include "nsCSSPseudoElementList.h"
-  #undef CSS_PSEUDO_ELEMENT
+  enum class Atoms {
+    #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
+      NS_STATIC_ATOM_ENUM(name_)
+    #include "nsCSSPseudoElementList.h"
+    #undef CSS_PSEUDO_ELEMENT
+    AtomsCount
+  };
+
+  const nsICSSPseudoElement mAtoms[static_cast<size_t>(Atoms::AtomsCount)];
 };
 
 extern const CSSPseudoElementAtoms gCSSPseudoElementAtoms;
 
 } // namespace detail
 
 } // namespace mozilla
 
-// Empty class derived from nsAtom so that function signatures can
-// require an atom from this atom list.
-class nsICSSPseudoElement : public nsAtom {};
-
 class nsCSSPseudoElements
 {
   typedef mozilla::CSSPseudoElementType Type;
   typedef mozilla::CSSEnabledState EnabledState;
 
 public:
   static void RegisterStaticAtoms();
 
@@ -119,20 +131,26 @@ public:
   // This must match EAGER_PSEUDO_COUNT in Rust code.
   static const size_t kEagerPseudoCount = 4;
 
   static bool IsEagerlyCascadedInServo(const Type aType)
   {
     return PseudoElementHasFlags(aType, CSS_PSEUDO_ELEMENT_IS_CSS2);
   }
 
-#define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
-  NS_STATIC_ATOM_SUBCLASS_DECL_PTR(nsICSSPseudoElement, name_)
-#include "nsCSSPseudoElementList.h"
-#undef CSS_PSEUDO_ELEMENT
+private:
+  static const nsStaticAtom* const sAtoms;
+  static constexpr size_t sAtomsLen =
+    mozilla::ArrayLength(mozilla::detail::gCSSPseudoElementAtoms.mAtoms);
+
+public:
+  #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
+    NS_STATIC_ATOM_DECL_PTR(nsICSSPseudoElement, name_);
+  #include "nsCSSPseudoElementList.h"
+  #undef CSS_PSEUDO_ELEMENT
 
   static Type GetPseudoType(nsAtom* aAtom, EnabledState aEnabledState);
 
   // Get the atom for a given Type. aType must be < CSSPseudoElementType::Count.
   // This only ever returns static atoms, so it's fine to return a raw pointer.
   static nsAtom* GetPseudoAtom(Type aType);
 
   // Get the atom for a given pseudo-element string (e.g. "::before").  This can
--- a/layout/xul/nsMenuPopupFrame.cpp
+++ b/layout/xul/nsMenuPopupFrame.cpp
@@ -14,17 +14,16 @@
 #include "nsNameSpaceManager.h"
 #include "nsViewManager.h"
 #include "nsWidgetsCID.h"
 #include "nsMenuFrame.h"
 #include "nsMenuBarFrame.h"
 #include "nsPopupSetFrame.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMEvent.h"
-#include "nsIDOMScreen.h"
 #include "nsIDOMXULMenuListElement.h"
 #include "nsIPresShell.h"
 #include "nsFrameManager.h"
 #include "nsIDocument.h"
 #include "nsRect.h"
 #include "nsIComponentManager.h"
 #include "nsBoxLayoutState.h"
 #include "nsIScrollableFrame.h"
--- a/parser/htmlparser/nsHTMLTags.cpp
+++ b/parser/htmlparser/nsHTMLTags.cpp
@@ -3,17 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsHTMLTags.h"
 #include "nsCRT.h"
 #include "nsDataHashtable.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
-#include "nsStaticAtom.h"
 #include "nsUnicharUtils.h"
 #include "mozilla/HashFunctions.h"
 #include <algorithm>
 
 using namespace mozilla;
 
 // static array of unicode tag names
 #define HTML_TAG(_tag, _classname, _interfacename) (u"" #_tag),
--- a/parser/htmlparser/nsHTMLTags.h
+++ b/parser/htmlparser/nsHTMLTags.h
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsHTMLTags_h___
 #define nsHTMLTags_h___
 
-#include "nsStaticAtom.h"
 #include "nsString.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 
 /*
    Declare the enum list using the magic of preprocessing
    enum values are "eHTMLTag_foo" (where foo is the tag)
 
--- a/xpcom/ds/nsAtomTable.cpp
+++ b/xpcom/ds/nsAtomTable.cpp
@@ -274,17 +274,17 @@ class nsAtomTable
 public:
   nsAtomSubTable& SelectSubTable(AtomTableKey& aKey);
   void AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, AtomsSizes& aSizes);
   void GC(GCKind aKind);
   already_AddRefed<nsAtom> Atomize(const nsAString& aUTF16String);
   already_AddRefed<nsAtom> Atomize(const nsACString& aUTF8String);
   already_AddRefed<nsAtom> AtomizeMainThread(const nsAString& aUTF16String);
   nsStaticAtom* GetStaticAtom(const nsAString& aUTF16String);
-  void RegisterStaticAtoms(const nsStaticAtomSetup* aSetup, uint32_t aCount);
+  void RegisterStaticAtoms(const nsStaticAtom* aAtoms, size_t aAtomsLen);
 
   // The result of this function may be imprecise if other threads are operating
   // on atoms concurrently. It's also slow, since it triggers a GC before
   // counting.
   size_t RacySlowCount();
 
   // This hash table op is a static member of this class so that it can take
   // advantage of |friend| declarations.
@@ -642,26 +642,23 @@ nsAtomSubTable::AddSizeOfExcludingThisLo
   aSizes.mTable += mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
   for (auto iter = mTable.Iter(); !iter.Done(); iter.Next()) {
     auto entry = static_cast<AtomTableEntry*>(iter.Get());
     entry->mAtom->AddSizeOfIncludingThis(aMallocSizeOf, aSizes);
   }
 }
 
 void
-nsAtomTable::RegisterStaticAtoms(const nsStaticAtomSetup* aSetup,
-                                 uint32_t aCount)
+nsAtomTable::RegisterStaticAtoms(const nsStaticAtom* aAtoms, size_t aAtomsLen)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(!gStaticAtomsDone, "Static atom insertion is finished!");
 
-  for (uint32_t i = 0; i < aCount; ++i) {
-    const nsStaticAtom* atom = aSetup[i].mAtom;
-    nsStaticAtom** atomp = aSetup[i].mAtomp;
-
+  for (uint32_t i = 0; i < aAtomsLen; ++i) {
+    const nsStaticAtom* atom = &aAtoms[i];
     MOZ_ASSERT(nsCRT::IsAscii(atom->String()));
     MOZ_ASSERT(NS_strlen(atom->String()) == atom->GetLength());
 
     AtomTableKey key(atom);
     nsAtomSubTable& table = SelectSubTable(key);
     MutexAutoLock lock(table.mLock);
     AtomTableEntry* he = table.Add(key);
 
@@ -671,25 +668,25 @@ nsAtomTable::RegisterStaticAtoms(const n
       // - Create a dynamic atom and then register a static atom with the same
       //   string while the dynamic atom is alive.
       // Both cases can cause subtle bugs, and are disallowed. We're
       // programming in C++ here, not Smalltalk.
       nsAutoCString name;
       he->mAtom->ToUTF8String(name);
       MOZ_CRASH_UNSAFE_PRINTF("Atom for '%s' already exists", name.get());
     }
-    he->mAtom = *atomp = const_cast<nsStaticAtom*>(atom);
+    he->mAtom = const_cast<nsStaticAtom*>(atom);
   }
 }
 
 void
-RegisterStaticAtoms(const nsStaticAtomSetup* aSetup, uint32_t aCount)
+NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, size_t aAtomsLen)
 {
   MOZ_ASSERT(gAtomTable);
-  gAtomTable->RegisterStaticAtoms(aSetup, aCount);
+  gAtomTable->RegisterStaticAtoms(aAtoms, aAtomsLen);
 }
 
 already_AddRefed<nsAtom>
 NS_Atomize(const char* aUTF8String)
 {
   MOZ_ASSERT(gAtomTable);
   return gAtomTable->Atomize(nsDependentCString(aUTF8String));
 }
--- a/xpcom/ds/nsGkAtoms.cpp
+++ b/xpcom/ds/nsGkAtoms.cpp
@@ -9,35 +9,34 @@
 namespace mozilla {
 namespace detail {
 
 MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
 extern constexpr GkAtoms gGkAtoms = {
   #define GK_ATOM(name_, value_) NS_STATIC_ATOM_INIT_STRING(value_)
   #include "nsGkAtomList.h"
   #undef GK_ATOM
-
-  #define GK_ATOM(name_, value_) \
-    NS_STATIC_ATOM_INIT_ATOM(GkAtoms, name_, value_)
-  #include "nsGkAtomList.h"
-  #undef GK_ATOM
+  {
+    #define GK_ATOM(name_, value_) \
+      NS_STATIC_ATOM_INIT_ATOM(nsStaticAtom, GkAtoms, name_, value_)
+    #include "nsGkAtomList.h"
+    #undef GK_ATOM
+  }
 };
 MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
 
 } // namespace detail
 } // namespace mozilla
 
-#define GK_ATOM(name_, value_) NS_STATIC_ATOM_DEFN_PTR(nsGkAtoms, name_)
+const nsStaticAtom* const nsGkAtoms::sAtoms = mozilla::detail::gGkAtoms.mAtoms;
+
+#define GK_ATOM(name_, value_) \
+  NS_STATIC_ATOM_DEFN_PTR( \
+    nsStaticAtom, mozilla::detail::GkAtoms, mozilla::detail::gGkAtoms, \
+    nsGkAtoms, name_)
 #include "nsGkAtomList.h"
 #undef GK_ATOM
 
-static const nsStaticAtomSetup sGkAtomSetup[] = {
-  #define GK_ATOM(name_, value_) \
-    NS_STATIC_ATOM_SETUP(mozilla::detail::gGkAtoms, nsGkAtoms, name_)
-  #include "nsGkAtomList.h"
-  #undef GK_ATOM
-};
-
 void nsGkAtoms::RegisterStaticAtoms()
 {
-  NS_RegisterStaticAtoms(sGkAtomSetup);
+  NS_RegisterStaticAtoms(sAtoms, sAtomsLen);
 }
 
--- a/xpcom/ds/nsGkAtoms.h
+++ b/xpcom/ds/nsGkAtoms.h
@@ -14,29 +14,39 @@ namespace mozilla {
 namespace detail {
 
 struct GkAtoms
 {
   #define GK_ATOM(name_, value_) NS_STATIC_ATOM_DECL_STRING(name_, value_)
   #include "nsGkAtomList.h"
   #undef GK_ATOM
 
-  #define GK_ATOM(name_, value_) NS_STATIC_ATOM_DECL_ATOM(name_)
-  #include "nsGkAtomList.h"
-  #undef GK_ATOM
+  enum class Atoms {
+    #define GK_ATOM(name_, value_) NS_STATIC_ATOM_ENUM(name_)
+    #include "nsGkAtomList.h"
+    #undef GK_ATOM
+    AtomsCount
+  };
+
+  const nsStaticAtom mAtoms[static_cast<size_t>(Atoms::AtomsCount)];
 };
 
 extern const GkAtoms gGkAtoms;
 
 } // namespace detail
 } // namespace mozilla
 
 class nsGkAtoms
 {
+private:
+  static const nsStaticAtom* const sAtoms;
+  static constexpr size_t sAtomsLen =
+    mozilla::ArrayLength(mozilla::detail::gGkAtoms.mAtoms);
+
 public:
   static void RegisterStaticAtoms();
 
-  #define GK_ATOM(name_, value_) NS_STATIC_ATOM_DECL_PTR(name_)
+  #define GK_ATOM(name_, value_) NS_STATIC_ATOM_DECL_PTR(nsStaticAtom, name_)
   #include "nsGkAtomList.h"
   #undef GK_ATOM
 };
 
 #endif /* nsGkAtoms_h___ */
--- a/xpcom/ds/nsStaticAtom.h
+++ b/xpcom/ds/nsStaticAtom.h
@@ -4,245 +4,259 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsStaticAtom_h__
 #define nsStaticAtom_h__
 
 #include <stdint.h>
 #include "nsAtom.h"
+#include "mozilla/ArrayUtils.h"
 #include "mozilla/Maybe.h"
 
-// The following macros are used to define static atoms, typically in
-// conjunction with a .h file that defines the names and values of the atoms.
+// Static atoms are structured carefully to satisfy a lot of constraints.
+//
+// - We have ~2700 static atoms. They are divided across ~4 classes, with the
+//   majority in nsGkAtoms.
+//
+// - We want them to be constexpr so they end up in .rodata, and thus shared
+//   between processes, minimizing memory usage.
+//
+// - We need them to be in an array, so we can iterate over them (for
+//   registration and lookups).
+//
+// - Each static atom has a string literal associated with it. We can't use a
+//   pointer to the string literal because then the atoms won't end up in
+//   .rodata. Therefore the string literals and the atoms must be arranged in a
+//   way such that a numeric index can be used instead. This numeric index
+//   (nsStaticAtom::mStringOffset) must be computable at compile-time to keep
+//   the static atom constexpr. It should also not be too large (a uint32_t is
+//   reasonable).
+//
+// - Each static atom stores the hash value of its associated string literal;
+//   it's used in various ways. The hash value must be computed at
+//   compile-time, to keep the static atom constexpr.
+//
+// - As well as accessing each static atom via array indexing, we need an
+//   individual pointer, e.g. nsGkAtoms::foo. Ideally this would be constexpr
+//   so it doesn't take up any space in memory. Unfortunately MSVC's constexpr
+//   support is buggy and so this isn't possible yet. See bug 1449787.
+//
+// - The array of static atoms can't be in a .h file, because it's a huge
+//   constexpr expression, which would blow out compile times. But the
+//   individual pointers for the static atoms must be in a .h file so they are
+//   public.
+//
+// The macros below are used to define static atoms in a way that satisfies
+// these constraints. They are used in conjunction with a .h file that defines
+// the names and values of the atoms.
 //
 // For example, the .h file might be called MyAtomList.h and look like this:
 //
 //   MY_ATOM(one, "one")
 //   MY_ATOM(two, "two")
 //   MY_ATOM(three, "three")
 //
-// The code defining the static atoms should look something like this:
-//
-//   ====> MyAtoms.h <====
-//
-//   namespace detail {
-//
-//   struct MyAtoms
-//   {
-//     #define MY_ATOM(name_, value_) NS_STATIC_ATOM_DECL_STRING(name_, value_)
-//     #include "MyAtomList.h"
-//     #undef MY_ATOM
-//
-//     #define MY_ATOM(name_, value_) NS_STATIC_ATOM_DECL_ATOM(name_)
-//     #include "MyAtomList.h"
-//     #undef MY_ATOM
-//   };
-//
-//   extern const MyAtoms gMyAtoms;
-//
-//   } // namespace detail
-//
-//   class nsMyAtoms
-//   {
-//   public:
-//     #define MY_ATOM(name_, value_) NS_STATIC_ATOM_DECL_PTR(name_)
-//     #include "MyAtomList.h"
-//     #undef MY_ATOM
-//   };
-//
-//   ====> MyAtoms.cpp <====
-//
-//   MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
-//   static constexpr MyAtoms gMyAtoms = {
-//     #define MY_ATOM(name_, value_) NS_STATIC_ATOM_INIT_STRING(value_)
-//     #include "MyAtomList.h"
-//     #undef MY_ATOM
-//
-//     #define MY_ATOM(name_, value_) NS_STATIC_ATOM_INIT_ATOM(MyAtoms, name_, value_)
-//     #include "MyAtomList.h"
-//     #undef MY_ATOM
-//   };
-//   MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
-//
-//   #define MY_ATOM(name_, value_) NS_STATIC_ATOM_DEFN_PTR(nsMyAtoms, name_)
-//   #include "MyAtomList.h"
-//   #undef MY_ATOM
-//
-//   static const nsStaticAtomSetup sMyAtomSetup[] = {
-//     #define MY_ATOM(name_, value_) NS_STATIC_ATOM_SETUP(mozilla::detail::gMyAtoms, nsMyAtoms, name_)
-//     #include "MyAtomList.h"
-//     #undef MY_ATOM
-//   };
-//
-// The macros expand to the following:
+// The code defining the static atoms should look something like the following.
+// ("<<<"/"---"/">>>" markers are used below to indicate what the macros look
+// like before and after expansion.)
 //
 //   ====> MyAtoms.h <====
 //
 //   // A `detail` namespace is used because the things within it aren't
 //   // directly referenced by external users of these static atoms.
 //   namespace detail {
 //
 //   // This `detail` class contains the atom strings and the atom objects.
 //   // Because they are together in a class, the mStringOffset field of the
 //   // atoms will be small and can be initialized at compile time.
 //   struct MyAtoms
 //   {
+//     <<<
+//     #define MY_ATOM(name_, value_) NS_STATIC_ATOM_DECL_STRING(name_, value_)
+//     #include "MyAtomList.h"
+//     #undef MY_ATOM
+//     ---
 //     const char16_t one_string[4];
 //     const char16_t two_string[4];
 //     const char16_t three_string[6];
+//     >>>
 //
-//     const nsStaticAtom one_atom;
-//     const nsStaticAtom two_atom;
-//     const nsStaticAtom three_atom;
+//     enum class Atoms {
+//       <<<
+//       #define MY_ATOM(name_, value_) NS_STATIC_ATOM_ENUM(name_)
+//       #include "MyAtomList.h"
+//       #undef MY_ATOM
+//       ---
+//       one,
+//       two,
+//       three,
+//       >>>
+//       AtomsCount
+//     };
+//
+//     const nsStaticAtom mAtoms[static_cast<size_t>(Atoms::AtomsCount)];
 //   };
 //
+//   // The MyAtoms instance is `extern const` so it can be defined in a .cpp
+//   // file.
 //   extern const MyAtoms gMyAtoms;
 //
 //   } // namespace detail
 //
 //   // This class holds the pointers to the individual atoms.
 //   class nsMyAtoms
 //   {
+//   private:
+//     // This is a useful handle to the array of atoms, used below and also
+//     // possibly by Rust code.
+//     static const nsStaticAtom* const sAtoms;
+//
+//     // The number of atoms, used below.
+//     static constexpr size_t sAtomsLen =
+//       mozilla::ArrayLength(detail::gMyAtoms.mAtoms);
+//
 //   public:
+//     // The type is not `nsStaticAtom* const` -- even though these atoms are
+//     // immutable -- because they are often passed to functions with
+//     // `nsAtom*` parameters, i.e. that can be passed both dynamic and
+//     // static.
+//     <<<
+//     #define MY_ATOM(name_, value_) NS_STATIC_ATOM_DECL_PTR(nsStaticAtom, name_)
+//     #include "MyAtomList.h"
+//     #undef MY_ATOM
+//     ---
 //     static nsStaticAtom* one;
 //     static nsStaticAtom* two;
 //     static nsStaticAtom* three;
+//     >>>
 //   };
 //
 //   ====> MyAtoms.cpp <====
 //
+//   namespace detail {
+//
 //   // Need to suppress some MSVC warning weirdness with WrappingMultiply().
 //   MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
 //   // Because this is `constexpr` it ends up in read-only memory where it can
 //   // be shared between processes.
-//   extern constexpr MyAtoms gMyAtoms = {
+//   static constexpr MyAtoms gMyAtoms = {
+//     <<<
+//     #define MY_ATOM(name_, value_) NS_STATIC_ATOM_INIT_STRING(value_)
+//     #include "MyAtomList.h"
+//     #undef MY_ATOM
+//     ---
 //     u"one",
 //     u"two",
 //     u"three",
-//
-//     nsStaticAtom(u"one", 3, offsetof(MyAtoms, one_atom) -
-//                             offsetof(MyAtoms, one_string)),
-//     nsStaticAtom(u"two", 3, offsetof(MyAtoms, two_atom) -
-//                             offsetof(MyAtoms, two_string)),
-//     nsStaticAtom(u"three", 3, offsetof(MyAtoms, three_atom) -
-//                               offsetof(MyAtoms, three_string)),
+//     >>>
+//     {
+//       <<<
+//       #define MY_ATOM(name_, value_) NS_STATIC_ATOM_INIT_ATOM(nsStaticAtom, MyAtoms, name_, value_)
+//       #include "MyAtomList.h"
+//       #undef MY_ATOM
+//       ---
+//       nsStaticAtom(
+//         u"one", 3,
+//         offsetof(MyAtoms, mAtoms[static_cast<size_t>(MyAtoms::Atoms::one)]) -
+//         offsetof(MyAtoms, one_string)),
+//       nsStaticAtom(
+//         u"two", 3,
+//         offsetof(MyAtoms, mAtoms[static_cast<size_t>(MyAtoms::Atoms::two)]) -
+//         offsetof(MyAtoms, two_string)),
+//       nsStaticAtom(
+//         u"three", 3,
+//         offsetof(MyAtoms, mAtoms[static_cast<size_t>(MyAtoms::Atoms::three)]) -
+//         offsetof(MyAtoms, three_string)),
+//       >>>
+//     }
 //   };
 //   MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
 //
-//   nsStaticAtom* MyAtoms::one;
-//   nsStaticAtom* MyAtoms::two;
-//   nsStaticAtom* MyAtoms::three;
+//   } // namespace detail
+//
+//   const nsStaticAtom* const nsMyAtoms::sAtoms =
+//     mozilla::detail::gMyAtoms.mAtoms;
 //
-//   static const nsStaticAtomSetup sMyAtomSetup[] = {
-//     { &detail::gMyAtoms.one_atom, &nsMyAtoms::one },
-//     { &detail::gMyAtoms.two_atom, &nsMyAtoms::two },
-//     { &detail::gMyAtoms.three_atom, &nsMyAtoms::three },
-//   };
+//   <<<
+//   #define MY_ATOM(name_, value_) NS_STATIC_ATOM_DEFN_PTR(nsStaticAtom, detail::MyAtoms, detail::gMyAtoms, nsMyAtoms, name_)
+//   #include "MyAtomList.h"
+//   #undef MY_ATOM
+//   ---
+//   nsStaticAtom* nsMyAtoms::one =
+//     const_cast<nsStaticAtom*>(&detail::gMyAtoms.mAtoms[
+//       static_cast<size_t>(detail::MyAtoms::Atoms::one)]);
+//   nsStaticAtom* nsMyAtoms::two =
+//     const_cast<nsStaticAtom*>(&detail::gMyAtoms.mAtoms[
+//       static_cast<size_t>(detail::MyAtoms::Atoms::two)]);
+//   nsStaticAtom* nsMyAtoms::three =
+//     const_cast<nsStaticAtom*>(&detail::gMyAtoms.mAtoms[
+//       static_cast<size_t>(detail::MyAtoms::Atoms::three)]);
+//   >>>
 //
-// When RegisterStaticAtoms(sMyAtomSetup) is called it iterates over
-// sMyAtomSetup[]. E.g. for the first atom it does roughly the following:
-// - MyAtoms::one = one_atom
-// - inserts one_atom into the atom table
+// When NS_RegisterStaticAtoms(sAtoms, sAtomsLen) is called it iterates
+// over the atoms, inserting them into the atom table.
 
-// The declaration of the atom's string, which must be within the same `detail`
-// class as NS_STATIC_ATOM_DECL_ATOM.
+// The declaration of the atom's string.
 #define NS_STATIC_ATOM_DECL_STRING(name_, value_) \
   const char16_t name_##_string[sizeof(value_)];
 
-// The declaration of the static atom itself, which must be within the same
-// `detail` class as NS_STATIC_ATOM_DECL_STRING.
-#define NS_STATIC_ATOM_DECL_ATOM(name_) \
-  const nsStaticAtom name_##_atom;
+// The enum value for the atom.
+#define NS_STATIC_ATOM_ENUM(name_) \
+  name_,
 
-// The declaration of the pointer to the static atom, which must be within
-// a class.
-#define NS_STATIC_ATOM_DECL_PTR(name_) \
-  static nsStaticAtom* name_;
-
-// Like NS_STATIC_ATOM_DECL, but for sub-classes of nsStaticAtom.
-#define NS_STATIC_ATOM_SUBCLASS_DECL_PTR(type_, name_) \
+// The declaration of the pointer to the static atom. `type_` must be
+// `nsStaticAtom` or a subclass thereof.
+// XXX: Eventually this should be combined with NS_STATIC_ATOM_DEFN_PTR and the
+// pointer should be made `constexpr`. See bug 1449787.
+#define NS_STATIC_ATOM_DECL_PTR(type_, name_) \
   static type_* name_;
 
-// The initialization of the atom's string, which must be within a `constexpr`
-// instance of the `detail` class.
+// The initialization of the atom's string.
 #define NS_STATIC_ATOM_INIT_STRING(value_) \
   u"" value_,
 
-// The initialization of the static atom itself, which must be within a
-// `constexpr` instance of the `detail` class.
+// The initialization of the atom itself. `type_` must be `nsStaticAtom` or a
+// subclass thereof.
 //
 // Note that |value_| is an 8-bit string, and so |sizeof(value_)| is equal
 // to the number of chars (including the terminating '\0'). The |u""| prefix
 // converts |value_| to a 16-bit string.
-#define NS_STATIC_ATOM_INIT_ATOM(class_, name_, value_) \
-  nsStaticAtom(u"" value_, \
-               sizeof(value_) - 1, \
-               offsetof(class_, name_##_atom) - \
-               offsetof(class_, name_##_string)),
-
-// The definition of the pointer to the static atom. Initially null, it is
-// set by RegisterStaticAtoms() to point to a heap-allocated nsStaticAtom.
-#define NS_STATIC_ATOM_DEFN_PTR(class_, name_) \
-  nsStaticAtom* class_::name_;
-
-// Like NS_STATIC_ATOM_DEFN, but for sub-classes of nsStaticAtom.
-#define NS_STATIC_ATOM_SUBCLASS_DEFN_PTR(type_, class_, name_) \
-  type_* class_::name_;
+#define NS_STATIC_ATOM_INIT_ATOM(type_, detailClass_, name_, value_) \
+  type_(u"" value_, \
+        sizeof(value_) - 1, \
+        offsetof(detailClass_, \
+                 mAtoms[static_cast<size_t>(detailClass_::Atoms::name_)]) - \
+        offsetof(detailClass_, name_##_string)),
 
-// The StaticAtomSetup. Used during start-up, and in some cases afterwards.
-#define NS_STATIC_ATOM_SETUP(detailObj_, class_, name_) \
-  { &detailObj_.name_##_atom, &class_::name_ },
-
-// Like NS_STATIC_ATOM_SUBCLASS, but for sub-classes of nsStaticAtom.
-#define NS_STATIC_ATOM_SUBCLASS_SETUP(detailObj_, class_, name_) \
-  { &detailObj_.name_##_atom, \
-    reinterpret_cast<nsStaticAtom**>(&class_::name_) },
-
-// Holds data used to initialize large number of atoms during startup. Use
-// NS_STATIC_ATOM_SETUP to initialize these structs.
-struct nsStaticAtomSetup
-{
-  const nsStaticAtom* const mAtom;
-  nsStaticAtom** const mAtomp;
-};
+// Definition of the pointer to the static atom. `type_` must be `nsStaticAtom`
+// or a subclass thereof.
+#define NS_STATIC_ATOM_DEFN_PTR(type_, detailClass_, detailObj_, class_, name_) \
+  type_* class_::name_ = const_cast<type_*>( \
+    &detailObj_.mAtoms[static_cast<size_t>(detailClass_::Atoms::name_)]);
 
 // Register an array of static atoms with the atom table.
-template<uint32_t N>
 void
-NS_RegisterStaticAtoms(const nsStaticAtomSetup (&aSetup)[N])
-{
-  extern void RegisterStaticAtoms(const nsStaticAtomSetup* aSetup,
-                                  uint32_t aCount);
-  RegisterStaticAtoms(aSetup, N);
-}
+NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, size_t aAtomsLen);
 
 // This class holds basic operations on arrays of static atoms.
 class nsStaticAtomUtils {
 public:
-  template<uint32_t N>
-  static mozilla::Maybe<uint32_t> Lookup(nsAtom *aAtom,
-                                         const nsStaticAtomSetup (&aSetup)[N])
-  {
-    return Lookup(aAtom, aSetup, N);
-  }
-
-  template<uint32_t N>
-  static bool IsMember(nsAtom *aAtom, const nsStaticAtomSetup (&aSetup)[N])
-  {
-    return Lookup(aAtom, aSetup, N).isSome();
-  }
-
-private:
   static mozilla::Maybe<uint32_t> Lookup(nsAtom* aAtom,
-                                         const nsStaticAtomSetup* aSetup,
+                                         const nsStaticAtom* aAtoms,
                                          uint32_t aCount)
   {
     for (uint32_t i = 0; i < aCount; i++) {
-      if (aAtom == *(aSetup[i].mAtomp)) {
+      if (aAtom == &aAtoms[i]) {
         return mozilla::Some(i);
       }
     }
     return mozilla::Nothing();
   }
+
+  static bool IsMember(nsAtom* aAtom, const nsStaticAtom* aAtoms,
+                       uint32_t aCount)
+  {
+    return Lookup(aAtom, aAtoms, aCount).isSome();
+  }
 };
 
 #endif
--- a/xpcom/io/nsDirectoryService.cpp
+++ b/xpcom/io/nsDirectoryService.cpp
@@ -7,17 +7,16 @@
 #include "mozilla/ArrayUtils.h"
 
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsDirectoryService.h"
 #include "nsLocalFile.h"
 #include "nsDebug.h"
 #include "nsGkAtoms.h"
-#include "nsStaticAtom.h"
 #include "nsEnumeratorUtils.h"
 
 #include "nsICategoryManager.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIStringEnumerator.h"
 
 #if defined(XP_WIN)
 #include <windows.h>
@@ -98,56 +97,54 @@ nsDirectoryService::Create(nsISupports* 
 namespace mozilla {
 namespace detail {
 
 MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
 extern constexpr DirectoryAtoms gDirectoryAtoms = {
   #define DIR_ATOM(name_, value_) NS_STATIC_ATOM_INIT_STRING(value_)
   #include "nsDirectoryServiceAtomList.h"
   #undef DIR_ATOM
-
-  #define DIR_ATOM(name_, value_) \
-    NS_STATIC_ATOM_INIT_ATOM(DirectoryAtoms, name_, value_)
-  #include "nsDirectoryServiceAtomList.h"
-  #undef DIR_ATOM
+  {
+    #define DIR_ATOM(name_, value_) \
+      NS_STATIC_ATOM_INIT_ATOM(nsStaticAtom, DirectoryAtoms, name_, value_)
+    #include "nsDirectoryServiceAtomList.h"
+    #undef DIR_ATOM
+  }
 };
 MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
 
 } // namespace detail
 } // namespace mozilla
 
+const nsStaticAtom* const nsDirectoryService::sAtoms =
+  mozilla::detail::gDirectoryAtoms.mAtoms;
+
 #define DIR_ATOM(name_, value_) \
-  NS_STATIC_ATOM_DEFN_PTR(nsDirectoryService, name_)
+  NS_STATIC_ATOM_DEFN_PTR( \
+    nsStaticAtom, mozilla::detail::DirectoryAtoms, \
+    mozilla::detail::gDirectoryAtoms, nsDirectoryService, name_)
 #include "nsDirectoryServiceAtomList.h"
 #undef DIR_ATOM
 
-static const nsStaticAtomSetup sDirectoryServiceAtomSetup[] = {
-  #define DIR_ATOM(name_, value_) \
-    NS_STATIC_ATOM_SETUP( \
-      mozilla::detail::gDirectoryAtoms, nsDirectoryService, name_)
-  #include "nsDirectoryServiceAtomList.h"
-  #undef DIR_ATOM
-};
-
 NS_IMETHODIMP
 nsDirectoryService::Init()
 {
   NS_NOTREACHED("nsDirectoryService::Init() for internal use only!");
   return NS_OK;
 }
 
 void
 nsDirectoryService::RealInit()
 {
   NS_ASSERTION(!gService,
                "nsDirectoryService::RealInit Mustn't initialize twice!");
 
   gService = new nsDirectoryService();
 
-  NS_RegisterStaticAtoms(sDirectoryServiceAtomSetup);
+  NS_RegisterStaticAtoms(sAtoms, sAtomsLen);
 
   // Let the list hold the only reference to the provider.
   nsAppFileLocationProvider* defaultProvider = new nsAppFileLocationProvider;
   gService->mProviders.AppendElement(defaultProvider);
 }
 
 nsDirectoryService::~nsDirectoryService()
 {
--- a/xpcom/io/nsDirectoryService.h
+++ b/xpcom/io/nsDirectoryService.h
@@ -25,19 +25,24 @@ namespace mozilla {
 namespace detail {
 
 struct DirectoryAtoms
 {
   #define DIR_ATOM(name_, value_) NS_STATIC_ATOM_DECL_STRING(name_, value_)
   #include "nsDirectoryServiceAtomList.h"
   #undef DIR_ATOM
 
-  #define DIR_ATOM(name_, value_) NS_STATIC_ATOM_DECL_ATOM(name_)
-  #include "nsDirectoryServiceAtomList.h"
-  #undef DIR_ATOM
+  enum class Atoms {
+    #define DIR_ATOM(name_, value_) NS_STATIC_ATOM_ENUM(name_)
+    #include "nsDirectoryServiceAtomList.h"
+    #undef DIR_ATOM
+    AtomsCount
+  };
+
+  const nsStaticAtom mAtoms[static_cast<size_t>(Atoms::AtomsCount)];
 };
 
 extern const DirectoryAtoms gDirectoryAtoms;
 
 } // namespace detail
 } // namespace mozilla
 
 class nsDirectoryService final
@@ -69,15 +74,19 @@ public:
 private:
   ~nsDirectoryService();
 
   nsresult GetCurrentProcessDirectory(nsIFile** aFile);
 
   nsInterfaceHashtable<nsCStringHashKey, nsIFile> mHashtable;
   nsTArray<nsCOMPtr<nsIDirectoryServiceProvider>> mProviders;
 
+  static const nsStaticAtom* const sAtoms;
+  static constexpr size_t sAtomsLen =
+    mozilla::ArrayLength(mozilla::detail::gDirectoryAtoms.mAtoms);
+
 public:
-  #define DIR_ATOM(name_, value_) NS_STATIC_ATOM_DECL_PTR(name_)
+  #define DIR_ATOM(name_, value_) NS_STATIC_ATOM_DECL_PTR(nsStaticAtom, name_)
   #include "nsDirectoryServiceAtomList.h"
   #undef DIR_ATOM
 };
 
 #endif
--- a/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
+++ b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
@@ -20,17 +20,16 @@
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMGeoPositionError.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMOfflineResourceList.h"
 #include "nsIDOMParser.h"
 #include "nsIDOMRange.h"
-#include "nsIDOMScreen.h"
 #include "nsIDOMSerializer.h"
 #include "nsIDOMXMLDocument.h"
 #include "nsIDOMXULElement.h"
 #include "nsIListBoxObject.h"
 #include "nsIMessageManager.h"
 #include "nsISelection.h"
 #include "nsITreeBoxObject.h"
 #include "nsIWebBrowserPersistable.h"
@@ -64,17 +63,16 @@
 #include "mozilla/dom/NodeBinding.h"
 #include "mozilla/dom/EventBinding.h"
 #include "mozilla/dom/OfflineResourceListBinding.h"
 #include "mozilla/dom/PositionErrorBinding.h"
 #include "mozilla/dom/RangeBinding.h"
 #ifdef MOZ_WEBRTC
 #include "mozilla/dom/RTCDataChannelBinding.h"
 #endif
-#include "mozilla/dom/ScreenBinding.h"
 #include "mozilla/dom/SelectionBinding.h"
 #include "mozilla/dom/StorageEventBinding.h"
 #include "mozilla/dom/StyleSheetBinding.h"
 #include "mozilla/dom/StyleSheetListBinding.h"
 #include "mozilla/dom/SVGElementBinding.h"
 #include "mozilla/dom/TimeEventBinding.h"
 #include "mozilla/dom/TreeBoxObjectBinding.h"
 #include "mozilla/dom/XMLDocumentBinding.h"
@@ -153,17 +151,16 @@ const ComponentsInterfaceShimEntry kComp
   DEFINE_SHIM(NodeList),
   DEFINE_SHIM(Node),
   DEFINE_SHIM(OfflineResourceList),
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMParser, DOMParser),
   DEFINE_SHIM(Range),
 #ifdef MOZ_WEBRTC
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMDataChannel, RTCDataChannel),
 #endif
-  DEFINE_SHIM(Screen),
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMSerializer, XMLSerializer),
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsITreeBoxObject, TreeBoxObject),
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIWebBrowserPersistable, FrameLoader),
   DEFINE_SHIM(XMLDocument),
   DEFINE_SHIM(XULElement),
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsISelection, Selection),
 };
 
--- a/xpcom/string/nsSubstring.cpp
+++ b/xpcom/string/nsSubstring.cpp
@@ -18,17 +18,16 @@
 #include <stdlib.h>
 #include "nsAString.h"
 #include "nsString.h"
 #include "nsStringBuffer.h"
 #include "nsDependentString.h"
 #include "nsPrintfCString.h"
 #include "nsMemory.h"
 #include "prprf.h"
-#include "nsStaticAtom.h"
 #include "nsCOMPtr.h"
 
 #include "mozilla/IntegerPrintfMacros.h"
 #ifdef XP_WIN
 #include <windows.h>
 #include <process.h>
 #define getpid() _getpid()
 #define pthread_self() GetCurrentThreadId()
--- a/xpcom/tests/gtest/TestAtoms.cpp
+++ b/xpcom/tests/gtest/TestAtoms.cpp
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ArrayUtils.h"
 
 #include "nsAtom.h"
 #include "nsString.h"
 #include "UTFStrings.h"
 #include "nsIServiceManager.h"
-#include "nsStaticAtom.h"
 #include "nsThreadUtils.h"
 
 #include "gtest/gtest.h"
 
 using namespace mozilla;
 
 int32_t NS_GetUnusedAtomCount(void);
 
--- a/xpfe/appshell/nsXULWindow.cpp
+++ b/xpfe/appshell/nsXULWindow.cpp
@@ -15,26 +15,27 @@
 #include "nsString.h"
 #include "nsWidgetsCID.h"
 #include "nsThreadUtils.h"
 #include "nsNetCID.h"
 #include "nsQueryObject.h"
 #include "mozilla/Sprintf.h"
 
 //Interfaces needed to be included
+#include "nsGlobalWindowOuter.h"
 #include "nsIAppShell.h"
 #include "nsIAppShellService.h"
 #include "nsIServiceManager.h"
 #include "nsIContentViewer.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMXULElement.h"
 #include "nsPIDOMWindow.h"
-#include "nsIDOMScreen.h"
+#include "nsScreen.h"
 #include "nsIEmbeddingSiteWindow.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIIOService.h"
 #include "nsILoadContext.h"
 #include "nsIObserverService.h"
 #include "nsIWindowMediator.h"
 #include "nsIScreenManager.h"
@@ -1023,33 +1024,35 @@ NS_IMETHODIMP nsXULWindow::EnsureAuthPro
     if (wwatch)
       wwatch->GetNewAuthPrompter(ourWindow, getter_AddRefs(mAuthPrompter));
   }
   return mAuthPrompter ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP nsXULWindow::GetAvailScreenSize(int32_t* aAvailWidth, int32_t* aAvailHeight)
 {
-  nsresult rv;
-
   nsCOMPtr<mozIDOMWindowProxy> domWindow;
   GetWindowDOMWindow(getter_AddRefs(domWindow));
   NS_ENSURE_STATE(domWindow);
 
-  auto* window = nsPIDOMWindowOuter::From(domWindow);
-  NS_ENSURE_STATE(window);
+  auto* window = nsGlobalWindowOuter::Cast(domWindow);
 
-  nsCOMPtr<nsIDOMScreen> screen = window->GetScreen();
+  RefPtr<nsScreen> screen = window->GetScreen();
   NS_ENSURE_STATE(screen);
 
-  rv = screen->GetAvailWidth(aAvailWidth);
-  NS_ENSURE_SUCCESS(rv, rv);
+  ErrorResult rv;
+  *aAvailWidth = screen->GetAvailWidth(rv);
+  if (NS_WARN_IF(rv.Failed())) {
+    return rv.StealNSResult();
+  }
 
-  rv = screen->GetAvailHeight(aAvailHeight);
-  NS_ENSURE_SUCCESS(rv, rv);
+  *aAvailHeight = screen->GetAvailHeight(rv);
+  if (NS_WARN_IF(rv.Failed())) {
+    return rv.StealNSResult();
+  }
 
   return NS_OK;
 }
 
 // Rounds window size to 1000x1000, or, if there isn't enough available
 // screen space, to a multiple of 200x100.
 NS_IMETHODIMP nsXULWindow::ForceRoundedDimensions()
 {