Merge mozilla-central to inbound. a=merge CLOSED TREE
authorshindli <shindli@mozilla.com>
Sat, 05 Jan 2019 06:09:57 +0200
changeset 509734 df5c4c4e6a7a6b29a61acdc18184c6a7708ba369
parent 509721 135c1ea8854e871f40a2c42211157f37e2b4eda3 (current diff)
parent 509688 6dd228164d427b7b247e59e7d9d0251206dea83d (diff)
child 509735 cf02de018ec52940d002efde37c539dec74a7469
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to inbound. a=merge CLOSED TREE
modules/libpref/init/all.js
servo/support/gecko/nsstring/Cargo.toml
servo/support/gecko/nsstring/src/conversions.rs
servo/support/gecko/nsstring/src/lib.rs
toolkit/components/prompts/content/tabprompts.xml
--- a/accessible/tests/mochitest/relations/test_ui_modalprompt.html
+++ b/accessible/tests/mochitest/relations/test_ui_modalprompt.html
@@ -44,17 +44,17 @@
         window.setTimeout(
           function() {
             currentTabDocument().defaultView.alert("hello");
           }, 0);
       };
 
       this.check = function showAlert_finalCheck(aEvent) {
         var dialog = aEvent.accessible.DOMNode;
-        var info = dialog.ui.infoBody;
+        var info = dialog.querySelector(".tabmodalprompt-infoBody");
         testRelation(info, RELATION_DESCRIPTION_FOR, dialog);
         testRelation(dialog, RELATION_DESCRIBED_BY, info);
       };
 
       this.getID = function showAlert_getID() {
         return "show alert";
       };
     }
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -52,16 +52,17 @@ XPCOMUtils.defineLazyModuleGetters(this,
   SafeBrowsing: "resource://gre/modules/SafeBrowsing.jsm",
   Sanitizer: "resource:///modules/Sanitizer.jsm",
   SessionStartup: "resource:///modules/sessionstore/SessionStartup.jsm",
   SessionStore: "resource:///modules/sessionstore/SessionStore.jsm",
   ShortcutUtils: "resource://gre/modules/ShortcutUtils.jsm",
   SimpleServiceDiscovery: "resource://gre/modules/SimpleServiceDiscovery.jsm",
   SiteDataManager: "resource:///modules/SiteDataManager.jsm",
   SitePermissions: "resource:///modules/SitePermissions.jsm",
+  TabModalPrompt: "chrome://global/content/tabprompts.jsm",
   TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
   TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.jsm",
   Translation: "resource:///modules/translation/Translation.jsm",
   UITour: "resource:///modules/UITour.jsm",
   UpdateUtils: "resource://gre/modules/UpdateUtils.jsm",
   UrlbarInput: "resource:///modules/UrlbarInput.jsm",
   UrlbarPrefs: "resource:///modules/UrlbarPrefs.jsm",
   UrlbarTokenizer: "resource:///modules/UrlbarTokenizer.jsm",
@@ -8009,40 +8010,48 @@ const SafeBrowsingNotificationBox = {
 
       this._currentURIBaseDomain = null;
     }
   },
 };
 
 function TabModalPromptBox(browser) {
   this._weakBrowserRef = Cu.getWeakReference(browser);
+  /*
+   * This WeakMap holds the TabModalPrompt instances, key to the <tabmodalprompt> prompt
+   * in the DOM. We don't want to hold the instances directly to avoid leaking.
+   *
+   * WeakMap also prevents us from reading back its insertion order.
+   * Order of the elements in the DOM should be the only order to consider.
+   */
+  this.prompts = new WeakMap();
 }
 
 TabModalPromptBox.prototype = {
   _promptCloseCallback(onCloseCallback, principalToAllowFocusFor, allowFocusCheckbox, ...args) {
     if (principalToAllowFocusFor && allowFocusCheckbox &&
         allowFocusCheckbox.checked) {
       Services.perms.addFromPrincipal(principalToAllowFocusFor, "focus-tab-by-prompt",
                                       Services.perms.ALLOW_ACTION);
     }
     onCloseCallback.apply(this, args);
   },
 
   appendPrompt(args, onCloseCallback) {
-    let newPrompt = document.createXULElement("tabmodalprompt");
+    let newPrompt = new TabModalPrompt(window);
+    this.prompts.set(newPrompt.element, newPrompt);
+
     let browser = this.browser;
-    browser.parentNode.insertBefore(newPrompt, browser.nextElementSibling);
+    browser.parentNode.insertBefore(newPrompt.element, browser.nextElementSibling);
     browser.setAttribute("tabmodalPromptShowing", true);
 
-    newPrompt.clientTop; // style flush to assure binding is attached
-
     let prompts = this.listPrompts();
     if (prompts.length > 1) {
       // Let's hide ourself behind the current prompt.
-      newPrompt.hidden = true;
+      newPrompt.element.hidden = true;
     }
 
     let principalToAllowFocusFor = this._allowTabFocusByPromptPrincipal;
     delete this._allowTabFocusByPromptPrincipal;
 
     let allowFocusCheckbox; // Define outside the if block so we can bind it into the callback.
     let hostForAllowFocusCheckbox = "";
     try {
@@ -8052,46 +8061,47 @@ TabModalPromptBox.prototype = {
       let allowFocusRow = document.createXULElement("row");
       allowFocusCheckbox = document.createXULElement("checkbox");
       let spacer = document.createXULElement("spacer");
       allowFocusRow.appendChild(spacer);
       let label = gTabBrowserBundle.formatStringFromName("tabs.allowTabFocusByPromptForSite",
                                                       [hostForAllowFocusCheckbox], 1);
       allowFocusCheckbox.setAttribute("label", label);
       allowFocusRow.appendChild(allowFocusCheckbox);
-      newPrompt.appendChild(allowFocusRow);
+      newPrompt.ui.rows.append(allowFocusRow);
     }
 
     let tab = gBrowser.getTabForBrowser(browser);
     let closeCB = this._promptCloseCallback.bind(null, onCloseCallback, principalToAllowFocusFor,
                                                  allowFocusCheckbox);
     newPrompt.init(args, tab, closeCB);
     return newPrompt;
   },
 
   removePrompt(aPrompt) {
+    this.prompts.delete(aPrompt.element);
     let browser = this.browser;
-    browser.parentNode.removeChild(aPrompt);
+    aPrompt.element.remove();
 
     let prompts = this.listPrompts();
     if (prompts.length) {
       let prompt = prompts[prompts.length - 1];
-      prompt.hidden = false;
+      prompt.element.hidden = false;
       prompt.Dialog.setDefaultFocus();
     } else {
       browser.removeAttribute("tabmodalPromptShowing");
       browser.focus();
     }
   },
 
   listPrompts(aPrompt) {
-    // Get the nodelist, then return as an array
+    // Get the nodelist, then return the TabModalPrompt instances as an array
     const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
     let els = this.browser.parentNode.getElementsByTagNameNS(XUL_NS, "tabmodalprompt");
-    return Array.from(els);
+    return Array.from(els).map(el => this.prompts.get(el));
   },
 
   onNextPromptShowAllowFocusCheckboxFor(principal) {
     this._allowTabFocusByPromptPrincipal = principal;
   },
 
   get browser() {
     let browser = this._weakBrowserRef.get();
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -1144,17 +1144,17 @@ window._gBrowser = {
     // Don't steal focus from the tab bar.
     if (document.activeElement == newTab)
       return;
 
     let newBrowser = this.getBrowserForTab(newTab);
 
     // If there's a tabmodal prompt showing, focus it.
     if (newBrowser.hasAttribute("tabmodalPromptShowing")) {
-      let prompts = newBrowser.parentNode.getElementsByTagNameNS(this._XUL_NS, "tabmodalprompt");
+      let prompts = newBrowser.tabModalPromptBox.listPrompts();
       let prompt = prompts[prompts.length - 1];
       // @tabmodalPromptShowing is also set for other tab modal prompts
       // (e.g. the Payment Request dialog) so there may not be a <tabmodalprompt>.
       // Bug 1492814 will implement this for the Payment Request dialog.
       if (prompt) {
         prompt.Dialog.setDefaultFocus();
         return;
       }
--- a/browser/base/content/test/general/browser_beforeunload_duplicate_dialogs.js
+++ b/browser/base/content/test/general/browser_beforeunload_duplicate_dialogs.js
@@ -3,20 +3,20 @@ const TEST_PAGE = "http://mochi.test:888
 var expectingDialog = false;
 var wantToClose = true;
 var resolveDialogPromise;
 function onTabModalDialogLoaded(node) {
   ok(expectingDialog, "Should be expecting this dialog.");
   expectingDialog = false;
   if (wantToClose) {
     // This accepts the dialog, closing it
-    node.Dialog.ui.button0.click();
+    node.querySelector(".tabmodalprompt-button0").click();
   } else {
     // This keeps the page open
-    node.Dialog.ui.button1.click();
+    node.querySelector(".tabmodalprompt-button1").click();
   }
   if (resolveDialogPromise) {
     resolveDialogPromise();
   }
 }
 
 SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
 
--- a/browser/base/content/test/general/browser_double_close_tab.js
+++ b/browser/base/content/test/general/browser_double_close_tab.js
@@ -48,17 +48,17 @@ add_task(async function() {
   await new Promise(resolveOuter => {
     waitForDialog(dialogNode => {
       waitForDialogDestroyed(dialogNode, () => {
         let doCompletion = () => setTimeout(resolveOuter, 0);
         info("Now checking if dialog is destroyed");
         ok(!dialogNode.parentNode, "onbeforeunload dialog should be gone.");
         if (dialogNode.parentNode) {
           // Failed to remove onbeforeunload dialog, so do it ourselves:
-          let leaveBtn = dialogNode.ui.button0;
+          let leaveBtn = dialogNode.querySelector(".tabmodalprompt-button0");
           waitForDialogDestroyed(dialogNode, doCompletion);
           EventUtils.synthesizeMouseAtCenter(leaveBtn, {});
           return;
         }
         doCompletion();
       });
       // Click again:
       document.getAnonymousElementByAttribute(testTab, "anonid", "close-button").click();
--- a/browser/base/content/test/tabPrompts/browser_multiplePrompts.js
+++ b/browser/base/content/test/tabPrompts/browser_multiplePrompts.js
@@ -35,38 +35,39 @@ add_task(async function() {
     }, "tabmodal-dialog-loaded");
   });
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url, true);
   info("Tab loaded");
 
   await promptsOpenedPromise;
 
-  let promptsCount = PROMPTCOUNT;
-  while (promptsCount--) {
-    let prompts = tab.linkedBrowser.parentNode.querySelectorAll("tabmodalprompt");
-    is(prompts.length, promptsCount + 1, "There should be " + (promptsCount + 1) + " prompt(s).");
+  let promptElementsCount = PROMPTCOUNT;
+  while (promptElementsCount--) {
+    let promptElements = tab.linkedBrowser.parentNode.querySelectorAll("tabmodalprompt");
+    is(promptElements.length, promptElementsCount + 1, "There should be " + (promptElementsCount + 1) + " prompt(s).");
     // The oldest should be the first.
     let i = 0;
-    for (let prompt of prompts) {
+    for (let promptElement of promptElements) {
+      let prompt = tab.linkedBrowser.tabModalPromptBox.prompts.get(promptElement);
       is(prompt.Dialog.args.text, "Alert countdown #" + i, "The #" + i + " alert should be labelled as such.");
-      if (i !== promptsCount) {
-        is(prompt.hidden, true, "This prompt should be hidden.");
+      if (i !== promptElementsCount) {
+        is(prompt.element.hidden, true, "This prompt should be hidden.");
         i++;
         continue;
       }
 
-      is(prompt.hidden, false, "The last prompt should not be hidden.");
+      is(prompt.element.hidden, false, "The last prompt should not be hidden.");
       prompt.onButtonClick(0);
 
       // The click is handled async; wait for an event loop turn for that to
       // happen.
       await new Promise(function(resolve) {
         Services.tm.dispatchToMainThread(resolve);
       });
     }
   }
 
-  let prompts = tab.linkedBrowser.parentNode.querySelectorAll("tabmodalprompt");
-  is(prompts.length, 0, "Prompts should all be dismissed.");
+  let promptElements = tab.linkedBrowser.parentNode.querySelectorAll("tabmodalprompt");
+  is(promptElements.length, 0, "Prompts should all be dismissed.");
 
   BrowserTestUtils.removeTab(tab);
 });
--- a/browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js
+++ b/browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js
@@ -25,26 +25,25 @@ add_task(async function() {
   await openedTabGotAttentionPromise;
   // check for attention attribute
   is(openedTab.getAttribute("attention"), "true", "Tab with alert should have 'attention' attribute.");
   ok(!openedTab.selected, "Tab with alert should not be selected");
 
   // switch tab back, and check the checkbox is displayed:
   await BrowserTestUtils.switchTab(gBrowser, openedTab);
   // check the prompt is there, and the extra row is present
-  let prompts = openedTab.linkedBrowser.parentNode.querySelectorAll("tabmodalprompt");
-  is(prompts.length, 1, "There should be 1 prompt");
-  let ourPrompt = prompts[0];
-  let row = ourPrompt.querySelector("row");
-  ok(row, "Should have found the row with our checkbox");
-  let checkbox = row.querySelector("checkbox[label*='example.com']");
+  let promptElements = openedTab.linkedBrowser.parentNode.querySelectorAll("tabmodalprompt");
+  is(promptElements.length, 1, "There should be 1 prompt");
+  let ourPromptElement = promptElements[0];
+  let checkbox = ourPromptElement.querySelector("checkbox[label*='example.com']");
   ok(checkbox, "The checkbox should be there");
   ok(!checkbox.checked, "Checkbox shouldn't be checked");
   // tick box and accept dialog
   checkbox.checked = true;
+  let ourPrompt = openedTab.linkedBrowser.tabModalPromptBox.prompts.get(ourPromptElement);
   ourPrompt.onButtonClick(0);
   // Wait for that click to actually be handled completely.
   await new Promise(function(resolve) {
     Services.tm.dispatchToMainThread(resolve);
   });
   // check permission is set
   let ps = Services.perms;
   is(ps.ALLOW_ACTION, ps.testPermission(makeURI(pageWithAlert), "focus-tab-by-prompt"),
--- a/browser/components/extensions/test/browser/browser_ext_optionsPage_modals.js
+++ b/browser/components/extensions/test/browser/browser_ext_optionsPage_modals.js
@@ -78,17 +78,17 @@ add_task(async function test_tab_options
     stack = gBrowser.selectedBrowser.parentNode;
   }
 
   let dialogs = stack.querySelectorAll("tabmodalprompt");
 
   Assert.equal(dialogs.length, 1, "Expect a tab modal opened for the about addons tab");
 
   info("Close the tab modal prompt");
-  dialogs[0].onButtonClick(0);
+  dialogs[0].querySelector(".tabmodalprompt-button0").click();
 
   await extension.awaitFinish("options-ui-modals");
 
   Assert.equal(stack.querySelectorAll("tabmodalprompt").length, 0,
                "Expect the tab modal to be closed");
 
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 
--- a/browser/components/places/tests/browser/browser_sidebarpanels_click.js
+++ b/browser/components/places/tests/browser/browser_sidebarpanels_click.js
@@ -139,17 +139,21 @@ async function testPlacesPanel(testInfo,
 
 function promiseAlertDialogObserved() {
   return new Promise(resolve => {
     function observer(subject) {
       info("alert dialog observed as expected");
       Services.obs.removeObserver(observer, "common-dialog-loaded");
       Services.obs.removeObserver(observer, "tabmodal-dialog-loaded");
 
-      subject.Dialog.ui.button0.click();
+      if (subject.Dialog) {
+        subject.Dialog.ui.button0.click();
+      } else {
+        subject.querySelector(".tabmodalprompt-button0").click();
+      }
       resolve();
     }
     Services.obs.addObserver(observer, "common-dialog-loaded");
     Services.obs.addObserver(observer, "tabmodal-dialog-loaded");
   });
 }
 
 function changeSidebarDirection(aDirection) {
--- a/browser/extensions/formautofill/FormAutofillParent.jsm
+++ b/browser/extensions/formautofill/FormAutofillParent.jsm
@@ -348,19 +348,25 @@ FormAutofillParent.prototype = {
     }
 
     target.sendAsyncMessage("FormAutofill:Records", records);
   },
 
   _updateSavedFieldNames() {
     log.debug("_updateSavedFieldNames");
 
-    Services.ppmm.initialProcessData.autofillSavedFieldNames =
-      new Set([...this.formAutofillStorage.addresses.getSavedFieldNames(),
-        ...this.formAutofillStorage.creditCards.getSavedFieldNames()]);
+    // Don't access the credit cards store unless it is enabled.
+    if (FormAutofill.isAutofillCreditCardsAvailable) {
+      Services.ppmm.initialProcessData.autofillSavedFieldNames =
+        new Set([...this.formAutofillStorage.addresses.getSavedFieldNames(),
+          ...this.formAutofillStorage.creditCards.getSavedFieldNames()]);
+    } else {
+      Services.ppmm.initialProcessData.autofillSavedFieldNames =
+        this.formAutofillStorage.addresses.getSavedFieldNames();
+    }
 
     Services.ppmm.broadcastAsyncMessage("FormAutofill:savedFieldNames",
                                         Services.ppmm.initialProcessData.autofillSavedFieldNames);
     this._updateStatus();
   },
 
   async _onAddressSubmit(address, target, timeStartedFillingMS) {
     let showDoorhanger = null;
--- a/devtools/server/tests/browser/browser_navigateEvents.js
+++ b/devtools/server/tests/browser/browser_navigateEvents.js
@@ -71,17 +71,17 @@ function assertEvent(event, data) {
   }
 }
 
 function waitForOnBeforeUnloadDialog(browser, callback) {
   browser.addEventListener("DOMWillOpenModalDialog", async function(event) {
     const stack = browser.parentNode;
     const dialogs = stack.getElementsByTagName("tabmodalprompt");
     await waitUntil(() => dialogs[0]);
-    const {button0, button1} = dialogs[0].ui;
+    const {button0, button1} = browser.tabModalPromptBox.prompts.get(dialogs[0]).ui;
     callback(button0, button1);
   }, {capture: true, once: true});
 }
 
 var httpObserver = function(subject, topic, state) {
   const channel = subject.QueryInterface(Ci.nsIHttpChannel);
   const url = channel.URI.spec;
   // Only listen for our document request, as many other requests can happen
--- a/docshell/test/browser/browser_bug1415918_beforeunload_options.js
+++ b/docshell/test/browser/browser_bug1415918_beforeunload_options.js
@@ -18,17 +18,17 @@ add_task(async function test() {
   let stack = browser.parentNode;
   let buttonId;
   let promptShown = false;
 
   let observer = new MutationObserver(function(mutations) {
     mutations.forEach(function(mutation) {
       if (buttonId && mutation.type == "attributes" && browser.hasAttribute("tabmodalPromptShowing")) {
         let prompt = stack.getElementsByTagNameNS(XUL_NS, "tabmodalprompt")[0];
-        document.getAnonymousElementByAttribute(prompt, "anonid", buttonId).click();
+        prompt.querySelector(`.tabmodalprompt-${buttonId}`).click();
         promptShown = true;
       }
     });
   });
   observer.observe(browser, { attributes: true });
 
   /*
    * Check condition where beforeunload handlers request a prompt.
--- a/docshell/test/browser/browser_onbeforeunload_navigation.js
+++ b/docshell/test/browser/browser_onbeforeunload_navigation.js
@@ -180,17 +180,17 @@ function onTabModalDialogLoaded(node) {
       Services.tm.dispatchToMainThread(() => {
         mm.sendAsyncMessage("test-beforeunload:dialog-gone");
       });
     }
   });
   observer.observe(node.parentNode, {childList: true});
 
   BrowserTestUtils.waitForMessage(mm, "test-beforeunload:dialog-response").then((stayingOnPage) => {
-    let button = stayingOnPage ? node.ui.button1 : node.ui.button0;
+    let button = node.querySelector(stayingOnPage ? ".tabmodalprompt-button1" : ".tabmodalprompt-button0");
     // ... and then actually make the dialog go away
     info("Clicking button: " + button.label);
     EventUtils.synthesizeMouseAtCenter(button, {});
   });
 }
 
 // Listen for the dialog being created
 Services.obs.addObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded");
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -713,16 +713,17 @@ skip-if = !e10s # Track Bug 1281415
 [test_meta_viewport_maximum_scale_2.html]
 [test_meta_viewport_negative_width_and_negative_height.html]
 [test_meta_viewport_negative_width_and_no_height.html]
 [test_meta_viewport_negative_width_and_valid_height.html]
 [test_meta_viewport_valid_width_and_negative_height.html]
 [test_meta_viewport_valid_width_and_no_height.html]
 [test_meta_viewport_no_width_and_negative_height.html]
 [test_meta_viewport_no_width_and_valid_height.html]
+[test_meta_viewport_tiny_display_size.html]
 [test_mozbrowser_apis_blocked.html]
 [test_mozMatchesSelector.html]
 [test_mutationobserver_anonymous.html]
 [test_mutationobservers.html]
 [test_named_frames.html]
 [test_navigator_hardwareConcurrency.html]
 [test_navigator_language.html]
 [test_navigatorPrefOverride.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_meta_viewport_tiny_display_size.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>meta viewport test</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/AddTask.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <meta name="viewport" content="width=device-width">
+  <script src="viewport_helpers.js"></script>
+</head>
+<body>
+  <p>width=device-width</p>
+  <script type="application/javascript">
+    "use strict";
+
+    add_task(async function test1() {
+      await SpecialPowers.pushPrefEnv(scaleRatio(1.0));
+
+      // Check that the minimum viewport dimension of (200,40) are not enforced 
+      // in cases where the display size itself has a smaller dimension. 
+      let info = getViewportInfo(192, 32);
+      is(info.defaultZoom, 1,    "initial zoom is 100%");
+      is(info.width,       192,  "width is the same as the displayWidth");
+      is(info.height,      32,   "height is the same as the displayHeight");
+    });
+  </script>
+</body>
+</html>
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -2052,22 +2052,36 @@ void HTMLInputElement::MozSetDirectory(c
 void HTMLInputElement::GetDateTimeInputBoxValue(DateTimeValue& aValue) {
   if (NS_WARN_IF(!IsDateTimeInputType(mType)) || !mDateTimeInputBoxValue) {
     return;
   }
 
   aValue = *mDateTimeInputBoxValue;
 }
 
+Element* HTMLInputElement::GetDateTimeBoxElementInUAWidget() {
+  if (GetShadowRoot()) {
+    // The datetimebox <div> is the only child of the UA Widget Shadow Root
+    // if it is present.
+    MOZ_ASSERT(GetShadowRoot()->IsUAWidget());
+    MOZ_ASSERT(1 >= GetShadowRoot()->GetChildCount());
+    if (nsIContent* inputAreaContent = GetShadowRoot()->GetFirstChild()) {
+      return inputAreaContent->AsElement();
+    }
+  }
+
+  return nullptr;
+}
+
 Element* HTMLInputElement::GetDateTimeBoxElement() {
   nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
   if (frame && frame->GetInputAreaContent()) {
     return frame->GetInputAreaContent()->AsElement();
   }
-  return nullptr;
+  return GetDateTimeBoxElementInUAWidget();
 }
 
 void HTMLInputElement::OpenDateTimePicker(const DateTimeValue& aInitialValue) {
   if (NS_WARN_IF(!IsDateTimeInputType(mType))) {
     return;
   }
 
   mDateTimeInputBoxValue = new DateTimeValue(aInitialValue);
@@ -2615,19 +2629,27 @@ nsresult HTMLInputElement::SetValueInter
           nsRangeFrame* frame = do_QueryFrame(GetPrimaryFrame());
           if (frame) {
             frame->UpdateForValueChange();
           }
         } else if ((mType == NS_FORM_INPUT_TIME ||
                     mType == NS_FORM_INPUT_DATE) &&
                    !IsExperimentalMobileType(mType) &&
                    !(aFlags & nsTextEditorState::eSetValue_BySetUserInput)) {
-          nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
-          if (frame) {
-            frame->OnValueChanged();
+          if (Element* dateTimeBoxElement = GetDateTimeBoxElementInUAWidget()) {
+            AsyncEventDispatcher* dispatcher = new AsyncEventDispatcher(
+                dateTimeBoxElement,
+                NS_LITERAL_STRING("MozDateTimeValueChanged"), CanBubble::eNo,
+                ChromeOnlyDispatch::eNo);
+            dispatcher->RunDOMEventWhenSafe();
+          } else {
+            nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
+            if (frame) {
+              frame->OnValueChanged();
+            }
           }
         }
         if (mDoneCreating) {
           OnValueChanged(/* aNotify = */ true,
                          /* aWasInteractiveUserChange = */ false);
         }
         // else DoneCreatingElement calls us again once mDoneCreating is true
       }
@@ -2904,20 +2926,28 @@ void HTMLInputElement::Blur(ErrorResult&
         textControl->Blur(aError);
         return;
       }
     }
   }
 
   if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
       !IsExperimentalMobileType(mType)) {
-    nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
-    if (frame) {
-      frame->HandleBlurEvent();
+    if (Element* dateTimeBoxElement = GetDateTimeBoxElementInUAWidget()) {
+      AsyncEventDispatcher* dispatcher = new AsyncEventDispatcher(
+          dateTimeBoxElement, NS_LITERAL_STRING("MozBlurInnerTextBox"),
+          CanBubble::eNo, ChromeOnlyDispatch::eNo);
+      dispatcher->RunDOMEventWhenSafe();
       return;
+    } else {
+      nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
+      if (frame) {
+        frame->HandleBlurEvent();
+        return;
+      }
     }
   }
 
   nsGenericHTMLElement::Blur(aError);
 }
 
 void HTMLInputElement::Focus(ErrorResult& aError) {
   if (mType == NS_FORM_INPUT_NUMBER) {
@@ -2930,20 +2960,28 @@ void HTMLInputElement::Focus(ErrorResult
         textControl->Focus(aError);
         return;
       }
     }
   }
 
   if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
       !IsExperimentalMobileType(mType)) {
-    nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
-    if (frame) {
-      frame->HandleFocusEvent();
+    if (Element* dateTimeBoxElement = GetDateTimeBoxElementInUAWidget()) {
+      AsyncEventDispatcher* dispatcher = new AsyncEventDispatcher(
+          dateTimeBoxElement, NS_LITERAL_STRING("MozFocusInnerTextBox"),
+          CanBubble::eNo, ChromeOnlyDispatch::eNo);
+      dispatcher->RunDOMEventWhenSafe();
       return;
+    } else {
+      nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
+      if (frame) {
+        frame->HandleFocusEvent();
+        return;
+      }
     }
   }
 
   if (mType != NS_FORM_INPUT_FILE) {
     nsGenericHTMLElement::Focus(aError);
     return;
   }
 
@@ -3240,21 +3278,28 @@ void HTMLInputElement::GetEventTargetPar
     if (frame) {
       frame->InvalidateFrameSubtree();
     }
   }
 
   if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
       !IsExperimentalMobileType(mType) && aVisitor.mEvent->mMessage == eFocus &&
       aVisitor.mEvent->mOriginalTarget == this) {
-    // If original target is this and not the anonymous text control, we should
-    // pass the focus to the anonymous text control.
-    nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
-    if (frame) {
-      frame->HandleFocusEvent();
+    // If original target is this and not the inner text control, we should
+    // pass the focus to the inner text control.
+    if (Element* dateTimeBoxElement = GetDateTimeBoxElementInUAWidget()) {
+      AsyncEventDispatcher* dispatcher = new AsyncEventDispatcher(
+          dateTimeBoxElement, NS_LITERAL_STRING("MozFocusInnerTextBox"),
+          CanBubble::eNo, ChromeOnlyDispatch::eNo);
+      dispatcher->RunDOMEventWhenSafe();
+    } else {
+      nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
+      if (frame) {
+        frame->HandleFocusEvent();
+      }
     }
   }
 
   if (mType == NS_FORM_INPUT_NUMBER && aVisitor.mEvent->IsTrusted()) {
     if (mNumberControlSpinnerIsSpinning) {
       // If the timer is running the user has depressed the mouse on one of the
       // spin buttons. If the mouse exits the button we either want to reverse
       // the direction of spin if it has moved over the other button, or else
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -743,18 +743,26 @@ class HTMLInputElement final : public ns
 
   /*
    * The following functions are called from datetime picker to let input box
    * know the current state of the picker or to update the input box on changes.
    */
   void GetDateTimeInputBoxValue(DateTimeValue& aValue);
 
   /*
+   * This locates the inner datetimebox UA Widget element and only the
+   * UA Widget
+   * element. This should fold into GetDateTimeBoxElement() when the XBL binding is removed.
+   */
+  Element* GetDateTimeBoxElementInUAWidget();
+
+  /*
    * This allows chrome JavaScript to dispatch event to the inner datetimebox
-   * anonymous element or access nsIDateTimeInputArea implmentation.
+   * anonymous or UA Widget element and access nsIDateTimeInputArea
+   * implementation.
    */
   Element* GetDateTimeBoxElement();
 
   /*
    * The following functions are called from datetime input box XBL to control
    * and update the picker.
    */
   void OpenDateTimePicker(const DateTimeValue& aInitialValue);
--- a/dom/html/input/DateTimeInputTypes.cpp
+++ b/dom/html/input/DateTimeInputTypes.cpp
@@ -2,25 +2,30 @@
 /* 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 "DateTimeInputTypes.h"
 
 #include "js/Date.h"
+#include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "nsDateTimeControlFrame.h"
+#include "nsDOMTokenList.h"
 
 const double DateTimeInputTypeBase::kMinimumYear = 1;
 const double DateTimeInputTypeBase::kMaximumYear = 275760;
 const double DateTimeInputTypeBase::kMaximumMonthInMaximumYear = 9;
 const double DateTimeInputTypeBase::kMaximumWeekInMaximumYear = 37;
 const double DateTimeInputTypeBase::kMsPerDay = 24 * 60 * 60 * 1000;
 
+using namespace mozilla;
+using namespace mozilla::dom;
+
 /* static */ bool DateTimeInputTypeBase::IsInputDateTimeEnabled() {
   static bool sDateTimeEnabled = false;
   static bool sDateTimePrefCached = false;
   if (!sDateTimePrefCached) {
     sDateTimePrefCached = true;
     mozilla::Preferences::AddBoolVarCache(&sDateTimeEnabled,
                                           "dom.forms.datetime", false);
   }
@@ -90,23 +95,52 @@ bool DateTimeInputTypeBase::HasStepMisma
     return false;
   }
 
   // Value has to be an integral multiple of step.
   return NS_floorModulo(value - GetStepBase(), step) != mozilla::Decimal(0);
 }
 
 bool DateTimeInputTypeBase::HasBadInput() const {
+  Element* editWrapperElement = nullptr;
   nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
-  if (!frame) {
+  if (frame && frame->GetInputAreaContent()) {
+    // edit-wrapper is inside an XBL binding
+    editWrapperElement =
+        mInputElement->GetComposedDoc()->GetAnonymousElementByAttribute(
+            frame->GetInputAreaContent(), nsGkAtoms::anonid,
+            NS_LITERAL_STRING("edit-wrapper"));
+  } else if (mInputElement->GetShadowRoot()) {
+    // edit-wrapper is inside an UA Widget Shadow DOM
+    editWrapperElement = mInputElement->GetShadowRoot()->GetElementById(
+        NS_LITERAL_STRING("edit-wrapper"));
+  }
+  if (!editWrapperElement) {
     return false;
   }
 
-  return frame->HasBadInput();
-  ;
+  // Incomplete field does not imply bad input.
+  for (Element* child = editWrapperElement->GetFirstElementChild(); child;
+       child = child->GetNextElementSibling()) {
+    if (child->ClassList()->Contains(
+            NS_LITERAL_STRING("datetime-edit-field"))) {
+      nsAutoString value;
+      child->GetAttr(kNameSpaceID_None, nsGkAtoms::value, value);
+      if (value.IsEmpty()) {
+        return false;
+      }
+    }
+  }
+
+  // All fields are available but input element's value is empty implies
+  // it has been sanitized.
+  nsAutoString value;
+  mInputElement->GetValue(value, CallerType::System);
+
+  return value.IsEmpty();
 }
 
 nsresult DateTimeInputTypeBase::GetRangeOverflowMessage(nsAString& aMessage) {
   nsAutoString maxStr;
   mInputElement->GetAttr(kNameSpaceID_None, nsGkAtoms::max, maxStr);
 
   const char16_t* params[] = {maxStr.get()};
   return nsContentUtils::FormatLocalizedString(
@@ -120,19 +154,27 @@ nsresult DateTimeInputTypeBase::GetRange
 
   const char16_t* params[] = {minStr.get()};
   return nsContentUtils::FormatLocalizedString(
       nsContentUtils::eDOM_PROPERTIES, "FormValidationDateTimeRangeUnderflow",
       params, aMessage);
 }
 
 nsresult DateTimeInputTypeBase::MinMaxStepAttrChanged() {
-  nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
-  if (frame) {
-    frame->OnMinMaxStepAttrChanged();
+  if (Element* dateTimeBoxElement =
+          mInputElement->GetDateTimeBoxElementInUAWidget()) {
+    AsyncEventDispatcher* dispatcher = new AsyncEventDispatcher(
+        dateTimeBoxElement, NS_LITERAL_STRING("MozNotifyMinMaxStepAttrChanged"),
+        CanBubble::eNo, ChromeOnlyDispatch::eNo);
+    dispatcher->RunDOMEventWhenSafe();
+  } else {
+    nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
+    if (frame) {
+      frame->OnMinMaxStepAttrChanged();
+    }
   }
 
   return NS_OK;
 }
 
 bool DateTimeInputTypeBase::GetTimeFromMs(double aValue, uint16_t* aHours,
                                           uint16_t* aMinutes,
                                           uint16_t* aSeconds,
--- a/dom/html/test/forms/mochitest.ini
+++ b/dom/html/test/forms/mochitest.ini
@@ -33,16 +33,17 @@ skip-if = android_version == '18' # Andr
 [test_input_color_picker_update.html]
 skip-if = android_version == '18' # Android, bug 1147974
 [test_input_date_bad_input.html]
 [test_input_date_key_events.html]
 [test_input_datetime_input_change_events.html]
 [test_input_datetime_focus_blur.html]
 [test_input_datetime_focus_blur_events.html]
 [test_input_datetime_focus_state.html]
+[test_input_datetime_hidden.html]
 [test_input_datetime_tabindex.html]
 [test_input_defaultValue.html]
 [test_input_email.html]
 [test_input_event.html]
 skip-if = android_version == '18' # bug 1147974
 [test_input_file_picker.html]
 [test_input_hasBeenTypePassword.html]
 [test_input_hasBeenTypePassword_navigation.html]
new file mode 100644
--- /dev/null
+++ b/dom/html/test/forms/test_input_datetime_hidden.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1514040
+-->
+<head>
+  <title>Test construction of hidden date input type</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1514040">Mozilla Bug 1514040</a>
+<p id="display"></p>
+<div id="content">
+  <input id="date" type="date" hidden value="1947-02-28">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+let el = document.getElementById("date");
+ok(el.hidden, "element is hidden");
+is(el.value, "1947-02-28", ".value is set correctly");
+let fieldElements = Array.from(SpecialPowers.wrap(el).openOrClosedShadowRoot.getElementsByClassName("datetime-edit-field"));
+is(fieldElements[0].textContent, "02", "month is set");
+is(fieldElements[1].textContent, "28", "day is set");
+is(fieldElements[2].textContent, "1947", "year is set");
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/html/test/forms/test_input_datetime_tabindex.html
+++ b/dom/html/test/forms/test_input_datetime_tabindex.html
@@ -29,16 +29,25 @@ https://bugzilla.mozilla.org/show_bug.cg
  * correctly.
  **/
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(function() {
   test();
   SimpleTest.finish();
 });
 
+function checkInnerTextboxTabindex(input, tabindex) {
+  let fields = SpecialPowers.wrap(input).openOrClosedShadowRoot.getElementsByClassName("datetime-edit-field");
+
+  for (let field of fields) {
+    is(field.tabIndex, tabindex, "tabIndex in the inner textbox should be correct");
+  }
+
+}
+
 function testTabindex(type) {
   let input1 = document.getElementById(type + "1");
   let input2 = document.getElementById(type + "2");
   let input3 = document.getElementById(type + "3");
 
   input1.focus();
   is(document.activeElement, input1,
      "input element with tabindex=0 is focusable");
@@ -57,21 +66,27 @@ function testTabindex(type) {
   synthesizeKey("KEY_Tab");
   is(document.activeElement, input3,
      "input element with tabindex=-1 is not tabbable");
 
   input2.focus();
   is(document.activeElement, input2,
      "input element with tabindex=-1 is still focusable");
 
+  checkInnerTextboxTabindex(input1, 0);
+  checkInnerTextboxTabindex(input2, -1);
+  checkInnerTextboxTabindex(input3, 0);
+
   // Changing the tabindex attribute dynamically.
   input3.setAttribute("tabindex", "-1");
   synthesizeKey("KEY_Tab"); // need only one TAB since input2 is not tabbable
   isnot(document.activeElement, input3,
         "element with tabindex changed to -1 should not be tabbable");
+
+  checkInnerTextboxTabindex(input3, -1);
 }
 
 function test() {
   let inputTypes = ["time", "date"];
 
   for (let i = 0; i < inputTypes.length; i++) {
     testTabindex(inputTypes[i]);
   }
--- a/dom/media/gtest/mp4_demuxer/TestParser.cpp
+++ b/dom/media/gtest/mp4_demuxer/TestParser.cpp
@@ -161,18 +161,18 @@ struct TestFileData {
   bool mHasCrypto;
   uint64_t mMoofReachedOffset;  // or 0 for the end.
   bool mValidMoof;
   bool mHeader;
   int8_t mAudioProfile;
 };
 
 static const TestFileData testFiles[] = {
-    // filename                     parse #V dur   w    h  #A dur  crypt  off
-    // moof  headr  audio_profile
+    // filename parses? #V hasVideoIndex vDur w h #A aDur hasCrypto? moofOffset
+    // validMoof? hasHeader? audio_profile
     {"test_case_1156505.mp4", false, 0, false, -1, 0, 0, 0, -1, false, 152,
      false, false, 0},  // invalid ''trak box
     {"test_case_1181213.mp4", true, 1, true, 416666, 320, 240, 1, 477460, true,
      0, false, false, 2},
     {"test_case_1181215.mp4", true, 0, false, -1, 0, 0, 0, -1, false, 0, false,
      false, 0},
     {"test_case_1181220.mp4", false, 0, false, -1, 0, 0, 0, -1, false, 0, false,
      false, 0},  // invalid audio 'sinf' box
@@ -344,20 +344,23 @@ TEST(MP4Metadata, test_case_mp4) {
         << tests[test].mFilename;
     // We can see anywhere in any MPEG4.
     EXPECT_TRUE(metadata.CanSeek()) << tests[test].mFilename;
     EXPECT_EQ(tests[test].mHasCrypto, metadata.Crypto().Ref()->valid)
         << tests[test].mFilename;
   }
 }
 
-// Bug 1224019: This test produces way to much output, disabling for now.
+// This test was disabled by Bug 1224019 for producing way too much output.
+// This test no longer produces such output, as we've moved away from
+// stagefright, but it does take a long time to run. I can be useful to enable
+// as a sanity check on changes to the parser, but is too taxing to run as part
+// of normal test execution.
 #if 0
-TEST(MPEG4Metadata, test_case_mp4_subsets)
-{
+TEST(MP4Metadata, test_case_mp4_subsets) {
   static const size_t step = 1u;
   for (size_t test = 0; test < ArrayLength(testFiles); ++test) {
     nsTArray<uint8_t> buffer = ReadTestFile(testFiles[test].mFilename);
     ASSERT_FALSE(buffer.IsEmpty());
     ASSERT_LE(step, buffer.Length());
     // Just exercizing the parser starting at different points through the file,
     // making sure it doesn't crash.
     // No checks because results would differ for each position.
@@ -428,20 +431,65 @@ TEST(MoofParser, test_case_mp4) {
         << tests[test].mFilename;
     EXPECT_TRUE(parser.FirstCompleteMediaSegment().IsEmpty())
         << tests[test].mFilename;
     EXPECT_EQ(tests[test].mHeader, !parser.FirstCompleteMediaHeader().IsEmpty())
         << tests[test].mFilename;
   }
 }
 
-// Bug 1224019: This test produces way to much output, disabling for now.
+TEST(MoofParser, test_case_sample_description_entries) {
+  const TestFileData* tests = testFiles;
+  size_t length = ArrayLength(testFiles);
+
+  for (size_t test = 0; test < length; ++test) {
+    nsTArray<uint8_t> buffer = ReadTestFile(tests[test].mFilename);
+    ASSERT_FALSE(buffer.IsEmpty());
+    RefPtr<ByteStream> stream =
+        new TestStream(buffer.Elements(), buffer.Length());
+
+    // Parse the first track. Treating it as audio is hacky, but this doesn't
+    // affect how we read the sample description entries.
+    MoofParser parser(stream, 1, false);
+    EXPECT_EQ(0u, parser.mOffset) << tests[test].mFilename;
+    EXPECT_FALSE(parser.ReachedEnd()) << tests[test].mFilename;
+    EXPECT_TRUE(parser.mInitRange.IsEmpty()) << tests[test].mFilename;
+
+    // Explicitly don't call parser.Metadata() so that the parser itself will
+    // read the metadata as if we're in a fragmented case. Otherwise the parser
+    // won't read the sample description table.
+
+    const MediaByteRangeSet byteRanges(
+        MediaByteRange(0, int64_t(buffer.Length())));
+    EXPECT_EQ(tests[test].mValidMoof, parser.RebuildFragmentedIndex(byteRanges))
+        << tests[test].mFilename;
+
+    // We only care about crypto data from the samples descriptions right now.
+    // This test should be expanded should we read further information.
+    if (tests[test].mHasCrypto) {
+      uint32_t numEncryptedEntries = 0;
+      // It's possible to have multiple sample description entries, but we only
+      // expect one to carry crypto info for encrypted tracks.
+      for (SampleDescriptionEntry entry : parser.mSampleDescriptions) {
+        if (entry.mIsEncryptedEntry) {
+          numEncryptedEntries++;
+        }
+      }
+      EXPECT_EQ(1u, numEncryptedEntries) << tests[test].mFilename;
+    }
+  }
+}
+
+// This test was disabled by Bug 1224019 for producing way too much output.
+// This test no longer produces such output, as we've moved away from
+// stagefright, but it does take a long time to run. I can be useful to enable
+// as a sanity check on changes to the parser, but is too taxing to run as part
+// of normal test execution.
 #if 0
-TEST(MoofParser, test_case_mp4_subsets)
-{
+TEST(MoofParser, test_case_mp4_subsets) {
   const size_t step = 1u;
   for (size_t test = 0; test < ArrayLength(testFiles); ++test) {
     nsTArray<uint8_t> buffer = ReadTestFile(testFiles[test].mFilename);
     ASSERT_FALSE(buffer.IsEmpty());
     ASSERT_LE(step, buffer.Length());
     // Just exercizing the parser starting at different points through the file,
     // making sure it doesn't crash.
     // No checks because results would differ for each position.
--- a/dom/media/mp4/MoofParser.cpp
+++ b/dom/media/mp4/MoofParser.cpp
@@ -294,21 +294,42 @@ void MoofParser::ParseStbl(Box& aBox) {
           return;
         }
       }
     }
   }
 }
 
 void MoofParser::ParseStsd(Box& aBox) {
+  if (mTrex.mTrackId == 0) {
+    // If mTrex.mTrackId is 0, then the parser is being used to read multiple
+    // tracks metadata, and it is not a sane operation to try and map multiple
+    // sample description boxes, from different tracks, onto the parser, which
+    // is modeled around storing metadata for a single track.
+    return;
+  }
+  MOZ_ASSERT(
+      mSampleDescriptions.IsEmpty(),
+      "Shouldn't have any sample descriptions when starting to parse stsd");
+  uint32_t numberEncryptedEntries = 0;
   for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
+    SampleDescriptionEntry sampleDescriptionEntry{false};
     if (box.IsType("encv") || box.IsType("enca")) {
       ParseEncrypted(box);
+      sampleDescriptionEntry.mIsEncryptedEntry = true;
+      numberEncryptedEntries++;
+    }
+    if (!mSampleDescriptions.AppendElement(sampleDescriptionEntry,
+                                           mozilla::fallible)) {
+      LOG(Moof, "OOM");
+      return;
     }
   }
+  MOZ_ASSERT(numberEncryptedEntries <= 1,
+             "We don't expect or handle mulitple encrypted entries per track");
 }
 
 void MoofParser::ParseEncrypted(Box& aBox) {
   for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
     // Some MP4 files have been found to have multiple sinf boxes in the same
     // enc* box. This does not match spec anyway, so just choose the first
     // one that parses properly.
     if (box.IsType("sinf")) {
@@ -328,17 +349,17 @@ class CtsComparator {
   }
   bool LessThan(Sample* const aA, Sample* const aB) const {
     return aA->mCompositionRange.start < aB->mCompositionRange.start;
   }
 };
 
 Moof::Moof(Box& aBox, Trex& aTrex, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts,
            Sinf& aSinf, uint64_t* aDecodeTime, bool aIsAudio)
-    : mRange(aBox.Range()), mMaxRoundingError(35000) {
+    : mRange(aBox.Range()), mTfhd(aTrex), mMaxRoundingError(35000) {
   nsTArray<Box> psshBoxes;
   for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
     if (box.IsType("traf")) {
       ParseTraf(box, aTrex, aMvhd, aMdhd, aEdts, aSinf, aDecodeTime, aIsAudio);
     }
     if (box.IsType("pssh")) {
       psshBoxes.AppendElement(box);
     }
@@ -482,23 +503,22 @@ bool Moof::ProcessCenc() {
   }
   return true;
 }
 
 void Moof::ParseTraf(Box& aBox, Trex& aTrex, Mvhd& aMvhd, Mdhd& aMdhd,
                      Edts& aEdts, Sinf& aSinf, uint64_t* aDecodeTime,
                      bool aIsAudio) {
   MOZ_ASSERT(aDecodeTime);
-  Tfhd tfhd(aTrex);
   Tfdt tfdt;
 
   for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
     if (box.IsType("tfhd")) {
-      tfhd = Tfhd(box, aTrex);
-    } else if (!aTrex.mTrackId || tfhd.mTrackId == aTrex.mTrackId) {
+      mTfhd = Tfhd(box, aTrex);
+    } else if (!aTrex.mTrackId || mTfhd.mTrackId == aTrex.mTrackId) {
       if (box.IsType("tfdt")) {
         tfdt = Tfdt(box);
       } else if (box.IsType("sgpd")) {
         Sgpd sgpd(box);
         if (sgpd.IsValid() && sgpd.mGroupingType == "seig") {
           mFragmentSampleEncryptionInfoEntries.Clear();
           if (!mFragmentSampleEncryptionInfoEntries.AppendElements(
                   sgpd.mEntries, mozilla::fallible)) {
@@ -526,26 +546,25 @@ void Moof::ParseTraf(Box& aBox, Trex& aT
         if (!mSaios.AppendElement(Saio(box, aSinf.mDefaultEncryptionType),
                                   mozilla::fallible)) {
           LOG(Moof, "OOM");
           return;
         }
       }
     }
   }
-  if (aTrex.mTrackId && tfhd.mTrackId != aTrex.mTrackId) {
+  if (aTrex.mTrackId && mTfhd.mTrackId != aTrex.mTrackId) {
     return;
   }
   // Now search for TRUN boxes.
   uint64_t decodeTime =
       tfdt.IsValid() ? tfdt.mBaseMediaDecodeTime : *aDecodeTime;
   for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
     if (box.IsType("trun")) {
-      if (ParseTrun(box, tfhd, aMvhd, aMdhd, aEdts, &decodeTime, aIsAudio)
-              .isOk()) {
+      if (ParseTrun(box, aMvhd, aMdhd, aEdts, &decodeTime, aIsAudio).isOk()) {
         mValid = true;
       } else {
         LOG(Moof, "ParseTrun failed");
         mValid = false;
         break;
       }
     }
   }
@@ -554,23 +573,23 @@ void Moof::ParseTraf(Box& aBox, Trex& aT
 
 void Moof::FixRounding(const Moof& aMoof) {
   Microseconds gap = aMoof.mTimeRange.start - mTimeRange.end;
   if (gap > 0 && gap <= mMaxRoundingError) {
     mTimeRange.end = aMoof.mTimeRange.start;
   }
 }
 
-Result<Ok, nsresult> Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Mvhd& aMvhd,
-                                     Mdhd& aMdhd, Edts& aEdts,
-                                     uint64_t* aDecodeTime, bool aIsAudio) {
-  if (!aTfhd.IsValid() || !aMvhd.IsValid() || !aMdhd.IsValid() ||
+Result<Ok, nsresult> Moof::ParseTrun(Box& aBox, Mvhd& aMvhd, Mdhd& aMdhd,
+                                     Edts& aEdts, uint64_t* aDecodeTime,
+                                     bool aIsAudio) {
+  if (!mTfhd.IsValid() || !aMvhd.IsValid() || !aMdhd.IsValid() ||
       !aEdts.IsValid()) {
-    LOG(Moof, "Invalid dependencies: aTfhd(%d) aMvhd(%d) aMdhd(%d) aEdts(%d)",
-        aTfhd.IsValid(), aMvhd.IsValid(), aMdhd.IsValid(), !aEdts.IsValid());
+    LOG(Moof, "Invalid dependencies: mTfhd(%d) aMvhd(%d) aMdhd(%d) aEdts(%d)",
+        mTfhd.IsValid(), aMvhd.IsValid(), aMdhd.IsValid(), !aEdts.IsValid());
     return Err(NS_ERROR_FAILURE);
   }
 
   BoxReader reader(aBox);
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Moof, "Incomplete Box (missing flags)");
     return Err(NS_ERROR_FAILURE);
   }
@@ -582,44 +601,44 @@ Result<Ok, nsresult> Moof::ParseTrun(Box
     return Err(NS_ERROR_FAILURE);
   }
   uint32_t sampleCount;
   MOZ_TRY_VAR(sampleCount, reader->ReadU32());
   if (sampleCount == 0) {
     return Ok();
   }
 
-  uint64_t offset = aTfhd.mBaseDataOffset;
+  uint64_t offset = mTfhd.mBaseDataOffset;
   if (flags & 0x01) {
     uint32_t tmp;
     MOZ_TRY_VAR(tmp, reader->ReadU32());
     offset += tmp;
   }
-  uint32_t firstSampleFlags = aTfhd.mDefaultSampleFlags;
+  uint32_t firstSampleFlags = mTfhd.mDefaultSampleFlags;
   if (flags & 0x04) {
     MOZ_TRY_VAR(firstSampleFlags, reader->ReadU32());
   }
   uint64_t decodeTime = *aDecodeTime;
   nsTArray<MP4Interval<Microseconds>> timeRanges;
 
   if (!mIndex.SetCapacity(sampleCount, fallible)) {
     LOG(Moof, "Out of Memory");
     return Err(NS_ERROR_FAILURE);
   }
 
   for (size_t i = 0; i < sampleCount; i++) {
-    uint32_t sampleDuration = aTfhd.mDefaultSampleDuration;
+    uint32_t sampleDuration = mTfhd.mDefaultSampleDuration;
     if (flags & 0x100) {
       MOZ_TRY_VAR(sampleDuration, reader->ReadU32());
     }
-    uint32_t sampleSize = aTfhd.mDefaultSampleSize;
+    uint32_t sampleSize = mTfhd.mDefaultSampleSize;
     if (flags & 0x200) {
       MOZ_TRY_VAR(sampleSize, reader->ReadU32());
     }
-    uint32_t sampleFlags = i ? aTfhd.mDefaultSampleFlags : firstSampleFlags;
+    uint32_t sampleFlags = i ? mTfhd.mDefaultSampleFlags : firstSampleFlags;
     if (flags & 0x400) {
       MOZ_TRY_VAR(sampleFlags, reader->ReadU32());
     }
     int32_t ctsOffset = 0;
     if (flags & 0x800) {
       MOZ_TRY_VAR(ctsOffset, reader->Read32());
     }
 
--- a/dom/media/mp4/MoofParser.h
+++ b/dom/media/mp4/MoofParser.h
@@ -203,24 +203,23 @@ class Sgpd final : public Atom  // Sampl
 
   AtomType mGroupingType;
   FallibleTArray<CencSampleEncryptionInfoEntry> mEntries;
 
  protected:
   Result<Ok, nsresult> Parse(Box& aBox);
 };
 
-class AuxInfo {
- public:
-  AuxInfo(int64_t aMoofOffset, Saiz& aSaiz, Saio& aSaio);
-
- private:
-  int64_t mMoofOffset;
-  Saiz& mSaiz;
-  Saio& mSaio;
+// Audio/video entries from the sample description box (stsd). We only need to
+// store if these are encrypted, so do not need a specialized class for
+// different audio and video data. Currently most of the parsing of these
+// entries is by the mp4parse-rust, but moof pasrser needs to know which of
+// these are encrypted when parsing the track fragment header (tfhd).
+struct SampleDescriptionEntry {
+  bool mIsEncryptedEntry = false;
 };
 
 class Moof final : public Atom {
  public:
   Moof(Box& aBox, Trex& aTrex, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts,
        Sinf& aSinf, uint64_t* aDecoderTime, bool aIsAudio);
   bool GetAuxInfo(AtomType aType, FallibleTArray<MediaByteRange>* aByteRanges);
   void FixRounding(const Moof& aMoof);
@@ -229,30 +228,29 @@ class Moof final : public Atom {
   mozilla::MediaByteRange mMdatRange;
   MP4Interval<Microseconds> mTimeRange;
   FallibleTArray<Sample> mIndex;
 
   FallibleTArray<CencSampleEncryptionInfoEntry>
       mFragmentSampleEncryptionInfoEntries;
   FallibleTArray<SampleToGroupEntry> mFragmentSampleToGroupEntries;
 
+  Tfhd mTfhd;
   FallibleTArray<Saiz> mSaizs;
   FallibleTArray<Saio> mSaios;
   nsTArray<nsTArray<uint8_t>> mPsshes;
 
  private:
   // aDecodeTime is updated to the end of the parsed TRAF on return.
   void ParseTraf(Box& aBox, Trex& aTrex, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts,
                  Sinf& aSinf, uint64_t* aDecodeTime, bool aIsAudio);
   // aDecodeTime is updated to the end of the parsed TRUN on return.
-  Result<Ok, nsresult> ParseTrun(Box& aBox, Tfhd& aTfhd, Mvhd& aMvhd,
-                                 Mdhd& aMdhd, Edts& aEdts,
-                                 uint64_t* aDecodeTime, bool aIsAudio);
-  void ParseSaiz(Box& aBox);
-  void ParseSaio(Box& aBox);
+  Result<Ok, nsresult> ParseTrun(Box& aBox, Mvhd& aMvhd, Mdhd& aMdhd,
+                                 Edts& aEdts, uint64_t* aDecodeTime,
+                                 bool aIsAudio);
   bool ProcessCenc();
   uint64_t mMaxRoundingError;
 };
 
 DDLoggedTypeDeclName(MoofParser);
 
 class MoofParser : public DecoderDoctorLifeLogger<MoofParser> {
  public:
@@ -280,17 +278,16 @@ class MoofParser : public DecoderDoctorL
   void ParseTrak(Box& aBox);
   void ParseMdia(Box& aBox, Tkhd& aTkhd);
   void ParseMvex(Box& aBox);
 
   void ParseMinf(Box& aBox);
   void ParseStbl(Box& aBox);
   void ParseStsd(Box& aBox);
   void ParseEncrypted(Box& aBox);
-  void ParseSinf(Box& aBox);
 
   bool BlockingReadNextMoof();
 
   already_AddRefed<mozilla::MediaByteBuffer> Metadata();
   MediaByteRange FirstCompleteMediaSegment();
   MediaByteRange FirstCompleteMediaHeader();
 
   mozilla::MediaByteRange mInitRange;
@@ -301,16 +298,17 @@ class MoofParser : public DecoderDoctorL
   Trex mTrex;
   Tfdt mTfdt;
   Edts mEdts;
   Sinf mSinf;
 
   FallibleTArray<CencSampleEncryptionInfoEntry>
       mTrackSampleEncryptionInfoEntries;
   FallibleTArray<SampleToGroupEntry> mTrackSampleToGroupEntries;
+  FallibleTArray<SampleDescriptionEntry> mSampleDescriptions;
 
   nsTArray<Moof>& Moofs() { return mMoofs; }
 
  private:
   void ScanForMetadata(mozilla::MediaByteRange& aMoov);
   nsTArray<Moof> mMoofs;
   nsTArray<MediaByteRange> mMediaRanges;
   bool mIsAudio;
--- a/dom/tests/browser/browser_beforeunload_between_chrome_content.js
+++ b/dom/tests/browser/browser_beforeunload_between_chrome_content.js
@@ -19,17 +19,18 @@ function injectBeforeUnload(browser) {
   });
 }
 
 // Wait for onbeforeunload dialog, and dismiss it immediately.
 function awaitAndCloseBeforeUnloadDialog(doStayOnPage) {
   return new Promise(resolve => {
     function onDialogShown(node) {
       Services.obs.removeObserver(onDialogShown, "tabmodal-dialog-loaded");
-      let button = doStayOnPage ? node.ui.button1 : node.ui.button0;
+      let button =
+        node.querySelector(doStayOnPage ? ".tabmodalprompt-button1" : ".tabmodalprompt-button0");
       button.click();
       resolve();
     }
 
     Services.obs.addObserver(onDialogShown, "tabmodal-dialog-loaded");
   });
 }
 
--- a/dom/tests/browser/browser_cancel_keydown_keypress_event.js
+++ b/dom/tests/browser/browser_cancel_keydown_keypress_event.js
@@ -1,17 +1,17 @@
 const URL =
   "https://example.com/browser/dom/tests/browser/prevent_return_key.html";
 
 // Wait for alert dialog and dismiss it immediately.
 function awaitAndCloseAlertDialog() {
   return new Promise(resolve => {
     function onDialogShown(node) {
       Services.obs.removeObserver(onDialogShown, "tabmodal-dialog-loaded");
-      let button = node.ui.button0;
+      let button = node.querySelector(".tabmodalprompt-button0");
       button.click();
       resolve();
     }
     Services.obs.addObserver(onDialogShown, "tabmodal-dialog-loaded");
   });
 }
 
 add_task(async function() {
--- a/dom/tests/browser/browser_test_focus_after_modal_state.js
+++ b/dom/tests/browser/browser_test_focus_after_modal_state.js
@@ -1,16 +1,16 @@
 const TEST_URL =
   "https://example.com/browser/dom/tests/browser/focus_after_prompt.html";
 
 function awaitAndClosePrompt() {
   return new Promise(resolve => {
     function onDialogShown(node) {
       Services.obs.removeObserver(onDialogShown, "tabmodal-dialog-loaded");
-      let button = node.ui.button0;
+      let button = node.querySelector(".tabmodalprompt-button0");
       button.click();
       resolve();
     }
     Services.obs.addObserver(onDialogShown, "tabmodal-dialog-loaded");
   });
 }
 
 let lastMessageReceived = "";
--- a/editor/libeditor/tests/test_bug569988.html
+++ b/editor/libeditor/tests/test_bug569988.html
@@ -30,21 +30,29 @@ function runTest() {
     const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm", null);
     var gPromptInput = null;
     var os = Services.obs;
 
     os.addObserver(onPromptLoad, "common-dialog-loaded");
     os.addObserver(onPromptLoad, "tabmodal-dialog-loaded");
 
     function onPromptLoad(subject, topic, data) {
+      let ui = subject.Dialog ? subject.Dialog.ui : undefined;
+      if (!ui) {
+        // subject is an tab prompt, find the elements ourselves
+        ui = {
+          loginTextbox: subject.querySelector(".tabmodalprompt-loginTextbox"),
+          button0: subject.querySelector(".tabmodalprompt-button0"),
+        };
+      }
       sendAsyncMessage("ok", [true, "onPromptLoad is called"]);
-      gPromptInput = subject.Dialog.ui.loginTextbox;
+      gPromptInput = ui.loginTextbox;
       gPromptInput.addEventListener("focus", onPromptFocus);
       // shift focus to ensure it fires.
-      subject.Dialog.ui.button0.focus();
+      ui.button0.focus();
       gPromptInput.focus();
     }
 
     function onPromptFocus() {
       sendAsyncMessage("ok", [true, "onPromptFocus is called"]);
       gPromptInput.removeEventListener("focus", onPromptFocus);
 
       var listenerService = Services.els;
--- a/gfx/webrender_bindings/Cargo.toml
+++ b/gfx/webrender_bindings/Cargo.toml
@@ -6,17 +6,17 @@ license = "MPL-2.0"
 
 [dependencies]
 rayon = "1"
 thread_profiler = "0.1.1"
 euclid = { version = "0.19.4", features = ["serde"] }
 app_units = "0.7"
 gleam = "0.6.8"
 log = "0.4"
-nsstring = { path = "../../servo/support/gecko/nsstring" }
+nsstring = { path = "../../xpcom/rust/nsstring" } 
 bincode = "1.0"
 uuid = { version = "0.6", features = ["v4"] }
 fxhash = "0.2.1"
 
 [dependencies.webrender]
 path = "../wr/webrender"
 version = "0.58.0"
 default-features = false
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1,1 +1,1 @@
-e8ef39b4499aa93e008a25e851c01f4dff36b301
+5e06512aee0a2e09379a49111c36f91d0ae489f4
--- a/gfx/wr/webrender/src/border.rs
+++ b/gfx/wr/webrender/src/border.rs
@@ -39,27 +39,16 @@ pub const MAX_DASH_COUNT: u32 = 2048;
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct BorderRadiusAu {
     pub top_left: LayoutSizeAu,
     pub top_right: LayoutSizeAu,
     pub bottom_left: LayoutSizeAu,
     pub bottom_right: LayoutSizeAu,
 }
 
-impl BorderRadiusAu {
-    pub fn zero() -> Self {
-        BorderRadiusAu {
-            top_left: LayoutSizeAu::zero(),
-            top_right: LayoutSizeAu::zero(),
-            bottom_left: LayoutSizeAu::zero(),
-            bottom_right: LayoutSizeAu::zero(),
-        }
-    }
-}
-
 impl From<BorderRadius> for BorderRadiusAu {
     fn from(radius: BorderRadius) -> BorderRadiusAu {
         BorderRadiusAu {
             top_left: radius.top_left.to_au(),
             top_right: radius.top_right.to_au(),
             bottom_right: radius.bottom_right.to_au(),
             bottom_left: radius.bottom_left.to_au(),
         }
--- a/gfx/wr/webrender/src/prim_store/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/mod.rs
@@ -486,25 +486,16 @@ impl<U> From<TypedSize2D<f32, U>> for Si
     fn from(size: TypedSize2D<f32, U>) -> SizeKey {
         SizeKey {
             w: size.width,
             h: size.height,
         }
     }
 }
 
-impl SizeKey {
-    pub fn zero() -> SizeKey {
-        SizeKey {
-            w: 0.0,
-            h: 0.0,
-        }
-    }
-}
-
 /// A hashable vec for using as a key during primitive interning.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 #[derive(Copy, Debug, Clone, PartialEq)]
 pub struct VectorKey {
     pub x: f32,
     pub y: f32,
 }
--- a/intl/encoding_glue/Cargo.toml
+++ b/intl/encoding_glue/Cargo.toml
@@ -5,10 +5,10 @@ version = "0.1.0"
 authors = ["Henri Sivonen <hsivonen@hsivonen.fi>"]
 license = "MIT/Apache-2.0"
 
 [features]
 simd-accel = ["encoding_rs/simd-accel"]
 
 [dependencies]
 encoding_rs = "0.8.0"
-nsstring = { path = "../../servo/support/gecko/nsstring" }
+nsstring = { path = "../../xpcom/rust/nsstring" } 
 nserror = { path = "../../xpcom/rust/nserror" }
--- a/layout/base/tests/browser_disableDialogs_onbeforeunload.js
+++ b/layout/base/tests/browser_disableDialogs_onbeforeunload.js
@@ -11,17 +11,17 @@ SpecialPowers.pushPrefEnv({"set": [["dom
 const PAGE_URL =
   "data:text/html," + encodeURIComponent("<script>(" + pageScript.toSource() + ")();</script>");
 
 add_task(async function enableDialogs() {
   // The onbeforeunload dialog should appear.
   let dialogShown = false;
   function onDialogShown(node) {
     dialogShown = true;
-    let dismissButton = node.ui.button0;
+    let dismissButton = node.querySelector(".tabmodalprompt-button0");
     dismissButton.click();
   }
   let obsName = "tabmodal-dialog-loaded";
   Services.obs.addObserver(onDialogShown, obsName);
   await openPage(true);
   Services.obs.removeObserver(onDialogShown, obsName);
   Assert.ok(dialogShown);
 });
--- a/layout/base/tests/browser_onbeforeunload_only_after_interaction.js
+++ b/layout/base/tests/browser_onbeforeunload_only_after_interaction.js
@@ -11,17 +11,17 @@ SpecialPowers.pushPrefEnv({"set": [["dom
 const PAGE_URL =
   "data:text/html," + encodeURIComponent("<script>(" + pageScript.toSource() + ")();</script>");
 
 add_task(async function doClick() {
   // The onbeforeunload dialog should appear.
   let dialogShown = false;
   function onDialogShown(node) {
     dialogShown = true;
-    let dismissButton = node.ui.button0;
+    let dismissButton = node.querySelector(".tabmodalprompt-button0");
     dismissButton.click();
   }
   let obsName = "tabmodal-dialog-loaded";
   Services.obs.addObserver(onDialogShown, obsName);
   await openPage(true);
   Services.obs.removeObserver(onDialogShown, obsName);
   Assert.ok(dialogShown, "Should have shown dialog.");
 });
--- a/layout/base/tests/browser_onbeforeunload_only_after_interaction_in_frame.js
+++ b/layout/base/tests/browser_onbeforeunload_only_after_interaction_in_frame.js
@@ -15,17 +15,17 @@ const FRAME_URL =
 const PAGE_URL =
   "data:text/html," + encodeURIComponent("<iframe src='" + FRAME_URL + "'></iframe><script>(" + pageScript.toSource() + ")();</script>");
 
 add_task(async function doClick() {
   // The onbeforeunload dialog should appear.
   let dialogShown = false;
   function onDialogShown(node) {
     dialogShown = true;
-    let dismissButton = node.ui.button0;
+    let dismissButton = node.querySelector(".tabmodalprompt-button0");
     dismissButton.click();
   }
   let obsName = "tabmodal-dialog-loaded";
   Services.obs.addObserver(onDialogShown, obsName);
   await openPage(true);
   Services.obs.removeObserver(onDialogShown, obsName);
   Assert.ok(dialogShown, "Should have shown dialog.");
 });
--- a/layout/forms/nsDateTimeControlFrame.cpp
+++ b/layout/forms/nsDateTimeControlFrame.cpp
@@ -13,17 +13,16 @@
 
 #include "nsContentUtils.h"
 #include "nsCheckboxRadioFrame.h"
 #include "nsGkAtoms.h"
 #include "nsContentCreatorFunctions.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "mozilla/dom/MutationEventBinding.h"
-#include "nsDOMTokenList.h"
 #include "nsNodeInfoManager.h"
 #include "nsIDateTimeInputArea.h"
 #include "nsIObserverService.h"
 #include "jsapi.h"
 #include "nsJSUtils.h"
 #include "nsThreadUtils.h"
 
 using namespace mozilla;
@@ -46,131 +45,57 @@ nsDateTimeControlFrame::nsDateTimeContro
 
 void nsDateTimeControlFrame::DestroyFrom(nsIFrame* aDestructRoot,
                                          PostDestroyData& aPostDestroyData) {
   aPostDestroyData.AddAnonymousContent(mInputAreaContent.forget());
   nsContainerFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
 }
 
 void nsDateTimeControlFrame::OnValueChanged() {
-  if (mInputAreaContent) {
-    nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
-        do_QueryInterface(mInputAreaContent);
-    if (inputAreaContent) {
-      inputAreaContent->NotifyInputElementValueChanged();
-    }
-  } else {
-    Element* inputAreaContent = GetInputAreaContentAsElement();
-    if (!inputAreaContent) {
-      return;
-    }
-
-    AsyncEventDispatcher* dispatcher = new AsyncEventDispatcher(
-        inputAreaContent, NS_LITERAL_STRING("MozDateTimeValueChanged"),
-        CanBubble::eNo, ChromeOnlyDispatch::eNo);
-    dispatcher->RunDOMEventWhenSafe();
+  if (!mInputAreaContent) {
+    return;
+  }
+  nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
+      do_QueryInterface(mInputAreaContent);
+  if (inputAreaContent) {
+    inputAreaContent->NotifyInputElementValueChanged();
   }
 }
 
 void nsDateTimeControlFrame::OnMinMaxStepAttrChanged() {
-  if (mInputAreaContent) {
-    nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
-        do_QueryInterface(mInputAreaContent);
-    if (inputAreaContent) {
-      inputAreaContent->NotifyMinMaxStepAttrChanged();
-    }
-  } else {
-    Element* inputAreaContent = GetInputAreaContentAsElement();
-    if (!inputAreaContent) {
-      return;
-    }
-
-    AsyncEventDispatcher* dispatcher = new AsyncEventDispatcher(
-        inputAreaContent, NS_LITERAL_STRING("MozNotifyMinMaxStepAttrChanged"),
-        CanBubble::eNo, ChromeOnlyDispatch::eNo);
-    dispatcher->RunDOMEventWhenSafe();
+  if (!mInputAreaContent) {
+    return;
+  }
+  nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
+      do_QueryInterface(mInputAreaContent);
+  if (inputAreaContent) {
+    inputAreaContent->NotifyMinMaxStepAttrChanged();
   }
 }
 
 void nsDateTimeControlFrame::HandleFocusEvent() {
-  if (mInputAreaContent) {
-    nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
-        do_QueryInterface(mInputAreaContent);
-    if (inputAreaContent) {
-      inputAreaContent->FocusInnerTextBox();
-    }
-  } else {
-    Element* inputAreaContent = GetInputAreaContentAsElement();
-    if (!inputAreaContent) {
-      return;
-    }
-
-    AsyncEventDispatcher* dispatcher = new AsyncEventDispatcher(
-        inputAreaContent, NS_LITERAL_STRING("MozFocusInnerTextBox"),
-        CanBubble::eNo, ChromeOnlyDispatch::eNo);
-    dispatcher->RunDOMEventWhenSafe();
+  if (!mInputAreaContent) {
+    return;
+  }
+  nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
+      do_QueryInterface(mInputAreaContent);
+  if (inputAreaContent) {
+    inputAreaContent->FocusInnerTextBox();
   }
 }
 
 void nsDateTimeControlFrame::HandleBlurEvent() {
-  if (mInputAreaContent) {
-    nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
-        do_QueryInterface(mInputAreaContent);
-    if (inputAreaContent) {
-      inputAreaContent->BlurInnerTextBox();
-    }
-  } else {
-    Element* inputAreaContent = GetInputAreaContentAsElement();
-    if (!inputAreaContent) {
-      return;
-    }
-
-    AsyncEventDispatcher* dispatcher = new AsyncEventDispatcher(
-        inputAreaContent, NS_LITERAL_STRING("MozBlurInnerTextBox"),
-        CanBubble::eNo, ChromeOnlyDispatch::eNo);
-    dispatcher->RunDOMEventWhenSafe();
+  if (!mInputAreaContent) {
+    return;
   }
-}
-
-bool nsDateTimeControlFrame::HasBadInput() {
-  Element* editWrapperElement = nullptr;
-  if (mInputAreaContent) {
-    // edit-wrapper is inside an XBL binding
-    editWrapperElement =
-        mInputAreaContent->GetComposedDoc()->GetAnonymousElementByAttribute(
-            mInputAreaContent, nsGkAtoms::anonid,
-            NS_LITERAL_STRING("edit-wrapper"));
-  } else if (mContent->GetShadowRoot()) {
-    // edit-wrapper is inside an UA Widget Shadow DOM
-    editWrapperElement = mContent->GetShadowRoot()->GetElementById(
-        NS_LITERAL_STRING("edit-wrapper"));
-  }
-
-  if (!editWrapperElement) {
-    return false;
+  nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
+      do_QueryInterface(mInputAreaContent);
+  if (inputAreaContent) {
+    inputAreaContent->BlurInnerTextBox();
   }
-
-  // Incomplete field does not imply bad input.
-  for (Element* child = editWrapperElement->GetFirstElementChild(); child;
-       child = child->GetNextElementSibling()) {
-    if (child->ClassList()->Contains(
-            NS_LITERAL_STRING("datetime-edit-field"))) {
-      nsAutoString value;
-      child->GetAttr(kNameSpaceID_None, nsGkAtoms::value, value);
-      if (value.IsEmpty()) {
-        return false;
-      }
-    }
-  }
-
-  // All fields are available but input element's value is empty implies
-  // it has been sanitized.
-  nsAutoString value;
-  HTMLInputElement::FromNode(mContent)->GetValue(value, CallerType::System);
-  return value.IsEmpty();
 }
 
 nscoord nsDateTimeControlFrame::GetMinISize(gfxContext* aRenderingContext) {
   nscoord result;
   DISPLAY_MIN_INLINE_SIZE(this, result);
 
   nsIFrame* kid = mFrames.FirstChild();
   if (kid) {  // display:none?
@@ -379,23 +304,25 @@ void nsDateTimeControlFrame::SyncDisable
   if (mInputAreaContent) {
     nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
         do_QueryInterface(mInputAreaContent);
     if (!inputAreaContent) {
       return;
     }
     inputAreaContent->UpdateEditAttributes();
   } else {
-    Element* inputAreaContent = GetInputAreaContentAsElement();
-    if (!inputAreaContent) {
+    Element* dateTimeBoxElement =
+        static_cast<dom::HTMLInputElement*>(GetContent())
+            ->GetDateTimeBoxElementInUAWidget();
+    if (!dateTimeBoxElement) {
       return;
     }
 
     AsyncEventDispatcher* dispatcher = new AsyncEventDispatcher(
-        inputAreaContent, NS_LITERAL_STRING("MozDateTimeAttributeChanged"),
+        dateTimeBoxElement, NS_LITERAL_STRING("MozDateTimeAttributeChanged"),
         CanBubble::eNo, ChromeOnlyDispatch::eNo);
     dispatcher->RunDOMEventWhenSafe();
   }
 }
 
 nsresult nsDateTimeControlFrame::AttributeChanged(int32_t aNameSpaceID,
                                                   nsAtom* aAttribute,
                                                   int32_t aModType) {
@@ -421,61 +348,45 @@ nsresult nsDateTimeControlFrame::Attribu
                   &nsIDateTimeInputArea::NotifyInputElementValueChanged));
             }
           } else {
             if (inputAreaContent) {
               inputAreaContent->UpdateEditAttributes();
             }
           }
         } else {
-          Element* inputAreaContent = GetInputAreaContentAsElement();
+          Element* dateTimeBoxElement =
+              static_cast<dom::HTMLInputElement*>(GetContent())
+                  ->GetDateTimeBoxElementInUAWidget();
           if (aAttribute == nsGkAtoms::value) {
-            if (inputAreaContent) {
+            if (dateTimeBoxElement) {
               AsyncEventDispatcher* dispatcher = new AsyncEventDispatcher(
-                  inputAreaContent,
-                  NS_LITERAL_STRING("NotifyInputElementValueChanged"),
-                  CanBubble::eNo, ChromeOnlyDispatch::eNo);
+                  dateTimeBoxElement,
+                  NS_LITERAL_STRING("MozDateTimeValueChanged"), CanBubble::eNo,
+                  ChromeOnlyDispatch::eNo);
               dispatcher->RunDOMEventWhenSafe();
             }
           } else {
-            if (inputAreaContent) {
+            if (dateTimeBoxElement) {
               AsyncEventDispatcher* dispatcher = new AsyncEventDispatcher(
-                  inputAreaContent,
-                  NS_LITERAL_STRING("MozDateTimeValueChanged"), CanBubble::eNo,
-                  ChromeOnlyDispatch::eNo);
+                  dateTimeBoxElement,
+                  NS_LITERAL_STRING("MozDateTimeAttributeChanged"),
+                  CanBubble::eNo, ChromeOnlyDispatch::eNo);
               dispatcher->RunDOMEventWhenSafe();
             }
           }
         }
       }
     }
   }
 
   return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
 
 nsIContent* nsDateTimeControlFrame::GetInputAreaContent() {
-  if (mInputAreaContent) {
-    return mInputAreaContent;
-  }
-  if (mContent->GetShadowRoot()) {
-    // The datetimebox <div> is the only child of the UA Widget Shadow Root
-    // if it is present.
-    MOZ_ASSERT(mContent->GetShadowRoot()->IsUAWidget());
-    MOZ_ASSERT(1 >= mContent->GetShadowRoot()->GetChildCount());
-    return mContent->GetShadowRoot()->GetFirstChild();
-  }
-  return nullptr;
-}
-
-Element* nsDateTimeControlFrame::GetInputAreaContentAsElement() {
-  nsIContent* inputAreaContent = GetInputAreaContent();
-  if (inputAreaContent) {
-    return inputAreaContent->AsElement();
-  }
-  return nullptr;
+  return mInputAreaContent;
 }
 
 void nsDateTimeControlFrame::ContentStatesChanged(EventStates aStates) {
   if (aStates.HasState(NS_EVENT_STATE_DISABLED)) {
     nsContentUtils::AddScriptRunner(new SyncDisabledStateEvent(this));
   }
 }
--- a/layout/forms/nsDateTimeControlFrame.h
+++ b/layout/forms/nsDateTimeControlFrame.h
@@ -75,17 +75,16 @@ class nsDateTimeControlFrame final : pub
                             int32_t aModType) override;
 
   nsIContent* GetInputAreaContent();
 
   void OnValueChanged();
   void OnMinMaxStepAttrChanged();
   void HandleFocusEvent();
   void HandleBlurEvent();
-  bool HasBadInput();
 
  private:
   class SyncDisabledStateEvent;
   friend class SyncDisabledStateEvent;
   class SyncDisabledStateEvent : public mozilla::Runnable {
    public:
     explicit SyncDisabledStateEvent(nsDateTimeControlFrame* aFrame)
         : mozilla::Runnable("nsDateTimeControlFrame::SyncDisabledStateEvent"),
@@ -104,16 +103,14 @@ class nsDateTimeControlFrame final : pub
     WeakFrame mFrame;
   };
 
   /**
    * Sync the disabled state of the anonymous children up with our content's.
    */
   void SyncDisabledState();
 
-  mozilla::dom::Element* GetInputAreaContentAsElement();
-
   // Anonymous child which is bound via XBL to an element that wraps the input
   // area and reset button.
   RefPtr<mozilla::dom::Element> mInputAreaContent;
 };
 
 #endif  // nsDateTimeControlFrame_h__
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1485,20 +1485,22 @@ bool nsIFrame::HasAnimationOfTransform()
 
 bool nsIFrame::ChildrenHavePerspective(
     const nsStyleDisplay* aStyleDisplay) const {
   MOZ_ASSERT(aStyleDisplay == StyleDisplay());
   return aStyleDisplay->HasPerspective(this);
 }
 
 bool nsIFrame::HasOpacityInternal(float aThreshold,
+                                  const nsStyleDisplay* aStyleDisplay,
+                                  const nsStyleEffects* aStyleEffects,
                                   EffectSet* aEffectSet) const {
   MOZ_ASSERT(0.0 <= aThreshold && aThreshold <= 1.0, "Invalid argument");
-  if (StyleEffects()->mOpacity < aThreshold ||
-      (StyleDisplay()->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY)) {
+  if (aStyleEffects->mOpacity < aThreshold ||
+      (aStyleDisplay->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY)) {
     return true;
   }
 
   if (!mMayHaveOpacityAnimation) {
     return false;
   }
 
   EffectSet* effects = aEffectSet ? aEffectSet : EffectSet::GetEffectSet(this);
@@ -1513,37 +1515,38 @@ bool nsIFrame::HasOpacityInternal(float 
 }
 
 bool nsIFrame::IsSVGTransformed(gfx::Matrix* aOwnTransforms,
                                 gfx::Matrix* aFromParentTransforms) const {
   return false;
 }
 
 bool nsIFrame::Extend3DContext(const nsStyleDisplay* aStyleDisplay,
+                               const nsStyleEffects* aStyleEffects,
                                mozilla::EffectSet* aEffectSet) const {
   if (!(mState & NS_FRAME_MAY_BE_TRANSFORMED)) {
     return false;
   }
   const nsStyleDisplay* disp = StyleDisplayWithOptionalParam(aStyleDisplay);
   if (disp->mTransformStyle != NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
       !IsFrameOfType(nsIFrame::eSupportsCSSTransforms)) {
     return false;
   }
 
   // If we're all scroll frame, then all descendants will be clipped, so we
   // can't preserve 3d.
   if (IsScrollFrame()) {
     return false;
   }
 
-  if (HasOpacity(aEffectSet)) {
+  const nsStyleEffects* effects = StyleEffectsWithOptionalParam(aStyleEffects);
+  if (HasOpacity(disp, effects, aEffectSet)) {
     return false;
   }
 
-  const nsStyleEffects* effects = StyleEffects();
   return !nsFrame::ShouldApplyOverflowClipping(this, disp) &&
          !GetClipPropClipRect(disp, effects, GetSize()) &&
          !nsSVGIntegrationUtils::UsingEffectsForFrame(this);
 }
 
 bool nsIFrame::Combines3DTransformWithAncestors(
     const nsStyleDisplay* aStyleDisplay) const {
   MOZ_ASSERT(aStyleDisplay == StyleDisplay());
@@ -2718,19 +2721,31 @@ void nsIFrame::BuildDisplayListForStacki
   }
 
   // For preserves3d, use the dirty rect already installed on the
   // builder, since aDirtyRect maybe distorted for transforms along
   // the chain.
   nsRect visibleRect = aBuilder->GetVisibleRect();
   nsRect dirtyRect = aBuilder->GetDirtyRect();
 
+  // We build an opacity item if it's not going to be drawn by SVG content.
+  // We could in principle skip creating an nsDisplayOpacity item if
+  // nsDisplayOpacity::NeedsActiveLayer returns false and usingSVGEffects is
+  // true (the nsDisplayFilter/nsDisplayMasksAndClipPaths could handle the
+  // opacity). Since SVG has perf issues where we sometimes spend a lot of
+  // time creating display list items that might be helpful.  We'd need to
+  // restore our mechanism to do that (changed in bug 1482403), and we'd
+  // need to invalidate the frame if the value that would be return from
+  // NeedsActiveLayer was to change, which we don't currently do.
+  const bool useOpacity = HasVisualOpacity(disp, effects, effectSet) &&
+                          !nsSVGUtils::CanOptimizeOpacity(this);
+
   const bool isTransformed = IsTransformed(disp);
   const bool hasPerspective = isTransformed && HasPerspective(disp);
-  const bool extend3DContext = Extend3DContext(disp, effectSet);
+  const bool extend3DContext = Extend3DContext(disp, effects, effectSet);
   const bool combines3DTransformWithAncestors =
       (extend3DContext || isTransformed) &&
       Combines3DTransformWithAncestors(disp);
 
   Maybe<nsDisplayListBuilder::AutoPreserves3DContext> autoPreserves3DContext;
   if (extend3DContext && !combines3DTransformWithAncestors) {
     // Start a new preserves3d context to keep informations on
     // nsDisplayListBuilder.
@@ -2742,16 +2757,21 @@ void nsIFrame::BuildDisplayListForStacki
     // We rebuild everything within preserve-3d and don't try
     // to retain, so override the dirty rect now.
     if (aBuilder->IsRetainingDisplayList()) {
       dirtyRect = visibleRect;
       aBuilder->SetDisablePartialUpdates(true);
     }
   }
 
+  const bool useBlendMode = effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
+  if (useBlendMode) {
+    aBuilder->SetContainsBlendMode(true);
+  }
+
   // reset blend mode so we can keep track if this stacking context needs have
   // a nsDisplayBlendContainer. Set the blend mode back when the routine exits
   // so we keep track if the parent stacking context needs a container too.
   AutoSaveRestoreContainsBlendMode autoRestoreBlendMode(*aBuilder);
   aBuilder->SetContainsBlendMode(false);
 
   nsRect visibleRectOutsideTransform = visibleRect;
   bool allowAsyncAnimation = false;
@@ -2826,29 +2846,16 @@ void nsIFrame::BuildDisplayListForStacki
   if (usingSVGEffects) {
     dirtyRect =
         nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
     visibleRect = nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(
         this, visibleRect);
     aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage);
   }
 
-  // We build an opacity item if it's not going to be drawn by SVG content.
-  // We could in principle skip creating an nsDisplayOpacity item if
-  // nsDisplayOpacity::NeedsActiveLayer returns false and usingSVGEffects is
-  // true (the nsDisplayFilter/nsDisplayMasksAndClipPaths could handle the
-  // opacity). Since SVG has perf issues where we sometimes spend a lot of
-  // time creating display list items that might be helpful.  We'd need to
-  // restore our mechanism to do that (changed in bug 1482403), and we'd
-  // need to invalidate the frame if the value that would be return from
-  // NeedsActiveLayer was to change, which we don't currently do.
-  bool useOpacity =
-      HasVisualOpacity(effectSet) && !nsSVGUtils::CanOptimizeOpacity(this);
-
-  bool useBlendMode = effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
   bool useStickyPosition =
       disp->mPosition == NS_STYLE_POSITION_STICKY &&
       IsScrollFrameActive(
           aBuilder,
           nsLayoutUtils::GetNearestScrollableFrame(
               GetParent(), nsLayoutUtils::SCROLLABLE_SAME_DOC |
                                nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN));
   bool useFixedPosition = disp->mPosition == NS_STYLE_POSITION_FIXED &&
@@ -3347,233 +3354,251 @@ static nsDisplayItem* WrapInWrapList(nsD
   // clipping all their contents, they themselves don't need to be clipped.
   return MakeDisplayItem<nsDisplayWrapList>(aBuilder, aFrame, aList,
                                             aContainerASR, true);
 }
 
 /**
  * Check if a frame should be visited for building display list.
  */
-static bool DescendIntoChild(nsDisplayListBuilder* aBuilder, nsIFrame* aChild,
-                             const nsRect& aVisible, const nsRect& aDirty) {
-  nsIFrame* child = aChild;
-  const nsRect& dirty = aDirty;
-
-  if (!(child->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) {
-    // No need to descend into child to catch placeholders for visible
-    // positioned stuff. So see if we can short-circuit frame traversal here.
-
-    // We can stop if child's frame subtree's intersection with the
-    // dirty area is empty.
-    // If the child is a scrollframe that we want to ignore, then we need
-    // to descend into it because its scrolled child may intersect the dirty
-    // area even if the scrollframe itself doesn't.
-    // There are cases where the "ignore scroll frame" on the builder is not set
-    // correctly, and so we additionally want to catch cases where the child is
-    // a root scrollframe and we are ignoring scrolling on the viewport.
-    nsIPresShell* shell = child->PresShell();
-    bool keepDescending = child == aBuilder->GetIgnoreScrollFrame() ||
-                          (shell->IgnoringViewportScrolling() &&
-                           child == shell->GetRootScrollFrame());
-    if (!keepDescending) {
-      nsRect childDirty;
-      if (!childDirty.IntersectRect(dirty, child->GetVisualOverflowRect()) &&
-          (!child->ForceDescendIntoIfVisible())) {
-        return false;
-      }
-      if (!childDirty.IntersectRect(aVisible, child->GetVisualOverflowRect())) {
-        return false;
-      }
-      // Usually we could set dirty to childDirty now but there's no
-      // benefit, and it can be confusing. It can especially confuse
-      // situations where we're going to ignore a scrollframe's clipping;
-      // we wouldn't want to clip the dirty area to the scrollframe's
-      // bounds in that case.
-    }
-  }
-  return true;
+static bool DescendIntoChild(nsDisplayListBuilder* aBuilder,
+                             const nsIFrame* aChild, const nsRect& aVisible,
+                             const nsRect& aDirty) {
+  if (aChild->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) {
+    return true;
+  }
+
+  // If the child is a scrollframe that we want to ignore, then we need
+  // to descend into it because its scrolled child may intersect the dirty
+  // area even if the scrollframe itself doesn't.
+  if (aChild == aBuilder->GetIgnoreScrollFrame()) {
+    return true;
+  }
+
+  // There are cases where the "ignore scroll frame" on the builder is not set
+  // correctly, and so we additionally want to catch cases where the child is
+  // a root scrollframe and we are ignoring scrolling on the viewport.
+  if (aChild == aBuilder->GetPresShellIgnoreScrollFrame()) {
+    return true;
+  }
+
+  const nsRect overflow = aChild->GetVisualOverflowRect();
+
+  if (aDirty.Intersects(overflow)) {
+    return true;
+  }
+
+  if (aChild->ForceDescendIntoIfVisible() && aVisible.Intersects(overflow)) {
+    return true;
+  }
+
+  return false;
+}
+
+void nsIFrame::BuildDisplayListForSimpleChild(nsDisplayListBuilder* aBuilder,
+                                              nsIFrame* aChild,
+                                              const nsDisplayListSet& aLists) {
+  // This is the shortcut for frames been handled along the common
+  // path, the most common one of THE COMMON CASE mentioned later.
+  MOZ_ASSERT(aChild->Type() != LayoutFrameType::Placeholder);
+  MOZ_ASSERT(!aBuilder->GetSelectedFramesOnly() &&
+                 !aBuilder->GetIncludeAllOutOfFlows(),
+             "It should be held for painting to window");
+  MOZ_ASSERT(aChild->GetStateBits() & NS_FRAME_SIMPLE_DISPLAYLIST);
+
+  const nsPoint offset = aChild->GetOffsetTo(this);
+  const nsRect visible = aBuilder->GetVisibleRect() - offset;
+  const nsRect dirty = aBuilder->GetDirtyRect() - offset;
+
+  if (!DescendIntoChild(aBuilder, aChild, visible, dirty)) {
+    return;
+  }
+
+  nsDisplayListBuilder::AutoBuildingDisplayList buildingForChild(
+      aBuilder, aChild, visible, dirty, false);
+
+  CheckForApzAwareEventHandlers(aBuilder, aChild);
+
+  aBuilder->BuildCompositorHitTestInfoIfNeeded(
+      aChild, aLists.BorderBackground(), false);
+
+  aChild->MarkAbsoluteFramesForDisplayList(aBuilder);
+  aBuilder->AdjustWindowDraggingRegion(aChild);
+  aBuilder->Check();
+  aChild->BuildDisplayList(aBuilder, aLists);
+  aBuilder->Check();
+  aBuilder->DisplayCaret(aChild, aLists.Content());
+#ifdef DEBUG
+  DisplayDebugBorders(aBuilder, aChild, aLists);
+#endif
+}
+
+static bool ShouldSkipFrame(nsDisplayListBuilder* aBuilder,
+                            const nsIFrame* aFrame) {
+  // If painting is restricted to just the background of the top level frame,
+  // then we have nothing to do here.
+  if (aBuilder->IsBackgroundOnly()) {
+    return true;
+  }
+
+  if ((aBuilder->IsForGenerateGlyphMask() ||
+       aBuilder->IsForPaintingSelectionBG()) &&
+      (!aFrame->IsTextFrame() && aFrame->IsLeaf())) {
+    return true;
+  }
+
+  // The placeholder frame should have the same content as the OOF frame.
+  if (aBuilder->GetSelectedFramesOnly() &&
+      (aFrame->IsLeaf() && !aFrame->IsSelected())) {
+    return true;
+  }
+
+  static const nsFrameState skipFlags =
+      (NS_FRAME_TOO_DEEP_IN_FRAME_TREE | NS_FRAME_IS_NONDISPLAY);
+
+  return (aFrame->GetStateBits() & skipFlags);
 }
 
 void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
                                         nsIFrame* aChild,
                                         const nsDisplayListSet& aLists,
                                         uint32_t aFlags) {
   AutoCheckBuilder check(aBuilder);
-  // If painting is restricted to just the background of the top level frame,
-  // then we have nothing to do here.
-  if (aBuilder->IsBackgroundOnly()) return;
-
-  if (aBuilder->IsForGenerateGlyphMask() ||
-      aBuilder->IsForPaintingSelectionBG()) {
-    if (!aChild->IsTextFrame() && aChild->IsLeaf()) {
-      return;
-    }
+
+  if (ShouldSkipFrame(aBuilder, aChild)) {
+    return;
   }
 
   nsIFrame* child = aChild;
-  if (child->HasAnyStateBits(NS_FRAME_TOO_DEEP_IN_FRAME_TREE |
-                             NS_FRAME_IS_NONDISPLAY))
+  aBuilder->RemoveFromWillChangeBudget(child);
+
+  const bool isPaintingToWindow = aBuilder->IsPaintingToWindow();
+  const bool doingShortcut =
+      isPaintingToWindow &&
+      (child->GetStateBits() & NS_FRAME_SIMPLE_DISPLAYLIST) &&
+      // Animations may change the stacking context state.
+      !(child->MayHaveTransformAnimation() || child->MayHaveOpacityAnimation());
+
+  if (doingShortcut) {
+    BuildDisplayListForSimpleChild(aBuilder, child, aLists);
     return;
-
-  aBuilder->RemoveFromWillChangeBudget(child);
-
-  const bool shortcutPossible =
-      aBuilder->IsPaintingToWindow() && aBuilder->BuildCompositorHitTestInfo();
-
-  const bool doingShortcut =
-      shortcutPossible &&
-      (child->GetStateBits() & NS_FRAME_SIMPLE_DISPLAYLIST) &&
-      // Animations may change the value of |HasOpacity()|.
-      !(child->GetContent() && child->GetContent()->MayHaveAnimations());
+  }
 
   // dirty rect in child-relative coordinates
   NS_ASSERTION(aBuilder->GetCurrentFrame() == this, "Wrong coord space!");
   const nsPoint offset = child->GetOffsetTo(this);
   nsRect visible = aBuilder->GetVisibleRect() - offset;
   nsRect dirty = aBuilder->GetDirtyRect() - offset;
 
-  if (doingShortcut) {
-    // This is the shortcut for frames been handled along the common
-    // path, the most common one of THE COMMON CASE mentioned later.
-    MOZ_ASSERT(child->Type() != LayoutFrameType::Placeholder);
-    MOZ_ASSERT(!aBuilder->GetSelectedFramesOnly() &&
-                   !aBuilder->GetIncludeAllOutOfFlows(),
-               "It should be held for painting to window");
-
-    if (!DescendIntoChild(aBuilder, child, visible, dirty)) {
+  nsDisplayListBuilder::OutOfFlowDisplayData* savedOutOfFlowData = nullptr;
+  const bool isPlaceholder = child->IsPlaceholderFrame();
+  if (isPlaceholder) {
+    nsPlaceholderFrame* placeholder = static_cast<nsPlaceholderFrame*>(child);
+    if (placeholder->GetStateBits() & PLACEHOLDER_FOR_TOPLAYER) {
+      // If the out-of-flow frame is in the top layer, the viewport frame
+      // will paint it. Skip it here. Note that, only out-of-flow frames
+      // with this property should be skipped, because non-HTML elements
+      // may stop their children from being out-of-flow. Those frames
+      // should still be handled in the normal in-flow path.
       return;
     }
 
-    nsDisplayListBuilder::AutoBuildingDisplayList buildingForChild(
-        aBuilder, child, visible, dirty, false);
-
-    CheckForApzAwareEventHandlers(aBuilder, child);
-
-    aBuilder->BuildCompositorHitTestInfoIfNeeded(
-        child, aLists.BorderBackground(), false);
-
-    child->MarkAbsoluteFramesForDisplayList(aBuilder);
-    aBuilder->AdjustWindowDraggingRegion(child);
-    aBuilder->Check();
-    child->BuildDisplayList(aBuilder, aLists);
-    aBuilder->Check();
-    aBuilder->DisplayCaret(child, aLists.Content());
-#ifdef DEBUG
-    DisplayDebugBorders(aBuilder, child, aLists);
-#endif
+    child = placeholder->GetOutOfFlowFrame();
+    NS_ASSERTION(child, "No out of flow frame?");
+
+    if (child) {
+      aBuilder->RemoveFromWillChangeBudget(child);
+    }
+
+    // If 'child' is a pushed float then it's owned by a block that's not an
+    // ancestor of the placeholder, and it will be painted by that block and
+    // should not be painted through the placeholder. Also recheck
+    // NS_FRAME_TOO_DEEP_IN_FRAME_TREE and NS_FRAME_IS_NONDISPLAY.
+    static const nsFrameState skipFlags =
+        (NS_FRAME_IS_PUSHED_FLOAT | NS_FRAME_TOO_DEEP_IN_FRAME_TREE |
+         NS_FRAME_IS_NONDISPLAY);
+    if (!child || (child->GetStateBits() & skipFlags) ||
+        nsLayoutUtils::IsPopup(child)) {
+      return;
+    }
+
+    MOZ_ASSERT(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW);
+    savedOutOfFlowData = nsDisplayListBuilder::GetOutOfFlowData(child);
+
+    if (aBuilder->GetIncludeAllOutOfFlows()) {
+      visible = child->GetVisualOverflowRect();
+      dirty = child->GetVisualOverflowRect();
+    } else if (savedOutOfFlowData) {
+      visible =
+          savedOutOfFlowData->GetVisibleRectForFrame(aBuilder, child, &dirty);
+    } else {
+      // The out-of-flow frame did not intersect the dirty area. We may still
+      // need to traverse into it, since it may contain placeholders we need
+      // to enter to reach other out-of-flow frames that are visible.
+      visible.SetEmpty();
+      dirty.SetEmpty();
+    }
+  }
+
+  NS_ASSERTION(!child->IsPlaceholderFrame(),
+               "Should have dealt with placeholders already");
+
+  if (!DescendIntoChild(aBuilder, child, visible, dirty)) {
     return;
   }
 
   const bool isSVG = child->GetStateBits() & NS_FRAME_SVG_LAYOUT;
 
-  // It is raised if the control flow strays off the common path.
-  // The common path is the most common one of THE COMMON CASE
-  // mentioned later.
-  bool awayFromCommonPath = false;
+  // This flag is raised if the control flow strays off the common path.
+  // The common path is the most common one of THE COMMON CASE mentioned later.
+  bool awayFromCommonPath = !isPaintingToWindow;
 
   // true if this is a real or pseudo stacking context
   bool pseudoStackingContext =
       (aFlags & DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT) != 0;
 
   if (!pseudoStackingContext && !isSVG && (aFlags & DISPLAY_CHILD_INLINE) &&
       !child->IsFrameOfType(eLineParticipant)) {
     // child is a non-inline frame in an inline context, i.e.,
     // it acts like inline-block or inline-table. Therefore it is a
     // pseudo-stacking-context.
     pseudoStackingContext = true;
   }
 
-  nsDisplayListBuilder::OutOfFlowDisplayData* savedOutOfFlowData = nullptr;
-  bool isPlaceholder = false;
-  if (child->IsPlaceholderFrame()) {
-    isPlaceholder = true;
-    nsPlaceholderFrame* placeholder = static_cast<nsPlaceholderFrame*>(child);
-    child = placeholder->GetOutOfFlowFrame();
-    aBuilder->RemoveFromWillChangeBudget(child);
-    NS_ASSERTION(child, "No out of flow frame?");
-    // If 'child' is a pushed float then it's owned by a block that's not an
-    // ancestor of the placeholder, and it will be painted by that block and
-    // should not be painted through the placeholder.
-    if (!child || nsLayoutUtils::IsPopup(child) ||
-        (child->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT))
-      return;
-    MOZ_ASSERT(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW);
-    // If the out-of-flow frame is in the top layer, the viewport frame
-    // will paint it. Skip it here. Note that, only out-of-flow frames
-    // with this property should be skipped, because non-HTML elements
-    // may stop their children from being out-of-flow. Those frames
-    // should still be handled in the normal in-flow path.
-    if (placeholder->GetStateBits() & PLACEHOLDER_FOR_TOPLAYER) {
-      return;
-    }
-    // Recheck NS_FRAME_TOO_DEEP_IN_FRAME_TREE
-    if (child->GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE) return;
-    savedOutOfFlowData = nsDisplayListBuilder::GetOutOfFlowData(child);
-    if (savedOutOfFlowData) {
-      visible =
-          savedOutOfFlowData->GetVisibleRectForFrame(aBuilder, child, &dirty);
-    } else {
-      // The out-of-flow frame did not intersect the dirty area. We may still
-      // need to traverse into it, since it may contain placeholders we need
-      // to enter to reach other out-of-flow frames that are visible.
-      visible.SetEmpty();
-      dirty.SetEmpty();
-    }
-
-    pseudoStackingContext = true;
-  }
-
-  NS_ASSERTION(!child->IsPlaceholderFrame(),
-               "Should have dealt with placeholders already");
-  if (aBuilder->GetSelectedFramesOnly() && child->IsLeaf() &&
-      !aChild->IsSelected()) {
-    return;
-  }
-
-  if (aBuilder->GetIncludeAllOutOfFlows() && isPlaceholder) {
-    visible = child->GetVisualOverflowRect();
-    dirty = child->GetVisualOverflowRect();
-  } else if (!DescendIntoChild(aBuilder, child, visible, dirty)) {
-    return;
-  }
-
-  // XXX need to have inline-block and inline-table set pseudoStackingContext
-
   const nsStyleDisplay* ourDisp = StyleDisplay();
   // REVIEW: Taken from nsBoxFrame::Paint
   // Don't paint our children if the theme object is a leaf.
   if (IsThemed(ourDisp) &&
       !PresContext()->GetTheme()->WidgetIsContainer(ourDisp->mAppearance))
     return;
 
   // Since we're now sure that we're adding this frame to the display list
   // (which means we're painting it, modulo occlusion), mark it as visible
   // within the displayport.
-  if (aBuilder->IsPaintingToWindow() && child->TrackingVisibility()) {
+  if (isPaintingToWindow && child->TrackingVisibility()) {
     child->PresShell()->EnsureFrameInApproximatelyVisibleList(child);
     awayFromCommonPath = true;
   }
 
   child->SetBuiltDisplayList(true);
 
   // Child is composited if it's transformed, partially transparent, or has
   // SVG effects or a blend mode..
-  EffectSet* effectSet = EffectSet::GetEffectSet(child);
   const nsStyleDisplay* disp = child->StyleDisplay();
   const nsStyleEffects* effects = child->StyleEffects();
   const nsStylePosition* pos = child->StylePosition();
 
   const bool isPositioned = disp->IsAbsPosContainingBlock(child);
 
   const bool isStackingContext =
-      child->IsStackingContext(effectSet, disp, pos, effects, isPositioned) ||
-      (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT);
+      (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT) ||
+      child->IsStackingContext(disp, pos, effects, isPositioned);
 
   if (pseudoStackingContext || isStackingContext || isPositioned ||
-      (!isSVG && disp->IsFloating(child)) ||
+      isPlaceholder || (!isSVG && disp->IsFloating(child)) ||
       (isSVG && (effects->mClipFlags & NS_STYLE_CLIP_RECT) &&
        IsSVGContentWithCSSClip(child))) {
     pseudoStackingContext = true;
     awayFromCommonPath = true;
   }
 
   NS_ASSERTION(!isStackingContext || pseudoStackingContext,
                "Stacking contexts must also be pseudo-stacking-contexts");
@@ -3623,19 +3648,16 @@ void nsIFrame::BuildDisplayListForChild(
     awayFromCommonPath = true;
   }
 
   nsDisplayList list;
   nsDisplayList extraPositionedDescendants;
   const ActiveScrolledRoot* wrapListASR;
   bool canSkipWrapList = false;
   if (isStackingContext) {
-    if (effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
-      aBuilder->SetContainsBlendMode(true);
-    }
     // True stacking context.
     // For stacking contexts, BuildDisplayListForStackingContext handles
     // clipping and MarkAbsoluteFramesForDisplayList.
     nsDisplayListBuilder::AutoContainerASRTracker contASRTracker(aBuilder);
     child->BuildDisplayListForStackingContext(aBuilder, &list,
                                               &canSkipWrapList);
     wrapListASR = contASRTracker.GetContainerASR();
     if (aBuilder->GetCaretFrame() == child) {
@@ -3649,21 +3671,19 @@ void nsIFrame::BuildDisplayListForChild(
       aBuilder->IntersectDirtyRect(*clipPropClip);
       clipState.ClipContentDescendants(*clipPropClip +
                                        aBuilder->ToReferenceFrame(child));
       awayFromCommonPath = true;
     }
 
     child->MarkAbsoluteFramesForDisplayList(aBuilder);
 
-    const bool differentAGR =
-        buildingForChild.IsAnimatedGeometryRoot() || isPositioned;
-
-    if (!awayFromCommonPath && shortcutPossible && !differentAGR &&
-        !buildingForChild.MaybeAnimatedGeometryRoot()) {
+    const bool differentAGR = buildingForChild.IsAnimatedGeometryRoot();
+
+    if (!awayFromCommonPath) {
       // The shortcut is available for the child for next time.
       child->AddStateBits(NS_FRAME_SIMPLE_DISPLAYLIST);
     }
 
     if (!pseudoStackingContext) {
       // THIS IS THE COMMON CASE.
       // Not a pseudo or real stacking context. Do the simple thing and
       // return early.
@@ -3684,17 +3704,17 @@ void nsIFrame::BuildDisplayListForChild(
 
     // A pseudo-stacking context (e.g., a positioned element with z-index auto).
     // We allow positioned descendants of the child to escape to our parent
     // stacking context's positioned descendant list, because they might be
     // z-index:non-auto
     nsDisplayListCollection pseudoStack(aBuilder);
 
     aBuilder->BuildCompositorHitTestInfoIfNeeded(
-        child, pseudoStack.BorderBackground(), differentAGR);
+        child, pseudoStack.BorderBackground(), differentAGR || isPositioned);
 
     aBuilder->AdjustWindowDraggingRegion(child);
     nsDisplayListBuilder::AutoContainerASRTracker contASRTracker(aBuilder);
     aBuilder->Check();
     child->BuildDisplayList(aBuilder, pseudoStack);
     aBuilder->Check();
     if (aBuilder->DisplayCaret(child, pseudoStack.Content())) {
       canSkipWrapList = false;
@@ -8994,17 +9014,17 @@ bool nsIFrame::FinishAndStoreOverflow(ns
         o = nsDisplayTransform::TransformRect(o, this);
       }
 
       /* If we're the root of the 3d context, then we want to include the
        * overflow areas of all the participants. This won't have happened yet as
        * the code above set their overflow area to empty. Manually collect these
        * overflow areas now.
        */
-      if (Extend3DContext(disp, effectSet)) {
+      if (Extend3DContext(disp, effects, effectSet)) {
         ComputePreserve3DChildrenOverflow(aOverflowAreas);
       }
     }
   } else {
     DeleteProperty(nsIFrame::PreTransformOverflowAreasProperty());
   }
 
   /* Revert the size change in case some caller is depending on this. */
@@ -9085,17 +9105,17 @@ void nsIFrame::ComputePreserve3DChildren
           nsRect& o = childOverflow.Overflow(otype);
           o = nsDisplayTransform::TransformRect(o, child);
         }
 
         aOverflowAreas.UnionWith(childOverflow);
 
         // If this child also extends the 3d context, then recurse into it
         // looking for more participants.
-        if (child->Extend3DContext(childDisp)) {
+        if (child->Extend3DContext(childDisp, child->StyleEffects())) {
           child->ComputePreserve3DChildrenOverflow(aOverflowAreas);
         }
       }
     }
   }
 }
 
 uint32_t nsIFrame::GetDepthInFrameTree() const {
@@ -10294,22 +10314,22 @@ void nsIFrame::CreateOwnLayerIfNeeded(ns
     aList->AppendToTop(MakeDisplayItem<nsDisplayOwnLayer>(
         aBuilder, this, aList, aBuilder->CurrentActiveScrolledRoot()));
     if (aCreatedContainerItem) {
       *aCreatedContainerItem = true;
     }
   }
 }
 
-bool nsIFrame::IsStackingContext(EffectSet* aEffectSet,
-                                 const nsStyleDisplay* aStyleDisplay,
+bool nsIFrame::IsStackingContext(const nsStyleDisplay* aStyleDisplay,
                                  const nsStylePosition* aStylePosition,
                                  const nsStyleEffects* aStyleEffects,
                                  bool aIsPositioned) {
-  return HasOpacity(aEffectSet) || IsTransformed(aStyleDisplay) ||
+  return HasOpacity(aStyleDisplay, aStyleEffects, nullptr) ||
+         IsTransformed(aStyleDisplay) ||
          (IsFrameOfType(eSupportsContainLayoutAndPaint) &&
           (aStyleDisplay->IsContainPaint() ||
            aStyleDisplay->IsContainLayout())) ||
          // strictly speaking, 'perspective' doesn't require visual atomicity,
          // but the spec says it acts like the rest of these
          ChildrenHavePerspective(aStyleDisplay) ||
          aStyleEffects->mMixBlendMode != NS_STYLE_BLEND_NORMAL ||
          nsSVGIntegrationUtils::UsingEffectsForFrame(this) ||
@@ -10319,18 +10339,17 @@ bool nsIFrame::IsStackingContext(EffectS
          (aStyleDisplay->mWillChangeBitField &
           NS_STYLE_WILL_CHANGE_STACKING_CONTEXT) ||
          aStyleDisplay->mIsolation != NS_STYLE_ISOLATION_AUTO;
 }
 
 bool nsIFrame::IsStackingContext() {
   const nsStyleDisplay* disp = StyleDisplay();
   const bool isPositioned = disp->IsAbsPosContainingBlock(this);
-  return IsStackingContext(EffectSet::GetEffectSet(this), disp, StylePosition(),
-                           StyleEffects(), isPositioned);
+  return IsStackingContext(disp, StylePosition(), StyleEffects(), isPositioned);
 }
 
 static bool IsFrameScrolledOutOfView(const nsIFrame* aTarget,
                                      const nsRect& aTargetRect,
                                      const nsIFrame* aParent) {
   nsIScrollableFrame* scrollableFrame =
       nsLayoutUtils::GetNearestScrollableFrame(
           const_cast<nsIFrame*>(aParent),
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1686,16 +1686,20 @@ class nsIFrame : public nsQueryFrame {
    * @param aFlags combination of DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT,
    *    DISPLAY_CHILD_FORCE_STACKING_CONTEXT and DISPLAY_CHILD_INLINE
    */
   void BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
                                 nsIFrame* aChild,
                                 const nsDisplayListSet& aLists,
                                 uint32_t aFlags = 0);
 
+  void BuildDisplayListForSimpleChild(nsDisplayListBuilder* aBuilder,
+                                      nsIFrame* aChild,
+                                      const nsDisplayListSet& aLists);
+
   bool RefusedAsyncAnimation() const {
     return GetProperty(RefusedAsyncAnimationProperty());
   }
 
   /**
    * Returns true if this frame is transformed (e.g. has CSS or SVG transforms)
    * or if its parent is an SVG frame that has children-only transforms (e.g.
    * an SVG viewBox attribute) or if its transform-style is preserve-3d or
@@ -1718,35 +1722,47 @@ class nsIFrame : public nsQueryFrame {
    *
    */
   bool HasAnimationOfTransform() const;
 
   /**
    * Returns true if the frame is translucent or the frame has opacity
    * animations for the purposes of creating a stacking context.
    *
+   * @param aStyleDisplay:  This function needs style display struct.
+   *
+   * @param aStyleEffects:  This function needs style effects struct.
+   *
    * @param aEffectSet: This function may need to look up EffectSet property.
    *   If a caller already have one, pass it in can save property look up
-   *   time; otherwise, just left it as nullptr.
-   */
-  bool HasOpacity(mozilla::EffectSet* aEffectSet = nullptr) const {
-    return HasOpacityInternal(1.0f, aEffectSet);
+   *   time; otherwise, just leave it as nullptr.
+   */
+  bool HasOpacity(const nsStyleDisplay* aStyleDisplay,
+                  const nsStyleEffects* aStyleEffects,
+                  mozilla::EffectSet* aEffectSet = nullptr) const {
+    return HasOpacityInternal(1.0f, aStyleDisplay, aStyleEffects, aEffectSet);
   }
   /**
    * Returns true if the frame is translucent for display purposes.
    *
+   * @param aStyleDisplay:  This function needs style display struct.
+   *
+   * @param aStyleEffects:  This function needs style effects struct.
+   *
    * @param aEffectSet: This function may need to look up EffectSet property.
    *   If a caller already have one, pass it in can save property look up
-   *   time; otherwise, just left it as nullptr.
-   */
-  bool HasVisualOpacity(mozilla::EffectSet* aEffectSet = nullptr) const {
+   *   time; otherwise, just leave it as nullptr.
+   */
+  bool HasVisualOpacity(const nsStyleDisplay* aStyleDisplay,
+                        const nsStyleEffects* aStyleEffects,
+                        mozilla::EffectSet* aEffectSet = nullptr) const {
     // Treat an opacity value of 0.99 and above as opaque.  This is an
     // optimization aimed at Web content which use opacity:0.99 as a hint for
     // creating a stacking context only.
-    return HasOpacityInternal(0.99f, aEffectSet);
+    return HasOpacityInternal(0.99f, aStyleDisplay, aStyleEffects, aEffectSet);
   }
 
   /**
    * Return true if this frame might be using a transform getter.
    */
   virtual bool HasTransformGetter() const { return false; }
 
   /**
@@ -1764,24 +1780,28 @@ class nsIFrame : public nsQueryFrame {
   /**
    * Returns whether this frame will attempt to extend the 3d transforms of its
    * children. This requires transform-style: preserve-3d, as well as no
    * clipping or svg effects.
    *
    * @param aStyleDisplay:  If the caller has this->StyleDisplay(), providing
    *   it here will improve performance.
    *
+   * @param aStyleEffects:  If the caller has this->StyleEffects(), providing
+   *   it here will improve performance.
+   *
    * @param aEffectSet: This function may need to look up EffectSet property.
    *   If a caller already have one, pass it in can save property look up
-   *   time; otherwise, just left it as nullptr.
+   *   time; otherwise, just leave it as nullptr.
    */
   bool Extend3DContext(const nsStyleDisplay* aStyleDisplay,
+                       const nsStyleEffects* aStyleEffects,
                        mozilla::EffectSet* aEffectSet = nullptr) const;
   bool Extend3DContext(mozilla::EffectSet* aEffectSet = nullptr) const {
-    return Extend3DContext(StyleDisplay(), aEffectSet);
+    return Extend3DContext(StyleDisplay(), StyleEffects(), aEffectSet);
   }
 
   /**
    * Returns whether this frame has a parent that Extend3DContext() and has
    * its own transform (or hidden backface) to be combined with the parent's
    * transform.
    *
    * @param aStyleDisplay:  If the caller has this->StyleDisplay(), providing
@@ -1799,17 +1819,17 @@ class nsIFrame : public nsQueryFrame {
    * backface can safely be ignored if it could not be visible anyway.
    *
    */
   bool In3DContextAndBackfaceIsHidden() const;
 
   bool IsPreserve3DLeaf(const nsStyleDisplay* aStyleDisplay,
                         mozilla::EffectSet* aEffectSet = nullptr) const {
     return Combines3DTransformWithAncestors(aStyleDisplay) &&
-           !Extend3DContext(aStyleDisplay, aEffectSet);
+           !Extend3DContext(aStyleDisplay, StyleEffects(), aEffectSet);
   }
   bool IsPreserve3DLeaf(mozilla::EffectSet* aEffectSet = nullptr) const {
     return IsPreserve3DLeaf(StyleDisplay(), aEffectSet);
   }
 
   bool HasPerspective(const nsStyleDisplay* aStyleDisplay) const;
   bool HasPerspective() const { return HasPerspective(StyleDisplay()); }
 
@@ -3422,18 +3442,17 @@ class nsIFrame : public nsQueryFrame {
   bool IsVisibleOrCollapsedForPainting();
 
   /**
    * Determines if this frame is a stacking context.
    *
    * @param aIsPositioned The precomputed result of IsAbsPosContainingBlock
    * on the StyleDisplay().
    */
-  bool IsStackingContext(mozilla::EffectSet* aEffectSet,
-                         const nsStyleDisplay* aStyleDisplay,
+  bool IsStackingContext(const nsStyleDisplay* aStyleDisplay,
                          const nsStylePosition* aStylePosition,
                          const nsStyleEffects* aStyleEffects,
                          bool aIsPositioned);
   bool IsStackingContext();
 
   virtual bool HonorPrintBackgroundSettings() { return true; }
 
   /**
@@ -4028,17 +4047,17 @@ class nsIFrame : public nsQueryFrame {
   }
 
   void AddDisplayItem(nsDisplayItem* aItem);
   bool RemoveDisplayItem(nsDisplayItem* aItem);
   void RemoveDisplayItemDataForDeletion();
   bool HasDisplayItems();
   bool HasDisplayItem(nsDisplayItem* aItem);
 
-  bool ForceDescendIntoIfVisible() { return mForceDescendIntoIfVisible; }
+  bool ForceDescendIntoIfVisible() const { return mForceDescendIntoIfVisible; }
   void SetForceDescendIntoIfVisible(bool aForce) {
     mForceDescendIntoIfVisible = aForce;
   }
 
   bool BuiltDisplayList() { return mBuiltDisplayList; }
   void SetBuiltDisplayList(bool aBuilt) { mBuiltDisplayList = aBuilt; }
 
   bool IsFrameModified() { return mFrameIsModified; }
@@ -4420,17 +4439,18 @@ class nsIFrame : public nsQueryFrame {
 
   // Helper-functions for SortFrameList():
   template <bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
   static nsIFrame* SortedMerge(nsIFrame* aLeft, nsIFrame* aRight);
 
   template <bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
   static nsIFrame* MergeSort(nsIFrame* aSource);
 
-  bool HasOpacityInternal(float aThreshold,
+  bool HasOpacityInternal(float aThreshold, const nsStyleDisplay* aStyleDisplay,
+                          const nsStyleEffects* aStyleEffects,
                           mozilla::EffectSet* aEffectSet = nullptr) const;
 
   // Maps mClass to LayoutFrameType.
   static const mozilla::LayoutFrameType sLayoutFrameTypes[
 #define FRAME_ID(...) 1 +
 #define ABSTRACT_FRAME_ID(...)
 #include "nsFrameIdList.h"
 #undef FRAME_ID
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -1344,30 +1344,38 @@ void nsDisplayListBuilder::EnterPresShel
 
   bool pointerEventsNone = aPointerEventsNoneDoc;
   if (IsInSubdocument()) {
     pointerEventsNone |= mPresShellStates[mPresShellStates.Length() - 2]
                              .mInsidePointerEventsNoneDoc;
   }
   state->mInsidePointerEventsNoneDoc = pointerEventsNone;
 
-  if (!buildCaret) return;
+  state->mPresShellIgnoreScrollFrame =
+      state->mPresShell->IgnoringViewportScrolling()
+          ? state->mPresShell->GetRootScrollFrame()
+          : nullptr;
+
+  nsPresContext* pc = aReferenceFrame->PresContext();
+  nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell();
+  if (docShell) {
+    docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed);
+  }
+
+  mIsInChromePresContext = pc->IsChrome();
+
+  if (!buildCaret) {
+    return;
+  }
 
   RefPtr<nsCaret> caret = state->mPresShell->GetCaret();
   state->mCaretFrame = caret->GetPaintGeometry(&state->mCaretRect);
   if (state->mCaretFrame) {
     MarkFrameForDisplay(state->mCaretFrame, aReferenceFrame);
   }
-
-  nsPresContext* pc = aReferenceFrame->PresContext();
-  nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell();
-  if (docShell) {
-    docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed);
-  }
-  mIsInChromePresContext = pc->IsChrome();
 }
 
 // A non-blank paint is a paint that does not just contain the canvas
 // background.
 static bool DisplayListIsNonBlank(nsDisplayList* aList) {
   for (nsDisplayItem* i = aList->GetBottom(); i != nullptr; i = i->GetAbove()) {
     switch (i->GetType()) {
       case DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO:
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -792,16 +792,25 @@ class nsDisplayListBuilder {
   /**
    * Get the rectangle we're supposed to draw the caret into.
    */
   const nsRect& GetCaretRect() { return CurrentPresShellState()->mCaretRect; }
   /**
    * Get the caret associated with the current presshell.
    */
   nsCaret* GetCaret();
+
+  /**
+   * Returns the root scroll frame for the current PresShell, if the PresShell
+   * is ignoring viewport scrolling.
+   */
+  nsIFrame* GetPresShellIgnoreScrollFrame() {
+    return CurrentPresShellState()->mPresShellIgnoreScrollFrame;
+  }
+
   /**
    * Notify the display list builder that we're entering a presshell.
    * aReferenceFrame should be a frame in the new presshell.
    * aPointerEventsNoneDoc should be set to true if the frame generating this
    * document is pointer-events:none.
    */
   void EnterPresShell(nsIFrame* aReferenceFrame,
                       bool aPointerEventsNoneDoc = false);
@@ -1828,16 +1837,17 @@ class nsDisplayListBuilder {
     mozilla::Maybe<OutOfFlowDisplayData> mFixedBackgroundDisplayData;
     uint32_t mFirstFrameMarkedForDisplay;
     uint32_t mFirstFrameWithOOFData;
     bool mIsBackgroundOnly;
     // This is a per-document flag turning off event handling for all content
     // in the document, and is set when we enter a subdocument for a pointer-
     // events:none frame.
     bool mInsidePointerEventsNoneDoc;
+    nsIFrame* mPresShellIgnoreScrollFrame;
   };
 
   PresShellState* CurrentPresShellState() {
     NS_ASSERTION(mPresShellStates.Length() > 0,
                  "Someone forgot to enter a presshell");
     return &mPresShellStates[mPresShellStates.Length() - 1];
   }
 
--- a/netwerk/base/mozurl/Cargo.toml
+++ b/netwerk/base/mozurl/Cargo.toml
@@ -1,10 +1,10 @@
 [package]
 name = "mozurl"
 version = "0.0.1"
 authors = ["Nika Layzell <nika@thelayzells.com>"]
 
 [dependencies]
 url = "1.7.2"
-nsstring = { path = "../../../servo/support/gecko/nsstring" }
 nserror = { path = "../../../xpcom/rust/nserror" }
+nsstring = { path = "../../../xpcom/rust/nsstring" }
 xpcom = { path = "../../../xpcom/rust/xpcom" }
--- a/netwerk/base/rust-helper/Cargo.toml
+++ b/netwerk/base/rust-helper/Cargo.toml
@@ -1,8 +1,8 @@
 [package]
 name = "netwerk_helper"
 version = "0.0.1"
 authors = ["Jeff Hemphill <jthemphill@mozilla.com>"]
 
 [dependencies]
 nserror = { path = "../../../xpcom/rust/nserror" }
-nsstring = { path = "../../../servo/support/gecko/nsstring" }
+nsstring = { path = "../../../xpcom/rust/nsstring" }
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,48 +19,39 @@
       "dev": true,
       "requires": {
         "chalk": "^2.0.0",
         "esutils": "^2.0.2",
         "js-tokens": "^4.0.0"
       }
     },
     "acorn": {
-      "version": "5.7.3",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
-      "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.5.tgz",
+      "integrity": "sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg==",
       "dev": true
     },
     "acorn-jsx": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz",
-      "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==",
-      "dev": true,
-      "requires": {
-        "acorn": "^5.0.3"
-      }
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
+      "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==",
+      "dev": true
     },
     "ajv": {
-      "version": "6.5.4",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz",
-      "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==",
+      "version": "6.6.2",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz",
+      "integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==",
       "dev": true,
       "requires": {
         "fast-deep-equal": "^2.0.1",
         "fast-json-stable-stringify": "^2.0.0",
         "json-schema-traverse": "^0.4.1",
         "uri-js": "^4.2.2"
       }
     },
-    "ajv-keywords": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
-      "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
-      "dev": true
-    },
     "ansi-escapes": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
       "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==",
       "dev": true
     },
     "ansi-regex": {
       "version": "3.0.0",
@@ -91,35 +82,20 @@
       "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
       "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
       "dev": true,
       "requires": {
         "define-properties": "^1.1.2",
         "es-abstract": "^1.7.0"
       }
     },
-    "array-union": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
-      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
-      "dev": true,
-      "requires": {
-        "array-uniq": "^1.0.1"
-      }
-    },
-    "array-uniq": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
-      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
-      "dev": true
-    },
-    "arrify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
-      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+    "astral-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
+      "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
       "dev": true
     },
     "balanced-match": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
       "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
       "dev": true
     },
@@ -202,39 +178,33 @@
       "dev": true
     },
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
       "dev": true
     },
-    "core-util-is": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
-      "dev": true
-    },
     "cross-spawn": {
       "version": "6.0.5",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
       "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
       "dev": true,
       "requires": {
         "nice-try": "^1.0.4",
         "path-key": "^2.0.1",
         "semver": "^5.5.0",
         "shebang-command": "^1.2.0",
         "which": "^1.2.9"
       }
     },
     "debug": {
-      "version": "3.2.5",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz",
-      "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+      "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
       "dev": true,
       "requires": {
         "ms": "^2.1.1"
       }
     },
     "deep-is": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@@ -245,31 +215,16 @@
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
       "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
       "dev": true,
       "requires": {
         "object-keys": "^1.0.12"
       }
     },
-    "del": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
-      "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
-      "dev": true,
-      "requires": {
-        "globby": "^5.0.0",
-        "is-path-cwd": "^1.0.0",
-        "is-path-in-cwd": "^1.0.0",
-        "object-assign": "^4.0.1",
-        "pify": "^2.0.0",
-        "pinkie-promise": "^2.0.0",
-        "rimraf": "^2.2.8"
-      }
-    },
     "doctrine": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
       "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
       "dev": true,
       "requires": {
         "esutils": "^2.0.2"
       }
@@ -288,19 +243,19 @@
           "version": "1.1.3",
           "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
           "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
           "dev": true
         }
       }
     },
     "domelementtype": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
-      "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+      "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
       "dev": true
     },
     "domhandler": {
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
       "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
       "dev": true,
       "requires": {
@@ -313,32 +268,33 @@
       "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
       "dev": true,
       "requires": {
         "dom-serializer": "0",
         "domelementtype": "1"
       }
     },
     "entities": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
-      "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+      "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
       "dev": true
     },
     "es-abstract": {
-      "version": "1.12.0",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
-      "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
+      "version": "1.13.0",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
+      "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
       "dev": true,
       "requires": {
-        "es-to-primitive": "^1.1.1",
+        "es-to-primitive": "^1.2.0",
         "function-bind": "^1.1.1",
-        "has": "^1.0.1",
-        "is-callable": "^1.1.3",
-        "is-regex": "^1.0.4"
+        "has": "^1.0.3",
+        "is-callable": "^1.1.4",
+        "is-regex": "^1.0.4",
+        "object-keys": "^1.0.12"
       }
     },
     "es-to-primitive": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
       "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
       "dev": true,
       "requires": {
@@ -349,96 +305,97 @@
     },
     "escape-string-regexp": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
       "dev": true
     },
     "eslint": {
-      "version": "5.6.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.6.0.tgz",
-      "integrity": "sha512-/eVYs9VVVboX286mBK7bbKnO1yamUy2UCRjiY6MryhQL2PaaXCExsCQ2aO83OeYRhU2eCU/FMFP+tVMoOrzNrA==",
+      "version": "5.11.1",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.11.1.tgz",
+      "integrity": "sha512-gOKhM8JwlFOc2acbOrkYR05NW8M6DCMSvfcJiBB5NDxRE1gv8kbvxKaC9u69e6ZGEMWXcswA/7eKR229cEIpvg==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.0.0",
         "ajv": "^6.5.3",
         "chalk": "^2.1.0",
         "cross-spawn": "^6.0.5",
-        "debug": "^3.1.0",
+        "debug": "^4.0.1",
         "doctrine": "^2.1.0",
         "eslint-scope": "^4.0.0",
         "eslint-utils": "^1.3.1",
         "eslint-visitor-keys": "^1.0.0",
-        "espree": "^4.0.0",
+        "espree": "^5.0.0",
         "esquery": "^1.0.1",
         "esutils": "^2.0.2",
         "file-entry-cache": "^2.0.0",
         "functional-red-black-tree": "^1.0.1",
         "glob": "^7.1.2",
         "globals": "^11.7.0",
         "ignore": "^4.0.6",
         "imurmurhash": "^0.1.4",
         "inquirer": "^6.1.0",
-        "is-resolvable": "^1.1.0",
         "js-yaml": "^3.12.0",
         "json-stable-stringify-without-jsonify": "^1.0.1",
         "levn": "^0.3.0",
         "lodash": "^4.17.5",
         "minimatch": "^3.0.4",
         "mkdirp": "^0.5.1",
         "natural-compare": "^1.4.0",
         "optionator": "^0.8.2",
         "path-is-inside": "^1.0.2",
         "pluralize": "^7.0.0",
         "progress": "^2.0.0",
-        "regexpp": "^2.0.0",
+        "regexpp": "^2.0.1",
         "require-uncached": "^1.0.3",
         "semver": "^5.5.1",
         "strip-ansi": "^4.0.0",
         "strip-json-comments": "^2.0.1",
-        "table": "^4.0.3",
+        "table": "^5.0.2",
         "text-table": "^0.2.0"
       }
     },
     "eslint-plugin-html": {
-      "version": "4.0.6",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-4.0.6.tgz",
-      "integrity": "sha512-nj6A9oK+7BKnMm0E7dMRH3r75BfpkXtcVIb3pFC4AcDdBTNyg2NGxHXyFNT1emW4VsR7P2SZvRXXQtUR+kY08w==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-5.0.0.tgz",
+      "integrity": "sha512-f7p/7YQdgQUFVAX3nB4dnMQbrDeTalcA01PDhuvTLk0ZadCwM4Pb+639SRuqEf1zMkIxckLY+ckCr0hVP5zl6A==",
       "dev": true,
       "requires": {
-        "htmlparser2": "^3.8.2"
+        "htmlparser2": "^3.10.0"
       }
     },
     "eslint-plugin-mozilla": {
       "version": "file:tools/lint/eslint/eslint-plugin-mozilla",
       "dev": true,
       "requires": {
-        "htmlparser2": "3.9.2",
+        "htmlparser2": "3.10.0",
         "ini-parser": "0.0.2",
         "sax": "1.2.4"
       }
     },
     "eslint-plugin-no-unsanitized": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-3.0.2.tgz",
       "integrity": "sha512-JnwpoH8Sv4QOjrTDutENBHzSnyYtspdjtglYtqUtAHe6f6LLKqykJle+UwFPg23GGwt5hI3amS9CRDezW8GAww==",
       "dev": true
     },
     "eslint-plugin-react": {
-      "version": "7.11.1",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz",
-      "integrity": "sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw==",
+      "version": "7.12.2",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.12.2.tgz",
+      "integrity": "sha512-6F8uOJXOsWWWD3Mg8cvz4onsqEYp2LFZCFlgjaTAzbPLwqdwRCeK78unbuEaMXYPxq8paXCzTpoaDCwXBvC/gg==",
       "dev": true,
       "requires": {
         "array-includes": "^3.0.3",
         "doctrine": "^2.1.0",
         "has": "^1.0.3",
         "jsx-ast-utils": "^2.0.1",
-        "prop-types": "^15.6.2"
+        "object.fromentries": "^2.0.0",
+        "prop-types": "^15.6.2",
+        "resolve": "^1.9.0"
       }
     },
     "eslint-plugin-spidermonkey-js": {
       "version": "file:tools/lint/eslint/eslint-plugin-spidermonkey-js",
       "dev": true
     },
     "eslint-scope": {
       "version": "4.0.0",
@@ -458,23 +415,24 @@
     },
     "eslint-visitor-keys": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
       "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
       "dev": true
     },
     "espree": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz",
-      "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.0.tgz",
+      "integrity": "sha512-1MpUfwsdS9MMoN7ZXqAr9e9UKdVHDcvrJpyx7mm1WuQlx/ygErEQBzgi5Nh5qBHIoYweprhtMkTCb9GhcAIcsA==",
       "dev": true,
       "requires": {
-        "acorn": "^5.6.0",
-        "acorn-jsx": "^4.1.1"
+        "acorn": "^6.0.2",
+        "acorn-jsx": "^5.0.0",
+        "eslint-visitor-keys": "^1.0.0"
       }
     },
     "esprima": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
       "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
       "dev": true
     },
@@ -552,24 +510,24 @@
       "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
       "dev": true,
       "requires": {
         "flat-cache": "^1.2.1",
         "object-assign": "^4.0.1"
       }
     },
     "flat-cache": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
-      "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
+      "version": "1.3.4",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
+      "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==",
       "dev": true,
       "requires": {
         "circular-json": "^0.3.1",
-        "del": "^2.0.2",
         "graceful-fs": "^4.1.2",
+        "rimraf": "~2.6.2",
         "write": "^0.2.1"
       }
     },
     "fs.realpath": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
       "dev": true
@@ -596,39 +554,25 @@
         "inflight": "^1.0.4",
         "inherits": "2",
         "minimatch": "^3.0.4",
         "once": "^1.3.0",
         "path-is-absolute": "^1.0.0"
       }
     },
     "globals": {
-      "version": "11.7.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz",
-      "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==",
+      "version": "11.9.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz",
+      "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==",
       "dev": true
     },
-    "globby": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
-      "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
-      "dev": true,
-      "requires": {
-        "array-union": "^1.0.1",
-        "arrify": "^1.0.0",
-        "glob": "^7.0.3",
-        "object-assign": "^4.0.1",
-        "pify": "^2.0.0",
-        "pinkie-promise": "^2.0.0"
-      }
-    },
     "graceful-fs": {
-      "version": "4.1.11",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
-      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+      "version": "4.1.15",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
+      "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
       "dev": true
     },
     "has": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
       "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
       "dev": true,
       "requires": {
@@ -643,27 +587,27 @@
     },
     "has-symbols": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
       "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
       "dev": true
     },
     "htmlparser2": {
-      "version": "3.9.2",
-      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
-      "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
+      "version": "3.10.0",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.0.tgz",
+      "integrity": "sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ==",
       "dev": true,
       "requires": {
         "domelementtype": "^1.3.0",
         "domhandler": "^2.3.0",
         "domutils": "^1.5.1",
         "entities": "^1.1.1",
         "inherits": "^2.0.1",
-        "readable-stream": "^2.0.2"
+        "readable-stream": "^3.0.6"
       }
     },
     "iconv-lite": {
       "version": "0.4.24",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
       "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
       "dev": true,
       "requires": {
@@ -700,34 +644,51 @@
     },
     "ini-parser": {
       "version": "0.0.2",
       "resolved": "https://registry.npmjs.org/ini-parser/-/ini-parser-0.0.2.tgz",
       "integrity": "sha1-+kF4flZ3Y7P/Zdel2alO23QHh+8=",
       "dev": true
     },
     "inquirer": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz",
-      "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==",
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.1.tgz",
+      "integrity": "sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg==",
       "dev": true,
       "requires": {
         "ansi-escapes": "^3.0.0",
         "chalk": "^2.0.0",
         "cli-cursor": "^2.1.0",
         "cli-width": "^2.0.0",
         "external-editor": "^3.0.0",
         "figures": "^2.0.0",
         "lodash": "^4.17.10",
         "mute-stream": "0.0.7",
         "run-async": "^2.2.0",
         "rxjs": "^6.1.0",
         "string-width": "^2.1.0",
-        "strip-ansi": "^4.0.0",
+        "strip-ansi": "^5.0.0",
         "through": "^2.3.6"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz",
+          "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==",
+          "dev": true
+        },
+        "strip-ansi": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz",
+          "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^4.0.0"
+          }
+        }
       }
     },
     "is-callable": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
       "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
       "dev": true
     },
@@ -738,76 +699,40 @@
       "dev": true
     },
     "is-fullwidth-code-point": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
       "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
       "dev": true
     },
-    "is-path-cwd": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
-      "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
-      "dev": true
-    },
-    "is-path-in-cwd": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
-      "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
-      "dev": true,
-      "requires": {
-        "is-path-inside": "^1.0.0"
-      }
-    },
-    "is-path-inside": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
-      "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
-      "dev": true,
-      "requires": {
-        "path-is-inside": "^1.0.1"
-      }
-    },
     "is-promise": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
       "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
       "dev": true
     },
     "is-regex": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
       "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
       "dev": true,
       "requires": {
         "has": "^1.0.1"
       }
     },
-    "is-resolvable": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
-      "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
-      "dev": true
-    },
     "is-symbol": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
       "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
       "dev": true,
       "requires": {
         "has-symbols": "^1.0.0"
       }
     },
-    "isarray": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-      "dev": true
-    },
     "isexe": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
       "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
       "dev": true
     },
     "js-tokens": {
       "version": "4.0.0",
@@ -904,17 +829,17 @@
     "ms": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
       "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
       "dev": true
     },
     "mute-stream": {
       "version": "0.0.7",
-      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+      "resolved": "http://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
       "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
       "dev": true
     },
     "natural-compare": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
       "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
       "dev": true
@@ -932,16 +857,28 @@
       "dev": true
     },
     "object-keys": {
       "version": "1.0.12",
       "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
       "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
       "dev": true
     },
+    "object.fromentries": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz",
+      "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.2",
+        "es-abstract": "^1.11.0",
+        "function-bind": "^1.1.1",
+        "has": "^1.0.1"
+      }
+    },
     "once": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
       "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
       "dev": true,
       "requires": {
         "wrappy": "1"
       }
@@ -966,81 +903,60 @@
         "levn": "~0.3.0",
         "prelude-ls": "~1.1.2",
         "type-check": "~0.3.2",
         "wordwrap": "~1.0.0"
       }
     },
     "os-tmpdir": {
       "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
       "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
       "dev": true
     },
     "path-is-absolute": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
       "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
       "dev": true
     },
     "path-is-inside": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
       "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
       "dev": true
     },
     "path-key": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
       "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
       "dev": true
     },
-    "pify": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-      "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+    "path-parse": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
       "dev": true
     },
-    "pinkie": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
-      "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
-      "dev": true
-    },
-    "pinkie-promise": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
-      "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
-      "dev": true,
-      "requires": {
-        "pinkie": "^2.0.0"
-      }
-    },
     "pluralize": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
       "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
       "dev": true
     },
     "prelude-ls": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
       "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
       "dev": true
     },
-    "process-nextick-args": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
-      "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
-      "dev": true
-    },
     "progress": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
-      "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=",
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+      "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
       "dev": true
     },
     "prop-types": {
       "version": "15.6.2",
       "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
       "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==",
       "dev": true,
       "requires": {
@@ -1050,46 +966,51 @@
     },
     "punycode": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
       "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
       "dev": true
     },
     "readable-stream": {
-      "version": "2.3.6",
-      "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
-      "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz",
+      "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==",
       "dev": true,
       "requires": {
-        "core-util-is": "~1.0.0",
-        "inherits": "~2.0.3",
-        "isarray": "~1.0.0",
-        "process-nextick-args": "~2.0.0",
-        "safe-buffer": "~5.1.1",
-        "string_decoder": "~1.1.1",
-        "util-deprecate": "~1.0.1"
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
       }
     },
     "regexpp": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.0.tgz",
-      "integrity": "sha512-g2FAVtR8Uh8GO1Nv5wpxW7VFVwHcCEr4wyA8/MHiRkO8uHoR5ntAA8Uq3P1vvMTX/BeQiRVSpDGLd+Wn5HNOTA==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
+      "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
       "dev": true
     },
     "require-uncached": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+      "resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
       "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
       "dev": true,
       "requires": {
         "caller-path": "^0.1.0",
         "resolve-from": "^1.0.0"
       }
     },
+    "resolve": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz",
+      "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==",
+      "dev": true,
+      "requires": {
+        "path-parse": "^1.0.6"
+      }
+    },
     "resolve-from": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
       "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
       "dev": true
     },
     "restore-cursor": {
       "version": "2.0.0",
@@ -1097,22 +1018,22 @@
       "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
       "dev": true,
       "requires": {
         "onetime": "^2.0.0",
         "signal-exit": "^3.0.2"
       }
     },
     "rimraf": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
-      "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+      "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
       "dev": true,
       "requires": {
-        "glob": "^7.0.5"
+        "glob": "^7.1.3"
       }
     },
     "run-async": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
       "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
       "dev": true,
       "requires": {
@@ -1142,19 +1063,19 @@
     },
     "sax": {
       "version": "1.2.4",
       "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
       "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
       "dev": true
     },
     "semver": {
-      "version": "5.5.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
-      "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==",
+      "version": "5.6.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+      "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
       "dev": true
     },
     "shebang-command": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
       "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
       "dev": true,
       "requires": {
@@ -1169,44 +1090,46 @@
     },
     "signal-exit": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
       "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
       "dev": true
     },
     "slice-ansi": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
-      "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.0.0.tgz",
+      "integrity": "sha512-4j2WTWjp3GsZ+AOagyzVbzp4vWGtZ0hEZ/gDY/uTvm6MTxUfTUIsnMIFb1bn8o0RuXiqUw15H1bue8f22Vw2oQ==",
       "dev": true,
       "requires": {
+        "ansi-styles": "^3.2.0",
+        "astral-regex": "^1.0.0",
         "is-fullwidth-code-point": "^2.0.0"
       }
     },
     "sprintf-js": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
       "dev": true
     },
     "string-width": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
       "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
       "dev": true,
       "requires": {
         "is-fullwidth-code-point": "^2.0.0",
         "strip-ansi": "^4.0.0"
       }
     },
     "string_decoder": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz",
+      "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==",
       "dev": true,
       "requires": {
         "safe-buffer": "~5.1.0"
       }
     },
     "strip-ansi": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
@@ -1227,26 +1150,24 @@
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
       "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
       "dev": true,
       "requires": {
         "has-flag": "^3.0.0"
       }
     },
     "table": {
-      "version": "4.0.3",
-      "resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz",
-      "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==",
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/table/-/table-5.1.1.tgz",
+      "integrity": "sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw==",
       "dev": true,
       "requires": {
-        "ajv": "^6.0.1",
-        "ajv-keywords": "^3.0.0",
-        "chalk": "^2.1.0",
-        "lodash": "^4.17.4",
-        "slice-ansi": "1.0.0",
+        "ajv": "^6.6.1",
+        "lodash": "^4.17.11",
+        "slice-ansi": "2.0.0",
         "string-width": "^2.1.1"
       }
     },
     "text-table": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
       "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
       "dev": true
--- a/package.json
+++ b/package.json
@@ -1,17 +1,17 @@
 {
   "name": "mozilla-central",
   "description": "This package file is for node modules used in mozilla-central",
   "repository": {},
   "license": "MPL-2.0",
   "dependencies": {},
   "devDependencies": {
-    "eslint": "5.6.0",
-    "eslint-plugin-html": "4.0.6",
+    "eslint": "5.11.1",
+    "eslint-plugin-html": "5.0.0",
     "eslint-plugin-mozilla": "file:tools/lint/eslint/eslint-plugin-mozilla",
     "eslint-plugin-no-unsanitized": "3.0.2",
-    "eslint-plugin-react": "7.11.1",
+    "eslint-plugin-react": "7.12.2",
     "eslint-plugin-spidermonkey-js": "file:tools/lint/eslint/eslint-plugin-spidermonkey-js"
   },
   "notes(private)": "We don't want to publish to npm, so this is marked as private",
   "private": true
 }
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -42,17 +42,17 @@ hashglobe = { path = "../hashglobe" }
 html5ever = {version = "0.22", optional = true}
 itertools = "0.7.6"
 itoa = "0.4"
 lazy_static = "1"
 log = "0.4"
 malloc_size_of = { path = "../malloc_size_of" }
 malloc_size_of_derive = { path = "../malloc_size_of_derive" }
 matches = "0.1"
-nsstring = {path = "../../support/gecko/nsstring", optional = true}
+nsstring = {path = "../../../xpcom/rust/nsstring/", optional = true}
 num_cpus = {version = "1.1.0", optional = true}
 num-integer = "0.1"
 num-traits = "0.2"
 num-derive = "0.2"
 ordered-float = "1.0"
 owning_ref = "0.3.3"
 parking_lot = "0.6"
 precomputed-hash = "0.1.1"
--- a/servo/ports/geckolib/Cargo.toml
+++ b/servo/ports/geckolib/Cargo.toml
@@ -14,16 +14,16 @@ gecko_debug = ["style/gecko_debug", "nss
 
 [dependencies]
 atomic_refcell = "0.1"
 cssparser = "0.25"
 cstr = "0.1.2"
 libc = "0.2"
 log = {version = "0.4", features = ["release_max_level_info"]}
 malloc_size_of = {path = "../../components/malloc_size_of"}
-nsstring = {path = "../../support/gecko/nsstring"}
+nsstring = {path = "../../../xpcom/rust/nsstring/"}
 num-traits = "0.2"
 parking_lot = "0.6"
 selectors = {path = "../../components/selectors"}
 servo_arc = {path = "../../components/servo_arc"}
 smallvec = "0.6"
 style = {path = "../../components/style", features = ["gecko"]}
 style_traits = {path = "../../components/style_traits"}
--- a/taskcluster/taskgraph/actions/create_interactive.py
+++ b/taskcluster/taskgraph/actions/create_interactive.py
@@ -53,16 +53,18 @@ SCOPE_WHITELIST = [
     # public downloads are OK
     re.compile(r'^docker-worker:relengapi-proxy:tooltool.download.public$'),
     # level-appropriate secrets are generally necessary to run a task; these
     # also are "not that secret" - most of them are built into the resulting
     # binary and could be extracted by someone with `strings`.
     re.compile(r'^secrets:get:project/releng/gecko/build/level-[0-9]/\*'),
     # ptracing is generally useful for interactive tasks, too!
     re.compile(r'^docker-worker:feature:allowPtrace$'),
+    # docker-worker capabilities include loopback devices
+    re.compile(r'^docker-worker:capability:device:.*$'),
 ]
 
 
 def context(params):
     # available for any docker-worker tasks at levels 1, 2; and for
     # test tasks on level 3 (level-3 builders are firewalled off)
     if int(params['level']) < 3:
         return [{'worker-implementation': 'docker-worker'}]
--- a/testing/marionette/browser.js
+++ b/testing/marionette/browser.js
@@ -269,19 +269,20 @@ browser.Context = class {
   getTabModalUI() {
     let br = this.contentBrowser;
     if (!br.hasAttribute("tabmodalPromptShowing")) {
       return null;
     }
 
     // The modal is a direct sibling of the browser element.
     // See tabbrowser.xml's getTabModalPromptBox.
-    let modals = br.parentNode.getElementsByTagNameNS(
+    let modalElements = br.parentNode.getElementsByTagNameNS(
         XUL_NS, "tabmodalprompt");
-    return modals[0].ui;
+
+    return br.tabModalPromptBox.prompts.get(modalElements[0]).ui;
   }
 
   /**
    * Close the current window.
    *
    * @return {Promise}
    *     A promise which is resolved when the current window has been closed.
    */
--- a/testing/raptor/raptor/results.py
+++ b/testing/raptor/raptor/results.py
@@ -67,17 +67,18 @@ class RaptorResultsHandler():
         self.supporting_data.append(supporting_data)
 
     def summarize_and_output(self, test_config):
         # summarize the result data, write to file and output PERFHERDER_DATA
         LOG.info("summarizing raptor test results")
         output = Output(self.results, self.supporting_data)
         output.summarize()
         output.summarize_screenshots(self.images)
-        if self.supporting_data is not None:
+        # only dump out supporting data (i.e. power) if actual Raptor test completed
+        if self.supporting_data is not None and len(self.results) != 0:
             output.summarize_supporting_data()
             output.output_supporting_data()
         return output.output()
 
 
 class RaptorTestResult():
     """Single Raptor test result class"""
 
rename from toolkit/components/prompts/content/tabprompts.xml
rename to toolkit/components/prompts/content/tabprompts.jsm
--- a/toolkit/components/prompts/content/tabprompts.xml
+++ b/toolkit/components/prompts/content/tabprompts.jsm
@@ -1,353 +1,311 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+/* This Source Code Form is subject to the terms of the Mozilla Public
+  * License, v. 2.0. If a copy of the MPL was not distributed with this
+  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-<!-- This file is imported into the browser window, and expects various variables,
-     e.g. Ci, Services, to be available. -->
+"use strict";
 
-<!DOCTYPE bindings [
-<!ENTITY % commonDialogDTD  SYSTEM "chrome://global/locale/commonDialog.dtd">
-<!ENTITY % dialogOverlayDTD SYSTEM "chrome://global/locale/dialogOverlay.dtd">
-%commonDialogDTD;
-%dialogOverlayDTD;
-]>
+var EXPORTED_SYMBOLS = [
+  "TabModalPrompt",
+];
 
-<bindings id="tabPrompts"
-   xmlns="http://www.mozilla.org/xbl"
-   xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-   xmlns:xbl="http://www.mozilla.org/xbl">
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 
-  <binding id="tabmodalprompt">
-    <xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-                 role="dialog"
-                 aria-describedby="infoBody">
-
-        <!-- This is based on the guts of commonDialog.xul -->
-        <spacer flex="1"/>
+var TabModalPrompt = class {
+  constructor(win) {
+    this.win = win;
+    let newPrompt = this.element = win.document.createXULElement("tabmodalprompt");
+    newPrompt.setAttribute("role", "dialog");
+    let randomIdSuffix = Math.random().toString(32).substr(2);
+    newPrompt.setAttribute("aria-describedby", `infoBody-${randomIdSuffix}`);
+    newPrompt.appendChild(win.MozXULElement.parseXULToFragment(`
+      <spacer flex="1"/>
         <hbox pack="center">
-            <vbox anonid="mainContainer" class="tabmodalprompt-mainContainer">
-                <grid class="tabmodalprompt-topContainer" flex="1">
-                    <columns>
-                        <column/>
-                        <column flex="1"/>
-                    </columns>
-
-                    <rows>
-                        <vbox anonid="infoContainer" align="center" pack="center" flex="1">
-                            <description anonid="infoTitle" class="infoTitle" hidden="true" />
-                            <description anonid="infoBody" class="infoBody"/>
-                        </vbox>
+          <vbox class="tabmodalprompt-mainContainer">
+            <grid class="tabmodalprompt-topContainer" flex="1">
+              <columns>
+                <column/>
+                <column flex="1"/>
+              </columns>
 
-                        <row anonid="loginContainer" hidden="true" align="center">
-                            <label anonid="loginLabel" value="&editfield0.label;" control="loginTextbox"/>
-                            <textbox anonid="loginTextbox"/>
-                        </row>
+              <rows class="tabmodalprompt-rows">
+                <vbox class="tabmodalprompt-infoContainer" align="center" pack="center" flex="1">
+                  <description class="tabmodalprompt-infoTitle infoTitle" hidden="true" />
+                  <description class="tabmodalprompt-infoBody infoBody" id="infoBody-${randomIdSuffix}"/>
+                </vbox>
 
-                        <row anonid="password1Container" hidden="true" align="center">
-                            <label anonid="password1Label" value="&editfield1.label;" control="password1Textbox"/>
-                            <textbox anonid="password1Textbox" type="password"/>
-                        </row>
+                <row class="tabmodalprompt-loginContainer" hidden="true" align="center">
+                  <label class="tabmodalprompt-loginLabel" value="&editfield0.label;" control="loginTextbox-${randomIdSuffix}"/>
+                  <textbox class="tabmodalprompt-loginTextbox" id="loginTextbox-${randomIdSuffix}"/>
+                </row>
 
-                        <row anonid="checkboxContainer" hidden="true">
-                            <spacer/>
-                            <checkbox anonid="checkbox"/>
-                        </row>
+                <row class="tabmodalprompt-password1Container" hidden="true" align="center">
+                  <label class="tabmodalprompt-password1Label" value="&editfield1.label;" control="password1Textbox-${randomIdSuffix}"/>
+                  <textbox class="tabmodalprompt-password1Textbox" type="password" id="password1Textbox-${randomIdSuffix}"/>
+                </row>
 
-                        <xbl:children includes="row"/>
-                    </rows>
-                </grid>
-                <xbl:children/>
-                <hbox class="tabmodalprompt-buttonContainer">
-#ifdef XP_UNIX
-                    <button anonid="button3" hidden="true"/>
-                    <button anonid="button2" hidden="true"/>
-                    <spacer anonid="buttonSpacer" flex="1"/>
-                    <button anonid="button1" label="&cancelButton.label;"/>
-                    <button anonid="button0" label="&okButton.label;"/>
-#else
-                    <button anonid="button3" hidden="true"/>
-                    <spacer anonid="buttonSpacer" flex="1"/>
-                    <button anonid="button0" label="&okButton.label;"/>
-                    <button anonid="button2" hidden="true"/>
-                    <button anonid="button1" label="&cancelButton.label;"/>
-#endif
-                </hbox>
-            </vbox>
-        </hbox>
-        <spacer flex="2"/>
-    </xbl:content>
+                <row class="tabmodalprompt-checkboxContainer" hidden="true">
+                  <spacer/>
+                  <checkbox class="tabmodalprompt-checkbox"/>
+                </row>
 
-    <implementation>
-        <constructor>
-        <![CDATA[
-            let self = this;
-            function getElement(anonid) {
-                return document.getAnonymousElementByAttribute(self, "anonid", anonid);
-            }
+                <!-- content goes here -->
+              </rows>
+            </grid>
+            <hbox class="tabmodalprompt-buttonContainer">
+              <button class="tabmodalprompt-button3" hidden="true"/>
+              <spacer class="tabmodalprompt-buttonSpacer" flex="1"/>
+              <button class="tabmodalprompt-button0" label="&okButton.label;"/>
+              <button class="tabmodalprompt-button2" hidden="true"/>
+              <button class="tabmodalprompt-button1" label="&cancelButton.label;"/>
+            </hbox>
+          </vbox>
+      </hbox>
+      <spacer flex="2"/>
+    `, ["chrome://global/locale/commonDialog.dtd", "chrome://global/locale/dialogOverlay.dtd"]));
 
-            this.ui = {
-                prompt: this,
-                loginContainer: getElement("loginContainer"),
-                loginTextbox: getElement("loginTextbox"),
-                loginLabel: getElement("loginLabel"),
-                password1Container: getElement("password1Container"),
-                password1Textbox: getElement("password1Textbox"),
-                password1Label: getElement("password1Label"),
-                infoBody: getElement("infoBody"),
-                infoTitle: getElement("infoTitle"),
-                infoIcon: null,
-                checkbox: getElement("checkbox"),
-                checkboxContainer: getElement("checkboxContainer"),
-                button3: getElement("button3"),
-                button2: getElement("button2"),
-                button1: getElement("button1"),
-                button0: getElement("button0"),
-                // focusTarget (for BUTTON_DELAY_ENABLE) not yet supported
-            };
+    this.ui = {
+      prompt: this,
+      promptContainer: this.element,
+      mainContainer: newPrompt.querySelector(".tabmodalprompt-mainContainer"),
+      loginContainer: newPrompt.querySelector(".tabmodalprompt-loginContainer"),
+      loginTextbox: newPrompt.querySelector(".tabmodalprompt-loginTextbox"),
+      loginLabel: newPrompt.querySelector(".tabmodalprompt-loginLabel"),
+      password1Container: newPrompt.querySelector(".tabmodalprompt-password1Container"),
+      password1Textbox: newPrompt.querySelector(".tabmodalprompt-password1Textbox"),
+      password1Label: newPrompt.querySelector(".tabmodalprompt-password1Label"),
+      infoContainer: newPrompt.querySelector(".tabmodalprompt-infoContainer"),
+      infoBody: newPrompt.querySelector(".tabmodalprompt-infoBody"),
+      infoTitle: newPrompt.querySelector(".tabmodalprompt-infoTitle"),
+      infoIcon: null,
+      rows: newPrompt.querySelector(".tabmodalprompt-rows"),
+      checkbox: newPrompt.querySelector(".tabmodalprompt-checkbox"),
+      checkboxContainer: newPrompt.querySelector(".tabmodalprompt-checkboxContainer"),
+      button3: newPrompt.querySelector(".tabmodalprompt-button3"),
+      button2: newPrompt.querySelector(".tabmodalprompt-button2"),
+      button1: newPrompt.querySelector(".tabmodalprompt-button1"),
+      button0: newPrompt.querySelector(".tabmodalprompt-button0"),
+      // focusTarget (for BUTTON_DELAY_ENABLE) not yet supported
+    };
 
-            this.ui.button0.addEventListener("command", this.onButtonClick.bind(this, 0));
-            this.ui.button1.addEventListener("command", this.onButtonClick.bind(this, 1));
-            this.ui.button2.addEventListener("command", this.onButtonClick.bind(this, 2));
-            this.ui.button3.addEventListener("command", this.onButtonClick.bind(this, 3));
-            // Anonymous wrapper used here because |Dialog| doesn't exist until init() is called!
-            this.ui.checkbox.addEventListener("command", function() { self.Dialog.onCheckbox(); });
-            this.isLive = false;
-        ]]>
-        </constructor>
-        <destructor>
-        <![CDATA[
-            if (this.isLive) {
-                this.abortPrompt();
-            }
-        ]]>
-        </destructor>
+    if (AppConstants.XP_UNIX) {
+      // Reorder buttons on Linux
+      let buttonContainer = newPrompt.querySelector(".tabmodalprompt-buttonContainer");
+      buttonContainer.appendChild(this.ui.button3);
+      buttonContainer.appendChild(this.ui.button2);
+      buttonContainer.appendChild(newPrompt.querySelector(".tabmodalprompt-buttonSpacer"));
+      buttonContainer.appendChild(this.ui.button1);
+      buttonContainer.appendChild(this.ui.button0);
+    }
+
+    this.ui.button0.addEventListener("command", this.onButtonClick.bind(this, 0));
+    this.ui.button1.addEventListener("command", this.onButtonClick.bind(this, 1));
+    this.ui.button2.addEventListener("command", this.onButtonClick.bind(this, 2));
+    this.ui.button3.addEventListener("command", this.onButtonClick.bind(this, 3));
+    // Anonymous wrapper used here because |Dialog| doesn't exist until init() is called!
+    this.ui.checkbox.addEventListener("command", () => { this.Dialog.onCheckbox(); });
 
-        <field name="ui"/>
-        <field name="args"/>
-        <field name="linkedTab"/>
-        <field name="onCloseCallback"/>
-        <field name="Dialog"/>
-        <field name="isLive"/>
-        <field name="availWidth"/>
-        <field name="availHeight"/>
-        <field name="minWidth"/>
-        <field name="minHeight"/>
+    /**
+     * Based on dialog.xml handlers
+     */
+    this.element.addEventListener("keypress", (event) => {
+      switch (event.keyCode) {
+        case KeyEvent.DOM_VK_RETURN:
+          this.onKeyAction("default", event);
+          break;
 
-        <method name="init">
-            <parameter name="args"/>
-            <parameter name="linkedTab"/>
-            <parameter name="onCloseCallback"/>
-            <body>
-            <![CDATA[
-                this.args = args;
-                this.linkedTab = linkedTab;
-                this.onCloseCallback = onCloseCallback;
+        case KeyEvent.DOM_VK_ESCAPE:
+          this.onKeyAction("cancel", event);
+          break;
 
-                if (args.enableDelay)
-                    throw "BUTTON_DELAY_ENABLE not yet supported for tab-modal prompts";
+        default:
+          if (AppConstants.platform == "macosx" && event.key == "." && event.metaKey) {
+            this.onKeyAction("cancel", event);
+          }
+          break;
+      }
+    }, { mozSystemGroup: true });
 
-                // We need to remove the prompt when the tab or browser window is closed or
-                // the page navigates, else we never unwind the event loop and that's sad times.
-                // Remember to cleanup in shutdownPrompt()!
-                this.isLive = true;
-                window.addEventListener("resize", this);
-                window.addEventListener("unload", this);
-                if (linkedTab) {
-                  linkedTab.addEventListener("TabClose", this);
-                }
-                // Note:
-                // nsPrompter.js or in e10s mode browser-parent.js call abortPrompt,
-                // when the domWindow, for which the prompt was created, generates
-                // a "pagehide" event.
+    this.element.addEventListener("focus", (event) => {
+      let bnum = this.args.defaultButtonNum || 0;
+      let defaultButton = this.ui["button" + bnum];
 
-                let tmp = {};
-                ChromeUtils.import("resource://gre/modules/CommonDialog.jsm", tmp);
-                this.Dialog = new tmp.CommonDialog(args, this.ui);
-                this.Dialog.onLoad(null);
-
-                // Display the tabprompt title that shows the prompt origin when
-                // the prompt origin is not the same as that of the top window.
-                if (!args.showAlertOrigin)
-                    this.ui.infoTitle.removeAttribute("hidden");
-
-                // TODO: should unhide buttonSpacer on Windows when there are 4 buttons.
-                //       Better yet, just drop support for 4-button dialogs. (bug 609510)
+      if (AppConstants.platform == "macosx") {
+        // On OS X, the default button always stays marked as such (until
+        // the entire prompt blurs).
+        defaultButton.setAttribute("default", "true");
+      } else {
+        // On other platforms, the default button is only marked as such
+        // when no other button has focus. XUL buttons on not-OSX will
+        // react to pressing enter as a command, so you can't trigger the
+        // default without tabbing to it or something that isn't a button.
+        let focusedDefault = (event.originalTarget == defaultButton);
+        let someButtonFocused = event.originalTarget.localName == "button" ||
+          event.originalTarget.localName == "toolbarbutton";
+        if (focusedDefault || !someButtonFocused) {
+          defaultButton.setAttribute("default", "true");
+        }
+      }
+    }, true);
 
-                this.onResize();
-            ]]>
-            </body>
-        </method>
+    this.element.addEventListener("blur", () => {
+      // If focus shifted to somewhere else in the browser, don't make
+      // the default button look active.
+      let bnum = this.args.defaultButtonNum || 0;
+      let button = this.ui["button" + bnum];
+      button.removeAttribute("default");
+    });
+  }
+
+  init(args, linkedTab, onCloseCallback) {
+    this.args = args;
+    this.linkedTab = linkedTab;
+    this.onCloseCallback = onCloseCallback;
+
+    if (args.enableDelay)
+      throw "BUTTON_DELAY_ENABLE not yet supported for tab-modal prompts";
 
-        <method name="shutdownPrompt">
-            <body>
-            <![CDATA[
-                // remove our event listeners
-                try {
-                    window.removeEventListener("resize", this);
-                    window.removeEventListener("unload", this);
-                    if (this.linkedTab) {
-                      this.linkedTab.removeEventListener("TabClose", this);
-                    }
-                } catch (e) { }
-                this.isLive = false;
-                // invoke callback
-                this.onCloseCallback();
-            ]]>
-            </body>
-        </method>
+    // We need to remove the prompt when the tab or browser window is closed or
+    // the page navigates, else we never unwind the event loop and that's sad times.
+    // Remember to cleanup in shutdownPrompt()!
+    this.win.addEventListener("resize", this);
+    this.win.addEventListener("unload", this);
+    if (linkedTab) {
+      linkedTab.addEventListener("TabClose", this);
+    }
+    // Note:
+    // nsPrompter.js or in e10s mode browser-parent.js call abortPrompt,
+    // when the domWindow, for which the prompt was created, generates
+    // a "pagehide" event.
 
-        <method name="abortPrompt">
-            <body>
-            <![CDATA[
-                // Called from other code when the page changes.
-                this.Dialog.abortPrompt();
-                this.shutdownPrompt();
-            ]]>
-            </body>
-        </method>
+    let tmp = {};
+    ChromeUtils.import("resource://gre/modules/CommonDialog.jsm", tmp);
+    this.Dialog = new tmp.CommonDialog(args, this.ui);
+    this.Dialog.onLoad(null);
 
-        <method name="handleEvent">
-            <parameter name="aEvent"/>
-            <body>
-            <![CDATA[
-                switch (aEvent.type) {
-                  case "resize":
-                    this.onResize();
-                    break;
-                  case "unload":
-                  case "TabClose":
-                    this.abortPrompt();
-                    break;
-                }
-            ]]>
-            </body>
-        </method>
+    // Display the tabprompt title that shows the prompt origin when
+    // the prompt origin is not the same as that of the top window.
+    if (!args.showAlertOrigin)
+      this.ui.infoTitle.removeAttribute("hidden");
+
+    // TODO: should unhide buttonSpacer on Windows when there are 4 buttons.
+    //       Better yet, just drop support for 4-button dialogs. (bug 609510)
+
+    this.onResize();
+  }
 
-        <method name="onResize">
-            <body>
-            <![CDATA[
-                let availWidth = this.clientWidth;
-                let availHeight = this.clientHeight;
-                if (availWidth == this.availWidth && availHeight == this.availHeight)
-                    return;
-                this.availWidth = availWidth;
-                this.availHeight = availHeight;
+  // Sadly this is needed to ensure all the bindings inside the <tabmodalprompt>
+  // are attached. This method had to be called by CommonDialog.jsm after
+  // it had set the visibility of each of the elements.
+  ensureXBLBindingAttached() {
+    for (let key in this.ui) {
+      if (this.ui[key] instanceof this.win.XULElement) {
+        if (this.ui[key].hidden) {
+          continue;
+        }
+        this.ui[key].clientTop;
+      }
+    }
+  }
 
-                let self = this;
-                function getElement(anonid) {
-                    return document.getAnonymousElementByAttribute(self, "anonid", anonid);
-                }
-                let main = getElement("mainContainer");
-                let info = getElement("infoContainer");
-                let body = this.ui.infoBody;
-
-                // cap prompt dimensions at 60% width and 60% height of content area
-                if (!this.minWidth)
-                  this.minWidth = parseInt(window.getComputedStyle(main).minWidth);
-                if (!this.minHeight)
-                  this.minHeight = parseInt(window.getComputedStyle(main).minHeight);
-                let maxWidth = Math.max(Math.floor(availWidth * 0.6), this.minWidth) +
-                               info.clientWidth - main.clientWidth;
-                let maxHeight = Math.max(Math.floor(availHeight * 0.6), this.minHeight) +
-                                info.clientHeight - main.clientHeight;
-                body.style.maxWidth = maxWidth + "px";
-                info.style.overflow = info.style.width = info.style.height = "";
+  shutdownPrompt() {
+    // remove our event listeners
+    try {
+      this.win.removeEventListener("resize", this);
+      this.win.removeEventListener("unload", this);
+      if (this.linkedTab) {
+        this.linkedTab.removeEventListener("TabClose", this);
+      }
+    } catch (e) {}
+    // invoke callback
+    this.onCloseCallback();
+    this.win = null;
+    this.ui = null;
+    // Intentionally not cleaning up |this.element| here --
+    // TabModalPromptBox.removePrompt() would need it and it might not
+    // be called yet -- see browser_double_close_tabs.js.
+  }
 
-                // when prompt text is too long, use scrollbars
-                if (info.clientWidth > maxWidth) {
-                    info.style.overflow = "auto";
-                    info.style.width = maxWidth + "px";
-                }
-                if (info.clientHeight > maxHeight) {
-                    info.style.overflow = "auto";
-                    info.style.height = maxHeight + "px";
-                }
-            ]]>
-            </body>
-        </method>
+  abortPrompt() {
+    // Called from other code when the page changes.
+    this.Dialog.abortPrompt();
+    this.shutdownPrompt();
+  }
+
+  handleEvent(aEvent) {
+    switch (aEvent.type) {
+      case "resize":
+        this.onResize();
+        break;
+      case "unload":
+      case "TabClose":
+        this.abortPrompt();
+        break;
+    }
+  }
 
-        <method name="onButtonClick">
-            <parameter name="buttonNum"/>
-            <body>
-            <![CDATA[
-                // We want to do all the work her asynchronously off a Gecko
-                // runnable, because of situations like the one described in
-                // https://bugzilla.mozilla.org/show_bug.cgi?id=1167575#c35 : we
-                // get here off processing of an OS event and will also process
-                // one more Gecko runnable before we break out of the event loop
-                // spin whoever posted the prompt is doing.  If we do all our
-                // work sync, we will exit modal state _before_ processing that
-                // runnable, and if exiting moral state posts a runnable we will
-                // incorrectly process that runnable before leaving our event
-                // loop spin.
-                Services.tm.dispatchToMainThread(() => {
-                    this.Dialog["onButton" + buttonNum]();
-                    this.shutdownPrompt();
-                  });
-            ]]>
-            </body>
-        </method>
+  onResize() {
+    let availWidth = this.clientWidth;
+    let availHeight = this.clientHeight;
+    if (availWidth == this.availWidth && availHeight == this.availHeight)
+      return;
+    this.availWidth = availWidth;
+    this.availHeight = availHeight;
+
+    let main = this.ui.mainContainer;
+    let info = this.ui.infoContainer;
+    let body = this.ui.infoBody;
 
-        <method name="onKeyAction">
-            <parameter name="action"/>
-            <parameter name="event"/>
-            <body>
-            <![CDATA[
-                if (event.defaultPrevented)
-                    return;
+    // cap prompt dimensions at 60% width and 60% height of content area
+    if (!this.minWidth)
+      this.minWidth = parseInt(this.win.getComputedStyle(main).minWidth);
+    if (!this.minHeight)
+      this.minHeight = parseInt(this.win.getComputedStyle(main).minHeight);
+    let maxWidth = Math.max(Math.floor(availWidth * 0.6), this.minWidth) +
+      info.clientWidth - main.clientWidth;
+    let maxHeight = Math.max(Math.floor(availHeight * 0.6), this.minHeight) +
+      info.clientHeight - main.clientHeight;
+    body.style.maxWidth = maxWidth + "px";
+    info.style.overflow = info.style.width = info.style.height = "";
 
-                event.stopPropagation();
-                if (action == "default") {
-                    let bnum = this.args.defaultButtonNum || 0;
-                    this.onButtonClick(bnum);
-                } else { // action == "cancel"
-                    this.onButtonClick(1); // Cancel button
-                }
-            ]]>
-            </body>
-        </method>
-    </implementation>
-
-    <handlers>
-        <!-- Based on dialog.xml handlers -->
-        <handler event="keypress" keycode="VK_RETURN"
-                 group="system" action="this.onKeyAction('default', event);"/>
-        <handler event="keypress" keycode="VK_ESCAPE"
-                 group="system" action="this.onKeyAction('cancel', event);"/>
-#ifdef XP_MACOSX
-        <handler event="keypress" key="." modifiers="meta"
-                 group="system" action="this.onKeyAction('cancel', event);"/>
-#endif
-        <handler event="focus" phase="capturing">
-            let bnum = this.args.defaultButtonNum || 0;
-            let defaultButton = this.ui["button" + bnum];
+    // when prompt text is too long, use scrollbars
+    if (info.clientWidth > maxWidth) {
+      info.style.overflow = "auto";
+      info.style.width = maxWidth + "px";
+    }
+    if (info.clientHeight > maxHeight) {
+      info.style.overflow = "auto";
+      info.style.height = maxHeight + "px";
+    }
+  }
 
-            let { AppConstants } =
-                ChromeUtils.import("resource://gre/modules/AppConstants.jsm", {});
-            if (AppConstants.platform == "macosx") {
-              // On OS X, the default button always stays marked as such (until
-              // the entire prompt blurs).
-              defaultButton.setAttribute("default", true);
-            } else {
-              // On other platforms, the default button is only marked as such
-              // when no other button has focus. XUL buttons on not-OSX will
-              // react to pressing enter as a command, so you can't trigger the
-              // default without tabbing to it or something that isn't a button.
-              let focusedDefault = (event.originalTarget == defaultButton);
-              let someButtonFocused = event.originalTarget.localName == "button" ||
-                                      event.originalTarget.localName == "toolbarbutton";
-              defaultButton.setAttribute("default", focusedDefault || !someButtonFocused);
-            }
-        </handler>
-        <handler event="blur">
-            // If focus shifted to somewhere else in the browser, don't make
-            // the default button look active.
-            let bnum = this.args.defaultButtonNum || 0;
-            let button = this.ui["button" + bnum];
-            button.setAttribute("default", false);
-        </handler>
-    </handlers>
+  onButtonClick(buttonNum) {
+    // We want to do all the work her asynchronously off a Gecko
+    // runnable, because of situations like the one described in
+    // https://bugzilla.mozilla.org/show_bug.cgi?id=1167575#c35 : we
+    // get here off processing of an OS event and will also process
+    // one more Gecko runnable before we break out of the event loop
+    // spin whoever posted the prompt is doing.  If we do all our
+    // work sync, we will exit modal state _before_ processing that
+    // runnable, and if exiting moral state posts a runnable we will
+    // incorrectly process that runnable before leaving our event
+    // loop spin.
+    Services.tm.dispatchToMainThread(() => {
+      this.Dialog["onButton" + buttonNum]();
+      this.shutdownPrompt();
+    });
+  }
 
-  </binding>
-</bindings>
+  onKeyAction(action, event) {
+    if (event.defaultPrevented)
+      return;
+
+    event.stopPropagation();
+    if (action == "default") {
+      let bnum = this.args.defaultButtonNum || 0;
+      this.onButtonClick(bnum);
+    } else { // action == "cancel"
+      this.onButtonClick(1); // Cancel button
+    }
+  }
+};
--- a/toolkit/components/prompts/jar.mn
+++ b/toolkit/components/prompts/jar.mn
@@ -4,9 +4,9 @@
 
 toolkit.jar:
    content/global/commonDialog.js             (content/commonDialog.js)
 *  content/global/commonDialog.xul            (content/commonDialog.xul)
    content/global/commonDialog.css            (content/commonDialog.css)
    content/global/selectDialog.js             (content/selectDialog.js)
    content/global/selectDialog.xul            (content/selectDialog.xul)
    content/global/tabprompts.css              (content/tabprompts.css)
-*  content/global/tabprompts.xml              (content/tabprompts.xml)
+   content/global/tabprompts.jsm              (content/tabprompts.jsm)
--- a/toolkit/components/prompts/src/CommonDialog.jsm
+++ b/toolkit/components/prompts/src/CommonDialog.jsm
@@ -133,16 +133,17 @@ CommonDialog.prototype = {
         }
         let infoBody = this.ui.infoBody;
         infoBody.appendChild(infoBody.ownerDocument.createTextNode(croppedMessage));
 
         let label = this.args.checkLabel;
         if (label) {
             // Only show the checkbox if label has a value.
             this.ui.checkboxContainer.hidden = false;
+            this.ui.checkboxContainer.clientTop; // style flush to assure binding is attached
             this.setLabelForNode(this.ui.checkbox, label);
             this.ui.checkbox.checked = this.args.checked;
         }
 
         // set the icon
         let icon = this.ui.infoIcon;
         if (icon)
             this.iconClass.forEach((el, idx, arr) => icon.classList.add(el));
@@ -156,16 +157,21 @@ CommonDialog.prototype = {
         let b = (this.args.defaultButtonNum || 0);
         let button = this.ui["button" + b];
 
         if (xulDialog)
             xulDialog.defaultButton = ["accept", "cancel", "extra1", "extra2"][b];
         else
             button.setAttribute("default", "true");
 
+        // For tab prompts, we will need to ensure its content bindings are attached.
+        if (!xulDialog) {
+            this.ui.prompt.ensureXBLBindingAttached();
+        }
+
         // Set default focus / selection.
         this.setDefaultFocus(true);
 
         if (this.args.enableDelay) {
             this.delayHelper = new EnableDelayHelper({
                 disableDialog: () => this.setButtonsEnabledState(false),
                 enableDialog: () => this.setButtonsEnabledState(true),
                 focusTarget: this.ui.focusTarget,
@@ -178,20 +184,23 @@ CommonDialog.prototype = {
                 Cc["@mozilla.org/sound;1"].
                 createInstance(Ci.nsISound).
                 playEventSound(this.soundID);
             }
         } catch (e) {
             Cu.reportError("Couldn't play common dialog event sound: " + e);
         }
 
-        let topic = "common-dialog-loaded";
-        if (!xulDialog)
-            topic = "tabmodal-dialog-loaded";
-        Services.obs.notifyObservers(this.ui.prompt, topic);
+        if (xulDialog) {
+            // ui.prompt is the window object of the dialog.
+            Services.obs.notifyObservers(this.ui.prompt, "common-dialog-loaded");
+        } else {
+            // ui.promptContainer is the <tabmodalprompt> element.
+            Services.obs.notifyObservers(this.ui.promptContainer, "tabmodal-dialog-loaded");
+        }
     },
 
     setLabelForNode(aNode, aLabel) {
         // This is for labels which may contain embedded access keys.
         // If we end in (&X) where X represents the access key, optionally preceded
         // by spaces and/or followed by the ':' character, store the access key and
         // remove the access key placeholder + leading spaces from the label.
         // Otherwise a character preceded by one but not two &s is the access key.
--- a/toolkit/components/prompts/test/chromeScript.js
+++ b/toolkit/components/prompts/test/chromeScript.js
@@ -81,18 +81,18 @@ function getSelectState(ui) {
 
 function getPromptState(ui) {
   let state = {};
   state.msg         = ui.infoBody.textContent;
   state.titleHidden = ui.infoTitle.getAttribute("hidden") == "true";
   state.textHidden  = ui.loginContainer.hidden;
   state.passHidden  = ui.password1Container.hidden;
   state.checkHidden = ui.checkboxContainer.hidden;
-  state.checkMsg    = ui.checkbox.label;
-  state.checked     = ui.checkbox.checked;
+  state.checkMsg    = state.checkHidden ? "" : ui.checkbox.label;
+  state.checked     = state.checkHidden ? false : ui.checkbox.checked;
   // tab-modal prompts don't have an infoIcon
   state.iconClass   = ui.infoIcon ? ui.infoIcon.className : null;
   state.textValue   = ui.loginTextbox.getAttribute("value");
   state.passValue   = ui.password1Textbox.getAttribute("value");
 
   state.butt0Label  = ui.button0.label;
   state.butt1Label  = ui.button1.label;
   state.butt2Label  = ui.button2.label;
@@ -114,19 +114,19 @@ function getPromptState(ui) {
   if (e == null) {
     state.focused = null;
   } else if (ui.button0.isSameNode(e)) {
     state.focused = "button0";
   } else if (ui.button1.isSameNode(e)) {
     state.focused = "button1";
   } else if (ui.button2.isSameNode(e)) {
     state.focused = "button2";
-  } else if (ui.loginTextbox.inputField.isSameNode(e)) {
+  } else if (e.isSameNode(ui.loginTextbox.inputField)) {
     state.focused = "textField";
-  } else if (ui.password1Textbox.inputField.isSameNode(e)) {
+  } else if (e.isSameNode(ui.password1Textbox.inputField)) {
     state.focused = "passField";
   } else if (ui.infoBody.isSameNode(e)) {
     state.focused = "infoBody";
   } else {
     state.focused = "ERROR: unexpected element focused: " + (e ? e.localName : "<null>");
   }
 
   return state;
--- a/toolkit/components/startup/tests/browser/head.js
+++ b/toolkit/components/startup/tests/browser/head.js
@@ -17,13 +17,13 @@ function waitForOnBeforeUnloadDialog(bro
       return;
     }
 
     browser.removeEventListener("DOMWillOpenModalDialog", onModalDialog, true);
 
     SimpleTest.waitForCondition(() => Services.focus.activeWindow == browser.ownerGlobal, function() {
       let stack = browser.parentNode;
       let dialogs = stack.getElementsByTagNameNS(XUL_NS, "tabmodalprompt");
-      let {button0, button1} = dialogs[0].ui;
+      let {button0, button1} = browser.tabModalPromptBox.prompts.get(dialogs[0]).ui;
       callback(button0, button1);
     }, "Waited too long for window with dialog to focus");
   }, true);
 }
--- a/toolkit/content/widgets/datetimebox.js
+++ b/toolkit/content/widgets/datetimebox.js
@@ -262,17 +262,17 @@ this.DateTimeInputBaseImplWidget = class
     field.setAttribute("disabled", this.mInputElement.disabled);
     // Set property as well for convenience.
     field.disabled = this.mInputElement.disabled;
     field.readOnly = this.mInputElement.readOnly;
     field.setAttribute("aria-label", aLabel);
 
     // Used to store the non-formatted value, cleared when value is
     // cleared.
-    // nsDateTimeControlFrame::HasBadInput() will read this to decide
+    // DateTimeInputTypeBase::HasBadInput() will read this to decide
     // if the input has value.
     field.setAttribute("value", "");
 
     if (aIsNumeric) {
       field.classList.add("numeric");
       // Maximum value allowed.
       field.setAttribute("min", aMinValue);
       // Minumim value allowed.
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -733,17 +733,16 @@ richlistitem {
 
 /*********** findbar ************/
 findbar {
   overflow-x: hidden;
 }
 
 /*********** tabmodalprompt ************/
 tabmodalprompt {
-  -moz-binding: url("chrome://global/content/tabprompts.xml#tabmodalprompt");
   overflow: hidden;
   text-shadow: none;
 }
 
 .button-highlightable-text:not([highlightable="true"]),
 .button-text[highlightable="true"],
 .menulist-highlightable-label:not([highlightable="true"]),
 .menulist-label[highlightable="true"],
--- a/toolkit/library/rust/shared/Cargo.toml
+++ b/toolkit/library/rust/shared/Cargo.toml
@@ -3,18 +3,18 @@ name = "gkrust-shared"
 version = "0.1.0"
 authors = ["nobody@mozilla.org"]
 license = "MPL-2.0"
 description = "Shared Rust code for libxul"
 
 [dependencies]
 geckoservo = { path = "../../../../servo/ports/geckolib", optional = true }
 mp4parse_capi = { path = "../../../../media/mp4parse-rust/mp4parse_capi" }
-nsstring = { path = "../../../../servo/support/gecko/nsstring" }
 nserror = { path = "../../../../xpcom/rust/nserror" }
+nsstring = { path = "../../../../xpcom/rust/nsstring" }
 netwerk_helper = { path = "../../../../netwerk/base/rust-helper" }
 xpcom = { path = "../../../../xpcom/rust/xpcom" }
 prefs_parser = { path = "../../../../modules/libpref/parser" }
 profiler_helper = { path = "../../../../tools/profiler/rust-helper", optional = true }
 mozurl = { path = "../../../../netwerk/base/mozurl" }
 webrender_bindings = { path = "../../../../gfx/webrender_bindings", optional = true }
 cubeb-pulse = { path = "../../../../media/libcubeb/cubeb-pulse-rs", optional = true, features=["pulse-dlopen"] }
 cubeb-sys = { version = "0.5.0", optional = true, features=["gecko-in-tree"] }
--- a/tools/lint/eslint/eslint-plugin-mozilla/manifest.tt
+++ b/tools/lint/eslint/eslint-plugin-mozilla/manifest.tt
@@ -1,10 +1,10 @@
 [
   {
     "algorithm": "sha512",
     "visibility": "public",
     "filename": "eslint-plugin-mozilla.tar.gz",
     "unpack": true,
-    "digest": "7b1a7ee0b4e91d7430f1e3377dc8075934b1385642af7d25d4342f5ad2291a3d24ee02366e493a5d7d88ff03d6949b52b7e03d90f46c54f3f6bf1c3edd795864",
-    "size": 4956648
+    "digest": "fe1e0e5d202bfe93fbcc7bef20ede85b14db4e05e4f30681aff7766cc4a839a65ed3e91fc2f7fc2c2139498b668f2e85ea8d2ea0b37de2b4347321380717287a",
+    "size": 4285163
   }
 ]
--- a/tools/lint/eslint/eslint-plugin-mozilla/package-lock.json
+++ b/tools/lint/eslint/eslint-plugin-mozilla/package-lock.json
@@ -1,522 +1,411 @@
 {
   "name": "eslint-plugin-mozilla",
   "version": "1.0.4",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "@babel/code-frame": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
+      "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
+      "dev": true,
+      "requires": {
+        "@babel/highlight": "^7.0.0"
+      }
+    },
+    "@babel/highlight": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
+      "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.0.0",
+        "esutils": "^2.0.2",
+        "js-tokens": "^4.0.0"
+      }
+    },
     "acorn": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz",
-      "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==",
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.5.tgz",
+      "integrity": "sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg==",
       "dev": true
     },
     "acorn-jsx": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz",
-      "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==",
-      "dev": true,
-      "requires": {
-        "acorn": "5.7.1"
-      }
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
+      "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==",
+      "dev": true
     },
     "ajv": {
-      "version": "6.5.2",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz",
-      "integrity": "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA==",
+      "version": "6.6.2",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz",
+      "integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==",
       "dev": true,
       "requires": {
-        "fast-deep-equal": "2.0.1",
-        "fast-json-stable-stringify": "2.0.0",
-        "json-schema-traverse": "0.4.1",
-        "uri-js": "4.2.2"
+        "fast-deep-equal": "^2.0.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
       }
     },
-    "ajv-keywords": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
-      "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
-      "dev": true
-    },
     "ansi-escapes": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
       "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==",
       "dev": true
     },
     "ansi-regex": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+      "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
       "dev": true
     },
     "ansi-styles": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-      "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
-      "dev": true
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "requires": {
+        "color-convert": "^1.9.0"
+      }
     },
     "argparse": {
       "version": "1.0.10",
       "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
       "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
       "dev": true,
       "requires": {
-        "sprintf-js": "1.0.3"
-      }
-    },
-    "array-union": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
-      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
-      "dev": true,
-      "requires": {
-        "array-uniq": "1.0.3"
+        "sprintf-js": "~1.0.2"
       }
     },
-    "array-uniq": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
-      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
-      "dev": true
-    },
-    "arrify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
-      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+    "astral-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
+      "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
       "dev": true
     },
-    "babel-code-frame": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
-      "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
-      "dev": true,
-      "requires": {
-        "chalk": "1.1.3",
-        "esutils": "2.0.2",
-        "js-tokens": "3.0.2"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "2.1.1"
-          }
-        }
-      }
-    },
     "balanced-match": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
       "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
       "dev": true
     },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
       "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
       "dev": true,
       "requires": {
-        "balanced-match": "1.0.0",
+        "balanced-match": "^1.0.0",
         "concat-map": "0.0.1"
       }
     },
     "browser-stdout": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
       "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
       "dev": true
     },
     "caller-path": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
       "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
       "dev": true,
       "requires": {
-        "callsites": "0.2.0"
+        "callsites": "^0.2.0"
       }
     },
     "callsites": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
       "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
       "dev": true
     },
     "chalk": {
       "version": "2.4.1",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
       "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
       "dev": true,
       "requires": {
-        "ansi-styles": "3.2.1",
-        "escape-string-regexp": "1.0.5",
-        "supports-color": "5.4.0"
-      },
-      "dependencies": {
-        "ansi-styles": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-          "dev": true,
-          "requires": {
-            "color-convert": "1.9.2"
-          }
-        },
-        "supports-color": {
-          "version": "5.4.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
-          "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
-          "dev": true,
-          "requires": {
-            "has-flag": "3.0.0"
-          }
-        }
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
       }
     },
     "chardet": {
-      "version": "0.4.2",
-      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
-      "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+      "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
       "dev": true
     },
     "circular-json": {
       "version": "0.3.3",
       "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
       "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
       "dev": true
     },
     "cli-cursor": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
       "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
       "dev": true,
       "requires": {
-        "restore-cursor": "2.0.0"
+        "restore-cursor": "^2.0.0"
       }
     },
     "cli-width": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
       "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
       "dev": true
     },
     "color-convert": {
-      "version": "1.9.2",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz",
-      "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==",
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
       "dev": true,
       "requires": {
-        "color-name": "1.1.1"
+        "color-name": "1.1.3"
       }
     },
     "color-name": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz",
-      "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=",
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
       "dev": true
     },
     "commander": {
       "version": "2.15.1",
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
       "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
       "dev": true
     },
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
       "dev": true
     },
-    "core-util-is": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
-    },
     "cross-spawn": {
       "version": "6.0.5",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
       "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
       "dev": true,
       "requires": {
-        "nice-try": "1.0.4",
-        "path-key": "2.0.1",
-        "semver": "5.5.0",
-        "shebang-command": "1.2.0",
-        "which": "1.3.1"
+        "nice-try": "^1.0.4",
+        "path-key": "^2.0.1",
+        "semver": "^5.5.0",
+        "shebang-command": "^1.2.0",
+        "which": "^1.2.9"
       }
     },
     "debug": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-      "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+      "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
       "dev": true,
       "requires": {
-        "ms": "2.0.0"
+        "ms": "^2.1.1"
       }
     },
     "deep-is": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
       "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
       "dev": true
     },
-    "define-properties": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
-      "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
-      "dev": true,
-      "requires": {
-        "foreach": "2.0.5",
-        "object-keys": "1.0.12"
-      }
-    },
-    "del": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
-      "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
-      "dev": true,
-      "requires": {
-        "globby": "5.0.0",
-        "is-path-cwd": "1.0.0",
-        "is-path-in-cwd": "1.0.1",
-        "object-assign": "4.1.1",
-        "pify": "2.3.0",
-        "pinkie-promise": "2.0.1",
-        "rimraf": "2.6.2"
-      }
-    },
     "diff": {
       "version": "3.5.0",
       "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
       "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
       "dev": true
     },
     "doctrine": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
       "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
       "dev": true,
       "requires": {
-        "esutils": "2.0.2"
+        "esutils": "^2.0.2"
       }
     },
     "dom-serializer": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
       "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
       "requires": {
-        "domelementtype": "1.1.3",
-        "entities": "1.1.1"
+        "domelementtype": "~1.1.1",
+        "entities": "~1.1.1"
       },
       "dependencies": {
         "domelementtype": {
           "version": "1.1.3",
           "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
           "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
         }
       }
     },
     "domelementtype": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
-      "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI="
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+      "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
     },
     "domhandler": {
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
       "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
       "requires": {
-        "domelementtype": "1.3.0"
+        "domelementtype": "1"
       }
     },
     "domutils": {
       "version": "1.7.0",
       "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
       "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
       "requires": {
-        "dom-serializer": "0.1.0",
-        "domelementtype": "1.3.0"
+        "dom-serializer": "0",
+        "domelementtype": "1"
       }
     },
     "entities": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
-      "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA="
-    },
-    "es-abstract": {
-      "version": "1.12.0",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
-      "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
-      "dev": true,
-      "requires": {
-        "es-to-primitive": "1.1.1",
-        "function-bind": "1.1.1",
-        "has": "1.0.3",
-        "is-callable": "1.1.4",
-        "is-regex": "1.0.4"
-      }
-    },
-    "es-to-primitive": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
-      "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
-      "dev": true,
-      "requires": {
-        "is-callable": "1.1.4",
-        "is-date-object": "1.0.1",
-        "is-symbol": "1.0.1"
-      }
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+      "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
     },
     "escape-string-regexp": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
       "dev": true
     },
     "eslint": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.3.0.tgz",
-      "integrity": "sha512-N/tCqlMKkyNvAvLu+zI9AqDasnSLt00K+Hu8kdsERliC9jYEc8ck12XtjvOXrBKu8fK6RrBcN9bat6Xk++9jAg==",
+      "version": "5.11.1",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.11.1.tgz",
+      "integrity": "sha512-gOKhM8JwlFOc2acbOrkYR05NW8M6DCMSvfcJiBB5NDxRE1gv8kbvxKaC9u69e6ZGEMWXcswA/7eKR229cEIpvg==",
       "dev": true,
       "requires": {
-        "ajv": "6.5.2",
-        "babel-code-frame": "6.26.0",
-        "chalk": "2.4.1",
-        "cross-spawn": "6.0.5",
-        "debug": "3.1.0",
-        "doctrine": "2.1.0",
-        "eslint-scope": "4.0.0",
-        "eslint-utils": "1.3.1",
-        "eslint-visitor-keys": "1.0.0",
-        "espree": "4.0.0",
-        "esquery": "1.0.1",
-        "esutils": "2.0.2",
-        "file-entry-cache": "2.0.0",
-        "functional-red-black-tree": "1.0.1",
-        "glob": "7.1.2",
-        "globals": "11.7.0",
-        "ignore": "4.0.3",
-        "imurmurhash": "0.1.4",
-        "inquirer": "5.2.0",
-        "is-resolvable": "1.1.0",
-        "js-yaml": "3.12.0",
-        "json-stable-stringify-without-jsonify": "1.0.1",
-        "levn": "0.3.0",
-        "lodash": "4.17.10",
-        "minimatch": "3.0.4",
-        "mkdirp": "0.5.1",
-        "natural-compare": "1.4.0",
-        "optionator": "0.8.2",
-        "path-is-inside": "1.0.2",
-        "pluralize": "7.0.0",
-        "progress": "2.0.0",
-        "regexpp": "2.0.0",
-        "require-uncached": "1.0.3",
-        "semver": "5.5.0",
-        "string.prototype.matchall": "2.0.0",
-        "strip-ansi": "4.0.0",
-        "strip-json-comments": "2.0.1",
-        "table": "4.0.3",
-        "text-table": "0.2.0"
+        "@babel/code-frame": "^7.0.0",
+        "ajv": "^6.5.3",
+        "chalk": "^2.1.0",
+        "cross-spawn": "^6.0.5",
+        "debug": "^4.0.1",
+        "doctrine": "^2.1.0",
+        "eslint-scope": "^4.0.0",
+        "eslint-utils": "^1.3.1",
+        "eslint-visitor-keys": "^1.0.0",
+        "espree": "^5.0.0",
+        "esquery": "^1.0.1",
+        "esutils": "^2.0.2",
+        "file-entry-cache": "^2.0.0",
+        "functional-red-black-tree": "^1.0.1",
+        "glob": "^7.1.2",
+        "globals": "^11.7.0",
+        "ignore": "^4.0.6",
+        "imurmurhash": "^0.1.4",
+        "inquirer": "^6.1.0",
+        "js-yaml": "^3.12.0",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "levn": "^0.3.0",
+        "lodash": "^4.17.5",
+        "minimatch": "^3.0.4",
+        "mkdirp": "^0.5.1",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.8.2",
+        "path-is-inside": "^1.0.2",
+        "pluralize": "^7.0.0",
+        "progress": "^2.0.0",
+        "regexpp": "^2.0.1",
+        "require-uncached": "^1.0.3",
+        "semver": "^5.5.1",
+        "strip-ansi": "^4.0.0",
+        "strip-json-comments": "^2.0.1",
+        "table": "^5.0.2",
+        "text-table": "^0.2.0"
       }
     },
     "eslint-scope": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
       "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==",
       "dev": true,
       "requires": {
-        "esrecurse": "4.2.1",
-        "estraverse": "4.2.0"
+        "esrecurse": "^4.1.0",
+        "estraverse": "^4.1.1"
       }
     },
     "eslint-utils": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
       "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==",
       "dev": true
     },
     "eslint-visitor-keys": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
       "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
       "dev": true
     },
     "espree": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz",
-      "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.0.tgz",
+      "integrity": "sha512-1MpUfwsdS9MMoN7ZXqAr9e9UKdVHDcvrJpyx7mm1WuQlx/ygErEQBzgi5Nh5qBHIoYweprhtMkTCb9GhcAIcsA==",
       "dev": true,
       "requires": {
-        "acorn": "5.7.1",
-        "acorn-jsx": "4.1.1"
+        "acorn": "^6.0.2",
+        "acorn-jsx": "^5.0.0",
+        "eslint-visitor-keys": "^1.0.0"
       }
     },
     "esprima": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
       "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
       "dev": true
     },
     "esquery": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
       "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
       "dev": true,
       "requires": {
-        "estraverse": "4.2.0"
+        "estraverse": "^4.0.0"
       }
     },
     "esrecurse": {
       "version": "4.2.1",
       "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
       "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
       "dev": true,
       "requires": {
-        "estraverse": "4.2.0"
+        "estraverse": "^4.1.0"
       }
     },
     "estraverse": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
       "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
       "dev": true
     },
     "esutils": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
       "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
       "dev": true
     },
     "external-editor": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
-      "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz",
+      "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==",
       "dev": true,
       "requires": {
-        "chardet": "0.4.2",
-        "iconv-lite": "0.4.23",
-        "tmp": "0.0.33"
+        "chardet": "^0.7.0",
+        "iconv-lite": "^0.4.24",
+        "tmp": "^0.0.33"
       }
     },
     "fast-deep-equal": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
       "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
       "dev": true
     },
@@ -533,316 +422,221 @@
       "dev": true
     },
     "figures": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
       "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
       "dev": true,
       "requires": {
-        "escape-string-regexp": "1.0.5"
+        "escape-string-regexp": "^1.0.5"
       }
     },
     "file-entry-cache": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
       "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
       "dev": true,
       "requires": {
-        "flat-cache": "1.3.0",
-        "object-assign": "4.1.1"
+        "flat-cache": "^1.2.1",
+        "object-assign": "^4.0.1"
       }
     },
     "flat-cache": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
-      "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
+      "version": "1.3.4",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
+      "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==",
       "dev": true,
       "requires": {
-        "circular-json": "0.3.3",
-        "del": "2.2.2",
-        "graceful-fs": "4.1.11",
-        "write": "0.2.1"
+        "circular-json": "^0.3.1",
+        "graceful-fs": "^4.1.2",
+        "rimraf": "~2.6.2",
+        "write": "^0.2.1"
       }
     },
-    "foreach": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
-      "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
-      "dev": true
-    },
     "fs.realpath": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
       "dev": true
     },
-    "function-bind": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
-      "dev": true
-    },
     "functional-red-black-tree": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
       "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
       "dev": true
     },
     "glob": {
-      "version": "7.1.2",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
-      "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+      "version": "7.1.3",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+      "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
       "dev": true,
       "requires": {
-        "fs.realpath": "1.0.0",
-        "inflight": "1.0.6",
-        "inherits": "2.0.3",
-        "minimatch": "3.0.4",
-        "once": "1.4.0",
-        "path-is-absolute": "1.0.1"
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
       }
     },
     "globals": {
-      "version": "11.7.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz",
-      "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==",
+      "version": "11.9.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz",
+      "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==",
       "dev": true
     },
-    "globby": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
-      "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
-      "dev": true,
-      "requires": {
-        "array-union": "1.0.2",
-        "arrify": "1.0.1",
-        "glob": "7.1.2",
-        "object-assign": "4.1.1",
-        "pify": "2.3.0",
-        "pinkie-promise": "2.0.1"
-      }
-    },
     "graceful-fs": {
-      "version": "4.1.11",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
-      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+      "version": "4.1.15",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
+      "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
       "dev": true
     },
     "growl": {
       "version": "1.10.5",
       "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
       "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
       "dev": true
     },
-    "has": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
-      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-      "dev": true,
-      "requires": {
-        "function-bind": "1.1.1"
-      }
-    },
-    "has-ansi": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
-      "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
-      "dev": true,
-      "requires": {
-        "ansi-regex": "2.1.1"
-      }
-    },
     "has-flag": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
       "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
       "dev": true
     },
-    "has-symbols": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
-      "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
-      "dev": true
-    },
     "he": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
       "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
       "dev": true
     },
     "htmlparser2": {
-      "version": "3.9.2",
-      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
-      "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
+      "version": "3.10.0",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.0.tgz",
+      "integrity": "sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ==",
       "requires": {
-        "domelementtype": "1.3.0",
-        "domhandler": "2.4.2",
-        "domutils": "1.7.0",
-        "entities": "1.1.1",
-        "inherits": "2.0.3",
-        "readable-stream": "2.3.6"
+        "domelementtype": "^1.3.0",
+        "domhandler": "^2.3.0",
+        "domutils": "^1.5.1",
+        "entities": "^1.1.1",
+        "inherits": "^2.0.1",
+        "readable-stream": "^3.0.6"
       }
     },
     "iconv-lite": {
-      "version": "0.4.23",
-      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
-      "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+      "version": "0.4.24",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
       "dev": true,
       "requires": {
-        "safer-buffer": "2.1.2"
+        "safer-buffer": ">= 2.1.2 < 3"
       }
     },
     "ignore": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.3.tgz",
-      "integrity": "sha512-Z/vAH2GGIEATQnBVXMclE2IGV6i0GyVngKThcGZ5kHgHMxLo9Ow2+XHRq1aEKEej5vOF1TPJNbvX6J/anT0M7A==",
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+      "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
       "dev": true
     },
     "imurmurhash": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
       "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
       "dev": true
     },
     "inflight": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
       "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
       "dev": true,
       "requires": {
-        "once": "1.4.0",
-        "wrappy": "1.0.2"
+        "once": "^1.3.0",
+        "wrappy": "1"
       }
     },
     "inherits": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
       "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
     },
     "ini-parser": {
       "version": "0.0.2",
       "resolved": "https://registry.npmjs.org/ini-parser/-/ini-parser-0.0.2.tgz",
       "integrity": "sha1-+kF4flZ3Y7P/Zdel2alO23QHh+8="
     },
     "inquirer": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz",
-      "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==",
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.1.tgz",
+      "integrity": "sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg==",
       "dev": true,
       "requires": {
-        "ansi-escapes": "3.1.0",
-        "chalk": "2.4.1",
-        "cli-cursor": "2.1.0",
-        "cli-width": "2.2.0",
-        "external-editor": "2.2.0",
-        "figures": "2.0.0",
-        "lodash": "4.17.10",
+        "ansi-escapes": "^3.0.0",
+        "chalk": "^2.0.0",
+        "cli-cursor": "^2.1.0",
+        "cli-width": "^2.0.0",
+        "external-editor": "^3.0.0",
+        "figures": "^2.0.0",
+        "lodash": "^4.17.10",
         "mute-stream": "0.0.7",
-        "run-async": "2.3.0",
-        "rxjs": "5.5.11",
-        "string-width": "2.1.1",
-        "strip-ansi": "4.0.0",
-        "through": "2.3.8"
+        "run-async": "^2.2.0",
+        "rxjs": "^6.1.0",
+        "string-width": "^2.1.0",
+        "strip-ansi": "^5.0.0",
+        "through": "^2.3.6"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz",
+          "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==",
+          "dev": true
+        },
+        "strip-ansi": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz",
+          "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^4.0.0"
+          }
+        }
       }
     },
-    "is-callable": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
-      "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
-      "dev": true
-    },
-    "is-date-object": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
-      "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
-      "dev": true
-    },
     "is-fullwidth-code-point": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
       "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
       "dev": true
     },
-    "is-path-cwd": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
-      "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
-      "dev": true
-    },
-    "is-path-in-cwd": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
-      "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
-      "dev": true,
-      "requires": {
-        "is-path-inside": "1.0.1"
-      }
-    },
-    "is-path-inside": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
-      "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
-      "dev": true,
-      "requires": {
-        "path-is-inside": "1.0.2"
-      }
-    },
     "is-promise": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
       "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
       "dev": true
     },
-    "is-regex": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
-      "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
-      "dev": true,
-      "requires": {
-        "has": "1.0.3"
-      }
-    },
-    "is-resolvable": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
-      "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
-      "dev": true
-    },
-    "is-symbol": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
-      "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
-      "dev": true
-    },
-    "isarray": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
-    },
     "isexe": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
       "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
       "dev": true
     },
     "js-tokens": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
-      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
       "dev": true
     },
     "js-yaml": {
       "version": "3.12.0",
       "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
       "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
       "dev": true,
       "requires": {
-        "argparse": "1.0.10",
-        "esprima": "4.0.1"
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
       }
     },
     "json-schema-traverse": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
       "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
       "dev": true
     },
@@ -853,50 +647,50 @@
       "dev": true
     },
     "levn": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
       "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
       "dev": true,
       "requires": {
-        "prelude-ls": "1.1.2",
-        "type-check": "0.3.2"
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2"
       }
     },
     "lodash": {
-      "version": "4.17.10",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
-      "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
+      "version": "4.17.11",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
+      "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
       "dev": true
     },
     "mimic-fn": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
       "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
       "dev": true
     },
     "minimatch": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
       "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
       "dev": true,
       "requires": {
-        "brace-expansion": "1.1.11"
+        "brace-expansion": "^1.1.7"
       }
     },
     "minimist": {
       "version": "0.0.8",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+      "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
       "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
       "dev": true
     },
     "mkdirp": {
       "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
       "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
       "dev": true,
       "requires": {
         "minimist": "0.0.8"
       }
     },
     "mocha": {
       "version": "5.2.0",
@@ -912,249 +706,233 @@
         "glob": "7.1.2",
         "growl": "1.10.5",
         "he": "1.1.1",
         "minimatch": "3.0.4",
         "mkdirp": "0.5.1",
         "supports-color": "5.4.0"
       },
       "dependencies": {
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "glob": {
+          "version": "7.1.2",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+          "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+          "dev": true
+        },
         "supports-color": {
           "version": "5.4.0",
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
           "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
           "dev": true,
           "requires": {
-            "has-flag": "3.0.0"
+            "has-flag": "^3.0.0"
           }
         }
       }
     },
     "ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+      "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
       "dev": true
     },
     "mute-stream": {
       "version": "0.0.7",
-      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+      "resolved": "http://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
       "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
       "dev": true
     },
     "natural-compare": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
       "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
       "dev": true
     },
     "nice-try": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz",
-      "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==",
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
       "dev": true
     },
     "object-assign": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
       "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
       "dev": true
     },
-    "object-keys": {
-      "version": "1.0.12",
-      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
-      "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
-      "dev": true
-    },
     "once": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
       "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
       "dev": true,
       "requires": {
-        "wrappy": "1.0.2"
+        "wrappy": "1"
       }
     },
     "onetime": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
       "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
       "dev": true,
       "requires": {
-        "mimic-fn": "1.2.0"
+        "mimic-fn": "^1.0.0"
       }
     },
     "optionator": {
       "version": "0.8.2",
       "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
       "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
       "dev": true,
       "requires": {
-        "deep-is": "0.1.3",
-        "fast-levenshtein": "2.0.6",
-        "levn": "0.3.0",
-        "prelude-ls": "1.1.2",
-        "type-check": "0.3.2",
-        "wordwrap": "1.0.0"
+        "deep-is": "~0.1.3",
+        "fast-levenshtein": "~2.0.4",
+        "levn": "~0.3.0",
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2",
+        "wordwrap": "~1.0.0"
       }
     },
     "os-tmpdir": {
       "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
       "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
       "dev": true
     },
     "path-is-absolute": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
       "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
       "dev": true
     },
     "path-is-inside": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
       "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
       "dev": true
     },
     "path-key": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
       "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
       "dev": true
     },
-    "pify": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-      "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
-      "dev": true
-    },
-    "pinkie": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
-      "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
-      "dev": true
-    },
-    "pinkie-promise": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
-      "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
-      "dev": true,
-      "requires": {
-        "pinkie": "2.0.4"
-      }
-    },
     "pluralize": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
       "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
       "dev": true
     },
     "prelude-ls": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
       "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
       "dev": true
     },
-    "process-nextick-args": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
-      "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
-    },
     "progress": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
-      "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=",
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+      "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
       "dev": true
     },
     "punycode": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
       "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
       "dev": true
     },
     "readable-stream": {
-      "version": "2.3.6",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
-      "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz",
+      "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==",
       "requires": {
-        "core-util-is": "1.0.2",
-        "inherits": "2.0.3",
-        "isarray": "1.0.0",
-        "process-nextick-args": "2.0.0",
-        "safe-buffer": "5.1.2",
-        "string_decoder": "1.1.1",
-        "util-deprecate": "1.0.2"
-      }
-    },
-    "regexp.prototype.flags": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz",
-      "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==",
-      "dev": true,
-      "requires": {
-        "define-properties": "1.1.2"
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
       }
     },
     "regexpp": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.0.tgz",
-      "integrity": "sha512-g2FAVtR8Uh8GO1Nv5wpxW7VFVwHcCEr4wyA8/MHiRkO8uHoR5ntAA8Uq3P1vvMTX/BeQiRVSpDGLd+Wn5HNOTA==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
+      "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
       "dev": true
     },
     "require-uncached": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+      "resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
       "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
       "dev": true,
       "requires": {
-        "caller-path": "0.1.0",
-        "resolve-from": "1.0.1"
+        "caller-path": "^0.1.0",
+        "resolve-from": "^1.0.0"
       }
     },
     "resolve-from": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
       "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
       "dev": true
     },
     "restore-cursor": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
       "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
       "dev": true,
       "requires": {
-        "onetime": "2.0.1",
-        "signal-exit": "3.0.2"
+        "onetime": "^2.0.0",
+        "signal-exit": "^3.0.2"
       }
     },
     "rimraf": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
-      "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+      "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
       "dev": true,
       "requires": {
-        "glob": "7.1.2"
+        "glob": "^7.1.3"
       }
     },
     "run-async": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
       "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
       "dev": true,
       "requires": {
-        "is-promise": "2.1.0"
+        "is-promise": "^2.1.0"
       }
     },
     "rxjs": {
-      "version": "5.5.11",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.11.tgz",
-      "integrity": "sha512-3bjO7UwWfA2CV7lmwYMBzj4fQ6Cq+ftHc2MvUe+WMS7wcdJ1LosDWmdjPQanYp2dBRj572p7PeU81JUxHKOcBA==",
+      "version": "6.3.3",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
+      "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
       "dev": true,
       "requires": {
-        "symbol-observable": "1.0.1"
+        "tslib": "^1.9.0"
       }
     },
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
       "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
     },
     "safer-buffer": {
@@ -1164,188 +942,170 @@
       "dev": true
     },
     "sax": {
       "version": "1.2.4",
       "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
       "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
     },
     "semver": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
-      "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+      "version": "5.6.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+      "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
       "dev": true
     },
     "shebang-command": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
       "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
       "dev": true,
       "requires": {
-        "shebang-regex": "1.0.0"
+        "shebang-regex": "^1.0.0"
       }
     },
     "shebang-regex": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
       "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
       "dev": true
     },
     "signal-exit": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
       "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
       "dev": true
     },
     "slice-ansi": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
-      "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.0.0.tgz",
+      "integrity": "sha512-4j2WTWjp3GsZ+AOagyzVbzp4vWGtZ0hEZ/gDY/uTvm6MTxUfTUIsnMIFb1bn8o0RuXiqUw15H1bue8f22Vw2oQ==",
       "dev": true,
       "requires": {
-        "is-fullwidth-code-point": "2.0.0"
+        "ansi-styles": "^3.2.0",
+        "astral-regex": "^1.0.0",
+        "is-fullwidth-code-point": "^2.0.0"
       }
     },
     "sprintf-js": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
       "dev": true
     },
     "string-width": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
       "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
       "dev": true,
       "requires": {
-        "is-fullwidth-code-point": "2.0.0",
-        "strip-ansi": "4.0.0"
-      }
-    },
-    "string.prototype.matchall": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz",
-      "integrity": "sha512-WoZ+B2ypng1dp4iFLF2kmZlwwlE19gmjgKuhL1FJfDgCREWb3ye3SDVHSzLH6bxfnvYmkCxbzkmWcQZHA4P//Q==",
-      "dev": true,
-      "requires": {
-        "define-properties": "1.1.2",
-        "es-abstract": "1.12.0",
-        "function-bind": "1.1.1",
-        "has-symbols": "1.0.0",
-        "regexp.prototype.flags": "1.2.0"
+        "is-fullwidth-code-point": "^2.0.0",
+        "strip-ansi": "^4.0.0"
       }
     },
     "string_decoder": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz",
+      "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==",
       "requires": {
-        "safe-buffer": "5.1.2"
+        "safe-buffer": "~5.1.0"
       }
     },
     "strip-ansi": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
       "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
       "dev": true,
       "requires": {
-        "ansi-regex": "3.0.0"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
-          "dev": true
-        }
+        "ansi-regex": "^3.0.0"
       }
     },
     "strip-json-comments": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
       "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
       "dev": true
     },
     "supports-color": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-      "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
-      "dev": true
-    },
-    "symbol-observable": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
-      "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
-      "dev": true
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "requires": {
+        "has-flag": "^3.0.0"
+      }
     },
     "table": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz",
-      "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==",
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/table/-/table-5.1.1.tgz",
+      "integrity": "sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw==",
       "dev": true,
       "requires": {
-        "ajv": "6.5.2",
-        "ajv-keywords": "3.2.0",
-        "chalk": "2.4.1",
-        "lodash": "4.17.10",
-        "slice-ansi": "1.0.0",
-        "string-width": "2.1.1"
+        "ajv": "^6.6.1",
+        "lodash": "^4.17.11",
+        "slice-ansi": "2.0.0",
+        "string-width": "^2.1.1"
       }
     },
     "text-table": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
       "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
       "dev": true
     },
     "through": {
       "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
       "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
       "dev": true
     },
     "tmp": {
       "version": "0.0.33",
       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
       "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
       "dev": true,
       "requires": {
-        "os-tmpdir": "1.0.2"
+        "os-tmpdir": "~1.0.2"
       }
     },
+    "tslib": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+      "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
+      "dev": true
+    },
     "type-check": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
       "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
       "dev": true,
       "requires": {
-        "prelude-ls": "1.1.2"
+        "prelude-ls": "~1.1.2"
       }
     },
     "uri-js": {
       "version": "4.2.2",
       "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
       "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
       "dev": true,
       "requires": {
-        "punycode": "2.1.1"
+        "punycode": "^2.1.0"
       }
     },
     "util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
       "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
     },
     "which": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
       "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
       "dev": true,
       "requires": {
-        "isexe": "2.0.0"
+        "isexe": "^2.0.0"
       }
     },
     "wordwrap": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
       "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
       "dev": true
     },
@@ -1356,13 +1116,13 @@
       "dev": true
     },
     "write": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
       "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
       "dev": true,
       "requires": {
-        "mkdirp": "0.5.1"
+        "mkdirp": "^0.5.1"
       }
     }
   }
 }
--- a/tools/lint/eslint/eslint-plugin-mozilla/package.json
+++ b/tools/lint/eslint/eslint-plugin-mozilla/package.json
@@ -17,20 +17,20 @@
     "type": "hg",
     "url": "https://hg.mozilla.org/mozilla-central/"
   },
   "author": "Mike Ratcliffe",
   "main": "lib/index.js",
   "dependencies": {
     "ini-parser": "0.0.2",
     "sax": "1.2.4",
-    "htmlparser2": "3.9.2"
+    "htmlparser2": "3.10.0"
   },
   "devDependencies": {
-    "eslint": "5.3.0",
+    "eslint": "5.11.1",
     "mocha": "5.2.0"
   },
   "peerDependencies": {
     "eslint": "^5.0.1",
     "eslint-plugin-no-unsanitized": "^3.0.0"
   },
   "engines": {
     "node": ">=6.9.1"
--- a/tools/lint/eslint/manifest.tt
+++ b/tools/lint/eslint/manifest.tt
@@ -1,10 +1,10 @@
 [
   {
     "algorithm": "sha512",
     "visibility": "public",
     "filename": "eslint.tar.gz",
     "unpack": true,
-    "digest": "dabef3ed93abe6be67a31907da34331aa299c359ebb0aa24c72a79cbc2fff1e1634829f9fdaa7761c944358820180c804b76feb1d8f85dfcdf7a7a97abc63125",
-    "size": 3892561
+    "digest": "ee67838a31ec12f06d6d33b4b401ea57bab2af49379907479fdd3cf53dab195b8c3eb96bc314ae9bf16205dcb14ffba3e38e46adec037ab46b3e494a4d6a2845",
+    "size": 4159721
   }
 ]
--- a/xpcom/rust/gtest/nsstring/Cargo.toml
+++ b/xpcom/rust/gtest/nsstring/Cargo.toml
@@ -1,12 +1,12 @@
 [package]
 name = "nsstring-gtest"
 version = "0.1.0"
 authors = ["nobody@mozilla.com"]
 license = "MPL-2.0"
 description = "Tests for rust bindings to xpcom string types"
 
 [dependencies]
-nsstring = { path = "../../../../servo/support/gecko/nsstring" }
+nsstring = { path = "../../nsstring" }
 
 [lib]
 path = "test.rs"
--- a/xpcom/rust/gtest/xpcom/Cargo.toml
+++ b/xpcom/rust/gtest/xpcom/Cargo.toml
@@ -3,12 +3,12 @@ name = "xpcom-gtest"
 version = "0.1.0"
 authors = ["michael@thelayzells.com"]
 license = "MPL-2.0"
 description = "Tests for rust bindings to xpcom interfaces"
 
 [dependencies]
 xpcom = { path = "../../xpcom" }
 nserror = { path = "../../nserror" }
-nsstring = { path = "../../../../servo/support/gecko/nsstring" }
+nsstring = { path = "../../nsstring" }
 
 [lib]
 path = "test.rs"
--- a/xpcom/rust/nserror/Cargo.toml
+++ b/xpcom/rust/nserror/Cargo.toml
@@ -1,9 +1,9 @@
 [package]
 name = "nserror"
 version = "0.1.0"
 authors = ["Michael Layzell <michael@thelayzells.com>"]
 license = "MPL-2.0"
 description = "Rust bindings to xpcom nsresult and NS_ERROR_ values"
 
 [dependencies]
-nsstring = { path = "../../../servo/support/gecko/nsstring" }
+nsstring = { path = "../nsstring" }
rename from servo/support/gecko/nsstring/Cargo.toml
rename to xpcom/rust/nsstring/Cargo.toml
rename from servo/support/gecko/nsstring/src/conversions.rs
rename to xpcom/rust/nsstring/src/conversions.rs
rename from servo/support/gecko/nsstring/src/lib.rs
rename to xpcom/rust/nsstring/src/lib.rs
--- a/xpcom/rust/xpcom/Cargo.toml
+++ b/xpcom/rust/xpcom/Cargo.toml
@@ -1,10 +1,10 @@
 [package]
 name = "xpcom"
 version = "0.1.0"
 authors = ["michael@thelayzells.com"]
 
 [dependencies]
 libc = "0.2"
-nsstring = { path = "../../../servo/support/gecko/nsstring" }
+nsstring = { path = "../nsstring" }
 nserror = { path = "../nserror" }
 xpcom_macros = { path = "xpcom_macros" }