Backed out 2 changesets (bug 1532712) for mochitest failures at browser_policy_set_homepage.js on a CLOSED TREE.
authorGurzau Raul <rgurzau@mozilla.com>
Wed, 13 Mar 2019 21:18:53 +0200
changeset 524754 b8c1398f5a9074d3741997199d3eb2fa568c5469
parent 524753 0a8500467d6df2d175fd64025e998d5a88a39696
child 524755 9f0635581b5c3450ad7521c9d1df0538da6e2469
child 524778 85d3d2603b8f8f90e658ae5ef4a728b450c8bb81
push id2032
push userffxbld-merge
push dateMon, 13 May 2019 09:36:57 +0000
treeherdermozilla-release@455c1065dcbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1532712
milestone67.0a1
backs out1af088f5fc34935f780c2153f1d279ca482e735a
5fb5272aec8ea6c5018441e7e9b5ba1e7e890203
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 2 changesets (bug 1532712) for mochitest failures at browser_policy_set_homepage.js on a CLOSED TREE. Backed out changeset 1af088f5fc34 (bug 1532712) Backed out changeset 5fb5272aec8e (bug 1532712)
browser/components/preferences/in-content/preferences.js
dom/webidl/DocumentL10n.webidl
intl/l10n/DocumentL10n.cpp
intl/l10n/DocumentL10n.h
intl/l10n/mozIDOMLocalization.idl
--- a/browser/components/preferences/in-content/preferences.js
+++ b/browser/components/preferences/in-content/preferences.js
@@ -19,62 +19,83 @@
 
 var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 ChromeUtils.defineModuleGetter(this, "AMTelemetry",
                                "resource://gre/modules/AddonManager.jsm");
 ChromeUtils.defineModuleGetter(this, "formAutofillParent",
                                "resource://formautofill/FormAutofillParent.jsm");
 
-var gLastCategory = {category: undefined, subcategory: undefined};
+var gLastHash = "";
 const gXULDOMParser = new DOMParser();
 
 var gCategoryInits = new Map();
 function init_category_if_required(category) {
   let categoryInfo = gCategoryInits.get(category);
   if (!categoryInfo) {
     throw "Unknown in-content prefs category! Can't init " + category;
   }
   if (categoryInfo.inited) {
-    return null;
+    return;
   }
-  return categoryInfo.init();
+  categoryInfo.init();
 }
 
 function register_module(categoryName, categoryObject) {
   gCategoryInits.set(categoryName, {
     inited: false,
-    async init() {
+    init() {
       let template = document.getElementById("template-" + categoryName);
       if (template) {
         // Replace the template element with the nodes from the parsed comment
         // string.
         let frag = MozXULElement.parseXULToFragment(template.firstChild.data);
 
-        await document.l10n.translateFragment(frag);
+        // Gather the to-be-translated elements so that we could pass them to
+        // l10n.translateElements() and get a translated promise.
+        // Here we loop through the first level elements (<hbox>/<groupbox>/<deck>/etc)
+        // because we know that they are not implemented by XBL bindings,
+        // so it's ok to get a reference of them before inserting the node
+        // to the DOM.
+        //
+        // If we don't have to worry about XBL, this can simply be
+        // let l10nUpdatedElements = Array.from(frag.querySelectorAll("[data-l10n-id]"))
+        //
+        // If we can get a translated promise after insertion, this can all be
+        // removed (see bug 1520659.)
+        let firstLevelElements = Array.from(frag.children);
 
         // Actually insert them into the DOM.
-        document.l10n.pauseObserving();
         template.replaceWith(frag);
-        document.l10n.resumeObserving();
+
+        let l10nUpdatedElements = [];
+        // Collect the elements from the newly inserted first level elements.
+        for (let el of firstLevelElements) {
+          l10nUpdatedElements = l10nUpdatedElements.concat(
+            Array.from(el.querySelectorAll("[data-l10n-id]")));
+        }
+
+        // Set a promise on the categoryInfo object that the highlight code can await on.
+        this.translated = document.l10n.translateElements(l10nUpdatedElements)
+          .then(() => this.translated = undefined);
 
         // Asks Preferences to update the attribute value of the entire
         // document again (this can be simplified if we could seperate the
         // preferences of each pane.)
         Preferences.updateAllElements();
       }
       categoryObject.init();
       this.inited = true;
     },
   });
 }
 
 document.addEventListener("DOMContentLoaded", init_all, {once: true});
 
-async function init_all() {
+function init_all() {
   Preferences.forceEnableInstantApply();
 
   gSubDialog.init();
   register_module("paneGeneral", gMainPane);
   register_module("paneHome", gHomePane);
   register_module("paneSearch", gSearchPane);
   register_module("panePrivacy", gPrivacyPane);
   register_module("paneContainers", gContainersPane);
@@ -96,17 +117,17 @@ async function init_all() {
   });
   categories.addEventListener("mousedown", function() {
     this.removeAttribute("keyboard-navigation");
   });
 
   maybeDisplayPoliciesNotice();
 
   window.addEventListener("hashchange", onHashChange);
-  await gotoPref();
+  gotoPref();
 
   let helpButton = document.getElementById("helpButton");
   let helpUrl = Services.urlFormatter.formatURLPref("app.support.baseURL") + "preferences";
   helpButton.setAttribute("href", helpUrl);
 
   document.getElementById("addonsButton")
     .addEventListener("click", () => {
       let mainWindow = window.docShell.rootTreeItem.domWindow;
@@ -138,17 +159,17 @@ function telemetryBucketForCategory(cate
       return "unknown";
   }
 }
 
 function onHashChange() {
   gotoPref();
 }
 
-async function gotoPref(aCategory) {
+function gotoPref(aCategory) {
   let categories = document.getElementById("categories");
   const kDefaultCategoryInternalName = "paneGeneral";
   const kDefaultCategory = "general";
   let hash = document.location.hash;
 
   let category = aCategory || hash.substr(1) || kDefaultCategoryInternalName;
   let breakIndex = category.indexOf("-");
   // Subcategories allow for selecting smaller sections of the preferences
@@ -169,57 +190,48 @@ async function gotoPref(aCategory) {
     // a query string. Default to the General pane instead.
     category = kDefaultCategoryInternalName;
     document.location.hash = kDefaultCategory;
     gSearchResultsPane.query = null;
   }
 
   // Updating the hash (below) or changing the selected category
   // will re-enter gotoPref.
-  if (gLastCategory.category == category && !subcategory)
+  if (gLastHash == category && !subcategory)
     return;
 
   let item;
   if (category != "paneSearchResults") {
     item = categories.querySelector(".category[value=" + category + "]");
     if (!item) {
       category = kDefaultCategoryInternalName;
       item = categories.querySelector(".category[value=" + category + "]");
     }
   }
 
-  if (gLastCategory.category || category != kDefaultCategoryInternalName || subcategory) {
-    let friendlyName = internalPrefCategoryNameToFriendlyName(category);
+  try {
+    init_category_if_required(category);
+  } catch (ex) {
+    Cu.reportError("Error initializing preference category " + category + ": " + ex);
+    throw ex;
+  }
+
+  let friendlyName = internalPrefCategoryNameToFriendlyName(category);
+  if (gLastHash || category != kDefaultCategoryInternalName || subcategory) {
     document.location.hash = friendlyName;
   }
-  // Need to set the gLastCategory before setting categories.selectedItem since
+  // Need to set the gLastHash before setting categories.selectedItem since
   // the categories 'select' event will re-enter the gotoPref codepath.
-  gLastCategory.category = category;
-  gLastCategory.subcategory = subcategory;
+  gLastHash = category;
   if (item) {
     categories.selectedItem = item;
   } else {
     categories.clearSelection();
   }
   window.history.replaceState(category, document.title);
-
-  try {
-    await init_category_if_required(category);
-  } catch (ex) {
-    Cu.reportError(new Error("Error initializing preference category " + category + ": " + ex));
-    throw ex;
-  }
-
-  // Bail out of this goToPref if the category
-  // or subcategory changed during async operation.
-  if (gLastCategory.category !== category ||
-      gLastCategory.subcategory !== subcategory) {
-    return;
-  }
-
   search(category, "data-category");
 
   let mainContent = document.querySelector(".main-content");
   mainContent.scrollTop = 0;
 
   spotlight(subcategory, category);
 }
 
@@ -267,16 +279,17 @@ async function spotlight(subcategory, ca
 }
 
 async function scrollAndHighlight(subcategory, category) {
   let element = document.querySelector(`[data-subcategory="${subcategory}"]`);
   if (!element) {
     return;
   }
   let header = getClosestDisplayedHeader(element);
+  await gCategoryInits.get(category).translated;
 
   scrollContentTo(header);
   element.classList.add("spotlight");
 }
 
 /**
  * If there is no visible second level header it will return first level header,
  * otherwise return second level header.
--- a/dom/webidl/DocumentL10n.webidl
+++ b/dom/webidl/DocumentL10n.webidl
@@ -137,25 +137,13 @@ interface DocumentL10n {
    * Example:
    *    await document.l10n.translateElements([elem1, elem2]);
    *    parent.appendChild(elem1);
    *    alert(elem2.textContent);
    */
   [NewObject] Promise<void> translateElements(sequence<Element> aElements);
 
   /**
-   * Pauses the MutationObserver set to observe
-   * localization related DOM mutations.
-   */
-  [Throws] void pauseObserving();
-
-  /**
-   * Resumes the MutationObserver set to observe
-   * localization related DOM mutations.
-   */
-  [Throws] void resumeObserving();
-
-  /**
    * A promise which gets resolved when the initial DOM localization resources
    * fetching is complete and the initial translation of the DOM is finished.
    */
   readonly attribute Promise<any> ready;
 };
--- a/intl/l10n/DocumentL10n.cpp
+++ b/intl/l10n/DocumentL10n.cpp
@@ -346,24 +346,16 @@ already_AddRefed<Promise> DocumentL10n::
   RefPtr<Promise> promise;
   aRv = mDOMLocalization->TranslateElements(elements, getter_AddRefs(promise));
   if (aRv.Failed()) {
     return nullptr;
   }
   return MaybeWrapPromise(promise);
 }
 
-void DocumentL10n::PauseObserving(ErrorResult& aRv) {
-  aRv = mDOMLocalization->PauseObserving();
-}
-
-void DocumentL10n::ResumeObserving(ErrorResult& aRv) {
-  aRv = mDOMLocalization->ResumeObserving();
-}
-
 class L10nReadyHandler final : public PromiseNativeHandler {
  public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(L10nReadyHandler)
 
   explicit L10nReadyHandler(Promise* aPromise, DocumentL10n* aDocumentL10n)
       : mPromise(aPromise), mDocumentL10n(aDocumentL10n) {}
 
--- a/intl/l10n/DocumentL10n.h
+++ b/intl/l10n/DocumentL10n.h
@@ -120,19 +120,16 @@ class DocumentL10n final : public nsIObs
                      ErrorResult& aRv);
   void GetAttributes(JSContext* aCx, Element& aElement, L10nKey& aResult,
                      ErrorResult& aRv);
 
   already_AddRefed<Promise> TranslateFragment(nsINode& aNode, ErrorResult& aRv);
   already_AddRefed<Promise> TranslateElements(
       const Sequence<OwningNonNull<Element>>& aElements, ErrorResult& aRv);
 
-  void PauseObserving(ErrorResult& aRv);
-  void ResumeObserving(ErrorResult& aRv);
-
   Promise* Ready();
 
   void TriggerInitialDocumentTranslation();
 
   void InitialDocumentTranslationCompleted();
 };
 
 }  // namespace dom
--- a/intl/l10n/mozIDOMLocalization.idl
+++ b/intl/l10n/mozIDOMLocalization.idl
@@ -20,20 +20,16 @@ interface mozIDOMLocalization : nsISuppo
   Promise formatValues(in Array<jsval> aKeys);
   Promise formatValue(in AString aId, [optional] in jsval aArgs);
 
   Promise translateFragment(in Node aNode);
   Promise translateElements(in Array<Element> aElements);
 
   void connectRoot(in Element aElement);
   void disconnectRoot(in Element aElement);
-
-  void pauseObserving();
-  void resumeObserving();
-
   Promise translateRoots();
   readonly attribute Promise ready;
 };
 
 [scriptable,uuid(96532d26-2422-11e9-a1ce-9bb586acd241)]
 interface mozIDOMLocalizationJSM : nsISupports
 {
   mozIDOMLocalization getDOMLocalization();