merge mozilla-inbound to mozilla-central. r=merge a=merge default tip
authorSebastian Hengst <archaeopteryx@coole-files.de>
Mon, 23 Oct 2017 11:39:19 +0200
changeset 387604 d49501f258b1
parent 387595 b39904cff06b (current diff)
parent 387603 75caeba85cb5 (diff)
push id32730
push userarchaeopteryx@coole-files.de
push date2017-10-23 09:39 +0000
treeherdermozilla-central@d49501f258b1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone58.0a1
merge mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: BcJNE0poEYk
editor/txtsvc/nsTSAtomList.h
modules/libpref/init/all.js
--- a/dom/base/nsAtomListUtils.cpp
+++ b/dom/base/nsAtomListUtils.cpp
@@ -9,18 +9,18 @@
  */
 
 #include "nsAtomListUtils.h"
 #include "nsAtom.h"
 #include "nsStaticAtom.h"
 
 /* static */ bool
 nsAtomListUtils::IsMember(nsAtom *aAtom,
-                          const nsStaticAtom* aInfo,
-                          uint32_t aInfoCount)
+                          const nsStaticAtomSetup* aSetup,
+                          uint32_t aCount)
 {
-    for (const nsStaticAtom *info = aInfo, *info_end = aInfo + aInfoCount;
-         info != info_end; ++info) {
-        if (aAtom == *(info->mAtom))
+    for (const nsStaticAtomSetup *setup = aSetup, *setup_end = aSetup + aCount;
+         setup != setup_end; ++setup) {
+        if (aAtom == *(setup->mAtom))
             return true;
     }
     return false;
 }
--- a/dom/base/nsAtomListUtils.h
+++ b/dom/base/nsAtomListUtils.h
@@ -9,18 +9,18 @@
  */
 
 #ifndef nsAtomListUtils_h__
 #define nsAtomListUtils_h__
 
 #include <stdint.h>
 
 class nsAtom;
-struct nsStaticAtom;
+struct nsStaticAtomSetup;
 
 class nsAtomListUtils {
 public:
-    static bool IsMember(nsAtom *aAtom,
-                           const nsStaticAtom* aInfo,
-                           uint32_t aInfoCount);
+  static bool IsMember(nsAtom *aAtom,
+                       const nsStaticAtomSetup* aSetup,
+                       uint32_t aCount);
 };
 
 #endif /* !defined(nsAtomListUtils_h__) */
--- a/dom/base/nsGkAtoms.cpp
+++ b/dom/base/nsGkAtoms.cpp
@@ -1,37 +1,30 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/*
- * This class wraps up the creation (and destruction) of the standard
- * set of atoms used by gklayout; the atoms are created when gklayout
- * is loaded and they are destroyed when gklayout is unloaded.
- */
-
 #include "nsGkAtoms.h"
 #include "nsStaticAtom.h"
 
 using namespace mozilla;
 
-// define storage for all atoms
-#define GK_ATOM(name_, value_) nsAtom* nsGkAtoms::name_;
+#define GK_ATOM(name_, value_) NS_STATIC_ATOM_DEFN(nsGkAtoms, name_)
 #include "nsGkAtomList.h"
 #undef GK_ATOM
 
-#define GK_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#define GK_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_, value_)
 #include "nsGkAtomList.h"
 #undef GK_ATOM
 
-static const nsStaticAtom GkAtoms_info[] = {
-#define GK_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &nsGkAtoms::name_),
-#include "nsGkAtomList.h"
-#undef GK_ATOM
+static const nsStaticAtomSetup sGkAtomSetup[] = {
+  #define GK_ATOM(name_, value_) NS_STATIC_ATOM_SETUP(nsGkAtoms, name_)
+  #include "nsGkAtomList.h"
+  #undef GK_ATOM
 };
 
 void nsGkAtoms::AddRefAtoms()
 {
-  NS_RegisterStaticAtoms(GkAtoms_info);
+  NS_RegisterStaticAtoms(sGkAtomSetup);
 }
 
--- a/dom/base/nsGkAtoms.h
+++ b/dom/base/nsGkAtoms.h
@@ -1,35 +1,22 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/*
- * This class wraps up the creation (and destruction) of the standard
- * set of atoms used by gklayout; the atoms are created when gklayout
- * is loaded and they are destroyed when gklayout is unloaded.
- */
-
 #ifndef nsGkAtoms_h___
 #define nsGkAtoms_h___
 
-class nsAtom;
+#include "nsStaticAtom.h"
 
-class nsGkAtoms {
+class nsGkAtoms
+{
 public:
-
   static void AddRefAtoms();
 
-  /* Declare all atoms
-
-     The atom names and values are stored in nsGkAtomList.h and
-     are brought to you by the magic of C preprocessing
-
-     Add new atoms to nsGkAtomList and all support logic will be auto-generated
-   */
-#define GK_ATOM(_name, _value) static nsAtom* _name;
-#include "nsGkAtomList.h"
-#undef GK_ATOM
+  #define GK_ATOM(_name, _value) NS_STATIC_ATOM_DECL(_name)
+  #include "nsGkAtomList.h"
+  #undef GK_ATOM
 };
 
 #endif /* nsGkAtoms_h___ */
deleted file mode 100644
--- a/editor/txtsvc/nsTSAtomList.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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 all text services nsAtoms and their values
-
-  It is designed to be used as inline input to nsTextServicesDocument.cpp *only*
-  through the magic of C preprocessing.
-
-  All entries must be enclosed in the macro TS_ATOM which will have cruel
-  and unusual things done to it
-
-  It is recommended (but not strictly necessary) to keep all entries
-  in alphabetical order
-
-  The first argument to TS_ATOM is the C++ identifier of the atom
-  The second argument is the string value of the atom
-
- ******/
-
-// OUTPUT_CLASS=nsTextServicesDocument
-// MACRO_NAME=TS_ATOM
-
-TS_ATOM(sAAtom, "a")
-TS_ATOM(sAddressAtom, "address")
-TS_ATOM(sBigAtom, "big")
-TS_ATOM(sBAtom, "b")
-TS_ATOM(sCiteAtom, "cite")
-TS_ATOM(sCodeAtom, "code")
-TS_ATOM(sDfnAtom, "dfn")
-TS_ATOM(sEmAtom, "em")
-TS_ATOM(sFontAtom, "font")
-TS_ATOM(sIAtom, "i")
-TS_ATOM(sKbdAtom, "kbd")
-TS_ATOM(sKeygenAtom, "keygen")
-TS_ATOM(sNobrAtom, "nobr")
-TS_ATOM(sSAtom, "s")
-TS_ATOM(sSampAtom, "samp")
-TS_ATOM(sSmallAtom, "small")
-TS_ATOM(sSpacerAtom, "spacer")
-TS_ATOM(sSpanAtom, "span")
-TS_ATOM(sStrikeAtom, "strike")
-TS_ATOM(sStrongAtom, "strong")
-TS_ATOM(sSubAtom, "sub")
-TS_ATOM(sSupAtom, "sup")
-TS_ATOM(sTtAtom, "tt")
-TS_ATOM(sUAtom, "u")
-TS_ATOM(sVarAtom, "var")
-TS_ATOM(sWbrAtom, "wbr")
--- a/editor/txtsvc/nsTextServicesDocument.cpp
+++ b/editor/txtsvc/nsTextServicesDocument.cpp
@@ -28,17 +28,17 @@
 #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 "nsIWordBreaker.h"             // for nsWordRange, nsIWordBreaker
 #include "nsRange.h"                    // for nsRange
-#include "nsStaticAtom.h"               // for NS_STATIC_ATOM, etc
+#include "nsStaticAtom.h"               // for NS_STATIC_ATOM_SETUP, etc
 #include "nsString.h"                   // for nsString, nsAutoString
 #include "nsTextServicesDocument.h"
 #include "nscore.h"                     // for nsresult, NS_IMETHODIMP, etc
 
 #define LOCK_DOC(doc)
 #define UNLOCK_DOC(doc)
 
 using namespace mozilla;
@@ -71,52 +71,31 @@ public:
   nsIDOMNode *mNode;
   int32_t mNodeOffset;
   int32_t mStrOffset;
   int32_t mLength;
   bool    mIsInsertedText;
   bool    mIsValid;
 };
 
-#define TS_ATOM(name_, value_) nsAtom* nsTextServicesDocument::name_ = 0;
-#include "nsTSAtomList.h" // IWYU pragma: keep
-#undef TS_ATOM
-
 nsTextServicesDocument::nsTextServicesDocument()
 {
   mSelStartIndex  = -1;
   mSelStartOffset = -1;
   mSelEndIndex    = -1;
   mSelEndOffset   = -1;
 
   mIteratorStatus = eIsDone;
 }
 
 nsTextServicesDocument::~nsTextServicesDocument()
 {
   ClearOffsetTable(&mOffsetTable);
 }
 
-#define TS_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
-#include "nsTSAtomList.h" // IWYU pragma: keep
-#undef TS_ATOM
-
-/* static */
-void
-nsTextServicesDocument::RegisterAtoms()
-{
-  static const nsStaticAtom ts_atoms[] = {
-#define TS_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &name_),
-#include "nsTSAtomList.h" // IWYU pragma: keep
-#undef TS_ATOM
-  };
-
-  NS_RegisterStaticAtoms(ts_atoms);
-}
-
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTextServicesDocument)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTextServicesDocument)
 
 NS_INTERFACE_MAP_BEGIN(nsTextServicesDocument)
   NS_INTERFACE_MAP_ENTRY(nsITextServicesDocument)
   NS_INTERFACE_MAP_ENTRY(nsIEditActionListener)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITextServicesDocument)
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsTextServicesDocument)
@@ -2035,42 +2014,42 @@ nsTextServicesDocument::IsBlockNode(nsIC
 {
   if (!aContent) {
     NS_ERROR("How did a null pointer get passed to IsBlockNode?");
     return false;
   }
 
   nsAtom *atom = aContent->NodeInfo()->NameAtom();
 
-  return (sAAtom       != atom &&
-          sAddressAtom != atom &&
-          sBigAtom     != atom &&
-          sBAtom       != atom &&
-          sCiteAtom    != atom &&
-          sCodeAtom    != atom &&
-          sDfnAtom     != atom &&
-          sEmAtom      != atom &&
-          sFontAtom    != atom &&
-          sIAtom       != atom &&
-          sKbdAtom     != atom &&
-          sKeygenAtom  != atom &&
-          sNobrAtom    != atom &&
-          sSAtom       != atom &&
-          sSampAtom    != atom &&
-          sSmallAtom   != atom &&
-          sSpacerAtom  != atom &&
-          sSpanAtom    != atom &&
-          sStrikeAtom  != atom &&
-          sStrongAtom  != atom &&
-          sSubAtom     != atom &&
-          sSupAtom     != atom &&
-          sTtAtom      != atom &&
-          sUAtom       != atom &&
-          sVarAtom     != atom &&
-          sWbrAtom     != atom);
+  return (nsGkAtoms::a       != atom &&
+          nsGkAtoms::address != atom &&
+          nsGkAtoms::big     != atom &&
+          nsGkAtoms::b       != atom &&
+          nsGkAtoms::cite    != atom &&
+          nsGkAtoms::code    != atom &&
+          nsGkAtoms::dfn     != atom &&
+          nsGkAtoms::em      != atom &&
+          nsGkAtoms::font    != atom &&
+          nsGkAtoms::i       != atom &&
+          nsGkAtoms::kbd     != atom &&
+          nsGkAtoms::keygen  != atom &&
+          nsGkAtoms::nobr    != atom &&
+          nsGkAtoms::s       != atom &&
+          nsGkAtoms::samp    != atom &&
+          nsGkAtoms::small   != atom &&
+          nsGkAtoms::spacer  != atom &&
+          nsGkAtoms::span    != atom &&
+          nsGkAtoms::strike  != atom &&
+          nsGkAtoms::strong  != atom &&
+          nsGkAtoms::sub     != atom &&
+          nsGkAtoms::sup     != atom &&
+          nsGkAtoms::tt      != atom &&
+          nsGkAtoms::u       != atom &&
+          nsGkAtoms::var     != atom &&
+          nsGkAtoms::wbr     != atom);
 }
 
 bool
 nsTextServicesDocument::HasSameBlockNodeParent(nsIContent *aContent1, nsIContent *aContent2)
 {
   nsIContent* p1 = aContent1->GetParent();
   nsIContent* p2 = aContent2->GetParent();
 
--- a/editor/txtsvc/nsTextServicesDocument.h
+++ b/editor/txtsvc/nsTextServicesDocument.h
@@ -12,17 +12,16 @@
 #include "nsISupportsImpl.h"
 #include "nsITextServicesDocument.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsStringFwd.h"
 #include "nsTArray.h"
 #include "nscore.h"
 
 class OffsetEntry;
-class nsAtom;
 class nsIContent;
 class nsIContentIterator;
 class nsIDOMCharacterData;
 class nsIDOMDocument;
 class nsIDOMNode;
 class nsIDOMRange;
 class nsIEditor;
 class nsISelection;
@@ -31,43 +30,16 @@ class nsITextServicesFilter;
 
 /** implementation of a text services object.
  *
  */
 class nsTextServicesDocument final : public nsITextServicesDocument,
                                      public nsIEditActionListener
 {
 private:
-  static nsAtom *sAAtom;
-  static nsAtom *sAddressAtom;
-  static nsAtom *sBigAtom;
-  static nsAtom *sBAtom;
-  static nsAtom *sCiteAtom;
-  static nsAtom *sCodeAtom;
-  static nsAtom *sDfnAtom;
-  static nsAtom *sEmAtom;
-  static nsAtom *sFontAtom;
-  static nsAtom *sIAtom;
-  static nsAtom *sKbdAtom;
-  static nsAtom *sKeygenAtom;
-  static nsAtom *sNobrAtom;
-  static nsAtom *sSAtom;
-  static nsAtom *sSampAtom;
-  static nsAtom *sSmallAtom;
-  static nsAtom *sSpacerAtom;
-  static nsAtom *sSpanAtom;
-  static nsAtom *sStrikeAtom;
-  static nsAtom *sStrongAtom;
-  static nsAtom *sSubAtom;
-  static nsAtom *sSupAtom;
-  static nsAtom *sTtAtom;
-  static nsAtom *sUAtom;
-  static nsAtom *sVarAtom;
-  static nsAtom *sWbrAtom;
-
   typedef enum { eIsDone=0,        // No iterator (I), or iterator doesn't point to anything valid.
                  eValid,           // I points to first text node (TN) in current block (CB).
                  ePrev,            // No TN in CB, I points to first TN in prev block.
                  eNext             // No TN in CB, I points to first TN in next block.
   } TSDIteratorStatus;
 
   nsCOMPtr<nsIDOMDocument>        mDOMDocument;
   nsCOMPtr<nsISelectionController>mSelCon;
@@ -93,20 +65,16 @@ protected:
   virtual ~nsTextServicesDocument();
 
 public:
 
   /** The default constructor.
    */
   nsTextServicesDocument();
 
-  /** To be called at module init
-   */
-  static void RegisterAtoms();
-
   /* Macro for AddRef(), Release(), and QueryInterface() */
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsTextServicesDocument, nsITextServicesDocument)
 
   /* nsITextServicesDocument method implementations. */
   NS_IMETHOD InitWithEditor(nsIEditor *aEditor) override;
   NS_IMETHOD GetDocument(nsIDOMDocument **aDoc) override;
   NS_IMETHOD SetExtent(nsIDOMRange* aDOMRange) override;
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -81,18 +81,16 @@
 #include "nsXULPrototypeCache.h"
 #include "nsXULTooltipListener.h"
 
 #include "inDOMView.h"
 
 #include "nsMenuBarListener.h"
 #endif
 
-#include "nsTextServicesDocument.h"
-
 #ifdef MOZ_WEBSPEECH
 #include "nsSynthVoiceRegistry.h"
 #endif
 
 #include "CubebUtils.h"
 #include "Latency.h"
 #include "WebAudioUtils.h"
 
@@ -149,17 +147,16 @@ nsLayoutStatics::Initialize()
   // Register all of our atoms once
   nsCSSAnonBoxes::AddRefAtoms();
   nsCSSPseudoClasses::AddRefAtoms();
   nsCSSPseudoElements::AddRefAtoms();
   nsCSSKeywords::AddRefTable();
   nsCSSProps::AddRefTable();
   nsColorNames::AddRefTable();
   nsGkAtoms::AddRefAtoms();
-  nsTextServicesDocument::RegisterAtoms();
   nsHTMLTags::RegisterAtoms();
   nsRDFAtoms::RegisterAtoms();
 
   NS_SealStaticAtomTable();
 
   StartupJSEnvironment();
   rv = nsRegion::InitStatic();
   if (NS_FAILED(rv)) {
--- a/layout/printing/nsIPrintProgressParams.idl
+++ b/layout/printing/nsIPrintProgressParams.idl
@@ -1,14 +1,14 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 #include "nsISupports.idl"
 
 [scriptable, uuid(CA89B55B-6FAF-4051-9645-1C03EF5108F8)]
-interface nsIPrintProgressParams: nsISupports {
-
-  /* message subject */
-  attribute wstring docTitle;
-  attribute wstring docURL;
-  
+interface nsIPrintProgressParams: nsISupports
+{
+  attribute AString docTitle;
+  attribute AString docURL;
 };
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -2678,18 +2678,18 @@ nsPrintEngine::SetDocAndURLIntoProgress(
   nsAutoString docTitleStr;
   nsAutoString docURLStr;
   GetDisplayTitleAndURL(aPO, docTitleStr, docURLStr, eDocTitleDefURLDoc);
 
   // Make sure the Titles & URLS don't get too long for the progress dialog
   EllipseLongString(docTitleStr, kTitleLength, false);
   EllipseLongString(docURLStr, kTitleLength, true);
 
-  aParams->SetDocTitle(docTitleStr.get());
-  aParams->SetDocURL(docURLStr.get());
+  aParams->SetDocTitle(docTitleStr);
+  aParams->SetDocURL(docURLStr);
 }
 
 //---------------------------------------------------------------------
 void
 nsPrintEngine::EllipseLongString(nsAString& aStr, const uint32_t aLen, bool aDoFront)
 {
   // Make sure the URLS don't get too long for the progress dialog
   if (aLen >= 3 && aStr.Length() > aLen) {
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -213,17 +213,16 @@ UNIFIED_SOURCES += [
     'nsAnimationManager.cpp',
     'nsComputedDOMStyle.cpp',
     'nsCSSAnonBoxes.cpp',
     'nsCSSDataBlock.cpp',
     'nsCSSKeywords.cpp',
     'nsCSSParser.cpp',
     'nsCSSProps.cpp',
     'nsCSSPseudoClasses.cpp',
-    'nsCSSPseudoElements.cpp',
     'nsCSSRuleProcessor.cpp',
     'nsCSSRules.cpp',
     'nsCSSScanner.cpp',
     'nsCSSValue.cpp',
     'nsDOMCSSAttrDeclaration.cpp',
     'nsDOMCSSDeclaration.cpp',
     'nsDOMCSSRect.cpp',
     'nsDOMCSSRGBColor.cpp',
@@ -272,19 +271,22 @@ UNIFIED_SOURCES += [
     'StreamLoader.cpp',
     'StyleAnimationValue.cpp',
     'StylePrefs.cpp',
     'StyleRule.cpp',
     'StyleSheet.cpp',
     'URLExtraData.cpp',
 ]
 
-# - nsLayoutStylesheetCache.cpp needs to be built separately because it uses
-# nsExceptionHandler.h, which includes windows.h.
 SOURCES += [
+    # Both nsCSSPseudoElements.cpp and nsCSSPseudoClasses.cpp defined a
+    # 'mozPlaceholder' static atom.
+    'nsCSSPseudoElements.cpp',
+    # nsLayoutStylesheetCache.cpp uses nsExceptionHandler.h, which includes
+    # windows.h.
     'nsLayoutStylesheetCache.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
--- a/layout/style/nsCSSAnonBoxes.cpp
+++ b/layout/style/nsCSSAnonBoxes.cpp
@@ -8,78 +8,74 @@
 #include "mozilla/ArrayUtils.h"
 
 #include "nsCSSAnonBoxes.h"
 #include "nsAtomListUtils.h"
 #include "nsStaticAtom.h"
 
 using namespace mozilla;
 
-// define storage for all atoms
 #define CSS_ANON_BOX(name_, value_) \
-  nsICSSAnonBoxPseudo* nsCSSAnonBoxes::name_;
+  NS_STATIC_ATOM_SUBCLASS_DEFN(nsICSSAnonBoxPseudo, nsCSSAnonBoxes, name_)
 #include "nsCSSAnonBoxList.h"
 #undef CSS_ANON_BOX
 
-#define CSS_ANON_BOX(name_, value_) \
-  NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#define CSS_ANON_BOX(name_, value_) NS_STATIC_ATOM_BUFFER(name_, value_)
 #include "nsCSSAnonBoxList.h"
 #undef CSS_ANON_BOX
 
-static const nsStaticAtom CSSAnonBoxes_info[] = {
+static const nsStaticAtomSetup sCSSAnonBoxAtomSetup[] = {
   // Put the non-inheriting anon boxes first, so we can index into them easily.
-#define CSS_ANON_BOX(name_, value_) /* nothing */
-#define CSS_NON_INHERITING_ANON_BOX(name_, value_) \
-  NS_STATIC_ATOM(name_##_buffer, (nsAtom**)&nsCSSAnonBoxes::name_),
-#include "nsCSSAnonBoxList.h"
-#undef CSS_NON_INHERITING_ANON_BOX
-#undef CSS_ANON_BOX
+  #define CSS_ANON_BOX(name_, value_) /* nothing */
+  #define CSS_NON_INHERITING_ANON_BOX(name_, value_) \
+    NS_STATIC_ATOM_SUBCLASS_SETUP(nsCSSAnonBoxes, name_)
+  #include "nsCSSAnonBoxList.h"
+  #undef CSS_NON_INHERITING_ANON_BOX
+  #undef CSS_ANON_BOX
 
-#define CSS_ANON_BOX(name_, value_) \
-  NS_STATIC_ATOM(name_##_buffer, (nsAtom**)&nsCSSAnonBoxes::name_),
-#define CSS_NON_INHERITING_ANON_BOX(name_, value_) /* nothing */
-#include "nsCSSAnonBoxList.h"
-#undef CSS_NON_INHERITING_ANON_BOX
-#undef CSS_ANON_BOX
+  #define CSS_ANON_BOX(name_, value_) \
+    NS_STATIC_ATOM_SUBCLASS_SETUP(nsCSSAnonBoxes, name_)
+  #define CSS_NON_INHERITING_ANON_BOX(name_, value_) /* nothing */
+  #include "nsCSSAnonBoxList.h"
+  #undef CSS_NON_INHERITING_ANON_BOX
+  #undef CSS_ANON_BOX
 };
 
 void nsCSSAnonBoxes::AddRefAtoms()
 {
-  NS_RegisterStaticAtoms(CSSAnonBoxes_info);
+  NS_RegisterStaticAtoms(sCSSAnonBoxAtomSetup);
 }
 
 bool nsCSSAnonBoxes::IsAnonBox(nsAtom *aAtom)
 {
-  return nsAtomListUtils::IsMember(aAtom, CSSAnonBoxes_info,
-                                   ArrayLength(CSSAnonBoxes_info));
+  return nsAtomListUtils::IsMember(aAtom, sCSSAnonBoxAtomSetup,
+                                   ArrayLength(sCSSAnonBoxAtomSetup));
 }
 
 #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));
-  for (NonInheritingBase i = 0;
-       i < ArrayLength(CSSAnonBoxes_info);
-       ++i) {
-    if (*CSSAnonBoxes_info[i].mAtom == aPseudo) {
+  for (NonInheritingBase i = 0; i < ArrayLength(sCSSAnonBoxAtomSetup); ++i) {
+    if (*sCSSAnonBoxAtomSetup[i].mAtom == aPseudo) {
       return static_cast<NonInheriting>(i);
     }
   }
 
   MOZ_CRASH("Bogus pseudo passed to NonInheritingTypeForPseudoTag");
 }
 
 /* static */ nsAtom*
 nsCSSAnonBoxes::GetNonInheritingPseudoAtom(NonInheriting aBoxType)
 {
   MOZ_ASSERT(aBoxType < NonInheriting::_Count);
-  return *CSSAnonBoxes_info[static_cast<NonInheritingBase>(aBoxType)].mAtom;
+  return *sCSSAnonBoxAtomSetup[static_cast<NonInheritingBase>(aBoxType)].mAtom;
 }
--- a/layout/style/nsCSSAnonBoxes.h
+++ b/layout/style/nsCSSAnonBoxes.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* 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 {};
 
 class nsCSSAnonBoxes {
 public:
 
@@ -24,17 +25,18 @@ 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) static nsICSSAnonBoxPseudo* _name;
+#define CSS_ANON_BOX(name_, value_) \
+  NS_STATIC_ATOM_SUBCLASS_DECL(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"
--- a/layout/style/nsCSSPseudoClasses.cpp
+++ b/layout/style/nsCSSPseudoClasses.cpp
@@ -13,81 +13,88 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/Element.h"
 #include "nsString.h"
 #include "nsAttrValueInlines.h"
 #include "nsIMozBrowserFrame.h"
 
 using namespace mozilla;
 
-// define storage for all atoms
-#define CSS_PSEUDO_CLASS(_name, _value, _flags, _pref) \
-  static nsAtom* sPseudoClass_##_name;
-#include "nsCSSPseudoClassList.h"
-#undef CSS_PSEUDO_CLASS
-
-#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-  NS_STATIC_ATOM_BUFFER(name_##_pseudo_class_buffer, value_)
-#include "nsCSSPseudoClassList.h"
-#undef CSS_PSEUDO_CLASS
-
 #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
   static_assert(!((flags_) & CSS_PSEUDO_CLASS_ENABLED_IN_CHROME) || \
                 ((flags_) & CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), \
                 "Pseudo-class '" #name_ "' is enabled in chrome, so it " \
                 "should also be enabled in UA sheets");
 #include "nsCSSPseudoClassList.h"
 #undef CSS_PSEUDO_CLASS
 
-// Array of nsStaticAtom for each of the pseudo-classes.
-static const nsStaticAtom CSSPseudoClasses_info[] = {
+class CSSPseudoClassAtoms
+{
+public:
+  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
+    NS_STATIC_ATOM_DECL(name_)
+  #include "nsCSSPseudoClassList.h"
+  #undef CSS_PSEUDO_CLASS
+};
+
 #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-  NS_STATIC_ATOM(name_##_pseudo_class_buffer, &sPseudoClass_##name_),
+  NS_STATIC_ATOM_DEFN(CSSPseudoClassAtoms, name_)
 #include "nsCSSPseudoClassList.h"
 #undef CSS_PSEUDO_CLASS
+
+#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
+  NS_STATIC_ATOM_BUFFER(name_, value_)
+#include "nsCSSPseudoClassList.h"
+#undef CSS_PSEUDO_CLASS
+
+static const nsStaticAtomSetup sCSSPseudoClassAtomSetup[] = {
+  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
+    NS_STATIC_ATOM_SETUP(CSSPseudoClassAtoms, name_)
+  #include "nsCSSPseudoClassList.h"
+  #undef CSS_PSEUDO_CLASS
 };
 
 // Flags data for each of the pseudo-classes, which must be separate
 // from the previous array since there's no place for it in
-// nsStaticAtom.
+// nsStaticAtomSetup.
 /* static */ const uint32_t
 nsCSSPseudoClasses::kPseudoClassFlags[] = {
-#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-  flags_,
-#include "nsCSSPseudoClassList.h"
-#undef CSS_PSEUDO_CLASS
+  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
+    flags_,
+  #include "nsCSSPseudoClassList.h"
+  #undef CSS_PSEUDO_CLASS
 };
 
 /* static */ bool
 nsCSSPseudoClasses::sPseudoClassEnabled[] = {
-// If the pseudo class has any "ENABLED_IN" flag set, it is disabled by
-// default. Note that, if a pseudo class has pref, whatever its default
-// value is, it'll later be changed in nsCSSPseudoClasses::AddRefAtoms()
-// If the pseudo class has "ENABLED_IN" flags but doesn't have a pref,
-// it is an internal pseudo class which is disabled elsewhere.
-#define IS_ENABLED_BY_DEFAULT(flags_) \
-  (!((flags_) & CSS_PSEUDO_CLASS_ENABLED_MASK))
-#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-  IS_ENABLED_BY_DEFAULT(flags_),
-#include "nsCSSPseudoClassList.h"
-#undef CSS_PSEUDO_CLASS
-#undef IS_ENABLED_BY_DEFAULT
+  // If the pseudo class has any "ENABLED_IN" flag set, it is disabled by
+  // default. Note that, if a pseudo class has pref, whatever its default
+  // value is, it'll later be changed in nsCSSPseudoClasses::AddRefAtoms()
+  // If the pseudo class has "ENABLED_IN" flags but doesn't have a pref,
+  // it is an internal pseudo class which is disabled elsewhere.
+  #define IS_ENABLED_BY_DEFAULT(flags_) \
+    (!((flags_) & CSS_PSEUDO_CLASS_ENABLED_MASK))
+  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
+    IS_ENABLED_BY_DEFAULT(flags_),
+  #include "nsCSSPseudoClassList.h"
+  #undef CSS_PSEUDO_CLASS
+  #undef IS_ENABLED_BY_DEFAULT
 };
 
 void nsCSSPseudoClasses::AddRefAtoms()
 {
-  NS_RegisterStaticAtoms(CSSPseudoClasses_info);
+  NS_RegisterStaticAtoms(sCSSPseudoClassAtomSetup);
 
-#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_)                        \
-  if (pref_[0]) {                                                             \
-    auto idx = static_cast<CSSPseudoElementTypeBase>(Type::name_);            \
-    Preferences::AddBoolVarCache(&sPseudoClassEnabled[idx], pref_);           \
-  }
-#include "nsCSSPseudoClassList.h"
-#undef CSS_PSEUDO_CLASS
+  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_)                      \
+    if (pref_[0]) {                                                           \
+      auto idx = static_cast<CSSPseudoElementTypeBase>(Type::name_);          \
+      Preferences::AddBoolVarCache(&sPseudoClassEnabled[idx], pref_);         \
+    }
+  #include "nsCSSPseudoClassList.h"
+  #undef CSS_PSEUDO_CLASS
 }
 
 bool
 nsCSSPseudoClasses::HasStringArg(Type aType)
 {
   return aType == Type::lang ||
          aType == Type::mozLocaleDir ||
          aType == Type::dir;
@@ -102,24 +109,24 @@ nsCSSPseudoClasses::HasNthPairArg(Type a
          aType == Type::nthLastOfType;
 }
 
 void
 nsCSSPseudoClasses::PseudoTypeToString(Type aType, nsAString& aString)
 {
   MOZ_ASSERT(aType < Type::Count, "Unexpected type");
   auto idx = static_cast<CSSPseudoClassTypeBase>(aType);
-  (*CSSPseudoClasses_info[idx].mAtom)->ToString(aString);
+  (*sCSSPseudoClassAtomSetup[idx].mAtom)->ToString(aString);
 }
 
 /* static */ CSSPseudoClassType
 nsCSSPseudoClasses::GetPseudoType(nsAtom* aAtom, EnabledState aEnabledState)
 {
-  for (uint32_t i = 0; i < ArrayLength(CSSPseudoClasses_info); ++i) {
-    if (*CSSPseudoClasses_info[i].mAtom == aAtom) {
+  for (uint32_t i = 0; i < ArrayLength(sCSSPseudoClassAtomSetup); ++i) {
+    if (*sCSSPseudoClassAtomSetup[i].mAtom == aAtom) {
       Type type = Type(i);
       return IsEnabled(type, aEnabledState) ? type : Type::NotPseudo;
     }
   }
   return Type::NotPseudo;
 }
 
 /* static */ bool
--- a/layout/style/nsCSSPseudoElements.cpp
+++ b/layout/style/nsCSSPseudoElements.cpp
@@ -11,55 +11,54 @@
 
 #include "nsAtomListUtils.h"
 #include "nsStaticAtom.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsDOMString.h"
 
 using namespace mozilla;
 
-// define storage for all atoms
 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
-  nsICSSPseudoElement* nsCSSPseudoElements::name_;
+  NS_STATIC_ATOM_BUFFER(name_, value_)
 #include "nsCSSPseudoElementList.h"
 #undef CSS_PSEUDO_ELEMENT
 
 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
-  NS_STATIC_ATOM_BUFFER(name_##_pseudo_element_buffer, value_)
+  NS_STATIC_ATOM_SUBCLASS_DEFN(nsICSSPseudoElement, nsCSSPseudoElements, name_)
 #include "nsCSSPseudoElementList.h"
 #undef CSS_PSEUDO_ELEMENT
 
-// Array of nsStaticAtom for each of the pseudo-elements.
-static const nsStaticAtom CSSPseudoElements_info[] = {
-#define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
-  NS_STATIC_ATOM(name_##_pseudo_element_buffer, (nsAtom**)&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(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
-// nsStaticAtom.
+// nsStaticAtomSetup.
 /* static */ const uint32_t
 nsCSSPseudoElements::kPseudoElementFlags[] = {
 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
   flags_,
 #include "nsCSSPseudoElementList.h"
 #undef CSS_PSEUDO_ELEMENT
 };
 
 void nsCSSPseudoElements::AddRefAtoms()
 {
-  NS_RegisterStaticAtoms(CSSPseudoElements_info);
+  NS_RegisterStaticAtoms(sCSSPseudoElementAtomSetup);
 }
 
 bool nsCSSPseudoElements::IsPseudoElement(nsAtom *aAtom)
 {
-  return nsAtomListUtils::IsMember(aAtom, CSSPseudoElements_info,
-                                   ArrayLength(CSSPseudoElements_info));
+  return nsAtomListUtils::IsMember(aAtom, sCSSPseudoElementAtomSetup,
+                                   ArrayLength(sCSSPseudoElementAtomSetup));
 }
 
 /* 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) ||
@@ -76,19 +75,19 @@ nsCSSPseudoElements::IsCSS2PseudoElement
                "result doesn't match flags");
   return result;
 }
 
 /* static */ CSSPseudoElementType
 nsCSSPseudoElements::GetPseudoType(nsAtom *aAtom, EnabledState aEnabledState)
 {
   for (CSSPseudoElementTypeBase i = 0;
-       i < ArrayLength(CSSPseudoElements_info);
+       i < ArrayLength(sCSSPseudoElementAtomSetup);
        ++i) {
-    if (*CSSPseudoElements_info[i].mAtom == aAtom) {
+    if (*sCSSPseudoElementAtomSetup[i].mAtom == aAtom) {
       auto type = static_cast<Type>(i);
       // ::moz-placeholder is an alias for ::placeholder
       if (type == CSSPseudoElementType::mozPlaceholder) {
         type = CSSPseudoElementType::placeholder;
       }
       return IsEnabled(type, aEnabledState) ? type : Type::NotPseudo;
     }
   }
@@ -109,17 +108,17 @@ nsCSSPseudoElements::GetPseudoType(nsAto
 
   return Type::NotPseudo;
 }
 
 /* static */ nsAtom*
 nsCSSPseudoElements::GetPseudoAtom(Type aType)
 {
   NS_ASSERTION(aType < Type::Count, "Unexpected type");
-  return *CSSPseudoElements_info[
+  return *sCSSPseudoElementAtomSetup[
     static_cast<CSSPseudoElementTypeBase>(aType)].mAtom;
 }
 
 /* static */ already_AddRefed<nsAtom>
 nsCSSPseudoElements::GetPseudoAtom(const nsAString& aPseudoElement)
 {
   if (DOMStringIsNull(aPseudoElement) || aPseudoElement.IsEmpty() ||
       aPseudoElement.First() != char16_t(':')) {
--- a/layout/style/nsCSSPseudoElements.h
+++ b/layout/style/nsCSSPseudoElements.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* atom list for CSS pseudo-elements */
 
 #ifndef nsCSSPseudoElements_h___
 #define nsCSSPseudoElements_h___
 
 #include "nsAtom.h"
+#include "nsStaticAtom.h"
 #include "mozilla/CSSEnabledState.h"
 #include "mozilla/Compiler.h"
 
 // Is this pseudo-element a CSS2 pseudo-element that can be specified
 // with the single colon syntax (in addition to the double-colon syntax,
 // which can be used for all pseudo-elements)?
 //
 // Note: We also rely on this for IsEagerlyCascadedInServo.
@@ -49,17 +50,17 @@
 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.
-#define CSS_PSEUDO_ELEMENT(_name, _value_, _flags) \
+#define CSS_PSEUDO_ELEMENT(_name, _value, _flags) \
   _name,
 #include "nsCSSPseudoElementList.h"
 #undef CSS_PSEUDO_ELEMENT
   Count,
   InheritingAnonBox = Count, // pseudo from nsCSSAnonBoxes,
                              // IsNonInheritingAnonBox false.
   NonInheritingAnonBox, // from nsCSSAnonBoxes, IsNonInheritingAnonBox true.
 #ifdef MOZ_XUL
@@ -91,17 +92,17 @@ public:
   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) \
-  static nsICSSPseudoElement* _name;
+  NS_STATIC_ATOM_SUBCLASS_DECL(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);
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -3705,17 +3705,21 @@ pref("font.name-list.sans-serif.he", "Ar
 pref("font.name-list.monospace.he", "Fixed Miriam Transparent, Miriam Fixed, Rod, Courier New");
 pref("font.name-list.cursive.he", "Guttman Yad, Ktav, Arial");
 
 pref("font.name-list.serif.ja", "Yu Mincho, MS PMincho, MS Mincho, Meiryo, Yu Gothic, MS PGothic, MS Gothic");
 pref("font.name-list.sans-serif.ja", "Meiryo, Yu Gothic, MS PGothic, MS Gothic, Yu Mincho, MS PMincho, MS Mincho");
 pref("font.name-list.monospace.ja", "MS Gothic, MS Mincho, Meiryo, Yu Gothic, Yu Mincho, MS PGothic, MS PMincho");
 
 pref("font.name-list.serif.ko", "Batang, Gulim");
+#ifdef EARLY_BETA_OR_EARLIER
+pref("font.name-list.sans-serif.ko", "Malgun Gothic, Gulim");
+#else
 pref("font.name-list.sans-serif.ko", "Gulim, Malgun Gothic");
+#endif
 pref("font.name-list.monospace.ko", "GulimChe");
 pref("font.name-list.cursive.ko", "Gungsuh");
 
 pref("font.name-list.serif.th", "Tahoma");
 pref("font.name-list.sans-serif.th", "Tahoma");
 pref("font.name-list.monospace.th", "Tahoma");
 pref("font.name-list.cursive.th", "Tahoma");
 
--- a/parser/htmlparser/nsHTMLTags.cpp
+++ b/parser/htmlparser/nsHTMLTags.cpp
@@ -18,24 +18,20 @@ using namespace mozilla;
 #define HTML_TAG(_tag, _classname, _interfacename) (u"" #_tag),
 #define HTML_OTHER(_tag)
 const char16_t* const nsHTMLTags::sTagUnicodeTable[] = {
 #include "nsHTMLTagList.h"
 };
 #undef HTML_TAG
 #undef HTML_OTHER
 
-// static array of tag atoms
-nsAtom* nsHTMLTags::sTagAtomTable[eHTMLTag_userdefined - 1];
-
 int32_t nsHTMLTags::gTableRefCount;
 PLHashTable* nsHTMLTags::gTagTable;
 PLHashTable* nsHTMLTags::gTagAtomTable;
 
-
 // char16_t* -> id hash
 static PLHashNumber
 HTMLTagsHashCodeUCPtr(const void *key)
 {
   return HashString(static_cast<const char16_t*>(key));
 }
 
 static int
@@ -51,54 +47,56 @@ HTMLTagsKeyCompareUCPtr(const void *key1
 static PLHashNumber
 HTMLTagsHashCodeAtom(const void *key)
 {
   return NS_PTR_TO_INT32(key) >> 2;
 }
 
 #define NS_HTMLTAG_NAME_MAX_LENGTH 10
 
-// static
-void
-nsHTMLTags::RegisterAtoms(void)
-{
-#define HTML_TAG(_tag, _classname, _interfacename) NS_STATIC_ATOM_BUFFER(Atombuffer_##_tag, #_tag)
+// This would use NS_STATIC_ATOM_DEFN if it wasn't an array.
+nsAtom* nsHTMLTags::sTagAtomTable[eHTMLTag_userdefined - 1];
+
+#define HTML_TAG(_tag, _classname, _interfacename) \
+  NS_STATIC_ATOM_BUFFER(_tag, #_tag)
 #define HTML_OTHER(_tag)
 #include "nsHTMLTagList.h"
 #undef HTML_TAG
 #undef HTML_OTHER
 
-// static array of tag StaticAtom structs
-#define HTML_TAG(_tag, _classname, _interfacename) NS_STATIC_ATOM(Atombuffer_##_tag, &nsHTMLTags::sTagAtomTable[eHTMLTag_##_tag - 1]),
-#define HTML_OTHER(_tag)
-  static const nsStaticAtom sTagAtoms_info[] = {
-#include "nsHTMLTagList.h"
+/* static */ void
+nsHTMLTags::RegisterAtoms(void)
+{
+  // This would use NS_STATIC_ATOM_SETUP if it wasn't an array.
+  static const nsStaticAtomSetup sTagAtomSetup[] = {
+    #define HTML_TAG(_tag, _classname, _interfacename) \
+      { _tag##_buffer, &nsHTMLTags::sTagAtomTable[eHTMLTag_##_tag - 1] },
+    #define HTML_OTHER(_tag)
+    #include "nsHTMLTagList.h"
+    #undef HTML_TAG
+    #undef HTML_OTHER
   };
-#undef HTML_TAG
-#undef HTML_OTHER
 
-  // Fill in our static atom pointers
-  NS_RegisterStaticAtoms(sTagAtoms_info);
-
+  NS_RegisterStaticAtoms(sTagAtomSetup);
 
 #if defined(DEBUG)
   {
     // let's verify that all names in the the table are lowercase...
     for (int32_t i = 0; i < NS_HTML_TAG_MAX; ++i) {
-      nsAutoString temp1((char16_t*)sTagAtoms_info[i].mString);
-      nsAutoString temp2((char16_t*)sTagAtoms_info[i].mString);
+      nsAutoString temp1((char16_t*)sTagAtomSetup[i].mString);
+      nsAutoString temp2((char16_t*)sTagAtomSetup[i].mString);
       ToLowerCase(temp1);
       NS_ASSERTION(temp1.Equals(temp2), "upper case char in table");
     }
 
     // let's verify that all names in the unicode strings above are
     // correct.
     for (int32_t i = 0; i < NS_HTML_TAG_MAX; ++i) {
       nsAutoString temp1(sTagUnicodeTable[i]);
-      nsAutoString temp2((char16_t*)sTagAtoms_info[i].mString);
+      nsAutoString temp2((char16_t*)sTagAtomSetup[i].mString);
       NS_ASSERTION(temp1.Equals(temp2), "Bad unicode tag name!");
     }
 
     // let's verify that NS_HTMLTAG_NAME_MAX_LENGTH is correct
     uint32_t maxTagNameLength = 0;
     for (int32_t i = 0; i < NS_HTML_TAG_MAX; ++i) {
       uint32_t len = NS_strlen(sTagUnicodeTable[i]);
       maxTagNameLength = std::max(len, maxTagNameLength);
--- a/parser/htmlparser/nsHTMLTags.h
+++ b/parser/htmlparser/nsHTMLTags.h
@@ -1,21 +1,20 @@
 /* -*- 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 "plhash.h"
 
-class nsAtom;
-
 /*
    Declare the enum list using the magic of preprocessing
    enum values are "eHTMLTag_foo" (where foo is the tag)
 
    To change the list of tags, see nsHTMLTagList.h
 
    These enum values are used as the index of array in various places.
    If we change the structure of the enum by adding entries to it or removing
@@ -71,16 +70,17 @@ public:
     return tag ? (nsHTMLTag)NS_PTR_TO_INT32(tag) : eHTMLTag_userdefined;
   }
 
 #ifdef DEBUG
   static void TestTagTable();
 #endif
 
 private:
+  // This would use NS_STATIC_ATOM_DECL if it wasn't an array.
   static nsAtom* sTagAtomTable[eHTMLTag_userdefined - 1];
   static const char16_t* const sTagUnicodeTable[];
 
   static int32_t gTableRefCount;
   static PLHashTable* gTagTable;
   static PLHashTable* gTagAtomTable;
 };
 
--- a/rdf/base/nsRDFContentSink.cpp
+++ b/rdf/base/nsRDFContentSink.cpp
@@ -121,19 +121,19 @@ public:
     static nsIRDFContainerUtils* gRDFContainerUtils;
     static nsIRDFResource* kRDF_type;
     static nsIRDFResource* kRDF_instanceOf; // XXX should be RDF:type
     static nsIRDFResource* kRDF_Alt;
     static nsIRDFResource* kRDF_Bag;
     static nsIRDFResource* kRDF_Seq;
     static nsIRDFResource* kRDF_nextVal;
 
-#define RDF_ATOM(name_, value_) static nsAtom* name_;
-#include "nsRDFContentSinkAtomList.h"
-#undef RDF_ATOM
+    #define RDF_ATOM(name_, value_) NS_STATIC_ATOM_DECL(name_)
+    #include "nsRDFContentSinkAtomList.h"
+    #undef RDF_ATOM
 
     typedef struct ContainerInfo {
         nsIRDFResource**  mType;
         nsContainerTestFn mTestFn;
         nsMakeContainerFn mMakeFn;
     } ContainerInfo;
 
 protected:
@@ -230,35 +230,36 @@ nsIRDFResource* RDFContentSinkImpl::kRDF
 nsIRDFResource* RDFContentSinkImpl::kRDF_Bag;
 nsIRDFResource* RDFContentSinkImpl::kRDF_Seq;
 nsIRDFResource* RDFContentSinkImpl::kRDF_nextVal;
 
 mozilla::LazyLogModule RDFContentSinkImpl::gLog("nsRDFContentSink");
 
 ////////////////////////////////////////////////////////////////////////
 
-#define RDF_ATOM(name_, value_) nsAtom* RDFContentSinkImpl::name_;
+#define RDF_ATOM(name_, value_) NS_STATIC_ATOM_DEFN(RDFContentSinkImpl, name_)
 #include "nsRDFContentSinkAtomList.h"
 #undef RDF_ATOM
 
-#define RDF_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#define RDF_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_, value_)
 #include "nsRDFContentSinkAtomList.h"
 #undef RDF_ATOM
 
-static const nsStaticAtom rdf_atoms[] = {
-#define RDF_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &RDFContentSinkImpl::name_),
-#include "nsRDFContentSinkAtomList.h"
-#undef RDF_ATOM
+static const nsStaticAtomSetup sRDFContentSinkAtomSetup[] = {
+  #define RDF_ATOM(name_, value_) \
+    NS_STATIC_ATOM_SETUP(RDFContentSinkImpl, name_)
+  #include "nsRDFContentSinkAtomList.h"
+  #undef RDF_ATOM
 };
 
 // static
 void
 nsRDFAtoms::RegisterAtoms()
 {
-    NS_RegisterStaticAtoms(rdf_atoms);
+    NS_RegisterStaticAtoms(sRDFContentSinkAtomSetup);
 }
 
 RDFContentSinkImpl::RDFContentSinkImpl()
     : mText(nullptr),
       mTextLength(0),
       mTextSize(0),
       mState(eRDFContentSinkState_InProlog),
       mParseMode(eRDFContentSinkParseMode_Literal),
--- a/rdf/datasource/nsLocalStore.cpp
+++ b/rdf/datasource/nsLocalStore.cpp
@@ -416,17 +416,17 @@ LocalStoreImpl::LoadData()
 
     return rv;
 }
 
 
 NS_IMETHODIMP
 LocalStoreImpl::GetURI(nsACString& aURI)
 {
-    aURI.AssignLiteral("rd:local-store");
+    aURI.AssignLiteral("rdf:local-store");
     return NS_OK;
 }
 
 
 NS_IMETHODIMP
 LocalStoreImpl::GetAllCmds(nsIRDFResource* aSource,
                                nsISimpleEnumerator/*<nsIRDFResource>*/** aCommands)
 {
--- a/toolkit/components/printingui/ipc/PrintProgressDialogChild.cpp
+++ b/toolkit/components/printingui/ipc/PrintProgressDialogChild.cpp
@@ -91,40 +91,40 @@ PrintProgressDialogChild::OnSecurityChan
                                            nsIRequest* aRequest,
                                            uint32_t aState)
 {
   return NS_OK;
 }
 
 // nsIPrintProgressParams
 
-NS_IMETHODIMP PrintProgressDialogChild::GetDocTitle(char16_t* *aDocTitle)
+NS_IMETHODIMP
+PrintProgressDialogChild::GetDocTitle(nsAString& aDocTitle)
 {
-  NS_ENSURE_ARG(aDocTitle);
-
-  *aDocTitle = ToNewUnicode(mDocTitle);
+  aDocTitle = mDocTitle;
   return NS_OK;
 }
 
-NS_IMETHODIMP PrintProgressDialogChild::SetDocTitle(const char16_t* aDocTitle)
+NS_IMETHODIMP
+PrintProgressDialogChild::SetDocTitle(const nsAString& aDocTitle)
 {
   mDocTitle = aDocTitle;
-  Unused << SendDocTitleChange(nsString(aDocTitle));
+  Unused << SendDocTitleChange(PromiseFlatString(aDocTitle));
   return NS_OK;
 }
 
-NS_IMETHODIMP PrintProgressDialogChild::GetDocURL(char16_t **aDocURL)
+NS_IMETHODIMP
+PrintProgressDialogChild::GetDocURL(nsAString& aDocURL)
 {
-  NS_ENSURE_ARG(aDocURL);
-
-  *aDocURL = ToNewUnicode(mDocURL);
+  aDocURL = mDocURL;
   return NS_OK;
 }
 
-NS_IMETHODIMP PrintProgressDialogChild::SetDocURL(const char16_t* aDocURL)
+NS_IMETHODIMP
+PrintProgressDialogChild::SetDocURL(const nsAString& aDocURL)
 {
   mDocURL = aDocURL;
-  Unused << SendDocURLChange(nsString(aDocURL));
+  Unused << SendDocURLChange(PromiseFlatString(aDocURL));
   return NS_OK;
 }
 
 } // namespace embedding
 } // namespace mozilla
--- a/toolkit/components/printingui/ipc/PrintProgressDialogParent.cpp
+++ b/toolkit/components/printingui/ipc/PrintProgressDialogParent.cpp
@@ -58,26 +58,26 @@ PrintProgressDialogParent::RecvProgressC
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 PrintProgressDialogParent::RecvDocTitleChange(const nsString& newTitle)
 {
   if (mPrintProgressParams) {
-    mPrintProgressParams->SetDocTitle(newTitle.get());
+    mPrintProgressParams->SetDocTitle(newTitle);
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 PrintProgressDialogParent::RecvDocURLChange(const nsString& newURL)
 {
   if (mPrintProgressParams) {
-    mPrintProgressParams->SetDocURL(newURL.get());
+    mPrintProgressParams->SetDocURL(newURL);
   }
   return IPC_OK();
 }
 
 void
 PrintProgressDialogParent::ActorDestroy(ActorDestroyReason aWhy)
 {
 }
--- a/toolkit/components/printingui/unixshared/nsPrintProgressParams.cpp
+++ b/toolkit/components/printingui/unixshared/nsPrintProgressParams.cpp
@@ -12,36 +12,36 @@ NS_IMPL_ISUPPORTS(nsPrintProgressParams,
 nsPrintProgressParams::nsPrintProgressParams()
 {
 }
 
 nsPrintProgressParams::~nsPrintProgressParams()
 {
 }
 
-NS_IMETHODIMP nsPrintProgressParams::GetDocTitle(char16_t * *aDocTitle)
+NS_IMETHODIMP
+nsPrintProgressParams::GetDocTitle(nsAString& aDocTitle)
 {
-  NS_ENSURE_ARG(aDocTitle);
-
-  *aDocTitle = ToNewUnicode(mDocTitle);
+  aDocTitle = mDocTitle;
   return NS_OK;
 }
 
-NS_IMETHODIMP nsPrintProgressParams::SetDocTitle(const char16_t * aDocTitle)
+NS_IMETHODIMP
+nsPrintProgressParams::SetDocTitle(const nsAString& aDocTitle)
 {
   mDocTitle = aDocTitle;
   return NS_OK;
 }
 
-NS_IMETHODIMP nsPrintProgressParams::GetDocURL(char16_t * *aDocURL)
+NS_IMETHODIMP
+nsPrintProgressParams::GetDocURL(nsAString& aDocURL)
 {
-  NS_ENSURE_ARG(aDocURL);
-
-  *aDocURL = ToNewUnicode(mDocURL);
+  aDocURL = mDocURL;
   return NS_OK;
 }
 
-NS_IMETHODIMP nsPrintProgressParams::SetDocURL(const char16_t * aDocURL)
+NS_IMETHODIMP
+nsPrintProgressParams::SetDocURL(const nsAString& aDocURL)
 {
   mDocURL = aDocURL;
   return NS_OK;
 }
 
--- a/toolkit/components/printingui/win/nsPrintProgressParams.cpp
+++ b/toolkit/components/printingui/win/nsPrintProgressParams.cpp
@@ -12,36 +12,36 @@ NS_IMPL_ISUPPORTS(nsPrintProgressParams,
 nsPrintProgressParams::nsPrintProgressParams()
 {
 }
 
 nsPrintProgressParams::~nsPrintProgressParams()
 {
 }
 
-NS_IMETHODIMP nsPrintProgressParams::GetDocTitle(char16_t * *aDocTitle)
+NS_IMETHODIMP
+nsPrintProgressParams::GetDocTitle(nsAString& aDocTitle)
 {
-  NS_ENSURE_ARG(aDocTitle);
-
-  *aDocTitle = ToNewUnicode(mDocTitle);
+  aDocTitle = mDocTitle;
   return NS_OK;
 }
 
-NS_IMETHODIMP nsPrintProgressParams::SetDocTitle(const char16_t * aDocTitle)
+NS_IMETHODIMP
+nsPrintProgressParams::SetDocTitle(const nsAString& aDocTitle)
 {
   mDocTitle = aDocTitle;
   return NS_OK;
 }
 
-NS_IMETHODIMP nsPrintProgressParams::GetDocURL(char16_t * *aDocURL)
+NS_IMETHODIMP
+nsPrintProgressParams::GetDocURL(nsAString& aDocURL)
 {
-  NS_ENSURE_ARG(aDocURL);
-
-  *aDocURL = ToNewUnicode(mDocURL);
+  aDocURL = mDocURL;
   return NS_OK;
 }
 
-NS_IMETHODIMP nsPrintProgressParams::SetDocURL(const char16_t * aDocURL)
+NS_IMETHODIMP
+nsPrintProgressParams::SetDocURL(const nsAString& aDocURL)
 {
   mDocURL = aDocURL;
   return NS_OK;
 }
 
--- a/xpcom/ds/nsAtomTable.cpp
+++ b/xpcom/ds/nsAtomTable.cpp
@@ -8,16 +8,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/Unused.h"
 
+#include "nsAtom.h"
 #include "nsAtomTable.h"
 #include "nsStaticAtom.h"
 #include "nsString.h"
 #include "nsCRT.h"
 #include "PLDHashTable.h"
 #include "prenv.h"
 #include "nsThreadUtils.h"
 #include "nsDataHashtable.h"
@@ -52,18 +53,18 @@ enum class GCKind {
   Shutdown,
 };
 
 // This class encapsulates the functions that need access to nsAtom's private
 // members.
 class nsAtomFriend
 {
 public:
-  static void RegisterStaticAtoms(const nsStaticAtom* aAtoms,
-                                  uint32_t aAtomCount);
+  static void RegisterStaticAtoms(const nsStaticAtomSetup* aSetup,
+                                  uint32_t aCount);
 
   static void AtomTableClearEntry(PLDHashTable* aTable,
                                   PLDHashEntryHdr* aEntry);
 
   static void GCAtomTableLocked(const MutexAutoLock& aProofOfLock,
                                 GCKind aKind);
 
   static already_AddRefed<nsAtom> Atomize(const nsACString& aUTF8String);
@@ -477,36 +478,45 @@ static bool gStaticAtomTableSealed = fal
 // shrink it to 4096 entries.
 //
 // By choosing an initial length of 4096, we get an initial capacity of 8192.
 // That's the biggest initial capacity that will let us be > 25% full when the
 // first dynamic atom is removed (when the count is ~2700), thus avoiding any
 // shrinking.
 #define ATOM_HASHTABLE_INITIAL_LENGTH  4096
 
+class DefaultAtoms
+{
+public:
+  NS_STATIC_ATOM_DECL(empty)
+};
+
+NS_STATIC_ATOM_DEFN(DefaultAtoms, empty)
+
+NS_STATIC_ATOM_BUFFER(empty, "")
+
+static const nsStaticAtomSetup sDefaultAtomSetup[] = {
+  NS_STATIC_ATOM_SETUP(DefaultAtoms, empty)
+};
+
 void
 NS_InitAtomTable()
 {
   MOZ_ASSERT(!gAtomTable);
   gAtomTable = new PLDHashTable(&AtomTableOps, sizeof(AtomTableEntry),
                                 ATOM_HASHTABLE_INITIAL_LENGTH);
   gAtomTableLock = new Mutex("Atom Table Lock");
 
   // Bug 1340710 has caused us to generate an empty atom at arbitrary times
   // after startup.  If we end up creating one before nsGkAtoms::_empty is
   // registered, we get an assertion about transmuting a dynamic atom into a
   // static atom.  In order to avoid that, we register an empty string static
   // atom as soon as we initialize the atom table to guarantee that the empty
   // string atom will always be static.
-  NS_STATIC_ATOM_BUFFER(empty, "");
-  static nsAtom* empty_atom = nullptr;
-  static const nsStaticAtom default_atoms[] = {
-    NS_STATIC_ATOM(empty, &empty_atom)
-  };
-  NS_RegisterStaticAtoms(default_atoms);
+  NS_RegisterStaticAtoms(sDefaultAtomSetup);
 }
 
 void
 NS_ShutdownAtomTable()
 {
   delete gStaticAtomTable;
   gStaticAtomTable = nullptr;
 
@@ -557,31 +567,31 @@ GetAtomHashEntry(const char16_t* aString
 {
   gAtomTableLock->AssertCurrentThreadOwns();
   AtomTableKey key(aString, aLength, aHashOut);
   // This is an infallible add.
   return static_cast<AtomTableEntry*>(gAtomTable->Add(&key));
 }
 
 void
-nsAtomFriend::RegisterStaticAtoms(const nsStaticAtom* aAtoms,
-                                  uint32_t aAtomCount)
+nsAtomFriend::RegisterStaticAtoms(const nsStaticAtomSetup* aSetup,
+                                  uint32_t aCount)
 {
   MutexAutoLock lock(*gAtomTableLock);
 
   MOZ_RELEASE_ASSERT(!gStaticAtomTableSealed,
                      "Atom table has already been sealed!");
 
   if (!gStaticAtomTable) {
     gStaticAtomTable = new StaticAtomTable();
   }
 
-  for (uint32_t i = 0; i < aAtomCount; ++i) {
-    const char16_t* string = aAtoms[i].mString;
-    nsAtom** atomp = aAtoms[i].mAtom;
+  for (uint32_t i = 0; i < aCount; ++i) {
+    const char16_t* string = aSetup[i].mString;
+    nsAtom** atomp = aSetup[i].mAtom;
 
     MOZ_ASSERT(nsCRT::IsAscii(string));
 
     uint32_t stringLen = NS_strlen(string);
 
     uint32_t hash;
     AtomTableEntry* he = GetAtomHashEntry(string, stringLen, &hash);
 
@@ -608,19 +618,19 @@ nsAtomFriend::RegisterStaticAtoms(const 
         gStaticAtomTable->PutEntry(nsDependentAtomString(atom));
       MOZ_ASSERT(atom->IsStaticAtom());
       entry->mAtom = atom;
     }
   }
 }
 
 void
-RegisterStaticAtoms(const nsStaticAtom* aAtoms, uint32_t aAtomCount)
+RegisterStaticAtoms(const nsStaticAtomSetup* aSetup, uint32_t aCount)
 {
-  nsAtomFriend::RegisterStaticAtoms(aAtoms, aAtomCount);
+  nsAtomFriend::RegisterStaticAtoms(aSetup, aCount);
 }
 
 already_AddRefed<nsAtom>
 NS_Atomize(const char* aUTF8String)
 {
   return nsAtomFriend::Atomize(nsDependentCString(aUTF8String));
 }
 
--- a/xpcom/ds/nsStaticAtom.h
+++ b/xpcom/ds/nsStaticAtom.h
@@ -2,42 +2,128 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsStaticAtom_h__
 #define nsStaticAtom_h__
 
-#include "nsAtom.h"
-#include "nsStringBuffer.h"
+#include <stdint.h>
+
+class nsAtom;
 
-#define NS_STATIC_ATOM(buffer_name, atom_ptr) \
-  { buffer_name, atom_ptr }
+// 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.
+//
+// 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 might look like this:
+//
+//   class MyAtoms {
+//   public:
+//     #define MY_ATOM(_name, _value) NS_STATIC_ATOM_DECL(_name)
+//     #include "MyAtomList.h"
+//     #undef MY_ATOM
+//   };
+//
+//   #define MY_ATOM(name_, value_) NS_STATIC_ATOM_DEFN(MyAtoms, name_)
+//   #include "MyAtomList.h"
+//   #undef MY_ATOM
+//
+//   #define MY_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_, value_)
+//   #include "MyAtomList.h"
+//   #undef MY_ATOM
+//
+//   static const nsStaticAtomSetup sMyAtomSetup[] = {
+//     #define MY_ATOM(name_, value_) NS_STATIC_ATOM_SETUP(MyAtoms, name_)
+//     #include "MyAtomList.h"
+//     #undef MY_ATOM
+//   };
+//
+// The macros expand to the following:
+//
+//   class MyAtoms
+//   {
+//   public:
+//     static nsAtom* one;
+//     static nsAtom* two;
+//     static nsAtom* three;
+//   };
+//
+//   nsAtom* MyAtoms::one;
+//   nsAtom* MyAtoms::two;
+//   nsAtom* MyAtoms::three;
+//
+//   static const char16_t one_buffer[4] = u"one";     // plus a static_assert
+//   static const char16_t two_buffer[4] = u"two";     // plus a static_assert
+//   static const char16_t three_buffer[6] = u"three"; // plus a static_assert
+//
+//   static const nsStaticAtomSetup sMyAtomSetup[] = {
+//     { one_buffer, &MyAtoms::one },
+//     { two_buffer, &MyAtoms::two },
+//     { three_buffer, &MyAtoms::three },
+//   };
+//
+// When RegisterStaticAtoms(sMyAtomSetup) is called it iterates over
+// sMyAtomSetup[]. E.g. for the first atom it does roughly the following:
+// - MyAtoms::one = new nsAtom(one_buffer)
+// - inserts MyAtoms::one into the atom table
 
-// Note that |str_data| is an 8-bit string, and so |sizeof(str_data)| is equal
+// The declaration of the pointer to the static atom, which must be within a
+// class.
+#define NS_STATIC_ATOM_DECL(name_) \
+  static nsAtom* name_;
+
+// Like NS_STATIC_ATOM_DECL, but for sub-classes of nsAtom.
+#define NS_STATIC_ATOM_SUBCLASS_DECL(type_, name_) \
+  static type_* name_;
+
+// The definition of the pointer to the static atom. Initially null, it is
+// set by RegisterStaticAtoms() to point to a heap-allocated nsAtom.
+#define NS_STATIC_ATOM_DEFN(class_, name_) \
+  nsAtom* class_::name_;
+
+// Like NS_STATIC_ATOM_DEFN, but for sub-classes of nsAtom.
+#define NS_STATIC_ATOM_SUBCLASS_DEFN(type_, class_, name_) \
+  type_* class_::name_;
+
+// The buffer of 16-bit chars that constitute the static atom.
+//
+// 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 |str_data| to a 16-bit string, which is assigned.
-#define NS_STATIC_ATOM_BUFFER(buffer_name, str_data) \
-  static const char16_t buffer_name[sizeof(str_data)] = u"" str_data; \
-  static_assert(sizeof(str_data[0]) == 1, "non-8-bit static atom literal");
+// converts |value_| to a 16-bit string, which is what is assigned.
+#define NS_STATIC_ATOM_BUFFER(name_, value_) \
+  static const char16_t name_##_buffer[sizeof(value_)] = u"" value_; \
+  static_assert(sizeof(value_[0]) == 1, "non-8-bit static atom literal");
+
+// The StaticAtomSetup. Used only during start-up.
+#define NS_STATIC_ATOM_SETUP(class_, name_) \
+  { name_##_buffer, &class_::name_ },
 
-/**
- * Holds data used to initialize large number of atoms during startup. Use
- * the above macros to initialize these structs. They should never be accessed
- * directly other than from AtomTable.cpp.
- */
-struct nsStaticAtom
+// Like NS_STATIC_ATOM_SUBCLASS, but for sub-classes of nsAtom.
+#define NS_STATIC_ATOM_SUBCLASS_SETUP(class_, name_) \
+  { name_##_buffer, reinterpret_cast<nsAtom**>(&class_::name_) },
+
+// Holds data used to initialize large number of atoms during startup. Use
+// NS_STATIC_ATOM_SETUP to initialize these structs. They should never be
+// accessed directly other than from nsAtomTable.cpp.
+struct nsStaticAtomSetup
 {
   const char16_t* const mString;
   nsAtom** const mAtom;
 };
 
-// Register an array of static atoms with the atom table
+// Register an array of static atoms with the atom table.
 template<uint32_t N>
 void
-NS_RegisterStaticAtoms(const nsStaticAtom (&aAtoms)[N])
+NS_RegisterStaticAtoms(const nsStaticAtomSetup (&aSetup)[N])
 {
-  extern void RegisterStaticAtoms(const nsStaticAtom*, uint32_t aAtomCount);
-  RegisterStaticAtoms(aAtoms, N);
+  extern void RegisterStaticAtoms(const nsStaticAtomSetup* aSetup,
+                                  uint32_t aCount);
+  RegisterStaticAtoms(aSetup, N);
 }
 
 #endif
--- a/xpcom/io/nsDirectoryService.cpp
+++ b/xpcom/io/nsDirectoryService.cpp
@@ -100,28 +100,29 @@ nsDirectoryService::Create(nsISupports* 
 
   if (!gService) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   return gService->QueryInterface(aIID, aResult);
 }
 
-#define DIR_ATOM(name_, value_) nsAtom* nsDirectoryService::name_ = nullptr;
+#define DIR_ATOM(name_, value_) NS_STATIC_ATOM_DEFN(nsDirectoryService, name_)
 #include "nsDirectoryServiceAtomList.h"
 #undef DIR_ATOM
 
-#define DIR_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#define DIR_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_, value_)
 #include "nsDirectoryServiceAtomList.h"
 #undef DIR_ATOM
 
-static const nsStaticAtom directory_atoms[] = {
-#define DIR_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &nsDirectoryService::name_),
-#include "nsDirectoryServiceAtomList.h"
-#undef DIR_ATOM
+static const nsStaticAtomSetup sDirectoryServiceAtomSetup[] = {
+  #define DIR_ATOM(name_, value_) \
+    NS_STATIC_ATOM_SETUP(nsDirectoryService, name_)
+  #include "nsDirectoryServiceAtomList.h"
+  #undef DIR_ATOM
 };
 
 NS_IMETHODIMP
 nsDirectoryService::Init()
 {
   NS_NOTREACHED("nsDirectoryService::Init() for internal use only!");
   return NS_OK;
 }
@@ -129,17 +130,17 @@ nsDirectoryService::Init()
 void
 nsDirectoryService::RealInit()
 {
   NS_ASSERTION(!gService,
                "nsDirectoryService::RealInit Mustn't initialize twice!");
 
   gService = new nsDirectoryService();
 
-  NS_RegisterStaticAtoms(directory_atoms);
+  NS_RegisterStaticAtoms(sDirectoryServiceAtomSetup);
 
   // 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
@@ -6,16 +6,17 @@
 
 #ifndef nsDirectoryService_h___
 #define nsDirectoryService_h___
 
 #include "nsIDirectoryService.h"
 #include "nsInterfaceHashtable.h"
 #include "nsIFile.h"
 #include "nsAtom.h"
+#include "nsStaticAtom.h"
 #include "nsTArray.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/StaticPtr.h"
 
 #define NS_XPCOM_INIT_CURRENT_PROCESS_DIR       "MozBinD"   // Can be used to set NS_XPCOM_CURRENT_PROCESS_DIR
                                                             // CANNOT be used to GET a location
 #define NS_DIRECTORY_SERVICE_CID  {0xf00152d0,0xb40b,0x11d3,{0x8c, 0x9c, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74}}
 
@@ -49,18 +50,14 @@ private:
   ~nsDirectoryService();
 
   nsresult GetCurrentProcessDirectory(nsIFile** aFile);
 
   nsInterfaceHashtable<nsCStringHashKey, nsIFile> mHashtable;
   nsTArray<nsCOMPtr<nsIDirectoryServiceProvider>> mProviders;
 
 public:
-
-#define DIR_ATOM(name_, value_) static nsAtom* name_;
-#include "nsDirectoryServiceAtomList.h"
-#undef DIR_ATOM
-
+  #define DIR_ATOM(name_, value_) NS_STATIC_ATOM_DECL(name_)
+  #include "nsDirectoryServiceAtomList.h"
+  #undef DIR_ATOM
 };
 
-
 #endif
-