Backed out 12 changesets (bug 1344629) for stylo build bustage
authorIris Hsiao <ihsiao@mozilla.com>
Tue, 14 Mar 2017 11:52:24 +0800
changeset 395559 8d1f842be870197a94b4c1538ddfe9d9d357b79f
parent 395558 4c62935c570fa37a3a0807d068e22565acb1f069
child 395560 7a5276126c9419c4ffc4775bb979bc2a7e385cce
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1344629
milestone55.0a1
backs outcf4273d3ac30ee8e9320ef1f70a6fd097ef3c7b8
a96390e044e0e82051335ad050222d1db73da65a
d9b330f9bc245c8bea3333aef3d47e1454d47180
2b460fe020afba0b8e3bee63dbab781e63350ef2
0ada91b0452e646a8e394e34f84fd3ad9160a2fc
083304fcd6bd97d0822439f8f04a13a47f49bc26
53d7d1ce2c97a8a82f8422ddc70efac986f46318
55eee7078ae4bc342710b9e3a7051a8aa177d872
7d3c06b3eca939c10e6f37eae4efa686f874dc9c
e5df14c3db61b8e434dcadee3db0ae8c3be22ab0
636095ff2815186ef647a7d05598ae75bf1ad6d8
0be052ad24c1d058cf629ef490c48f7c5b2510bb
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
Backed out 12 changesets (bug 1344629) for stylo build bustage Backed out changeset cf4273d3ac30 (bug 1344629) Backed out changeset a96390e044e0 (bug 1344629) Backed out changeset d9b330f9bc24 (bug 1344629) Backed out changeset 2b460fe020af (bug 1344629) Backed out changeset 0ada91b0452e (bug 1344629) Backed out changeset 083304fcd6bd (bug 1344629) Backed out changeset 53d7d1ce2c97 (bug 1344629) Backed out changeset 55eee7078ae4 (bug 1344629) Backed out changeset 7d3c06b3eca9 (bug 1344629) Backed out changeset e5df14c3db61 (bug 1344629) Backed out changeset 636095ff2815 (bug 1344629) Backed out changeset 0be052ad24c1 (bug 1344629)
browser/components/shell/nsWindowsShellService.cpp
dom/base/nsJSEnvironment.cpp
dom/html/ImageDocument.cpp
dom/html/MediaDocument.cpp
dom/jsurl/nsJSProtocolHandler.cpp
dom/power/PowerManagerService.cpp
dom/security/nsCSPParser.cpp
dom/xhr/XMLHttpRequestMainThread.cpp
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLStyleEditor.cpp
editor/libeditor/TextEditRules.cpp
layout/generic/nsPageFrame.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp
netwerk/base/nsIOService.cpp
netwerk/protocol/ftp/nsFtpConnectionThread.cpp
netwerk/protocol/http/nsHttpHandler.cpp
security/manager/ssl/nsNSSComponent.cpp
security/manager/ssl/nsNSSU2FToken.cpp
storage/VacuumManager.cpp
toolkit/components/find/nsWebBrowserFind.cpp
toolkit/components/startup/nsAppStartup.cpp
toolkit/xre/nsEmbedFunctions.cpp
toolkit/xre/nsNativeAppSupportWin.cpp
toolkit/xre/nsXREDirProvider.cpp
widget/android/jni/Refs.h
widget/android/nsAppShell.cpp
widget/windows/WindowsUIUtils.cpp
widget/windows/nsFilePicker.cpp
widget/windows/nsWindow.cpp
xpcom/base/nsSystemInfo.cpp
xpcom/io/SpecialSystemDirectory.cpp
xpcom/string/nsLiteralString.h
xpcom/string/nsStringFwd.h
xpcom/string/nsStringIterator.h
xpcom/string/nsSubstringTuple.cpp
xpcom/string/nsTLiteralString.h
xpcom/string/nsTPromiseFlatString.cpp
xpcom/string/nsTString.h
xpcom/string/nsTSubstring.cpp
xpcom/string/nsTSubstring.h
xpcom/string/nsTSubstringTuple.cpp
xpcom/string/nsTSubstringTuple.h
xpcom/string/string-template-def-char.h
xpcom/string/string-template-def-unichar.h
xpcom/string/string-template-undef.h
xpcom/tests/gtest/TestObserverService.cpp
xpcom/threads/nsThread.cpp
xpfe/appshell/nsAppShellFactory.cpp
xpfe/appshell/nsChromeTreeOwner.cpp
xpfe/appshell/nsChromeTreeOwner.h
--- a/browser/components/shell/nsWindowsShellService.cpp
+++ b/browser/components/shell/nsWindowsShellService.cpp
@@ -161,24 +161,24 @@ nsWindowsShellService::ShortcutMaintenan
   taskbarInfo->GetAvailable(&isSupported);
   if (!isSupported)
     return NS_OK;
 
   nsAutoString appId;
   if (NS_FAILED(taskbarInfo->GetDefaultGroupId(appId)))
     return NS_ERROR_UNEXPECTED;
 
-  const char* prefName = "browser.taskbar.lastgroupid";
+  NS_NAMED_LITERAL_CSTRING(prefName, "browser.taskbar.lastgroupid");
   nsCOMPtr<nsIPrefBranch> prefs =
     do_GetService(NS_PREFSERVICE_CONTRACTID);
   if (!prefs)
     return NS_ERROR_UNEXPECTED;
 
   nsCOMPtr<nsISupportsString> prefString;
-  rv = prefs->GetComplexValue(prefName,
+  rv = prefs->GetComplexValue(prefName.get(),
                               NS_GET_IID(nsISupportsString),
                               getter_AddRefs(prefString));
   if (NS_SUCCEEDED(rv)) {
     nsAutoString version;
     prefString->GetData(version);
     if (!version.IsEmpty() && version.Equals(appId)) {
       // We're all good, get out of here.
       return NS_OK;
@@ -186,17 +186,17 @@ nsWindowsShellService::ShortcutMaintenan
   }
   // Update the version in prefs
   prefString =
     do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
   if (NS_FAILED(rv))
     return rv;
 
   prefString->SetData(appId);
-  rv = prefs->SetComplexValue(prefName,
+  rv = prefs->SetComplexValue(prefName.get(),
                               NS_GET_IID(nsISupportsString),
                               prefString);
   if (NS_FAILED(rv)) {
     NS_WARNING("Couldn't set last user model id!");
     return NS_ERROR_UNEXPECTED;
   }
 
   nsAutoString appHelperPath;
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1627,21 +1627,21 @@ nsJSContext::EndCycleCollectionCallback(
       mergeMsg.AssignLiteral(" merged");
     }
 
     nsCString gcMsg;
     if (aResults.mForcedGC) {
       gcMsg.AssignLiteral(", forced a GC");
     }
 
-    const char16_t *kFmt =
+    NS_NAMED_LITERAL_STRING(kFmt,
       u"CC(T+%.1f)[%s-%i] max pause: %lums, total time: %lums, slices: %lu, suspected: %lu, visited: %lu RCed and %lu%s GCed, collected: %lu RCed and %lu GCed (%lu|%lu|%lu waiting for GC)%s\n"
-      u"ForgetSkippable %lu times before CC, min: %lu ms, max: %lu ms, avg: %lu ms, total: %lu ms, max sync: %lu ms, removed: %lu";
+      u"ForgetSkippable %lu times before CC, min: %lu ms, max: %lu ms, avg: %lu ms, total: %lu ms, max sync: %lu ms, removed: %lu");
     nsString msg;
-    msg.Adopt(nsTextFormatter::smprintf(kFmt, double(delta) / PR_USEC_PER_SEC,
+    msg.Adopt(nsTextFormatter::smprintf(kFmt.get(), double(delta) / PR_USEC_PER_SEC,
                                         ProcessNameForCollectorLog(), getpid(),
                                         gCCStats.mMaxSliceTime, gCCStats.mTotalSliceTime,
                                         aResults.mNumSlices, gCCStats.mSuspected,
                                         aResults.mVisitedRefCounted, aResults.mVisitedGCed, mergeMsg.get(),
                                         aResults.mFreedRefCounted, aResults.mFreedGCed,
                                         sCCollectedWaitingForGC, sCCollectedZonesWaitingForGC, sLikelyShortLivingObjectsNeedingGC,
                                         gcMsg.get(),
                                         sForgetSkippableBeforeCC,
@@ -1659,17 +1659,17 @@ nsJSContext::EndCycleCollectionCallback(
       }
     }
     if (gCCStats.mFile) {
       fprintf(gCCStats.mFile, "%s\n", NS_ConvertUTF16toUTF8(msg).get());
     }
   }
 
   if (sPostGCEventsToObserver) {
-    const char16_t* kJSONFmt =
+    NS_NAMED_LITERAL_STRING(kJSONFmt,
        u"{ \"timestamp\": %llu, "
          u"\"duration\": %lu, "
          u"\"max_slice_pause\": %lu, "
          u"\"total_slice_pause\": %lu, "
          u"\"max_finish_gc_duration\": %lu, "
          u"\"max_sync_skippable_duration\": %lu, "
          u"\"suspected\": %lu, "
          u"\"visited\": { "
@@ -1684,20 +1684,20 @@ nsJSContext::EndCycleCollectionCallback(
          u"\"forced_gc\": %d, "
          u"\"forget_skippable\": { "
              u"\"times_before_cc\": %lu, "
              u"\"min\": %lu, "
              u"\"max\": %lu, "
              u"\"avg\": %lu, "
              u"\"total\": %lu, "
              u"\"removed\": %lu } "
-       u"}";
+       u"}");
     nsString json;
 
-    json.Adopt(nsTextFormatter::smprintf(kJSONFmt, PR_Now(), ccNowDuration,
+    json.Adopt(nsTextFormatter::smprintf(kJSONFmt.get(), PR_Now(), ccNowDuration,
                                          gCCStats.mMaxSliceTime,
                                          gCCStats.mTotalSliceTime,
                                          gCCStats.mMaxGCDuration,
                                          gCCStats.mMaxSkippableDuration,
                                          gCCStats.mSuspected,
                                          aResults.mVisitedRefCounted, aResults.mVisitedGCed,
                                          aResults.mFreedRefCounted, aResults.mFreedGCed,
                                          sCCollectedWaitingForGC,
@@ -2134,19 +2134,20 @@ DOMGCSliceCallback(JSContext* aCx, JS::G
       sCCLockedOut = true;
       break;
     }
 
     case JS::GC_CYCLE_END: {
       PRTime delta = GetCollectionTimeDelta();
 
       if (sPostGCEventsToConsole) {
+        NS_NAMED_LITERAL_STRING(kFmt, "GC(T+%.1f)[%s-%i] ");
         nsString prefix, gcstats;
         gcstats.Adopt(aDesc.formatSummaryMessage(aCx));
-        prefix.Adopt(nsTextFormatter::smprintf(u"GC(T+%.1f)[%s-%i] ",
+        prefix.Adopt(nsTextFormatter::smprintf(kFmt.get(),
                                                double(delta) / PR_USEC_PER_SEC,
                                                ProcessNameForCollectorLog(),
                                                getpid()));
         nsString msg = prefix + gcstats;
         nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
         if (cs) {
           cs->LogStringMessage(msg.get());
         }
@@ -2217,19 +2218,20 @@ DOMGCSliceCallback(JSContext* aCx, JS::G
                                                       "InterSliceGCTimerFired");
       }
 
       if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
         nsCycleCollector_dispatchDeferredDeletion();
       }
 
       if (sPostGCEventsToConsole) {
+        NS_NAMED_LITERAL_STRING(kFmt, "[%s-%i] ");
         nsString prefix, gcstats;
         gcstats.Adopt(aDesc.formatSliceMessage(aCx));
-        prefix.Adopt(nsTextFormatter::smprintf(u"[%s-%i] ",
+        prefix.Adopt(nsTextFormatter::smprintf(kFmt.get(),
                                                ProcessNameForCollectorLog(),
                                                getpid()));
         nsString msg = prefix + gcstats;
         nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
         if (cs) {
           cs->LogStringMessage(msg.get());
         }
       }
--- a/dom/html/ImageDocument.cpp
+++ b/dom/html/ImageDocument.cpp
@@ -580,17 +580,18 @@ ImageDocument::OnLoadComplete(imgIReques
 
   // mImageContent can be null if the document is already destroyed
   if (NS_FAILED(aStatus) && mStringBundle && mImageContent) {
     nsAutoCString src;
     mDocumentURI->GetSpec(src);
     NS_ConvertUTF8toUTF16 srcString(src);
     const char16_t* formatString[] = { srcString.get() };
     nsXPIDLString errorMsg;
-    mStringBundle->FormatStringFromName(u"InvalidImage", formatString, 1,
+    NS_NAMED_LITERAL_STRING(str, "InvalidImage");
+    mStringBundle->FormatStringFromName(str.get(), formatString, 1,
                                         getter_Copies(errorMsg));
 
     mImageContent->SetAttr(kNameSpaceID_None, nsGkAtoms::alt, errorMsg, false);
   }
 
   return NS_OK;
 }
 
--- a/dom/html/MediaDocument.cpp
+++ b/dom/html/MediaDocument.cpp
@@ -413,17 +413,18 @@ MediaDocument::UpdateTitleAndCharset(con
   // set it on the document
   if (aStatus.IsEmpty()) {
     SetTitle(title);
   }
   else {
     nsXPIDLString titleWithStatus;
     const nsPromiseFlatString& status = PromiseFlatString(aStatus);
     const char16_t *formatStrings[2] = {title.get(), status.get()};
-    mStringBundle->FormatStringFromName(u"TitleWithStatus", formatStrings, 2,
+    NS_NAMED_LITERAL_STRING(fmtName, "TitleWithStatus");
+    mStringBundle->FormatStringFromName(fmtName.get(), formatStrings, 2,
                                         getter_Copies(titleWithStatus));
     SetTitle(titleWithStatus);
   }
 }
 
 void 
 MediaDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject)
 {
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -285,17 +285,17 @@ nsresult nsJSThunk::EvaluateScript(nsICh
         if (!result.init(cx, v)) {
             return NS_ERROR_OUT_OF_MEMORY;
         }
 
         char *bytes;
         uint32_t bytesLen;
         NS_NAMED_LITERAL_CSTRING(isoCharset, "ISO-8859-1");
         NS_NAMED_LITERAL_CSTRING(utf8Charset, "UTF-8");
-        const nsLiteralCString *charset;
+        const nsCString *charset;
         if (IsISO88591(result)) {
             // For compatibility, if the result is ISO-8859-1, we use
             // ISO-8859-1, so that people can compatibly create images
             // using javascript: URLs.
             bytes = ToNewCString(result);
             bytesLen = result.Length();
             charset = &isoCharset;
         }
--- a/dom/power/PowerManagerService.cpp
+++ b/dom/power/PowerManagerService.cpp
@@ -119,22 +119,22 @@ PowerManagerService::Notify(const WakeLo
   }
 }
 
 void
 PowerManagerService::SyncProfile()
 {
   nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
   if (obsServ) {
-    const char16_t* context = u"shutdown-persist";
-    obsServ->NotifyObservers(nullptr, "profile-change-net-teardown", context);
-    obsServ->NotifyObservers(nullptr, "profile-change-teardown", context);
-    obsServ->NotifyObservers(nullptr, "profile-before-change", context);
-    obsServ->NotifyObservers(nullptr, "profile-before-change-qm", context);
-    obsServ->NotifyObservers(nullptr, "profile-before-change-telemetry", context);
+    NS_NAMED_LITERAL_STRING(context, "shutdown-persist");
+    obsServ->NotifyObservers(nullptr, "profile-change-net-teardown", context.get());
+    obsServ->NotifyObservers(nullptr, "profile-change-teardown", context.get());
+    obsServ->NotifyObservers(nullptr, "profile-before-change", context.get());
+    obsServ->NotifyObservers(nullptr, "profile-before-change-qm", context.get());
+    obsServ->NotifyObservers(nullptr, "profile-before-change-telemetry", context.get());
   }
 }
 
 NS_IMETHODIMP
 PowerManagerService::Reboot()
 {
   LOG_FUNCTION_AND_JS_STACK() // bug 839452
 
--- a/dom/security/nsCSPParser.cpp
+++ b/dom/security/nsCSPParser.cpp
@@ -1111,17 +1111,17 @@ nsCSPParser::directiveName()
   // child-src has it's own class to handle frame-src if necessary
   if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE)) {
     mChildSrc = new nsCSPChildSrcDirective(CSP_StringToCSPDirective(mCurToken));
     return mChildSrc;
   }
 
   // if we have a frame-src, cache it so we can decide whether to use child-src
   if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE)) {
-    const char16_t* params[] = { mCurToken.get(), u"child-src" };
+    const char16_t* params[] = { mCurToken.get(), NS_LITERAL_STRING("child-src").get() };
     logWarningErrorToConsole(nsIScriptError::warningFlag, "deprecatedDirective",
                              params, ArrayLength(params));
     mFrameSrc = new nsCSPDirective(CSP_StringToCSPDirective(mCurToken));
     return mFrameSrc;
   }
 
   if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::REQUIRE_SRI_FOR)) {
     return new nsRequireSRIForDirective(CSP_StringToCSPDirective(mCurToken));
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -2583,20 +2583,21 @@ XMLHttpRequestMainThread::InitiateFetch(
     // always seem to implement the nsIUploadChannel2 interface, presumably
     // because it's a new interface. Eventually we should remove this and simply
     // require that http channels implement the new interface (see bug 529041).
     nsCOMPtr<nsIUploadChannel2> uploadChannel2 = do_QueryInterface(httpChannel);
     if (!uploadChannel2) {
       nsCOMPtr<nsIConsoleService> consoleService =
         do_GetService(NS_CONSOLESERVICE_CONTRACTID);
       if (consoleService) {
-        consoleService->LogStringMessage(
-          u"Http channel implementation doesn't support nsIUploadChannel2. "
+        consoleService->LogStringMessage(NS_LITERAL_STRING(
+          "Http channel implementation doesn't support nsIUploadChannel2. "
           "An extension has supplied a non-functional http protocol handler. "
-          "This will break behavior and in future releases not work at all.");
+          "This will break behavior and in future releases not work at all."
+        ).get());
       }
     }
 
     if (aUploadStream) {
       // If necessary, wrap the stream in a buffered stream so as to guarantee
       // support for our upload when calling ExplicitSetUploadStream.
       nsCOMPtr<nsIInputStream> bufferedStream;
       if (!NS_InputStreamIsBuffered(aUploadStream)) {
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -3459,18 +3459,17 @@ nsresult
 HTMLEditRules::WillMakeDefListItem(Selection* aSelection,
                                    const nsAString *aItemType,
                                    bool aEntireList,
                                    bool* aCancel,
                                    bool* aHandled)
 {
   // for now we let WillMakeList handle this
   NS_NAMED_LITERAL_STRING(listType, "dl");
-  return WillMakeList(aSelection, &listType.AsString(), aEntireList, nullptr,
-                      aCancel, aHandled, aItemType);
+  return WillMakeList(aSelection, &listType, aEntireList, nullptr, aCancel, aHandled, aItemType);
 }
 
 nsresult
 HTMLEditRules::WillMakeBasicBlock(Selection& aSelection,
                                   const nsAString& aBlockType,
                                   bool* aCancel,
                                   bool* aHandled)
 {
--- a/editor/libeditor/HTMLStyleEditor.cpp
+++ b/editor/libeditor/HTMLStyleEditor.cpp
@@ -1628,18 +1628,18 @@ HTMLEditor::GetFontFaceState(bool* aMixe
   NS_ENSURE_TRUE(aMixed, NS_ERROR_FAILURE);
   *aMixed = true;
   outFace.Truncate();
 
   bool first, any, all;
 
   NS_NAMED_LITERAL_STRING(attr, "face");
   nsresult rv =
-    GetInlinePropertyBase(*nsGkAtoms::font, &attr.AsString(), nullptr, &first,
-                          &any, &all, &outFace);
+    GetInlinePropertyBase(*nsGkAtoms::font, &attr, nullptr, &first, &any,
+                          &all, &outFace);
   NS_ENSURE_SUCCESS(rv, rv);
   if (any && !all) {
     return NS_OK; // mixed
   }
   if (all) {
     *aMixed = false;
     return NS_OK;
   }
@@ -1671,18 +1671,18 @@ HTMLEditor::GetFontColorState(bool* aMix
   NS_ENSURE_TRUE(aMixed, NS_ERROR_NULL_POINTER);
   *aMixed = true;
   aOutColor.Truncate();
 
   NS_NAMED_LITERAL_STRING(colorStr, "color");
   bool first, any, all;
 
   nsresult rv =
-    GetInlinePropertyBase(*nsGkAtoms::font, &colorStr.AsString(), nullptr,
-                          &first, &any, &all, &aOutColor);
+    GetInlinePropertyBase(*nsGkAtoms::font, &colorStr, nullptr, &first,
+                          &any, &all, &aOutColor);
   NS_ENSURE_SUCCESS(rv, rv);
   if (any && !all) {
     return NS_OK; // mixed
   }
   if (all) {
     *aMixed = false;
     return NS_OK;
   }
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -380,19 +380,18 @@ TextEditRules::WillInsertBreak(Selection
   if (IsSingleLineEditor()) {
     *aCancel = true;
   } else {
     // handle docs with a max length
     // NOTE, this function copies inString into outString for us.
     NS_NAMED_LITERAL_STRING(inString, "\n");
     nsAutoString outString;
     bool didTruncate;
-    nsresult rv = TruncateInsertionIfNeeded(aSelection, &inString.AsString(),
-                                            &outString, aMaxLength,
-                                            &didTruncate);
+    nsresult rv = TruncateInsertionIfNeeded(aSelection, &inString, &outString,
+                                            aMaxLength, &didTruncate);
     NS_ENSURE_SUCCESS(rv, rv);
     if (didTruncate) {
       *aCancel = true;
       return NS_OK;
     }
 
     *aCancel = false;
 
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -188,54 +188,54 @@ nsPageFrame::ProcessSpecialCodes(const n
 {
 
   aNewStr = aStr;
 
   // Search to see if the &D code is in the string 
   // then subst in the current date/time
   NS_NAMED_LITERAL_STRING(kDate, "&D");
   if (aStr.Find(kDate) != kNotFound) {
-    aNewStr.ReplaceSubstring(kDate, mPD->mDateTimeStr);
+    aNewStr.ReplaceSubstring(kDate.get(), mPD->mDateTimeStr.get());
   }
 
   // NOTE: Must search for &PT before searching for &P
   //
   // Search to see if the "page number and page" total code are in the string
   // and replace the page number and page total code with the actual
   // values
   NS_NAMED_LITERAL_STRING(kPageAndTotal, "&PT");
   if (aStr.Find(kPageAndTotal) != kNotFound) {
     char16_t * uStr = nsTextFormatter::smprintf(mPD->mPageNumAndTotalsFormat.get(), mPageNum, mTotNumPages);
-    aNewStr.ReplaceSubstring(kPageAndTotal, nsDependentString(uStr));
+    aNewStr.ReplaceSubstring(kPageAndTotal.get(), uStr);
     free(uStr);
   }
 
   // Search to see if the page number code is in the string
   // and replace the page number code with the actual value
   NS_NAMED_LITERAL_STRING(kPage, "&P");
   if (aStr.Find(kPage) != kNotFound) {
     char16_t * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat.get(), mPageNum);
-    aNewStr.ReplaceSubstring(kPage, nsDependentString(uStr));
+    aNewStr.ReplaceSubstring(kPage.get(), uStr);
     free(uStr);
   }
 
   NS_NAMED_LITERAL_STRING(kTitle, "&T");
   if (aStr.Find(kTitle) != kNotFound) {
-    aNewStr.ReplaceSubstring(kTitle, mPD->mDocTitle);
+    aNewStr.ReplaceSubstring(kTitle.get(), mPD->mDocTitle.get());
   }
 
   NS_NAMED_LITERAL_STRING(kDocURL, "&U");
   if (aStr.Find(kDocURL) != kNotFound) {
-    aNewStr.ReplaceSubstring(kDocURL, mPD->mDocURL);
+    aNewStr.ReplaceSubstring(kDocURL.get(), mPD->mDocURL.get());
   }
 
   NS_NAMED_LITERAL_STRING(kPageTotal, "&L");
   if (aStr.Find(kPageTotal) != kNotFound) {
     char16_t * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat.get(), mTotNumPages);
-    aNewStr.ReplaceSubstring(kPageTotal, nsDependentString(uStr));
+    aNewStr.ReplaceSubstring(kPageTotal.get(), uStr);
     free(uStr);
   }
 }
 
 
 //------------------------------------------------------------------------------
 nscoord nsPageFrame::GetXPosition(nsRenderingContext& aRenderingContext,
                                   nsFontMetrics&       aFontMetrics,
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp
@@ -80,20 +80,22 @@ public:
                                            NS_XPCOM_SHUTDOWN_OBSERVER_ID);
       MOZ_ALWAYS_SUCCEEDS(rv);
 
       // Make sure we're not deleted while still inside ::Observe()
       RefPtr<PeerConnectionCtxObserver> kungFuDeathGrip(this);
       PeerConnectionCtx::gPeerConnectionCtxObserver = nullptr;
     }
     if (strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC) == 0) {
-      if (NS_strcmp(aData, u"" NS_IOSERVICE_OFFLINE) == 0) {
+      const nsLiteralString onlineString(u"" NS_IOSERVICE_ONLINE);
+      const nsLiteralString offlineString(u"" NS_IOSERVICE_OFFLINE);
+      if (NS_strcmp(aData, offlineString.get()) == 0) {
         CSFLogDebug(logTag, "Updating network state to offline");
         PeerConnectionCtx::UpdateNetworkState(false);
-      } else if(NS_strcmp(aData, u"" NS_IOSERVICE_ONLINE) == 0) {
+      } else if(NS_strcmp(aData, onlineString.get()) == 0) {
         CSFLogDebug(logTag, "Updating network state to online");
         PeerConnectionCtx::UpdateNetworkState(true);
       } else {
         CSFLogDebug(logTag, "Received unsupported network state event");
         MOZ_CRASH();
       }
     }
     return NS_OK;
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -829,20 +829,19 @@ nsIOService::NewChannelFromURIWithProxyF
     // implement the new interface.
     // See bug 529041
     if (!gHasWarnedUploadChannel2 && scheme.EqualsLiteral("http")) {
         nsCOMPtr<nsIUploadChannel2> uploadChannel2 = do_QueryInterface(channel);
         if (!uploadChannel2) {
             nsCOMPtr<nsIConsoleService> consoleService =
                 do_GetService(NS_CONSOLESERVICE_CONTRACTID);
             if (consoleService) {
-                consoleService->LogStringMessage(u"Http channel implementation "
-                    "doesn't support nsIUploadChannel2. An extension has "
-                    "supplied a non-functional http protocol handler. This will "
-                    "break behavior and in future releases not work at all.");
+                consoleService->LogStringMessage(NS_LITERAL_STRING(
+                    "Http channel implementation doesn't support nsIUploadChannel2. An extension has supplied a non-functional http protocol handler. This will break behavior and in future releases not work at all."
+                                                                   ).get());
             }
             gHasWarnedUploadChannel2 = true;
         }
     }
 
     channel.forget(result);
     return NS_OK;
 }
@@ -1058,32 +1057,33 @@ nsIOService::SetOffline(bool offline)
         }
     }
 
     nsIIOService *subject = static_cast<nsIIOService *>(this);
     while (mSetOfflineValue != mOffline) {
         offline = mSetOfflineValue;
 
         if (offline && !mOffline) {
+            NS_NAMED_LITERAL_STRING(offlineString, NS_IOSERVICE_OFFLINE);
             mOffline = true; // indicate we're trying to shutdown
 
             // don't care if notifications fail
             if (observerService)
                 observerService->NotifyObservers(subject,
                                                  NS_IOSERVICE_GOING_OFFLINE_TOPIC,
-                                                 u"" NS_IOSERVICE_OFFLINE);
+                                                 offlineString.get());
 
             if (mSocketTransportService)
                 mSocketTransportService->SetOffline(true);
 
             mLastOfflineStateChange = PR_IntervalNow();
             if (observerService)
                 observerService->NotifyObservers(subject,
                                                  NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
-                                                 u"" NS_IOSERVICE_OFFLINE);
+                                                 offlineString.get());
         }
         else if (!offline && mOffline) {
             // go online
             if (mDNSService) {
                 DebugOnly<nsresult> rv = mDNSService->Init();
                 NS_ASSERTION(NS_SUCCEEDED(rv), "DNS service init failed");
             }
             InitializeSocketTransportService();
@@ -1188,22 +1188,23 @@ nsIOService::SetConnectivityInternal(boo
         // send the ONLINE notification
         observerService->NotifyObservers(
             static_cast<nsIIOService *>(this),
             NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
             (u"" NS_IOSERVICE_ONLINE));
     } else {
         // If we were previously online and lost connectivity
         // send the OFFLINE notification
+        const nsLiteralString offlineString(u"" NS_IOSERVICE_OFFLINE);
         observerService->NotifyObservers(static_cast<nsIIOService *>(this),
                                          NS_IOSERVICE_GOING_OFFLINE_TOPIC,
-                                         u"" NS_IOSERVICE_OFFLINE);
+                                         offlineString.get());
         observerService->NotifyObservers(static_cast<nsIIOService *>(this),
                                          NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
-                                         u"" NS_IOSERVICE_OFFLINE);
+                                         offlineString.get());
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsIOService::AllowPort(int32_t inPort, const char *scheme, bool *_retval)
 {
     int16_t port = inPort;
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
@@ -941,19 +941,20 @@ nsFtpState::R_syst() {
             nsCOMPtr<nsIStringBundle> bundle;
             nsresult rv = bundleService->CreateBundle(NECKO_MSGS_URL,
                                                       getter_AddRefs(bundle));
             if (NS_FAILED(rv))
                 return FTP_ERROR;
             
             char16_t* ucs2Response = ToNewUnicode(mResponseMsg);
             const char16_t *formatStrings[1] = { ucs2Response };
+            NS_NAMED_LITERAL_STRING(name, "UnsupportedFTPServer");
 
             nsXPIDLString formattedString;
-            rv = bundle->FormatStringFromName(u"UnsupportedFTPServer", formatStrings, 1,
+            rv = bundle->FormatStringFromName(name.get(), formatStrings, 1,
                                               getter_Copies(formattedString));
             free(ucs2Response);
             if (NS_FAILED(rv))
                 return FTP_ERROR;
 
             // TODO(darin): this code should not be dictating UI like this!
             nsCOMPtr<nsIPrompt> prompter;
             mChannel->GetCallback(prompter);
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -503,17 +503,17 @@ nsHttpHandler::AddConnectionHeader(nsHtt
     // RFC2616 section 19.6.2 states that the "Connection: keep-alive"
     // and "Keep-alive" request headers should not be sent by HTTP/1.1
     // user-agents.  But this is not a problem in practice, and the
     // alternative proxy-connection is worse. see 570283
 
     NS_NAMED_LITERAL_CSTRING(close, "close");
     NS_NAMED_LITERAL_CSTRING(keepAlive, "keep-alive");
 
-    const nsLiteralCString *connectionType = &close;
+    const nsACString *connectionType = &close;
     if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
         connectionType = &keepAlive;
     }
 
     return request->SetHeader(nsHttp::Connection, *connectionType);
 }
 
 bool
--- a/security/manager/ssl/nsNSSComponent.cpp
+++ b/security/manager/ssl/nsNSSComponent.cpp
@@ -1843,20 +1843,22 @@ nsNSSComponent::Init()
     return rv;
   }
 
   // Access our string bundles now, this prevents assertions from I/O
   // - nsStandardURL not thread-safe
   // - wrong thread: 'NS_IsMainThread()' in nsIOService.cpp
   // when loading error strings on the SSL threads.
   {
-    const char16_t* dummy = u"dummy";
+    NS_NAMED_LITERAL_STRING(dummy_name, "dummy");
     nsXPIDLString result;
-    mPIPNSSBundle->GetStringFromName(dummy, getter_Copies(result));
-    mNSSErrorsBundle->GetStringFromName(dummy, getter_Copies(result));
+    mPIPNSSBundle->GetStringFromName(dummy_name.get(),
+                                     getter_Copies(result));
+    mNSSErrorsBundle->GetStringFromName(dummy_name.get(),
+                                        getter_Copies(result));
   }
 
 
   rv = InitializeNSS();
   if (NS_FAILED(rv)) {
     MOZ_LOG(gPIPNSSLog, LogLevel::Error,
             ("nsNSSComponent::InitializeNSS() failed\n"));
     return rv;
--- a/security/manager/ssl/nsNSSU2FToken.cpp
+++ b/security/manager/ssl/nsNSSU2FToken.cpp
@@ -24,17 +24,17 @@ NS_IMPL_ISUPPORTS(nsNSSU2FToken, nsIU2FT
 // name causes the window.u2f object to disappear until preferences get
 // reloaded, as its' pref is a substring!
 #define PREF_U2F_NSSTOKEN_COUNTER "security.webauth.softtoken_counter"
 
 const nsCString nsNSSU2FToken::mSecretNickname =
   NS_LITERAL_CSTRING("U2F_NSSTOKEN");
 const nsString nsNSSU2FToken::mVersion =
   NS_LITERAL_STRING("U2F_V2");
-const char* kAttestCertSubjectName = "CN=Firefox U2F Soft Token";
+NS_NAMED_LITERAL_CSTRING(kAttestCertSubjectName, "CN=Firefox U2F Soft Token");
 
 // This U2F-compatible soft token uses FIDO U2F-compatible ECDSA keypairs
 // on the SEC_OID_SECG_EC_SECP256R1 curve. When asked to Register, it will
 // generate and return a new keypair KP, where the private component is wrapped
 // using AES-KW with the 128-bit mWrappingKey to make an opaque "key handle".
 // In other words, Register yields { KP_pub, AES-KW(KP_priv, key=mWrappingKey) }
 //
 // The value mWrappingKey is long-lived; it is persisted as part of the NSS DB
@@ -251,17 +251,17 @@ GetAttestationCertificate(const UniquePK
   nsresult rv = GenEcKeypair(aSlot, aAttestPrivKey, pubKey, locker);
   if (NS_FAILED(rv) || !aAttestPrivKey || !pubKey) {
     MOZ_LOG(gNSSTokenLog, LogLevel::Warning,
             ("Failed to gen keypair, NSS error #%d", PORT_GetError()));
     return NS_ERROR_FAILURE;
   }
 
   // Construct the Attestation Certificate itself
-  UniqueCERTName subjectName(CERT_AsciiToName(kAttestCertSubjectName));
+  UniqueCERTName subjectName(CERT_AsciiToName(kAttestCertSubjectName.get()));
   if (!subjectName) {
     MOZ_LOG(gNSSTokenLog, LogLevel::Warning,
             ("Failed to set subject name, NSS error #%d", PORT_GetError()));
       return NS_ERROR_FAILURE;
   }
 
   UniqueCERTSubjectPublicKeyInfo spki(
     SECKEY_CreateSubjectPublicKeyInfo(pubKey.get()));
--- a/storage/VacuumManager.cpp
+++ b/storage/VacuumManager.cpp
@@ -24,18 +24,18 @@
 #include "mozStorageHelper.h"
 #include "nsXULAppAPI.h"
 
 #define OBSERVER_TOPIC_IDLE_DAILY "idle-daily"
 #define OBSERVER_TOPIC_XPCOM_SHUTDOWN "xpcom-shutdown"
 
 // Used to notify begin and end of a heavy IO task.
 #define OBSERVER_TOPIC_HEAVY_IO "heavy-io-task"
-#define OBSERVER_DATA_VACUUM_BEGIN u"vacuum-begin"
-#define OBSERVER_DATA_VACUUM_END u"vacuum-end"
+#define OBSERVER_DATA_VACUUM_BEGIN NS_LITERAL_STRING("vacuum-begin")
+#define OBSERVER_DATA_VACUUM_END NS_LITERAL_STRING("vacuum-end")
 
 // This preferences root will contain last vacuum timestamps (in seconds) for
 // each database.  The database filename is used as a key.
 #define PREF_VACUUM_BRANCH "storage.vacuum.last."
 
 // Time between subsequent vacuum calls for a certain database.
 #define VACUUM_INTERVAL_SECONDS 30 * 86400 // 30 days.
 
@@ -186,17 +186,17 @@ Vacuumer::execute()
     return false;
   }
 
   // Notify a heavy IO task is about to start.
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
     rv =
       os->NotifyObservers(nullptr, OBSERVER_TOPIC_HEAVY_IO,
-                          OBSERVER_DATA_VACUUM_BEGIN);
+                          OBSERVER_DATA_VACUUM_BEGIN.get());
     MOZ_ASSERT(NS_SUCCEEDED(rv), "Should be able to notify");
   }
 
   // Execute the statements separately, since the pragma may conflict with the
   // vacuum, if they are executed in the same transaction.
   nsCOMPtr<mozIStorageAsyncStatement> pageSizeStmt;
   nsAutoCString pageSizeQuery(MOZ_STORAGE_UNIQUIFY_QUERY_STR
                               "PRAGMA page_size = ");
@@ -284,17 +284,17 @@ Vacuumer::HandleCompletion(uint16_t aRea
 }
 
 nsresult
 Vacuumer::notifyCompletion(bool aSucceeded)
 {
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
     os->NotifyObservers(nullptr, OBSERVER_TOPIC_HEAVY_IO,
-                        OBSERVER_DATA_VACUUM_END);
+                        OBSERVER_DATA_VACUUM_END.get());
   }
 
   nsresult rv = mParticipant->OnEndVacuum(aSucceeded);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
--- a/toolkit/components/find/nsWebBrowserFind.cpp
+++ b/toolkit/components/find/nsWebBrowserFind.cpp
@@ -87,19 +87,21 @@ nsWebBrowserFind::FindNext(bool* aResult
   nsCOMPtr<nsIObserverService> observerSvc =
     mozilla::services::GetObserverService();
   if (observerSvc) {
     nsCOMPtr<nsISupportsInterfacePointer> windowSupportsData =
       do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsISupports> searchWindowSupports = do_QueryInterface(rootFrame);
     windowSupportsData->SetData(searchWindowSupports);
+    NS_NAMED_LITERAL_STRING(dnStr, "down");
+    NS_NAMED_LITERAL_STRING(upStr, "up");
     observerSvc->NotifyObservers(windowSupportsData,
                                  "nsWebBrowserFind_FindAgain",
-                                 mFindBackwards ? u"up" : u"down");
+                                 mFindBackwards ? upStr.get() : dnStr.get());
     windowSupportsData->GetData(getter_AddRefs(searchWindowSupports));
     // findnext performed if search window data cleared out
     *aResult = searchWindowSupports == nullptr;
     if (*aResult) {
       return NS_OK;
     }
   }
 
--- a/toolkit/components/startup/nsAppStartup.cpp
+++ b/toolkit/components/startup/nsAppStartup.cpp
@@ -453,18 +453,21 @@ nsAppStartup::Quit(uint32_t aMode)
   }
 
   if (ferocity == eForceQuit) {
     // do it!
 
     // No chance of the shutdown being cancelled from here on; tell people
     // we're shutting down for sure while all services are still available.
     if (obsService) {
+      NS_NAMED_LITERAL_STRING(shutdownStr, "shutdown");
+      NS_NAMED_LITERAL_STRING(restartStr, "restart");
       obsService->NotifyObservers(nullptr, "quit-application",
-        (mRestart || mRestartNotSameProfile) ? u"restart" : u"shutdown");
+        (mRestart || mRestartNotSameProfile) ?
+         restartStr.get() : shutdownStr.get());
     }
 
     if (!mRunning) {
       postedExitEvent = true;
     }
     else {
       // no matter what, make sure we send the exit event.  If
       // worst comes to worst, we'll do a leaky shutdown but we WILL
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -578,17 +578,17 @@ XRE_InitChildProcess(int aArgc,
   // group with the parent app on the Win7 taskbar.
   const char* const appModelUserId = aArgv[--aArgc];
   if (appModelUserId) {
     // '-' implies no support
     if (*appModelUserId != '-') {
       nsString appId;
       appId.AssignWithConversion(nsDependentCString(appModelUserId));
       // The version string is encased in quotes
-      appId.Trim("\"");
+      appId.Trim(NS_LITERAL_CSTRING("\"").get());
       // Set the id
       SetTaskbarGroupId(appId);
     }
   }
 #endif
 
   base::AtExitManager exitManager;
 
--- a/toolkit/xre/nsNativeAppSupportWin.cpp
+++ b/toolkit/xre/nsNativeAppSupportWin.cpp
@@ -948,17 +948,17 @@ nsNativeAppSupportWin::HandleDDENotifica
                     // command, therefore it is returned as a null string
 
                     // This isn't really a loop.  We just use "break"
                     // statements to bypass the remaining steps when
                     // something goes wrong.
                     do {
                         // Get most recently used Nav window.
                         nsCOMPtr<mozIDOMWindowProxy> navWin;
-                        GetMostRecentWindow( u"navigator:browser",
+                        GetMostRecentWindow( NS_LITERAL_STRING( "navigator:browser" ).get(),
                                              getter_AddRefs( navWin ) );
                         nsCOMPtr<nsPIDOMWindowOuter> piNavWin = do_QueryInterface(navWin);
                         if ( !piNavWin ) {
                             // There is not a window open
                             break;
                         }
 
                         // Get content window.
@@ -1425,17 +1425,17 @@ nsNativeAppSupportWin::OpenBrowserWindow
 
     // Open the argument URL in the most recently used Navigator window.
     // If there is no Nav window, open a new one.
 
     // If at all possible, hand the request off to the most recent
     // browser window.
 
     nsCOMPtr<mozIDOMWindowProxy> navWin;
-    GetMostRecentWindow( u"navigator:browser", getter_AddRefs( navWin ) );
+    GetMostRecentWindow( NS_LITERAL_STRING( "navigator:browser" ).get(), getter_AddRefs( navWin ) );
 
     // This isn't really a loop.  We just use "break" statements to fall
     // out to the OpenWindow call when things go awry.
     do {
         // If caller requires a new window, then don't use an existing one.
         if ( !navWin ) {
             // Have to open a new one.
             break;
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -1283,19 +1283,19 @@ GetShellFolderPath(int folder, nsAString
  * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
  * querying the registry when the call to SHGetSpecialFolderLocation or
  * SHGetPathFromIDListW is unable to provide these paths (Bug 513958).
  */
 static nsresult
 GetRegWindowsAppDataFolder(bool aLocal, nsAString& _retval)
 {
   HKEY key;
-  LPCWSTR keyName =
-    L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
-  DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName, 0, KEY_READ,
+  NS_NAMED_LITERAL_STRING(keyName,
+  "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
+  DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName.get(), 0, KEY_READ,
                               &key);
   if (res != ERROR_SUCCESS) {
     _retval.SetLength(0);
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   DWORD type, size;
   res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
--- a/widget/android/jni/Refs.h
+++ b/widget/android/jni/Refs.h
@@ -743,36 +743,26 @@ public:
         , mEnv(nullptr)
     {}
 
     MOZ_IMPLICIT StringParam(const nsAString& str, JNIEnv* env = Ref::FindEnv())
         : Ref(GetString(env, str))
         , mEnv(env)
     {}
 
-    MOZ_IMPLICIT StringParam(const nsLiteralString& str, JNIEnv* env = Ref::FindEnv())
-        : Ref(GetString(env, str))
-        , mEnv(env)
-    {}
-
     MOZ_IMPLICIT StringParam(const char16_t* str, JNIEnv* env = Ref::FindEnv())
         : Ref(GetString(env, nsDependentString(str)))
         , mEnv(env)
     {}
 
     MOZ_IMPLICIT StringParam(const nsACString& str, JNIEnv* env = Ref::FindEnv())
         : Ref(GetString(env, NS_ConvertUTF8toUTF16(str)))
         , mEnv(env)
     {}
 
-    MOZ_IMPLICIT StringParam(const nsLiteralCString& str, JNIEnv* env = Ref::FindEnv())
-        : Ref(GetString(env, NS_ConvertUTF8toUTF16(str)))
-        , mEnv(env)
-    {}
-
     MOZ_IMPLICIT StringParam(const char* str, JNIEnv* env = Ref::FindEnv())
         : Ref(GetString(env, NS_ConvertUTF8toUTF16(str)))
         , mEnv(env)
     {}
 
     StringParam(StringParam&& other)
         : Ref(other.Get())
         , mEnv(other.mEnv)
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -162,17 +162,18 @@ public:
         if (sPauseCount != 1) {
             return;
         }
 
         nsCOMPtr<nsIObserverService> obsServ =
             mozilla::services::GetObserverService();
         obsServ->NotifyObservers(nullptr, "application-background", nullptr);
 
-        obsServ->NotifyObservers(nullptr, "memory-pressure", u"heap-minimize");
+        NS_NAMED_LITERAL_STRING(minimize, "heap-minimize");
+        obsServ->NotifyObservers(nullptr, "memory-pressure", minimize.get());
 
         // If we are OOM killed with the disk cache enabled, the entire
         // cache will be cleared (bug 105843), so shut down the cache here
         // and re-init on foregrounding
         if (nsCacheService::GlobalInstance()) {
             nsCacheService::GlobalInstance()->Shutdown();
         }
 
--- a/widget/windows/WindowsUIUtils.cpp
+++ b/widget/windows/WindowsUIUtils.cpp
@@ -163,18 +163,20 @@ WindowsUIUtils::UpdateTabletModeState()
       UserInteractionMode mode;
       hr = uiViewSettings->get_UserInteractionMode(&mode);
       if (SUCCEEDED(hr)) {
         TabletModeState oldTabletModeState = mInTabletMode;
         mInTabletMode = (mode == UserInteractionMode_Touch) ? eTabletModeOn : eTabletModeOff;
         if (mInTabletMode != oldTabletModeState) {
           nsCOMPtr<nsIObserverService> observerService =
             mozilla::services::GetObserverService();
+          NS_NAMED_LITERAL_STRING(tabletMode, "tablet-mode");
+          NS_NAMED_LITERAL_STRING(normalMode, "normal-mode");
           observerService->NotifyObservers(nullptr, "tablet-mode-change",
-            ((mInTabletMode == eTabletModeOn) ? u"tablet-mode" : u"normal-mode"));
+            ((mInTabletMode == eTabletModeOn) ? tabletMode.get() : normalMode.get()));
         }
       }
     }
   }
 #endif
 
   return NS_OK;
 }
--- a/widget/windows/nsFilePicker.cpp
+++ b/widget/windows/nsFilePicker.cpp
@@ -494,21 +494,23 @@ nsFilePicker::ShowFilePicker(const nsStr
   // title
   dialog->SetTitle(mTitle.get());
 
   // default filename
   if (!mDefaultFilename.IsEmpty()) {
     dialog->SetFileName(mDefaultFilename.get());
   }
   
+  NS_NAMED_LITERAL_STRING(htmExt, "html");
+
   // default extension to append to new files
   if (!mDefaultExtension.IsEmpty()) {
     dialog->SetDefaultExtension(mDefaultExtension.get());
   } else if (IsDefaultPathHtml()) {
-    dialog->SetDefaultExtension(L"html");
+    dialog->SetDefaultExtension(htmExt.get());
   }
 
   // initial location
   if (!aInitialDir.IsEmpty()) {
     RefPtr<IShellItem> folder;
     if (SUCCEEDED(
           SHCreateItemFromParsingName(aInitialDir.get(), nullptr,
                                       IID_IShellItem,
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -5052,26 +5052,26 @@ nsWindow::ProcessMessage(UINT msg, WPARA
       if (msg == MOZ_WM_APP_QUIT || (wParam == TRUE && sCanQuit == TRI_TRUE))
       {
         // Let's fake a shutdown sequence without actually closing windows etc.
         // to avoid Windows killing us in the middle. A proper shutdown would
         // require having a chance to pump some messages. Unfortunately
         // Windows won't let us do that. Bug 212316.
         nsCOMPtr<nsIObserverService> obsServ =
           mozilla::services::GetObserverService();
-        const char16_t* context = u"shutdown-persist";
-        const char16_t* syncShutdown = u"syncShutdown";
-        obsServ->NotifyObservers(nullptr, "quit-application-granted", syncShutdown);
+        NS_NAMED_LITERAL_STRING(context, "shutdown-persist");
+        NS_NAMED_LITERAL_STRING(syncShutdown, "syncShutdown");
+        obsServ->NotifyObservers(nullptr, "quit-application-granted", syncShutdown.get());
         obsServ->NotifyObservers(nullptr, "quit-application-forced", nullptr);
         obsServ->NotifyObservers(nullptr, "quit-application", nullptr);
-        obsServ->NotifyObservers(nullptr, "profile-change-net-teardown", context);
-        obsServ->NotifyObservers(nullptr, "profile-change-teardown", context);
-        obsServ->NotifyObservers(nullptr, "profile-before-change", context);
-        obsServ->NotifyObservers(nullptr, "profile-before-change-qm", context);
-        obsServ->NotifyObservers(nullptr, "profile-before-change-telemetry", context);
+        obsServ->NotifyObservers(nullptr, "profile-change-net-teardown", context.get());
+        obsServ->NotifyObservers(nullptr, "profile-change-teardown", context.get());
+        obsServ->NotifyObservers(nullptr, "profile-before-change", context.get());
+        obsServ->NotifyObservers(nullptr, "profile-before-change-qm", context.get());
+        obsServ->NotifyObservers(nullptr, "profile-before-change-telemetry", context.get());
         // Then a controlled but very quick exit.
         _exit(0);
       }
       sCanQuit = TRI_UNKNOWN;
       result = true;
       break;
 
     case WM_SYSCOLORCHANGE:
--- a/xpcom/base/nsSystemInfo.cpp
+++ b/xpcom/base/nsSystemInfo.cpp
@@ -178,17 +178,19 @@ GetHDDInfo(const char* aSpecialDirName, 
   free(deviceOutput);
   return NS_OK;
 }
 
 nsresult GetInstallYear(uint32_t& aYear)
 {
   HKEY hKey;
   LONG status = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
-                              L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
+                              NS_LITERAL_STRING(
+                              "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
+                              ).get(),
                               0, KEY_READ | KEY_WOW64_64KEY, &hKey);
 
   if (status != ERROR_SUCCESS) {
     return NS_ERROR_UNEXPECTED;
   }
 
   nsAutoRegKey key(hKey);
 
--- a/xpcom/io/SpecialSystemDirectory.cpp
+++ b/xpcom/io/SpecialSystemDirectory.cpp
@@ -146,19 +146,19 @@ GetLibrarySaveToPath(int aFallbackFolder
  * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
  * querying the registry when the call to SHGetSpecialFolderPathW is unable to
  * provide these paths (Bug 513958).
  */
 static nsresult
 GetRegWindowsAppDataFolder(bool aLocal, nsIFile** aFile)
 {
   HKEY key;
-  LPCWSTR keyName =
-    L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
-  DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName, 0, KEY_READ,
+  NS_NAMED_LITERAL_STRING(keyName,
+    "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
+  DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName.get(), 0, KEY_READ,
                               &key);
   if (res != ERROR_SUCCESS) {
     return NS_ERROR_FAILURE;
   }
 
   WCHAR path[MAX_PATH + 2];
   DWORD type, size;
   res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
--- a/xpcom/string/nsLiteralString.h
+++ b/xpcom/string/nsLiteralString.h
@@ -18,14 +18,16 @@
 // declare nsLiteralCString
 #include "string-template-def-char.h"
 #include "nsTLiteralString.h"
 #include "string-template-undef.h"
 
 #include "mozilla/Char16.h"
 
 #define NS_LITERAL_STRING(s)                      static_cast<const nsLiteralString&>(nsLiteralString(u"" s))
+#define NS_LITERAL_STRING_INIT(n,s)               n(u"" s)
 #define NS_NAMED_LITERAL_STRING(n,s)              const nsLiteralString n(u"" s)
 
 #define NS_LITERAL_CSTRING(s)                     static_cast<const nsLiteralCString&>(nsLiteralCString("" s))
+#define NS_LITERAL_CSTRING_INIT(n,s)              n("" s)
 #define NS_NAMED_LITERAL_CSTRING(n,s)             const nsLiteralCString n("" s)
 
 #endif /* !defined(nsLiteralString_h___) */
--- a/xpcom/string/nsStringFwd.h
+++ b/xpcom/string/nsStringFwd.h
@@ -10,25 +10,16 @@
 #define nsStringFwd_h___
 
 #include "nscore.h"
 
 #ifndef MOZILLA_INTERNAL_API
 #error Internal string headers are not available from external-linkage code.
 #endif
 
-namespace mozilla {
-namespace detail {
-
-class nsStringRepr;
-class nsCStringRepr;
-
-} // namespace detail
-} // namespace mozilla
-
 /**
  * double-byte (char16_t) string types
  */
 
 class nsAString;
 class nsSubstringTuple;
 class nsString;
 class nsAutoString;
--- a/xpcom/string/nsStringIterator.h
+++ b/xpcom/string/nsStringIterator.h
@@ -22,18 +22,18 @@ public:
   typedef nsReadingIterator<CharT>    self_type;
   typedef ptrdiff_t                   difference_type;
   typedef size_t                      size_type;
   typedef CharT                       value_type;
   typedef const CharT*                pointer;
   typedef const CharT&                reference;
 
 private:
-  friend class mozilla::detail::nsStringRepr;
-  friend class mozilla::detail::nsCStringRepr;
+  friend class nsAString;
+  friend class nsACString;
 
   // unfortunately, the API for nsReadingIterator requires that the
   // iterator know its start and end positions.  this was needed when
   // we supported multi-fragment strings, but now it is really just
   // extra baggage.  we should remove mStart and mEnd at some point.
 
   const CharT* mStart;
   const CharT* mEnd;
--- a/xpcom/string/nsSubstringTuple.cpp
+++ b/xpcom/string/nsSubstringTuple.cpp
@@ -1,16 +1,19 @@
 /* -*- 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 "nsSubstringTuple.h"
 
+// convert fragment to |const substring_type&|
+#define TO_SUBSTRING(_v) (*(_v))
+
 // define nsSubstringTuple
 #include "string-template-def-unichar.h"
 #include "nsTSubstringTuple.cpp"
 #include "string-template-undef.h"
 
 // define nsCSubstringTuple
 #include "string-template-def-char.h"
 #include "nsTSubstringTuple.cpp"
--- a/xpcom/string/nsTLiteralString.h
+++ b/xpcom/string/nsTLiteralString.h
@@ -1,77 +1,41 @@
 /* -*- 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/. */
 
+
 /**
  * nsTLiteralString_CharT
  *
  * Stores a null-terminated, immutable sequence of characters.
  *
- * nsTString-lookalike that restricts its string value to a literal character
- * sequence. Can be implicitly cast to const nsTString& (the const is
- * essential, since this class's data are not writable). The data are assumed
- * to be static (permanent) and therefore, as an optimization, this class
- * does not have a destructor.
+ * Subclass of nsTString that restricts string value to a literal
+ * character sequence.  This class does not own its data. The data is
+ * assumed to be permanent. In practice this is true because this code
+ * is only usable by and for libxul.
  */
-class nsTLiteralString_CharT : public mozilla::detail::nsTStringRepr_CharT
+class nsTLiteralString_CharT : public nsTString_CharT
 {
 public:
 
   typedef nsTLiteralString_CharT self_type;
 
 public:
 
   /**
    * constructor
    */
 
   template<size_type N>
   explicit nsTLiteralString_CharT(const char_type (&aStr)[N])
-    : base_string_type(const_cast<char_type*>(aStr), N - 1, F_TERMINATED | F_LITERAL)
-  {
-  }
-
-  /**
-   * For compatibility with existing code that requires const ns[C]String*.
-   * Use sparingly. If possible, rewrite code to use const ns[C]String&
-   * and the implicit cast will just work.
-   */
-  const nsTString_CharT& AsString() const
-  {
-    return *reinterpret_cast<const nsTString_CharT*>(this);
-  }
-
-  operator const nsTString_CharT&() const
+    : string_type(const_cast<char_type*>(aStr), N - 1, F_TERMINATED | F_LITERAL)
   {
-    return AsString();
-  }
-
-  /**
-   * Prohibit get() on temporaries as in nsLiteralCString("x").get().
-   * These should be written as just "x", using a string literal directly.
-   */
-#if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
-  char16ptr_t get() const && = delete;
-  char16ptr_t get() const &
-#else
-  const char_type* get() const && = delete;
-  const char_type* get() const &
-#endif
-  {
-    return mData;
   }
 
 private:
 
   // NOT TO BE IMPLEMENTED
   template<size_type N>
   nsTLiteralString_CharT(char_type (&aStr)[N]) = delete;
-
-  self_type& operator=(const self_type&) = delete;
 };
-
-static_assert(sizeof(nsTLiteralString_CharT) == sizeof(nsTString_CharT),
-              "nsTLiteralString_CharT can masquerade as nsTString_CharT, "
-              "so they must have identical layout");
--- a/xpcom/string/nsTPromiseFlatString.cpp
+++ b/xpcom/string/nsTPromiseFlatString.cpp
@@ -5,14 +5,14 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 void
 nsTPromiseFlatString_CharT::Init(const substring_type& str)
 {
   if (str.IsTerminated()) {
     mData = const_cast<char_type*>(static_cast<const char_type*>(str.Data()));
     mLength = str.Length();
-    mFlags = str.Flags() & (F_TERMINATED | F_LITERAL);
+    mFlags = str.mFlags & (F_TERMINATED | F_LITERAL);
     // does not promote F_VOIDED
   } else {
     Assign(str);
   }
 }
--- a/xpcom/string/nsTString.h
+++ b/xpcom/string/nsTString.h
@@ -456,16 +456,22 @@ public:
     NS_ASSERTION(mData[mLength] == 0,
                  "nsTDependentString must wrap only null-terminated strings. "
                  "You are probably looking for nsTDependentSubstring.");
   }
 
 
 protected:
 
+  explicit
+  nsTString_CharT(uint32_t aFlags)
+    : substring_type(aFlags)
+  {
+  }
+
   // allow subclasses to initialize fields directly
   nsTString_CharT(char_type* aData, size_type aLength, uint32_t aFlags)
     : substring_type(aData, aLength, aFlags)
   {
   }
 
   struct Segment {
     uint32_t mBegin, mLength;
--- a/xpcom/string/nsTSubstring.cpp
+++ b/xpcom/string/nsTSubstring.cpp
@@ -9,17 +9,19 @@
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Printf.h"
 
 using double_conversion::DoubleToStringConverter;
 
 #ifdef XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
 nsTSubstring_CharT::nsTSubstring_CharT(char_type* aData, size_type aLength,
                                        uint32_t aFlags)
-  : nsTStringRepr_CharT(aData, aLength, aFlags)
+  : mData(aData),
+    mLength(aLength),
+    mFlags(aFlags)
 {
   if (aFlags & F_OWNED) {
     STRING_STAT_INCREMENT(Adopt);
     MOZ_LOG_CTOR(mData, "StringAdopt", 1);
   }
 }
 #endif /* XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE */
 
@@ -27,16 +29,31 @@ nsTSubstring_CharT::nsTSubstring_CharT(c
  * helper function for down-casting a nsTSubstring to a nsTFixedString.
  */
 inline const nsTFixedString_CharT*
 AsFixedString(const nsTSubstring_CharT* aStr)
 {
   return static_cast<const nsTFixedString_CharT*>(aStr);
 }
 
+
+nsTSubstring_CharT::char_type
+nsTSubstring_CharT::First() const
+{
+  MOZ_RELEASE_ASSERT(mLength > 0, "|First()| called on an empty string");
+  return mData[0];
+}
+
+nsTSubstring_CharT::char_type
+nsTSubstring_CharT::Last() const
+{
+  MOZ_RELEASE_ASSERT(mLength > 0, "|Last()| called on an empty string");
+  return mData[mLength - 1];
+}
+
 /**
  * this function is called to prepare mData for writing.  the given capacity
  * indicates the required minimum storage size for mData, in sizeof(char_type)
  * increments.  this function returns true if the operation succeeds.  it also
  * returns the old data and old flags members if mData is newly allocated.
  * the old data must be released by the caller.
  */
 bool
@@ -742,145 +759,112 @@ nsTSubstring_CharT::SetIsVoid(bool aVal)
   if (aVal) {
     Truncate();
     mFlags |= F_VOIDED;
   } else {
     mFlags &= ~F_VOIDED;
   }
 }
 
-namespace mozilla {
-namespace detail {
-
-nsTStringRepr_CharT::char_type
-nsTStringRepr_CharT::First() const
-{
-  MOZ_RELEASE_ASSERT(mLength > 0, "|First()| called on an empty string");
-  return mData[0];
-}
-
-nsTStringRepr_CharT::char_type
-nsTStringRepr_CharT::Last() const
-{
-  MOZ_RELEASE_ASSERT(mLength > 0, "|Last()| called on an empty string");
-  return mData[mLength - 1];
-}
-
 bool
-nsTStringRepr_CharT::Equals(const self_type& aStr) const
+nsTSubstring_CharT::Equals(const self_type& aStr) const
 {
   return mLength == aStr.mLength &&
          char_traits::compare(mData, aStr.mData, mLength) == 0;
 }
 
 bool
-nsTStringRepr_CharT::Equals(const self_type& aStr,
-                            const comparator_type& aComp) const
+nsTSubstring_CharT::Equals(const self_type& aStr,
+                           const comparator_type& aComp) const
 {
   return mLength == aStr.mLength &&
          aComp(mData, aStr.mData, mLength, aStr.mLength) == 0;
 }
 
 bool
-nsTStringRepr_CharT::Equals(const substring_tuple_type& aTuple) const
-{
-  return Equals(substring_type(aTuple));
-}
-
-bool
-nsTStringRepr_CharT::Equals(const substring_tuple_type& aTuple,
-                            const comparator_type& aComp) const
-{
-  return Equals(substring_type(aTuple), aComp);
-}
-
-bool
-nsTStringRepr_CharT::Equals(const char_type* aData) const
+nsTSubstring_CharT::Equals(const char_type* aData) const
 {
   // unfortunately, some callers pass null :-(
   if (!aData) {
     NS_NOTREACHED("null data pointer");
     return mLength == 0;
   }
 
   // XXX avoid length calculation?
   size_type length = char_traits::length(aData);
   return mLength == length &&
          char_traits::compare(mData, aData, mLength) == 0;
 }
 
 bool
-nsTStringRepr_CharT::Equals(const char_type* aData,
-                            const comparator_type& aComp) const
+nsTSubstring_CharT::Equals(const char_type* aData,
+                           const comparator_type& aComp) const
 {
   // unfortunately, some callers pass null :-(
   if (!aData) {
     NS_NOTREACHED("null data pointer");
     return mLength == 0;
   }
 
   // XXX avoid length calculation?
   size_type length = char_traits::length(aData);
   return mLength == length && aComp(mData, aData, mLength, length) == 0;
 }
 
 bool
-nsTStringRepr_CharT::EqualsASCII(const char* aData, size_type aLen) const
+nsTSubstring_CharT::EqualsASCII(const char* aData, size_type aLen) const
 {
   return mLength == aLen &&
          char_traits::compareASCII(mData, aData, aLen) == 0;
 }
 
 bool
-nsTStringRepr_CharT::EqualsASCII(const char* aData) const
+nsTSubstring_CharT::EqualsASCII(const char* aData) const
 {
   return char_traits::compareASCIINullTerminated(mData, mLength, aData) == 0;
 }
 
 bool
-nsTStringRepr_CharT::LowerCaseEqualsASCII(const char* aData,
-                                          size_type aLen) const
+nsTSubstring_CharT::LowerCaseEqualsASCII(const char* aData,
+                                         size_type aLen) const
 {
   return mLength == aLen &&
          char_traits::compareLowerCaseToASCII(mData, aData, aLen) == 0;
 }
 
 bool
-nsTStringRepr_CharT::LowerCaseEqualsASCII(const char* aData) const
+nsTSubstring_CharT::LowerCaseEqualsASCII(const char* aData) const
 {
   return char_traits::compareLowerCaseToASCIINullTerminated(mData,
                                                             mLength,
                                                             aData) == 0;
 }
 
-nsTStringRepr_CharT::size_type
-nsTStringRepr_CharT::CountChar(char_type aChar) const
+nsTSubstring_CharT::size_type
+nsTSubstring_CharT::CountChar(char_type aChar) const
 {
   const char_type* start = mData;
   const char_type* end   = mData + mLength;
 
   return NS_COUNT(start, end, aChar);
 }
 
 int32_t
-nsTStringRepr_CharT::FindChar(char_type aChar, index_type aOffset) const
+nsTSubstring_CharT::FindChar(char_type aChar, index_type aOffset) const
 {
   if (aOffset < mLength) {
     const char_type* result = char_traits::find(mData + aOffset,
                                                 mLength - aOffset, aChar);
     if (result) {
       return result - mData;
     }
   }
   return -1;
 }
 
-} // namespace detail
-} // namespace mozilla
-
 void
 nsTSubstring_CharT::StripChar(char_type aChar, int32_t aOffset)
 {
   if (mLength == 0 || aOffset >= int32_t(mLength)) {
     return;
   }
 
   if (!EnsureMutable()) { // XXX do this lazily?
--- a/xpcom/string/nsTSubstring.h
+++ b/xpcom/string/nsTSubstring.h
@@ -45,63 +45,64 @@ public:
   }
 
   virtual int operator()(const char_type*, const char_type*,
                          uint32_t, uint32_t) const override;
 };
 
 class nsTSubstringSplitter_CharT;
 
-namespace mozilla {
-namespace detail {
-
 /**
- * nsTStringRepr defines a string's memory layout and some accessor methods.
- * This class exists so that nsTLiteralString can avoid inheriting
- * nsTSubstring's destructor. All methods on this class must be const because
- * literal strings are not writable.
- *
- * This class is an implementation detail and should not be instantiated
- * directly, nor used in any way outside of the string code itself. It is
- * buried in a namespace to discourage its use in function parameters.
- * If you need to take a parameter, use [const] ns[C]Substring&.
- * If you need to instantiate a string, use ns[C]String or descendents.
+ * nsTSubstring is the most abstract class in the string hierarchy. It
+ * represents a single contiguous array of characters, which may or may not
+ * be null-terminated. This type is not instantiated directly.  A sub-class
+ * is instantiated instead.  For example, see nsTString.
  *
  * NAMES:
- *   nsStringRepr for wide characters
- *   nsCStringRepr for narrow characters
+ *   nsAString for wide characters
+ *   nsACString for narrow characters
  *
+ * Many of the accessors on nsTSubstring are inlined as an optimization.
  */
-class nsTStringRepr_CharT
+class nsTSubstring_CharT
 {
 public:
   typedef mozilla::fallible_t                 fallible_t;
 
   typedef CharT                               char_type;
 
   typedef nsCharTraits<char_type>             char_traits;
   typedef char_traits::incompatible_char_type incompatible_char_type;
 
-  typedef nsTStringRepr_CharT                 self_type;
+  typedef nsTSubstring_CharT                  self_type;
+  typedef self_type                           abstract_string_type;
   typedef self_type                           base_string_type;
 
-  typedef nsTSubstring_CharT                  substring_type;
+  typedef self_type                           substring_type;
   typedef nsTSubstringTuple_CharT             substring_tuple_type;
   typedef nsTString_CharT                     string_type;
 
   typedef nsReadingIterator<char_type>        const_iterator;
   typedef nsWritingIterator<char_type>        iterator;
 
   typedef nsTStringComparator_CharT           comparator_type;
 
   typedef char_type*                          char_iterator;
   typedef const char_type*                    const_char_iterator;
 
+  typedef uint32_t                            size_type;
   typedef uint32_t                            index_type;
-  typedef uint32_t                            size_type;
+
+public:
+
+  // this acts like a virtual destructor
+  ~nsTSubstring_CharT()
+  {
+    Finalize();
+  }
 
   /**
    * reading iterators
    */
 
   const_char_iterator BeginReading() const
   {
     return mData;
@@ -136,16 +137,91 @@ public:
     return aIter = mData;
   }
 
   const_char_iterator& EndReading(const_char_iterator& aIter) const
   {
     return aIter = mData + mLength;
   }
 
+
+  /**
+   * writing iterators
+   */
+
+  char_iterator BeginWriting()
+  {
+    if (!EnsureMutable()) {
+      AllocFailed(mLength);
+    }
+
+    return mData;
+  }
+
+  char_iterator BeginWriting(const fallible_t&)
+  {
+    return EnsureMutable() ? mData : char_iterator(0);
+  }
+
+  char_iterator EndWriting()
+  {
+    if (!EnsureMutable()) {
+      AllocFailed(mLength);
+    }
+
+    return mData + mLength;
+  }
+
+  char_iterator EndWriting(const fallible_t&)
+  {
+    return EnsureMutable() ? (mData + mLength) : char_iterator(0);
+  }
+
+  char_iterator& BeginWriting(char_iterator& aIter)
+  {
+    return aIter = BeginWriting();
+  }
+
+  char_iterator& BeginWriting(char_iterator& aIter, const fallible_t& aFallible)
+  {
+    return aIter = BeginWriting(aFallible);
+  }
+
+  char_iterator& EndWriting(char_iterator& aIter)
+  {
+    return aIter = EndWriting();
+  }
+
+  char_iterator& EndWriting(char_iterator& aIter, const fallible_t& aFallible)
+  {
+    return aIter = EndWriting(aFallible);
+  }
+
+  /**
+   * deprecated writing iterators
+   */
+
+  iterator& BeginWriting(iterator& aIter)
+  {
+    char_type* data = BeginWriting();
+    aIter.mStart = data;
+    aIter.mEnd = data + mLength;
+    aIter.mPosition = aIter.mStart;
+    return aIter;
+  }
+
+  iterator& EndWriting(iterator& aIter)
+  {
+    char_type* data = BeginWriting();
+    aIter.mStart = data;
+    aIter.mEnd = data + mLength;
+    aIter.mPosition = aIter.mEnd;
+    return aIter;
+  }
+
   /**
    * accessors
    */
 
   // returns pointer to string data (not necessarily null-terminated)
 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
   char16ptr_t Data() const
 #else
@@ -210,20 +286,16 @@ public:
 
   /**
    * equality
    */
 
   bool NS_FASTCALL Equals(const self_type&) const;
   bool NS_FASTCALL Equals(const self_type&, const comparator_type&) const;
 
-  bool NS_FASTCALL Equals(const substring_tuple_type& aTuple) const;
-  bool NS_FASTCALL Equals(const substring_tuple_type& aTuple,
-                          const comparator_type& aComp) const;
-
   bool NS_FASTCALL Equals(const char_type* aData) const;
   bool NS_FASTCALL Equals(const char_type* aData,
                           const comparator_type& aComp) const;
 
 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
   bool NS_FASTCALL Equals(char16ptr_t aData) const
   {
     return Equals(static_cast<const char16_t*>(aData));
@@ -276,205 +348,16 @@ public:
   // LowerCaseEqualsASCII for them.
   template<int N>
   inline bool LowerCaseEqualsLiteral(const char (&aStr)[N]) const
   {
     return LowerCaseEqualsASCII(aStr, N - 1);
   }
 
   /**
-   * returns true if this string overlaps with the given string fragment.
-   */
-  bool IsDependentOn(const char_type* aStart, const char_type* aEnd) const
-  {
-    /**
-     * if it _isn't_ the case that one fragment starts after the other ends,
-     * or ends before the other starts, then, they conflict:
-     *
-     *   !(f2.begin >= f1.aEnd || f2.aEnd <= f1.begin)
-     *
-     * Simplified, that gives us:
-     */
-    return (aStart < (mData + mLength) && aEnd > mData);
-  }
-
-protected:
-  nsTStringRepr_CharT() = delete; // Never instantiate directly
-
-  constexpr
-  nsTStringRepr_CharT(char_type* aData, size_type aLength, uint32_t aFlags)
-    : mData(aData)
-    , mLength(aLength)
-    , mFlags(aFlags)
-  {
-  }
-
-  char_type*  mData;
-  size_type   mLength;
-  uint32_t    mFlags;
-
-public:
-  // mFlags is a bitwise combination of the following flags.  the meaning
-  // and interpretation of these flags is an implementation detail.
-  //
-  // NOTE: these flags are declared public _only_ for convenience inside
-  // the string implementation.
-
-  enum
-  {
-    F_NONE         = 0,       // no flags
-
-    // data flags are in the lower 16-bits
-    F_TERMINATED   = 1 << 0,  // IsTerminated returns true
-    F_VOIDED       = 1 << 1,  // IsVoid returns true
-    F_SHARED       = 1 << 2,  // mData points to a heap-allocated, shared buffer
-    F_OWNED        = 1 << 3,  // mData points to a heap-allocated, raw buffer
-    F_FIXED        = 1 << 4,  // mData points to a fixed-size writable, dependent buffer
-    F_LITERAL      = 1 << 5,  // mData points to a string literal; F_TERMINATED will also be set
-
-    // class flags are in the upper 16-bits
-    F_CLASS_FIXED  = 1 << 16   // indicates that |this| is of type nsTFixedString
-  };
-
-  //
-  // Some terminology:
-  //
-  //   "dependent buffer"    A dependent buffer is one that the string class
-  //                         does not own.  The string class relies on some
-  //                         external code to ensure the lifetime of the
-  //                         dependent buffer.
-  //
-  //   "shared buffer"       A shared buffer is one that the string class
-  //                         allocates.  When it allocates a shared string
-  //                         buffer, it allocates some additional space at
-  //                         the beginning of the buffer for additional
-  //                         fields, including a reference count and a
-  //                         buffer length.  See nsStringHeader.
-  //
-  //   "adopted buffer"      An adopted buffer is a raw string buffer
-  //                         allocated on the heap (using moz_xmalloc)
-  //                         of which the string class subsumes ownership.
-  //
-  // Some comments about the string flags:
-  //
-  //   F_SHARED, F_OWNED, and F_FIXED are all mutually exlusive.  They
-  //   indicate the allocation type of mData.  If none of these flags
-  //   are set, then the string buffer is dependent.
-  //
-  //   F_SHARED, F_OWNED, or F_FIXED imply F_TERMINATED.  This is because
-  //   the string classes always allocate null-terminated buffers, and
-  //   non-terminated substrings are always dependent.
-  //
-  //   F_VOIDED implies F_TERMINATED, and moreover it implies that mData
-  //   points to char_traits::sEmptyBuffer.  Therefore, F_VOIDED is
-  //   mutually exclusive with F_SHARED, F_OWNED, and F_FIXED.
-  //
-};
-
-} // namespace detail
-} // namespace mozilla
-
-/**
- * nsTSubstring is an abstract string class. From an API perspective, this
- * class is the root of the string class hierarchy. It represents a single
- * contiguous array of characters, which may or may not be null-terminated.
- * This type is not instantiated directly. A sub-class is instantiated
- * instead. For example, see nsTString.
- *
- * NAMES:
- *   nsAString for wide characters
- *   nsACString for narrow characters
- *
- */
-class nsTSubstring_CharT : public mozilla::detail::nsTStringRepr_CharT
-{
-public:
-  typedef nsTSubstring_CharT                  self_type;
-
-  // this acts like a virtual destructor
-  ~nsTSubstring_CharT()
-  {
-    Finalize();
-  }
-
-  /**
-   * writing iterators
-   */
-
-  char_iterator BeginWriting()
-  {
-    if (!EnsureMutable()) {
-      AllocFailed(mLength);
-    }
-
-    return mData;
-  }
-
-  char_iterator BeginWriting(const fallible_t&)
-  {
-    return EnsureMutable() ? mData : char_iterator(0);
-  }
-
-  char_iterator EndWriting()
-  {
-    if (!EnsureMutable()) {
-      AllocFailed(mLength);
-    }
-
-    return mData + mLength;
-  }
-
-  char_iterator EndWriting(const fallible_t&)
-  {
-    return EnsureMutable() ? (mData + mLength) : char_iterator(0);
-  }
-
-  char_iterator& BeginWriting(char_iterator& aIter)
-  {
-    return aIter = BeginWriting();
-  }
-
-  char_iterator& BeginWriting(char_iterator& aIter, const fallible_t& aFallible)
-  {
-    return aIter = BeginWriting(aFallible);
-  }
-
-  char_iterator& EndWriting(char_iterator& aIter)
-  {
-    return aIter = EndWriting();
-  }
-
-  char_iterator& EndWriting(char_iterator& aIter, const fallible_t& aFallible)
-  {
-    return aIter = EndWriting(aFallible);
-  }
-
-  /**
-   * deprecated writing iterators
-   */
-
-  iterator& BeginWriting(iterator& aIter)
-  {
-    char_type* data = BeginWriting();
-    aIter.mStart = data;
-    aIter.mEnd = data + mLength;
-    aIter.mPosition = aIter.mStart;
-    return aIter;
-  }
-
-  iterator& EndWriting(iterator& aIter)
-  {
-    char_type* data = BeginWriting();
-    aIter.mStart = data;
-    aIter.mEnd = data + mLength;
-    aIter.mPosition = aIter.mEnd;
-    return aIter;
-  }
-
-  /**
    * assignment
    */
 
   void NS_FASTCALL Assign(char_type aChar);
   MOZ_MUST_USE bool NS_FASTCALL Assign(char_type aChar, const fallible_t&);
 
   void NS_FASTCALL Assign(const char_type* aData);
   MOZ_MUST_USE bool NS_FASTCALL Assign(const char_type* aData,
@@ -963,21 +846,43 @@ public:
 
 public:
 
   /**
    * this is public to support automatic conversion of tuple to string
    * base type, which helps avoid converting to nsTAString.
    */
   MOZ_IMPLICIT nsTSubstring_CharT(const substring_tuple_type& aTuple)
-    : nsTStringRepr_CharT(nullptr, 0, F_NONE)
+    : mData(nullptr)
+    , mLength(0)
+    , mFlags(F_NONE)
   {
     Assign(aTuple);
   }
 
+  /**
+   * allows for direct initialization of a nsTSubstring object.
+   *
+   * NOTE: this constructor is declared public _only_ for convenience
+   * inside the string implementation.
+   */
+  // XXXbz or can I just include nscore.h and use NS_BUILD_REFCNT_LOGGING?
+#if defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING)
+#define XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
+  nsTSubstring_CharT(char_type* aData, size_type aLength, uint32_t aFlags);
+#else
+#undef XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
+  nsTSubstring_CharT(char_type* aData, size_type aLength, uint32_t aFlags)
+    : mData(aData)
+    , mLength(aLength)
+    , mFlags(aFlags)
+  {
+  }
+#endif /* DEBUG || FORCE_BUILD_REFCNT_LOGGING */
+
   size_t SizeOfExcludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf)
   const;
   size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf)
   const;
 
   /**
    * WARNING: Only use these functions if you really know what you are
    * doing, because they can easily lead to double-counting strings.  If
@@ -1000,45 +905,48 @@ public:
 
   MOZ_ALWAYS_INLINE void AllocFailed(size_t aLength)
   {
     ::NS_ABORT_OOM(aLength * sizeof(char_type));
   }
 
 protected:
 
+  friend class nsTObsoleteAStringThunk_CharT;
+  friend class nsTSubstringTuple_CharT;
+  friend class nsTPromiseFlatString_CharT;
+
+  char_type*  mData;
+  size_type   mLength;
+  uint32_t    mFlags;
+
   // default initialization
   nsTSubstring_CharT()
-    : nsTStringRepr_CharT(char_traits::sEmptyBuffer, 0, F_TERMINATED)
+    : mData(char_traits::sEmptyBuffer)
+    ,  mLength(0)
+    ,  mFlags(F_TERMINATED)
+  {
+  }
+
+  // version of constructor that leaves mData and mLength uninitialized
+  explicit
+  nsTSubstring_CharT(uint32_t aFlags)
+    : mFlags(aFlags)
   {
   }
 
   // copy-constructor, constructs as dependent on given object
   // (NOTE: this is for internal use only)
   nsTSubstring_CharT(const self_type& aStr)
-    : nsTStringRepr_CharT(aStr.mData, aStr.mLength,
-                          aStr.mFlags & (F_TERMINATED | F_VOIDED))
+    : mData(aStr.mData)
+    ,  mLength(aStr.mLength)
+    ,  mFlags(aStr.mFlags & (F_TERMINATED | F_VOIDED))
   {
   }
 
- /**
-   * allows for direct initialization of a nsTSubstring object.
-   */
-  // XXXbz or can I just include nscore.h and use NS_BUILD_REFCNT_LOGGING?
-#if defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING)
-#define XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
-  nsTSubstring_CharT(char_type* aData, size_type aLength, uint32_t aFlags);
-#else
-#undef XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
-  nsTSubstring_CharT(char_type* aData, size_type aLength, uint32_t aFlags)
-    : nsTStringRepr_CharT(aData, aLength, aFlags)
-  {
-  }
-#endif /* DEBUG || FORCE_BUILD_REFCNT_LOGGING */
-
   /**
    * this function releases mData and does not change the value of
    * any of its member variables.  in other words, this function acts
    * like a destructor.
    */
   void NS_FASTCALL Finalize();
 
   /**
@@ -1104,38 +1012,105 @@ protected:
   /**
    * this helper function can be called prior to directly manipulating
    * the contents of mData.  see, for example, BeginWriting.
    */
   MOZ_MUST_USE bool NS_FASTCALL EnsureMutable(
     size_type aNewLen = size_type(-1));
 
   /**
+   * returns true if this string overlaps with the given string fragment.
+   */
+  bool IsDependentOn(const char_type* aStart, const char_type* aEnd) const
+  {
+    /**
+     * if it _isn't_ the case that one fragment starts after the other ends,
+     * or ends before the other starts, then, they conflict:
+     *
+     *   !(f2.begin >= f1.aEnd || f2.aEnd <= f1.begin)
+     *
+     * Simplified, that gives us:
+     */
+    return (aStart < (mData + mLength) && aEnd > mData);
+  }
+
+  /**
    * this helper function stores the specified dataFlags in mFlags
    */
   void SetDataFlags(uint32_t aDataFlags)
   {
     NS_ASSERTION((aDataFlags & 0xFFFF0000) == 0, "bad flags");
     mFlags = aDataFlags | (mFlags & 0xFFFF0000);
   }
 
   void NS_FASTCALL ReplaceLiteral(index_type aCutStart, size_type aCutLength,
                                   const char_type* aData, size_type aLength);
 
 public:
 
   // NOTE: this method is declared public _only_ for convenience for
   // callers who don't have access to the original nsLiteralString_CharT.
   void NS_FASTCALL AssignLiteral(const char_type* aData, size_type aLength);
-};
+
+  // mFlags is a bitwise combination of the following flags.  the meaning
+  // and interpretation of these flags is an implementation detail.
+  //
+  // NOTE: these flags are declared public _only_ for convenience inside
+  // the string implementation.
+
+  enum
+  {
+    F_NONE         = 0,       // no flags
+
+    // data flags are in the lower 16-bits
+    F_TERMINATED   = 1 << 0,  // IsTerminated returns true
+    F_VOIDED       = 1 << 1,  // IsVoid returns true
+    F_SHARED       = 1 << 2,  // mData points to a heap-allocated, shared buffer
+    F_OWNED        = 1 << 3,  // mData points to a heap-allocated, raw buffer
+    F_FIXED        = 1 << 4,  // mData points to a fixed-size writable, dependent buffer
+    F_LITERAL      = 1 << 5,  // mData points to a string literal; F_TERMINATED will also be set
+
+    // class flags are in the upper 16-bits
+    F_CLASS_FIXED  = 1 << 16   // indicates that |this| is of type nsTFixedString
+  };
 
-static_assert(sizeof(nsTSubstring_CharT) ==
-              sizeof(mozilla::detail::nsTStringRepr_CharT),
-              "Don't add new data fields to nsTSubstring_CharT. "
-              "Add to nsTStringRepr_CharT instead.");
+  //
+  // Some terminology:
+  //
+  //   "dependent buffer"    A dependent buffer is one that the string class
+  //                         does not own.  The string class relies on some
+  //                         external code to ensure the lifetime of the
+  //                         dependent buffer.
+  //
+  //   "shared buffer"       A shared buffer is one that the string class
+  //                         allocates.  When it allocates a shared string
+  //                         buffer, it allocates some additional space at
+  //                         the beginning of the buffer for additional
+  //                         fields, including a reference count and a
+  //                         buffer length.  See nsStringHeader.
+  //
+  //   "adopted buffer"      An adopted buffer is a raw string buffer
+  //                         allocated on the heap (using moz_xmalloc)
+  //                         of which the string class subsumes ownership.
+  //
+  // Some comments about the string flags:
+  //
+  //   F_SHARED, F_OWNED, and F_FIXED are all mutually exlusive.  They
+  //   indicate the allocation type of mData.  If none of these flags
+  //   are set, then the string buffer is dependent.
+  //
+  //   F_SHARED, F_OWNED, or F_FIXED imply F_TERMINATED.  This is because
+  //   the string classes always allocate null-terminated buffers, and
+  //   non-terminated substrings are always dependent.
+  //
+  //   F_VOIDED implies F_TERMINATED, and moreover it implies that mData
+  //   points to char_traits::sEmptyBuffer.  Therefore, F_VOIDED is
+  //   mutually exclusive with F_SHARED, F_OWNED, and F_FIXED.
+  //
+};
 
 int NS_FASTCALL
 Compare(const nsTSubstring_CharT::base_string_type& aLhs,
         const nsTSubstring_CharT::base_string_type& aRhs,
         const nsTStringComparator_CharT& = nsTDefaultStringComparator_CharT());
 
 
 inline bool
--- a/xpcom/string/nsTSubstringTuple.cpp
+++ b/xpcom/string/nsTSubstringTuple.cpp
@@ -12,60 +12,85 @@
 
 nsTSubstringTuple_CharT::size_type
 nsTSubstringTuple_CharT::Length() const
 {
   mozilla::CheckedInt<size_type> len;
   if (mHead) {
     len = mHead->Length();
   } else {
-    len = mFragA->Length();
+    len = TO_SUBSTRING(mFragA).Length();
   }
 
-  len += mFragB->Length();
+  len += TO_SUBSTRING(mFragB).Length();
   MOZ_RELEASE_ASSERT(len.isValid(), "Substring tuple length is invalid");
   return len.value();
 }
 
 
 /**
  * writes the aggregate string to the given buffer. aBufLen is assumed
  * to be equal to or greater than the value returned by the Length()
  * method.  the string written to |aBuf| is not null-terminated.
  */
 
 void
 nsTSubstringTuple_CharT::WriteTo(char_type* aBuf, uint32_t aBufLen) const
 {
-  MOZ_RELEASE_ASSERT(aBufLen >= mFragB->Length(), "buffer too small");
-  uint32_t headLen = aBufLen - mFragB->Length();
+  const substring_type& b = TO_SUBSTRING(mFragB);
+
+  MOZ_RELEASE_ASSERT(aBufLen >= b.Length(), "buffer too small");
+  uint32_t headLen = aBufLen - b.Length();
   if (mHead) {
     mHead->WriteTo(aBuf, headLen);
   } else {
-    MOZ_RELEASE_ASSERT(mFragA->Length() == headLen, "buffer incorrectly sized");
-    char_traits::copy(aBuf, mFragA->Data(), mFragA->Length());
+    const substring_type& a = TO_SUBSTRING(mFragA);
+
+    MOZ_RELEASE_ASSERT(a.Length() == headLen, "buffer incorrectly sized");
+    char_traits::copy(aBuf, a.Data(), a.Length());
   }
 
-  char_traits::copy(aBuf + headLen, mFragB->Data(), mFragB->Length());
+  char_traits::copy(aBuf + headLen, b.Data(), b.Length());
+
+#if 0
+  // we need to write out data into |aBuf|, ending at |aBuf + aBufLen|. So our
+  // data needs to precede |aBuf + aBufLen| exactly. We trust that the buffer
+  // was properly sized!
+
+  const substring_type& b = TO_SUBSTRING(mFragB);
+
+  NS_ASSERTION(aBufLen >= b.Length(), "buffer is too small");
+  char_traits::copy(aBuf + aBufLen - b.Length(), b.Data(), b.Length());
+
+  aBufLen -= b.Length();
+
+  if (mHead) {
+    mHead->WriteTo(aBuf, aBufLen);
+  } else {
+    const substring_type& a = TO_SUBSTRING(mFragA);
+    NS_ASSERTION(aBufLen == a.Length(), "buffer is too small");
+    char_traits::copy(aBuf, a.Data(), a.Length());
+  }
+#endif
 }
 
 
 /**
  * returns true if this tuple is dependent on (i.e., overlapping with)
  * the given char sequence.
  */
 
 bool
 nsTSubstringTuple_CharT::IsDependentOn(const char_type* aStart,
                                        const char_type* aEnd) const
 {
   // we aStart with the right-most fragment since it is faster to check.
 
-  if (mFragB->IsDependentOn(aStart, aEnd)) {
+  if (TO_SUBSTRING(mFragB).IsDependentOn(aStart, aEnd)) {
     return true;
   }
 
   if (mHead) {
     return mHead->IsDependentOn(aStart, aEnd);
   }
 
-  return mFragA->IsDependentOn(aStart, aEnd);
+  return TO_SUBSTRING(mFragA).IsDependentOn(aStart, aEnd);
 }
--- a/xpcom/string/nsTSubstringTuple.h
+++ b/xpcom/string/nsTSubstringTuple.h
@@ -13,22 +13,23 @@
  *
  * NOTE: This class is a private implementation detail and should never be
  * referenced outside the string code.
  */
 class nsTSubstringTuple_CharT
 {
 public:
 
-  typedef CharT                                 char_type;
-  typedef nsCharTraits<char_type>               char_traits;
+  typedef CharT                      char_type;
+  typedef nsCharTraits<char_type>    char_traits;
 
-  typedef nsTSubstringTuple_CharT               self_type;
-  typedef mozilla::detail::nsTStringRepr_CharT  base_string_type;
-  typedef uint32_t                              size_type;
+  typedef nsTSubstringTuple_CharT    self_type;
+  typedef nsTSubstring_CharT         substring_type;
+  typedef nsTSubstring_CharT         base_string_type;
+  typedef uint32_t                   size_type;
 
 public:
 
   nsTSubstringTuple_CharT(const base_string_type* aStrA,
                           const base_string_type* aStrB)
     : mHead(nullptr)
     , mFragA(aStrA)
     , mFragB(aStrB)
@@ -58,19 +59,19 @@ public:
   /**
    * returns true if this tuple is dependent on (i.e., overlapping with)
    * the given char sequence.
    */
   bool IsDependentOn(const char_type* aStart, const char_type* aEnd) const;
 
 private:
 
-  const self_type*        const mHead;
-  const base_string_type* const mFragA;
-  const base_string_type* const mFragB;
+  const self_type*        mHead;
+  const base_string_type* mFragA;
+  const base_string_type* mFragB;
 };
 
 inline const nsTSubstringTuple_CharT
 operator+(const nsTSubstringTuple_CharT::base_string_type& aStrA,
           const nsTSubstringTuple_CharT::base_string_type& aStrB)
 {
   return nsTSubstringTuple_CharT(&aStrA, &aStrB);
 }
--- a/xpcom/string/string-template-def-char.h
+++ b/xpcom/string/string-template-def-char.h
@@ -4,17 +4,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/. */
 // IWYU pragma: private, include "nsString.h"
 
 #define CharT                               char
 #define CharT_is_char                       1
 #define nsTAString_IncompatibleCharT        nsAString
 #define nsTString_CharT                     nsCString
-#define nsTStringRepr_CharT                 nsCStringRepr
 #define nsTFixedString_CharT                nsFixedCString
 #define nsTAutoString_CharT                 nsAutoCString
 #define nsTSubstring_CharT                  nsACString
 #define PrintfAppend_CharT                  PrintfAppend_nsACString
 #define nsTSubstringTuple_CharT             nsCSubstringTuple
 #define nsTStringComparator_CharT           nsCStringComparator
 #define nsTDefaultStringComparator_CharT    nsDefaultCStringComparator
 #define nsTDependentString_CharT            nsDependentCString
--- a/xpcom/string/string-template-def-unichar.h
+++ b/xpcom/string/string-template-def-unichar.h
@@ -4,17 +4,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/. */
 // IWYU pragma: private, include "nsString.h"
 
 #define CharT                               char16_t
 #define CharT_is_PRUnichar                  1
 #define nsTAString_IncompatibleCharT        nsACString
 #define nsTString_CharT                     nsString
-#define nsTStringRepr_CharT                 nsStringRepr
 #define nsTFixedString_CharT                nsFixedString
 #define nsTAutoString_CharT                 nsAutoString
 #define nsTSubstring_CharT                  nsAString
 #define PrintfAppend_CharT                  PrintfAppend_nsAString
 #define nsTSubstringTuple_CharT             nsSubstringTuple
 #define nsTStringComparator_CharT           nsStringComparator
 #define nsTDefaultStringComparator_CharT    nsDefaultStringComparator
 #define nsTDependentString_CharT            nsDependentString
--- a/xpcom/string/string-template-undef.h
+++ b/xpcom/string/string-template-undef.h
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 // IWYU pragma: private, include "nsString.h"
 
 #undef CharT
 #undef CharT_is_PRUnichar
 #undef CharT_is_char
 #undef nsTAString_IncompatibleCharT
 #undef nsTString_CharT
-#undef nsTStringRepr_CharT
 #undef nsTFixedString_CharT
 #undef nsTAutoString_CharT
 #undef nsTSubstring_CharT
 #undef PrintfAppend_CharT
 #undef nsTSubstringTuple_CharT
 #undef nsTStringComparator_CharT
 #undef nsTDefaultStringComparator_CharT
 #undef nsTDependentString_CharT
--- a/xpcom/tests/gtest/TestObserverService.cpp
+++ b/xpcom/tests/gtest/TestObserverService.cpp
@@ -247,42 +247,42 @@ TEST(ObserverService, TestNotify)
   // Add two observers for topicA.
   testResult(svc->AddObserver(aObserver, topicA.get(), false));
   testResult(svc->AddObserver(bObserver, topicA.get(), false));
 
   // Add one observer for topicB.
   testResult(svc->AddObserver(bObserver, topicB.get(), false));
 
   // Notify topicA.
-  const char16_t* dataA = u"Testing Notify(observer-A, topic-A)";
+  NS_NAMED_LITERAL_STRING(dataA, "Testing Notify(observer-A, topic-A)");
   aObserver->mExpectedData = dataA;
   bObserver->mExpectedData = dataA;
   nsresult rv =
-      svc->NotifyObservers(ToSupports(aObserver), topicA.get(), dataA);
+      svc->NotifyObservers(ToSupports(aObserver), topicA.get(), dataA.get());
   testResult(rv);
   ASSERT_EQ(aObserver->mObservations, 1);
   ASSERT_EQ(bObserver->mObservations, 1);
 
   // Notify topicB.
-  const char16_t* dataB = u"Testing Notify(observer-B, topic-B)";
+  NS_NAMED_LITERAL_STRING(dataB, "Testing Notify(observer-B, topic-B)");
   bObserver->mExpectedData = dataB;
-  rv = svc->NotifyObservers(ToSupports(bObserver), topicB.get(), dataB);
+  rv = svc->NotifyObservers(ToSupports(bObserver), topicB.get(), dataB.get());
   testResult(rv);
   ASSERT_EQ(aObserver->mObservations, 1);
   ASSERT_EQ(bObserver->mObservations, 2);
 
   // Remove one of the topicA observers, make sure it's not notified.
   testResult(svc->RemoveObserver(aObserver, topicA.get()));
 
   // Notify topicA, only bObserver is expected to be notified.
   bObserver->mExpectedData = dataA;
-  rv = svc->NotifyObservers(ToSupports(aObserver), topicA.get(), dataA);
+  rv = svc->NotifyObservers(ToSupports(aObserver), topicA.get(), dataA.get());
   testResult(rv);
   ASSERT_EQ(aObserver->mObservations, 1);
   ASSERT_EQ(bObserver->mObservations, 3);
 
   // Remove the other topicA observer, make sure none are notified.
   testResult(svc->RemoveObserver(bObserver, topicA.get()));
-  rv = svc->NotifyObservers(ToSupports(aObserver), topicA.get(), dataA);
+  rv = svc->NotifyObservers(ToSupports(aObserver), topicA.get(), dataA.get());
   testResult(rv);
   ASSERT_EQ(aObserver->mObservations, 1);
   ASSERT_EQ(bObserver->mObservations, 3);
 }
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -1493,22 +1493,25 @@ nsThread::DoMainThreadSpecificProcessing
   }
 
   // Fire a memory pressure notification, if one is pending.
   if (!ShuttingDown()) {
     MemoryPressureState mpPending = NS_GetPendingMemoryPressure();
     if (mpPending != MemPressure_None) {
       nsCOMPtr<nsIObserverService> os = services::GetObserverService();
 
+      // Use no-forward to prevent the notifications from being transferred to
+      // the children of this process.
+      NS_NAMED_LITERAL_STRING(lowMem, "low-memory-no-forward");
+      NS_NAMED_LITERAL_STRING(lowMemOngoing, "low-memory-ongoing-no-forward");
+
       if (os) {
-        // Use no-forward to prevent the notifications from being transferred to
-        // the children of this process.
         os->NotifyObservers(nullptr, "memory-pressure",
-                            mpPending == MemPressure_New ? u"low-memory-no-forward" :
-                            u"low-memory-ongoing-no-forward");
+                            mpPending == MemPressure_New ? lowMem.get() :
+                            lowMemOngoing.get());
       } else {
         NS_WARNING("Can't get observer service!");
       }
     }
   }
 
 #ifdef MOZ_CRASHREPORTER
   if (!ShuttingDown()) {
--- a/xpfe/appshell/nsAppShellFactory.cpp
+++ b/xpfe/appshell/nsAppShellFactory.cpp
@@ -26,15 +26,31 @@ static const mozilla::Module::CIDEntry k
 };
 
 static const mozilla::Module::ContractIDEntry kAppShellContracts[] = {
   { NS_APPSHELLSERVICE_CONTRACTID, &kNS_APPSHELLSERVICE_CID },
   { NS_WINDOWMEDIATOR_CONTRACTID, &kNS_WINDOWMEDIATOR_CID },
   { nullptr }
 };
 
+static nsresult
+nsAppShellModuleConstructor()
+{
+  return nsChromeTreeOwner::InitGlobals();
+}
+
+static void
+nsAppShellModuleDestructor()
+{
+  nsChromeTreeOwner::FreeGlobals();
+}
+
 static const mozilla::Module kAppShellModule = {
   mozilla::Module::kVersion,
   kAppShellCIDs,
   kAppShellContracts,
+  nullptr,
+  nullptr,
+  nsAppShellModuleConstructor,
+  nsAppShellModuleDestructor
 };
 
 NSMODULE_DEFN(appshell) = &kAppShellModule;
--- a/xpfe/appshell/nsChromeTreeOwner.cpp
+++ b/xpfe/appshell/nsChromeTreeOwner.cpp
@@ -30,23 +30,53 @@
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 
 //*****************************************************************************
 // nsChromeTreeOwner string literals
 //*****************************************************************************
 
-const nsLiteralString kPersist(u"persist");
-const nsLiteralString kScreenX(u"screenX");
-const nsLiteralString kScreenY(u"screenY");
-const nsLiteralString kWidth(u"width");
-const nsLiteralString kHeight(u"height");
-const nsLiteralString kSizemode(u"sizemode");
-const nsLiteralString kSpace(u" ");
+struct nsChromeTreeOwnerLiterals
+{
+  const nsLiteralString kPersist;
+  const nsLiteralString kScreenX;
+  const nsLiteralString kScreenY;
+  const nsLiteralString kWidth;
+  const nsLiteralString kHeight;
+  const nsLiteralString kSizemode;
+  const nsLiteralString kSpace;
+
+  nsChromeTreeOwnerLiterals()
+    : NS_LITERAL_STRING_INIT(kPersist,"persist")
+    , NS_LITERAL_STRING_INIT(kScreenX,"screenX")
+    , NS_LITERAL_STRING_INIT(kScreenY,"screenY")
+    , NS_LITERAL_STRING_INIT(kWidth,"width")
+    , NS_LITERAL_STRING_INIT(kHeight,"height")
+    , NS_LITERAL_STRING_INIT(kSizemode,"sizemode")
+    , NS_LITERAL_STRING_INIT(kSpace," ")
+  {}
+};
+
+static nsChromeTreeOwnerLiterals *gLiterals;
+
+nsresult
+nsChromeTreeOwner::InitGlobals()
+{
+  NS_ASSERTION(gLiterals == nullptr, "already initialized");
+  gLiterals = new nsChromeTreeOwnerLiterals();
+  return NS_OK;
+}
+
+void
+nsChromeTreeOwner::FreeGlobals()
+{
+  delete gLiterals;
+  gLiterals = nullptr;
+}
 
 //*****************************************************************************
 //***    nsChromeTreeOwner: Object Management
 //*****************************************************************************
 
 nsChromeTreeOwner::nsChromeTreeOwner() : mXULWindow(nullptr)
 {
 }
@@ -194,67 +224,67 @@ nsChromeTreeOwner::SetPersistence(bool a
                                   bool aPersistSizeMode)
 {
   NS_ENSURE_STATE(mXULWindow);
   nsCOMPtr<dom::Element> docShellElement = mXULWindow->GetWindowDOMElement();
   if (!docShellElement)
     return NS_ERROR_FAILURE;
 
   nsAutoString persistString;
-  docShellElement->GetAttribute(kPersist, persistString);
+  docShellElement->GetAttribute(gLiterals->kPersist, persistString);
 
   bool saveString = false;
   int32_t index;
 
 #define FIND_PERSIST_STRING(aString, aCond)            \
   index = persistString.Find(aString);                 \
   if (!aCond && index > kNotFound) {                   \
     persistString.Cut(index, aString.Length());        \
     saveString = true;                              \
   } else if (aCond && index == kNotFound) {            \
-    persistString.Append(kSpace + aString); \
+    persistString.Append(gLiterals->kSpace + aString); \
     saveString = true;                              \
   }
-  FIND_PERSIST_STRING(kScreenX,  aPersistPosition);
-  FIND_PERSIST_STRING(kScreenY,  aPersistPosition);
-  FIND_PERSIST_STRING(kWidth,    aPersistSize);
-  FIND_PERSIST_STRING(kHeight,   aPersistSize);
-  FIND_PERSIST_STRING(kSizemode, aPersistSizeMode);
+  FIND_PERSIST_STRING(gLiterals->kScreenX,  aPersistPosition);
+  FIND_PERSIST_STRING(gLiterals->kScreenY,  aPersistPosition);
+  FIND_PERSIST_STRING(gLiterals->kWidth,    aPersistSize);
+  FIND_PERSIST_STRING(gLiterals->kHeight,   aPersistSize);
+  FIND_PERSIST_STRING(gLiterals->kSizemode, aPersistSizeMode);
 
   ErrorResult rv;
   if (saveString) {
-    docShellElement->SetAttribute(kPersist, persistString, rv);
+    docShellElement->SetAttribute(gLiterals->kPersist, persistString, rv);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsChromeTreeOwner::GetPersistence(bool* aPersistPosition,
                                   bool* aPersistSize,
                                   bool* aPersistSizeMode)
 {
   NS_ENSURE_STATE(mXULWindow);
   nsCOMPtr<dom::Element> docShellElement = mXULWindow->GetWindowDOMElement();
   if (!docShellElement)
     return NS_ERROR_FAILURE;
 
   nsAutoString persistString;
-  docShellElement->GetAttribute(kPersist, persistString);
+  docShellElement->GetAttribute(gLiterals->kPersist, persistString);
 
   // data structure doesn't quite match the question, but it's close enough
   // for what we want (since this method is never actually called...)
   if (aPersistPosition)
-    *aPersistPosition = persistString.Find(kScreenX) > kNotFound ||
-                        persistString.Find(kScreenY) > kNotFound;
+    *aPersistPosition = persistString.Find(gLiterals->kScreenX) > kNotFound ||
+                        persistString.Find(gLiterals->kScreenY) > kNotFound;
   if (aPersistSize)
-    *aPersistSize = persistString.Find(kWidth) > kNotFound ||
-                    persistString.Find(kHeight) > kNotFound;
+    *aPersistSize = persistString.Find(gLiterals->kWidth) > kNotFound ||
+                    persistString.Find(gLiterals->kHeight) > kNotFound;
   if (aPersistSizeMode)
-    *aPersistSizeMode = persistString.Find(kSizemode) > kNotFound;
+    *aPersistSizeMode = persistString.Find(gLiterals->kSizemode) > kNotFound;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsChromeTreeOwner::GetTabCount(uint32_t* aResult)
 {
   if (mXULWindow) {
--- a/xpfe/appshell/nsChromeTreeOwner.h
+++ b/xpfe/appshell/nsChromeTreeOwner.h
@@ -31,16 +31,19 @@ friend class nsXULWindow;
 public:
    NS_DECL_ISUPPORTS
 
    NS_DECL_NSIINTERFACEREQUESTOR
    NS_DECL_NSIBASEWINDOW
    NS_DECL_NSIDOCSHELLTREEOWNER
    NS_DECL_NSIWEBPROGRESSLISTENER
 
+   static nsresult InitGlobals();
+   static void     FreeGlobals();
+
 protected:
    nsChromeTreeOwner();
    virtual ~nsChromeTreeOwner();
 
    void XULWindow(nsXULWindow* aXULWindow);
    nsXULWindow* XULWindow();
 
 protected: