Merge mozilla-central to inbound. a=merge CLOSED TREE
authorOana Pop Rus <opoprus@mozilla.com>
Thu, 04 Jul 2019 06:38:21 +0300
changeset 544133 d927aec5915e828df126b9379d15595072758e6b
parent 544132 210d6d52e8b0677448cb8e84befeb637ca87eb29 (current diff)
parent 544015 8ad5fbc5b9358fc84aa43d9a1b19c851056b1f39 (diff)
child 544134 f01dbf4e564643fabe35ce553d44ea5b880360ce
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone69.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
browser/components/aboutlogins/content/components/copy-to-clipboard-button.css
browser/components/aboutlogins/content/components/copy-to-clipboard-button.js
browser/components/aboutlogins/content/components/reflected-fluent-element.js
browser/components/aboutlogins/tests/chrome/test_reflected_fluent_element.html
devtools/client/themes/images/webconsole/error.svg
devtools/client/themes/images/webconsole/info.svg
dom/clients/manager/ClientPrefs.cpp
dom/clients/manager/ClientPrefs.h
python/l10n/fluent_migrations/bug_1495861_panicButton.py
python/l10n/fluent_migrations/bug_1517528_aboutPrivateBrowsing.py
python/l10n/fluent_migrations/bug_1521800_passwordManager.py
python/l10n/fluent_migrations/bug_1523734_aboutBlocked.py
python/l10n/fluent_migrations/bug_1523741_aboutTelemetry.py
python/l10n/fluent_migrations/bug_1523747_customizeMode.py
python/l10n/fluent_migrations/bug_1523757_panelUI.py
python/l10n/fluent_migrations/bug_1523761_syncedTabs.py
python/l10n/fluent_migrations/bug_1523763_tabContextMenu.py
python/l10n/fluent_migrations/bug_1529071_printPreview.py
python/l10n/fluent_migrations/bug_1544501_toolbarContextMenu.py
testing/web-platform/meta/webmessaging/with-ports/016.html.ini
testing/web-platform/meta/webmessaging/without-ports/016.html.ini
--- a/.clang-format-ignore
+++ b/.clang-format-ignore
@@ -113,17 +113,17 @@ js/src/vtune/ittnotify_types.h
 js/src/vtune/jitprofiling.c
 js/src/vtune/jitprofiling.h
 js/src/vtune/legacy/.*
 media/ffvpx/.*
 media/gmp-clearkey/0.1/openaes/.*
 media/kiss_fft/.*
 media/libaom/.*
 media/libcubeb/.*
-media/libdav1d/version.h
+media/libdav1d/.*
 media/libjpeg/.*
 media/libmkv/.*
 media/libnestegg/.*
 media/libogg/.*
 media/libopus/.*
 media/libpng/.*
 media/libsoundtouch/.*
 media/libspeex_resampler/.*
--- a/.cron.yml
+++ b/.cron.yml
@@ -171,16 +171,19 @@ jobs:
                   - {weekday: 'Monday', hour: 10, minute: 0}
                   - {weekday: 'Thursday', hour: 10, minute: 0}
               mozilla-release:
                   - {weekday: 'Monday', hour: 10, minute: 0}
                   - {weekday: 'Thursday', hour: 10, minute: 0}
               mozilla-esr60:
                   - {weekday: 'Monday', hour: 10, minute: 0}
                   - {weekday: 'Thursday', hour: 10, minute: 0}
+              mozilla-esr68:
+                  - {weekday: 'Monday', hour: 10, minute: 0}
+                  - {weekday: 'Thursday', hour: 10, minute: 0}
 
     - name: pipfile-update
       job:
           type: decision-task
           treeherder-symbol: Nfile
           target-tasks-method: pipfile_update
       run-on-projects:
           - mozilla-central
--- a/accessible/tests/mochitest/name/test_list.html
+++ b/accessible/tests/mochitest/name/test_list.html
@@ -34,17 +34,23 @@
 
       this.finalCheck = function bulletUpdate_finalCheck() {
         testName("li_start", "1. list start");
         testName("li_end", "2. list end");
 
         // change list style type
         var list = getNode("list");
         list.setAttribute("style", "list-style-type: disc;");
-        getComputedStyle(list, "").color; // make style processing sync
+
+        // Flush both the style change and the resulting layout change.
+        // Flushing style on its own is not sufficient, because that can
+        // leave frames marked with NS_FRAME_IS_DIRTY, which will cause
+        // nsTextFrame::GetRenderedText to report the text of a text
+        // frame is empty.
+        list.offsetWidth; // flush layout (which also flushes style)
 
         testName("li_start", kDiscBulletText + "list start");
         testName("li_end", kDiscBulletText + "list end");
       };
 
       this.getID = function bulletUpdate_getID() {
         return "Update bullet of list items";
       };
--- a/browser/actors/ContextMenuChild.jsm
+++ b/browser/actors/ContextMenuChild.jsm
@@ -120,16 +120,17 @@ class ContextMenuChild extends JSWindowA
                 media.setAttribute("controls", "true");
                 break;
               case "fullscreen":
                 if (this.document.fullscreenEnabled) {
                   media.requestFullscreen();
                 }
                 break;
               case "pictureinpicture":
+                Services.telemetry.keyedScalarAdd("pictureinpicture.opened_method", "contextmenu", 1);
                 let event = new this.contentWindow.CustomEvent("MozTogglePictureInPicture", {
                   bubbles: true,
                 }, this.contentWindow);
                 media.dispatchEvent(event);
                 break;
             }
           }
         );
--- a/browser/base/content/browser-contentblocking.js
+++ b/browser/base/content/browser-contentblocking.js
@@ -966,46 +966,52 @@ var ContentBlocking = {
   openPreferences(origin) {
     openPreferences("privacy-trackingprotection", { origin });
   },
 
   backToMainView() {
     this.identityPopupMultiView.goBack();
   },
 
-  submitBreakageReport() {
+  onSubmitBreakageReportClicked() {
     this.identityPopup.hidePopup();
 
+    let comments = document.getElementById(
+      "identity-popup-breakageReportView-collection-comments");
+    this.submitBreakageReport(this.reportURI, comments);
+  },
+
+  submitBreakageReport(uri, commentsTextarea) {
     let reportEndpoint = Services.prefs.getStringPref(this.PREF_REPORT_BREAKAGE_URL);
     if (!reportEndpoint) {
       return;
     }
 
     let formData = new FormData();
-    formData.set("title", this.reportURI.host);
+    formData.set("title", uri.host);
 
     // Leave the ? at the end of the URL to signify that this URL had its query stripped.
-    let urlWithoutQuery = this.reportURI.asciiSpec.replace(this.reportURI.query, "");
+    let urlWithoutQuery = uri.asciiSpec.replace(uri.query, "");
     let body = `Full URL: ${urlWithoutQuery}\n`;
     body += `userAgent: ${navigator.userAgent}\n`;
 
     body += "\n**Preferences**\n";
     body += `${TrackingProtection.PREF_ENABLED_GLOBALLY}: ${Services.prefs.getBoolPref(TrackingProtection.PREF_ENABLED_GLOBALLY)}\n`;
     body += `${TrackingProtection.PREF_ENABLED_IN_PRIVATE_WINDOWS}: ${Services.prefs.getBoolPref(TrackingProtection.PREF_ENABLED_IN_PRIVATE_WINDOWS)}\n`;
     body += `urlclassifier.trackingTable: ${Services.prefs.getStringPref("urlclassifier.trackingTable")}\n`;
     body += `network.http.referer.defaultPolicy: ${Services.prefs.getIntPref("network.http.referer.defaultPolicy")}\n`;
     body += `network.http.referer.defaultPolicy.pbmode: ${Services.prefs.getIntPref("network.http.referer.defaultPolicy.pbmode")}\n`;
     body += `${ThirdPartyCookies.PREF_ENABLED}: ${Services.prefs.getIntPref(ThirdPartyCookies.PREF_ENABLED)}\n`;
     body += `network.cookie.lifetimePolicy: ${Services.prefs.getIntPref("network.cookie.lifetimePolicy")}\n`;
+    body += `privacy.annotate_channels.strict_list.enabled: ${Services.prefs.getBoolPref("privacy.annotate_channels.strict_list.enabled")}\n`;
     body += `privacy.restrict3rdpartystorage.expiration: ${Services.prefs.getIntPref("privacy.restrict3rdpartystorage.expiration")}\n`;
     body += `${Fingerprinting.PREF_ENABLED}: ${Services.prefs.getBoolPref(Fingerprinting.PREF_ENABLED)}\n`;
     body += `${Cryptomining.PREF_ENABLED}: ${Services.prefs.getBoolPref(Cryptomining.PREF_ENABLED)}\n`;
 
-    let comments = document.getElementById("identity-popup-breakageReportView-collection-comments");
-    body += "\n**Comments**\n" + comments.value;
+    body += "\n**Comments**\n" + commentsTextarea.value;
 
     formData.set("body", body);
 
     let activatedBlockers = [];
     for (let blocker of this.blockers) {
       if (blocker.activated) {
         activatedBlockers.push(blocker.reportBreakageLabel);
       }
@@ -1019,17 +1025,17 @@ var ContentBlocking = {
       method: "POST",
       credentials: "omit",
       body: formData,
     }).then(function(response) {
       if (!response.ok) {
         Cu.reportError(`Content Blocking report to ${reportEndpoint} failed with status ${response.status}`);
       } else {
         // Clear the textarea value when the report is submitted
-        comments.value = "";
+        commentsTextarea.value = "";
       }
     }).catch(Cu.reportError);
   },
 
   toggleReportBreakageButton() {
     // For release (due to the large volume) we only want to receive reports
     // for breakage that is directly related to third party cookie blocking.
     if (this.reportBreakageEnabled ||
--- a/browser/base/content/browser-siteProtections.js
+++ b/browser/base/content/browser-siteProtections.js
@@ -12,16 +12,21 @@ var gProtectionsHandler = {
   get _protectionsPopup() {
     delete this._protectionsPopup;
     return this._protectionsPopup = document.getElementById("protections-popup");
   },
   get _protectionsIconBox() {
     delete this._protectionsIconBox;
     return this._protectionsIconBox = document.getElementById("tracking-protection-icon-animatable-box");
   },
+  get _protectionsPopupMultiView() {
+    delete this._protectionsPopupMultiView;
+    return this._protectionsPopupMultiView =
+      document.getElementById("protections-popup-multiView");
+  },
   get _protectionsPopupMainView() {
     delete this._protectionsPopupMainView;
     return this._protectionsPopupMainView =
       document.getElementById("protections-popup-mainView");
   },
   get _protectionsPopupMainViewHeaderLabel() {
     delete this._protectionsPopupMainViewHeaderLabel;
     return this._protectionsPopupMainViewHeaderLabel =
@@ -47,16 +52,31 @@ var gProtectionsHandler = {
     return this._protectionPopupFooter =
       document.getElementById("protections-popup-footer");
   },
   get _protectionPopupTrackersCounterDescription() {
     delete this._protectionPopupTrackersCounterDescription;
     return this._protectionPopupTrackersCounterDescription =
       document.getElementById("protections-popup-trackers-blocked-counter-description");
   },
+  get _protectionsPopupSiteNotWorkingTPSwitch() {
+    delete this._protectionsPopupSiteNotWorkingTPSwitch;
+    return this._protectionsPopupSiteNotWorkingTPSwitch =
+      document.getElementById("protections-popup-siteNotWorking-tp-switch");
+  },
+  get _protectionsPopupSendReportLearnMore() {
+    delete this._protectionsPopupSendReportLearnMore;
+    return this._protectionsPopupSendReportLearnMore =
+      document.getElementById("protections-popup-sendReportView-learn-more");
+  },
+  get _protectionsPopupSendReportURL() {
+    delete this._protectionsPopupSendReportURL;
+    return this._protectionsPopupSendReportURL =
+      document.getElementById("protections-popup-sendReportView-collection-url");
+  },
   get _protectionsPopupToastTimeout() {
     delete this._protectionsPopupToastTimeout;
     XPCOMUtils.defineLazyPreferenceGetter(this, "_protectionsPopupToastTimeout",
                                           "browser.protections_panel.toast.timeout",
                                           5000);
     return this._protectionsPopupToastTimeout;
   },
 
@@ -123,31 +143,30 @@ var gProtectionsHandler = {
       // Hide the panel when focusing an element that is
       // neither an ancestor nor descendant unless the panel has
       // @noautohide (e.g. for a tour).
       PanelMultiView.hidePopup(this._protectionsPopup);
     }
   },
 
   refreshProtectionsPopup() {
-    // Refresh the state of the TP toggle switch.
-    this._protectionsPopupTPSwitch.toggleAttribute("enabled",
-      !this._protectionsPopup.hasAttribute("hasException"));
-
     let host = gIdentityHandler.getHostForDisplay();
 
     // Push the appropriate strings out to the UI.
     this._protectionsPopupMainViewHeaderLabel.textContent =
       // gNavigatorBundle.getFormattedString("protections.header", [host]);
       `Tracking Protections for ${host}`;
 
     let currentlyEnabled =
       !this._protectionsPopup.hasAttribute("hasException");
 
-    this._protectionsPopupTPSwitch.toggleAttribute("enabled", currentlyEnabled);
+    for (let tpSwitch of [this._protectionsPopupTPSwitch,
+                          this._protectionsPopupSiteNotWorkingTPSwitch]) {
+      tpSwitch.toggleAttribute("enabled", currentlyEnabled);
+    }
 
     // Display the breakage link according to the current enable state.
     // The display state of the breakage link will be fixed once the protections
     // panel opened no matter how the TP switch state is.
     this._protectionsPopupTPSwitchBreakageLink.hidden = !currentlyEnabled;
 
     // Set the counter of the 'Trackers blocked This Week'.
     // We need to get the statistics of trackers. So far, we haven't implemented
@@ -166,17 +185,20 @@ var gProtectionsHandler = {
     }
 
     this._TPSwitchCommanding = true;
 
     // Toggling the 'hasException' on the protections panel in order to do some
     // styling after toggling the TP switch.
     let newExceptionState =
       this._protectionsPopup.toggleAttribute("hasException");
-    this._protectionsPopupTPSwitch.toggleAttribute("enabled", !newExceptionState);
+    for (let tpSwitch of [this._protectionsPopupTPSwitch,
+                          this._protectionsPopupSiteNotWorkingTPSwitch]) {
+      tpSwitch.toggleAttribute("enabled", !newExceptionState);
+    }
 
     // Indicating that we need to show a toast after refreshing the page.
     // And caching the current URI and window ID in order to only show the mini
     // panel if it's still on the same page.
     this._showToastAfterRefresh = true;
     this._previousURI = gBrowser.currentURI.spec;
     this._previousOuterWindowID = gBrowser.selectedBrowser.outerWindowID;
 
@@ -243,9 +265,32 @@ var gProtectionsHandler = {
     }
 
     // Now open the popup, anchored off the primary chrome element
     PanelMultiView.openPopup(this._protectionsPopup, gIdentityHandler._identityIcon, {
       position: "bottomcenter topleft",
       triggerEvent: event,
     }).catch(Cu.reportError);
   },
+
+  showSiteNotWorkingView() {
+    this._protectionsPopupMultiView.showSubView("protections-popup-siteNotWorkingView");
+  },
+
+  showSendReportView() {
+    // Save this URI to make sure that the user really only submits the location
+    // they see in the report breakage dialog.
+    this.reportURI = gBrowser.currentURI;
+    let urlWithoutQuery = this.reportURI.asciiSpec.replace("?" + this.reportURI.query, "");
+    this._protectionsPopupSendReportURL.value = urlWithoutQuery;
+    this._protectionsPopupMultiView.showSubView("protections-popup-sendReportView");
+  },
+
+  onSendReportClicked() {
+    this._protectionsPopup.hidePopup();
+    let comments = document.getElementById(
+      "protections-popup-sendReportView-collection-comments");
+    ContentBlocking.submitBreakageReport(this.reportURI, comments);
+  },
 };
+
+let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
+gProtectionsHandler._protectionsPopupSendReportLearnMore.href = baseURL + "blocking-breakage";
--- a/browser/base/content/test/siteProtections/browser_protections_UI.js
+++ b/browser/base/content/test/siteProtections/browser_protections_UI.js
@@ -35,16 +35,32 @@ add_task(async function testToggleSwitch
   await popuphiddenPromise;
 
   await openProtectionsPanel();
   ok(!gProtectionsHandler._protectionsPopupTPSwitch.hasAttribute("enabled"), "TP Switch should be disabled");
   Services.perms.remove(ContentBlocking._baseURIForChannelClassifier, "trackingprotection");
   BrowserTestUtils.removeTab(tab);
 });
 
+add_task(async function testSiteNotWorking() {
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "https://example.com");
+  await openProtectionsPanel();
+  let viewShownPromise = BrowserTestUtils.waitForEvent(
+    gProtectionsHandler._protectionsPopupMultiView, "ViewShown");
+  document.getElementById("protections-popup-tp-switch-breakage-link").click();
+  let event = await viewShownPromise;
+  is(event.originalTarget.id, "protections-popup-siteNotWorkingView", "Site Not Working? view should be shown");
+  viewShownPromise = BrowserTestUtils.waitForEvent(
+    gProtectionsHandler._protectionsPopupMultiView, "ViewShown");
+  document.getElementById("protections-popup-siteNotWorkingView-sendReport").click();
+  event = await viewShownPromise;
+  is(event.originalTarget.id, "protections-popup-sendReportView", "Send Report view should be shown");
+  BrowserTestUtils.removeTab(tab);
+});
+
 /**
  * A test for the protection settings button.
  */
 add_task(async function testSettingsButton() {
   // Open a tab and its protection panel.
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "https://example.com");
   await openProtectionsPanel();
 
--- a/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
@@ -260,16 +260,17 @@ async function testReportBreakage(url, t
       let prefs = [
         "privacy.trackingprotection.enabled",
         "privacy.trackingprotection.pbmode.enabled",
         "urlclassifier.trackingTable",
         "network.http.referer.defaultPolicy",
         "network.http.referer.defaultPolicy.pbmode",
         "network.cookie.cookieBehavior",
         "network.cookie.lifetimePolicy",
+        "privacy.annotate_channels.strict_list.enabled",
         "privacy.restrict3rdpartystorage.expiration",
         "privacy.trackingprotection.fingerprinting.enabled",
         "privacy.trackingprotection.cryptomining.enabled",
       ];
       let prefsBody = "";
 
       for (let pref of prefs) {
         prefsBody += `${pref}: ${Preferences.get(pref)}\r\n`;
--- a/browser/components/aboutlogins/AboutLoginsParent.jsm
+++ b/browser/components/aboutlogins/AboutLoginsParent.jsm
@@ -215,45 +215,46 @@ var AboutLoginsParent = {
       }
       default: {
         break;
       }
     }
   },
 
   async showMasterPasswordLoginNotifications() {
-    if (!this._l10n) {
-      this._l10n = new Localization(["browser/aboutLogins.ftl"]);
-    }
+    for (let subscriber of this._subscriberIterator()) {
+      let MozXULElement = subscriber.ownerGlobal.MozXULElement;
+      MozXULElement.insertFTLIfNeeded("browser/aboutLogins.ftl");
 
-    let messageString = await this._l10n.formatValue("master-password-notification-message");
-    for (let subscriber of this._subscriberIterator()) {
       // If there's already an existing notification bar, don't do anything.
       let {gBrowser} = subscriber.ownerGlobal;
       let browser = subscriber;
       let notificationBox = gBrowser.getNotificationBox(browser);
       let notification = notificationBox.getNotificationWithValue(MASTER_PASSWORD_NOTIFICATION_ID);
       if (notification) {
         continue;
       }
 
       // Configure the notification bar
       let priority = notificationBox.PRIORITY_WARNING_MEDIUM;
       let iconURL = "chrome://browser/skin/login.svg";
-      let reloadLabel = await this._l10n.formatValue("master-password-reload-button-label");
-      let reloadKey = await this._l10n.formatValue("master-password-reload-button-accesskey");
+
+      let doc = subscriber.ownerDocument;
+      let messageFragment = doc.createDocumentFragment();
+      let message = doc.createElement("span");
+      doc.l10n.setAttributes(message, "master-password-notification-message");
+      messageFragment.appendChild(message);
 
       let buttons = [{
-        label: reloadLabel,
-        accessKey: reloadKey,
+        "l10n-id": "master-password-reload-button",
         popup: null,
         callback() { browser.reload(); },
       }];
 
-      notification = notificationBox.appendNotification(messageString, MASTER_PASSWORD_NOTIFICATION_ID,
+      notification = notificationBox.appendNotification(messageFragment, MASTER_PASSWORD_NOTIFICATION_ID,
                                                         iconURL, priority, buttons);
     }
   },
 
   removeMasterPasswordLoginNotifications() {
     for (let subscriber of this._subscriberIterator()) {
       let {gBrowser} = subscriber.ownerGlobal;
       let browser = subscriber;
--- a/browser/components/aboutlogins/content/aboutLogins.ftl
+++ b/browser/components/aboutlogins/content/aboutLogins.ftl
@@ -1,72 +1,81 @@
 # 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 not in a locales directory to prevent it from
 ### being translated as the feature is still in heavy development
 ### and strings are likely to change often.
 
-### Fluent isn't translating elements in the shadow DOM so the translated strings
-### need to be applied to the composed node where they can be moved to the proper
-### descendant after translation.
-
 about-logins-page-title = Logins & Passwords
 
-create-login-button = New Login
-
 login-filter =
   .placeholder = Search Logins
 
+create-login-button = New Login
+
+## The ⋯ menu that is in the top corner of the page
+menu =
+  .title = Open menu
+menu-menuitem-faq = Frequently Asked Questions
+menu-menuitem-feedback = Leave Feedback
+menu-menuitem-import = Import Passwords…
+menu-menuitem-preferences =
+  { PLATFORM() ->
+      [windows] Options
+     *[other] Preferences
+  }
+
+## Login List
 login-list =
   .aria-label = Logins matching search query
-  .count =
-    { $count ->
-        [one] { $count } login
-       *[other] { $count } logins
-    }
-  .last-changed-option = Last Changed
-  .last-used-option = Last Used
-  .missing-username = (no username)
-  .name-option = Name
-  .new-login-subtitle = Enter your login credentials
-  .new-login-title = New Login
-  .sort-label-text = Sort by:
+login-list-count =
+  { $count ->
+      [one] { $count } login
+     *[other] { $count } logins
+  }
+login-list-last-changed-option = Last Changed
+login-list-last-used-option = Last Used
+login-list-name-option = Name
+login-list-sort-label-text = Sort by:
+login-list-item-title-new-login = New Login
+login-list-item-subtitle-new-login = Enter your login credentials
+login-list-item-subtitle-missing-username = (no username)
 
-login-item =
-  .cancel-button = Cancel
-  .copied-password-button = ✓ Copied!
-  .copied-username-button = ✓ Copied!
-  .copy-password-button = Copy
-  .copy-username-button = Copy
-  .delete-button = Delete
-  .edit-button = Edit
-  .new-login-title = Create New Login
-  .open-site-button = Launch
-  .origin-label = Website Address
-  .origin-placeholder = https://www.example.com
-  .password-hide-title = Hide password
-  .password-label = Password
-  .password-show-title = Show password
-  .save-changes-button = Save Changes
-  .time-created = Created: { DATETIME($timeCreated, day: "numeric", month: "long", year: "numeric") }
-  .time-changed = Last modified: { DATETIME($timeChanged, day: "numeric", month: "long", year: "numeric") }
-  .time-used = Last used: { DATETIME($timeUsed, day: "numeric", month: "long", year: "numeric") }
-  .username-label = Username
-  .username-placeholder = name@example.com
+## Login
+login-item-new-login-title = Create New Login
+login-item-edit-button = Edit
+login-item-delete-button = Delete
+login-item-origin-label = Website Address
+login-item-origin =
+  .placeholder = https://www.example.com
+login-item-open-site-button = Launch
+login-item-username-label = Username
+login-item-username =
+  .placeholder = name@example.com
+login-item-copied-username-button-text = ✔ Copied!
+login-item-copy-username-button-text = Copy
+login-item-password-label = Password
+login-item-password-reveal-checkbox-show =
+  .title = Show password
+login-item-password-reveal-checkbox-hide =
+  .title = Hide password
+login-item-copied-password-button-text = ✔ Copied!
+login-item-copy-password-button-text = Copy
+login-item-save-changes-button = Save Changes
+login-item-cancel-button = Cancel
+login-item-time-changed = Last modified: { DATETIME($timeChanged, day: "numeric", month: "long", year: "numeric") }
+login-item-time-created = Created: { DATETIME($timeCreated, day: "numeric", month: "long", year: "numeric") }
+login-item-time-used = Last used: { DATETIME($timeUsed, day: "numeric", month: "long", year: "numeric") }
 
+## Master Password notification
 master-password-notification-message = Please enter your master password to view saved logins & passwords
-# TODO: Not sure how to use formatValue with these as attributes on a single ID
-master-password-reload-button-label = Log in
-# TODO: Not sure how to use formatValue with these as attributes on a single ID
-master-password-reload-button-accesskey = L
+master-password-reload-button =
+  .label = Log in
+  .accesskey = L
 
-menu-button =
-  .button-title = Open menu
-  .menuitem-faq = Frequently Asked Questions
-  .menuitem-feedback = Leave Feedback
-  .menuitem-import = Import Passwords…
-  .menuitem-preferences =
-    { PLATFORM() ->
-        [windows] Options
-       *[other] Preferences
-    }
+confirm-delete-dialog-title = Confirm Deletion
+confirm-delete-dialog-message = Are you sure you want to delete this login?
+confirm-delete-dialog-dismiss-button =
+  .title = Cancel
+confirm-delete-dialog-cancel-button = Cancel
+confirm-delete-dialog-confirm-button = Delete login
--- a/browser/components/aboutlogins/content/aboutLogins.html
+++ b/browser/components/aboutlogins/content/aboutLogins.html
@@ -4,164 +4,148 @@
 
 <!DOCTYPE html>
 <html>
   <head>
     <meta charset="utf-8">
     <meta http-equiv="Content-Security-Policy" content="default-src 'none'; object-src 'none'; script-src resource: chrome:; img-src data: blob:;"/>
     <title data-l10n-id="about-logins-page-title"></title>
     <link rel="localization" href="browser/aboutLogins.ftl">
-    <script type="module" src="chrome://browser/content/aboutlogins/components/copy-to-clipboard-button.js"></script>
+    <script type="module" src="chrome://browser/content/aboutlogins/components/confirm-delete-dialog.js"></script>
     <script type="module" src="chrome://browser/content/aboutlogins/components/login-filter.js"></script>
     <script type="module" src="chrome://browser/content/aboutlogins/components/login-item.js"></script>
     <script type="module" src="chrome://browser/content/aboutlogins/components/login-list.js"></script>
     <script type="module" src="chrome://browser/content/aboutlogins/components/login-list-item.js"></script>
     <script type="module" src="chrome://browser/content/aboutlogins/components/menu-button.js"></script>
     <script type="module" src="chrome://browser/content/aboutlogins/aboutLogins.js"></script>
     <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
     <link rel="stylesheet" href="chrome://browser/content/aboutlogins/aboutLogins.css">
     <link rel="icon" href="chrome://browser/content/aboutlogins/icons/favicon.svg">
   </head>
   <body>
     <header>
       <img id="branding-logo" src="chrome://branding/content/aboutlogins.svg" alt=""/>
-      <login-filter data-l10n-id="login-filter"
-                    data-l10n-attrs="placeholder"></login-filter>
+      <login-filter></login-filter>
       <button id="create-login-button" data-l10n-id="create-login-button"></button>
-      <menu-button data-l10n-id="menu-button"
-                   data-l10n-attrs="button-title,
-                                    menuitem-faq,
-                                    menuitem-feedback,
-                                    menuitem-import,
-                                    menuitem-preferences"></menu-button>
+      <menu-button></menu-button>
     </header>
-    <login-list data-l10n-id="login-list"
-                data-l10n-args='{"count": 0}'
-                data-l10n-attrs="aria-label,
-                                 count,
-                                 last-changed-option,
-                                 last-used-option,
-                                 missing-username,
-                                 name-option,
-                                 new-login-subtitle,
-                                 new-login-title,
-                                 sort-label-text"></login-list>
-    <login-item data-l10n-id="login-item"
-                data-l10n-args='{"timeCreated": 0, "timeChanged": 0, "timeUsed": 0}'
-                data-l10n-attrs="cancel-button,
-                                 copy-password-button,
-                                 copy-username-button,
-                                 copied-password-button,
-                                 copied-username-button,
-                                 delete-button,
-                                 edit-button,
-                                 new-login-title,
-                                 open-site-button,
-                                 origin-label,
-                                 origin-placeholder,
-                                 password-hide-title,
-                                 password-label,
-                                 password-show-title,
-                                 save-changes-button,
-                                 time-created,
-                                 time-changed,
-                                 time-used,
-                                 username-label,
-                                 username-placeholder"></login-item>
+    <login-list></login-list>
+    <login-item></login-item>
+    <confirm-delete-dialog hidden></confirm-delete-dialog>
+
+    <template id="confirm-delete-dialog-template">
+      <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
+      <link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/confirm-delete-dialog.css">
+      <div class="overlay">
+        <div class="container" role="dialog" aria-labelledby="title" aria-describedby="message">
+          <div class="title-bar">
+            <h1 class="title" id="title" data-l10n-id="confirm-delete-dialog-title"></h1>
+            <button class="dismiss-button" data-l10n-id="confirm-delete-dialog-dismiss-button"></button>
+          </div>
+          <div class="content">
+            <p class="message" id="message" data-l10n-id="confirm-delete-dialog-message"></p>
+          </div>
+          <div class="buttons">
+            <button class="cancel-button" data-l10n-id="confirm-delete-dialog-cancel-button"></button>
+            <button class="confirm-button" data-l10n-id="confirm-delete-dialog-confirm-button"></button>
+          </div>
+        </div>
+      </div>
+    </template>
 
     <template id="login-list-template">
       <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/login-list.css">
       <div class="meta">
         <label for="login-sort">
-          <span class="sort-label-text"></span>
+          <span data-l10n-id="login-list-sort-label-text"></span>
           <select id="login-sort">
-            <option class="name-option" value="name"/>
-            <option class="last-used-option" value="last-used"/>
-            <option class="last-changed-option" value="last-changed"/>
+            <option data-l10n-id="login-list-name-option" value="name"/>
+            <option data-l10n-id="login-list-last-used-option" value="last-used"/>
+            <option data-l10n-id="login-list-last-changed-option" value="last-changed"/>
           </select>
         </label>
-        <span class="count"></span>
+        <span class="count" data-l10n-id="login-list-count" data-l10n-args='{"count": 0}'></span>
       </div>
-      <ol role="listbox" tabindex="0">
+      <ol role="listbox" tabindex="0" data-l10n-id="login-list">
       </ol>
     </template>
 
     <template id="login-list-item-template">
       <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/login-list-item.css">
       <span class="title"></span>
       <span class="username"></span>
     </template>
 
     <template id="login-item-template">
       <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/login-item.css">
       <div class="header">
-        <h2 class="title"></h2>
-        <button class="edit-button alternate-button"></button>
-        <button class="delete-button alternate-button"></button>
+        <h2 class="title">
+          <span class="login-item-title"></span>
+          <span class="new-login-title" data-l10n-id="login-item-new-login-title"></span>
+        </h2>
+        <button class="edit-button alternate-button" data-l10n-id="login-item-edit-button"></button>
+        <button class="delete-button alternate-button" data-l10n-id="login-item-delete-button"></button>
       </div>
       <form>
         <div class="detail-row">
           <label class="detail-cell">
-            <span class="origin-label field-label"></span>
-            <input type="url" name="origin" required/>
+            <span class="origin-label field-label" data-l10n-id="login-item-origin-label"></span>
+            <input type="url" name="origin" required data-l10n-id="login-item-origin"/>
           </label>
-          <button class="open-site-button"></button>
+          <button class="open-site-button" data-l10n-id="login-item-open-site-button"></button>
         </div>
         <div class="detail-row">
           <label class="detail-cell">
-            <span class="username-label field-label"></span>
-            <input type="text" name="username"/>
+            <span class="username-label field-label" data-l10n-id="login-item-username-label"></span>
+            <input type="text" name="username" data-l10n-id="login-item-username"/>
           </label>
-          <copy-to-clipboard-button class="copy-username-button"
-                                    data-telemetry-object="username"></copy-to-clipboard-button>
+          <button class="copy-button copy-username-button" data-copy-login-property="username" data-telemetry-object="username">
+            <span class="copied-button-text" data-l10n-id="login-item-copied-username-button-text"></span>
+            <span class="copy-button-text" data-l10n-id="login-item-copy-username-button-text"></span>
+          </button>
         </div>
         <div class="detail-row">
           <label class="detail-cell">
-            <span class="password-label field-label"></span>
+            <span class="password-label field-label" data-l10n-id="login-item-password-label"></span>
             <div class="reveal-password-wrapper">
               <input type="password" name="password" required/>
-              <input type="checkbox" class="reveal-password-checkbox"/>
+              <input type="checkbox"
+                     class="reveal-password-checkbox"
+                     data-l10n-id="login-item-password-reveal-checkbox"/>
             </div>
           </label>
-          <copy-to-clipboard-button class="copy-password-button"
-                                    data-telemetry-object="password"></copy-to-clipboard-button>
+          <button class="copy-button copy-password-button" data-copy-login-property="password" data-telemetry-object="password">
+            <span class="copied-button-text" data-l10n-id="login-item-copied-password-button-text"></span>
+            <span class="copy-button-text" data-l10n-id="login-item-copy-password-button-text"></span>
+          </button>
         </div>
-        <p class="time-created meta-info"></p>
-        <p class="time-changed meta-info"></p>
-        <p class="time-used meta-info"></p>
-        <button class="save-changes-button"></button>
-        <button class="cancel-button"></button>
+        <p class="time-created meta-info" data-l10n-id="login-item-time-created" data-l10n-args='{"timeCreated": 0}'></p>
+        <p class="time-changed meta-info" data-l10n-id="login-item-time-changed" data-l10n-args='{"timeChanged": 0}'></p>
+        <p class="time-used meta-info" data-l10n-id="login-item-time-used" data-l10n-args='{"timeUsed": 0}'></p>
+        <button class="save-changes-button" data-l10n-id="login-item-save-changes-button"></button>
+        <button class="cancel-button" data-l10n-id="login-item-cancel-button"></button>
       </form>
     </template>
 
     <template id="login-filter-template">
       <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/login-filter.css">
-      <input class="filter" type="text"/>
+      <input data-l10n-id="login-filter" class="filter" type="text"/>
     </template>
 
     <template id="menu-button-template">
       <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/menu-button.css">
-      <button class="menu-button alternate-button"></button>
+      <button class="menu-button alternate-button" data-l10n-id="menu"></button>
       <ul class="menu" role="menu" hidden>
-        <button role="menuitem" class="menuitem-button menuitem-import alternate-button" hidden data-supported-platforms="Win32" data-event-name="AboutLoginsImport"></button>
-        <button role="menuitem" class="menuitem-button menuitem-preferences alternate-button" data-event-name="AboutLoginsOpenPreferences"></button>
-        <button role="menuitem" class="menuitem-button menuitem-feedback alternate-button" data-event-name="AboutLoginsOpenFeedback"></button>
-        <button role="menuitem" class="menuitem-button menuitem-faq alternate-button" data-event-name="AboutLoginsOpenFAQ"></button>
+        <button role="menuitem" class="menuitem-button menuitem-import alternate-button" hidden data-supported-platforms="Win32" data-event-name="AboutLoginsImport" data-l10n-id="menu-menuitem-import"></button>
+        <button role="menuitem" class="menuitem-button menuitem-preferences alternate-button" data-event-name="AboutLoginsOpenPreferences" data-l10n-id="menu-menuitem-preferences"></button>
+        <button role="menuitem" class="menuitem-button menuitem-feedback alternate-button" data-event-name="AboutLoginsOpenFeedback" data-l10n-id="menu-menuitem-feedback"></button>
+        <button role="menuitem" class="menuitem-button menuitem-faq alternate-button" data-event-name="AboutLoginsOpenFAQ" data-l10n-id="menu-menuitem-faq"></button>
       </ul>
     </template>
-
-    <template id="copy-to-clipboard-button-template">
-      <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
-      <link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/copy-to-clipboard-button.css">
-      <button class="copy-button">
-        <span class="copied-button-text"></span>
-        <span class="copy-button-text"></span>
-      </button>
-    </template>
   </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/browser/components/aboutlogins/content/components/confirm-delete-dialog.css
@@ -0,0 +1,94 @@
+:host {
+  /* these variable values come from about:preferences */
+  --in-content-dialogtitle-background: #f1f1f1;
+  --in-content-dialogtitle-border: #c1c1c1;
+}
+
+.overlay {
+  position: fixed;
+  z-index: 1;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  /* TODO: this color is used in the about:preferences overlay, but
+           why isn't it declared as a variable? */
+  background-color: rgba(0,0,0,0.5);
+  display: flex;
+  align-items: center;
+}
+
+.container {
+  z-index: 2;
+
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+
+  width: 50%;
+  min-width: 250px;
+  max-width: 500px;
+  height: 40%;
+  min-height: 200px;
+  margin: auto;
+  background: var(--in-content-page-background);
+  color: var(--in-content-page-color);
+}
+
+.title-bar {
+  position: relative;
+  flex: 0 1 auto;
+  text-align: center;
+  background-color: var(--in-content-dialogtitle-background);
+  padding: 5px;
+  border-bottom: 1px solid var(--in-content-dialogtitle-border);
+}
+
+.title {
+  font-size: .9em;
+  line-height: 1.8em;
+  font-weight: 600;
+  -moz-user-select: none;
+  margin: 0;
+}
+
+button.dismiss-button {
+  position: absolute;
+  top: 0;
+  right: 0;
+  min-width: 20px;
+  min-height: 20px;
+  margin: 8px 16px;
+  padding: 0;
+  background: url(chrome://global/skin/icons/close.svg) no-repeat center;
+  -moz-context-properties: fill, fill-opacity;
+  fill: currentColor;
+  fill-opacity: 0;
+}
+
+button.dismiss-button:dir(rtl) {
+  right: auto;
+  left: 0;
+}
+
+.content {
+  flex: 1 1 auto;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.buttons {
+  flex: 0 1 auto;
+  display: flex;
+  justify-content: space-between;
+}
+
+.buttons button {
+  margin: 0;
+}
+
+.content,
+.buttons {
+  margin: 16px;
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/aboutlogins/content/components/confirm-delete-dialog.js
@@ -0,0 +1,87 @@
+/* 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/. */
+
+export default class ConfirmDeleteDialog extends HTMLElement {
+  constructor() {
+    super();
+    this._promise = null;
+  }
+
+  connectedCallback() {
+    if (this.shadowRoot) {
+      return;
+    }
+    let template = document.querySelector("#confirm-delete-dialog-template");
+    let shadowRoot = this.attachShadow({mode: "open"});
+    document.l10n.connectRoot(shadowRoot);
+    shadowRoot.appendChild(template.content.cloneNode(true));
+
+    this._cancelButton = this.shadowRoot.querySelector(".cancel-button");
+    this._confirmButton = this.shadowRoot.querySelector(".confirm-button");
+    this._dismissButton = this.shadowRoot.querySelector(".dismiss-button");
+    this._message = this.shadowRoot.querySelector(".message");
+    this._overlay = this.shadowRoot.querySelector(".overlay");
+    this._title = this.shadowRoot.querySelector(".title");
+  }
+
+  handleEvent(event) {
+    switch (event.type) {
+      case "keydown":
+        if (event.key === "Escape" && !event.defaultPrevented) {
+          this.onCancel();
+        }
+        break;
+      case "click":
+        if (event.target.classList.contains("cancel-button") ||
+            event.target.classList.contains("dismiss-button") ||
+            event.target.classList.contains("overlay")) {
+          this.onCancel();
+        } else if (event.target.classList.contains("confirm-button")) {
+          this.onConfirm();
+        }
+    }
+  }
+
+  hide() {
+    this._cancelButton.removeEventListener("click", this);
+    this._confirmButton.removeEventListener("click", this);
+    this._dismissButton.removeEventListener("click", this);
+    this._overlay.removeEventListener("click", this);
+    window.removeEventListener("keydown", this);
+
+    this.hidden = true;
+  }
+
+  show() {
+    this.hidden = false;
+
+    this._cancelButton.addEventListener("click", this);
+    this._confirmButton.addEventListener("click", this);
+    this._dismissButton.addEventListener("click", this);
+    this._overlay.addEventListener("click", this);
+    window.addEventListener("keydown", this);
+
+    // For accessibility, focus the least destructive action button when the
+    // dialog loads.
+    this._cancelButton.focus();
+
+    this._promise = new Promise((resolve, reject) => {
+      this._resolve = resolve;
+      this._reject = reject;
+    });
+
+    return this._promise;
+  }
+
+  onCancel() {
+    this._reject();
+    this.hide();
+  }
+
+  onConfirm() {
+    this._resolve();
+    this.hide();
+  }
+}
+customElements.define("confirm-delete-dialog", ConfirmDeleteDialog);
deleted file mode 100644
--- a/browser/components/aboutlogins/content/components/copy-to-clipboard-button.css
+++ /dev/null
@@ -1,29 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-:host {
-  --success-color: #00c100;
-}
-
-@supports -moz-bool-pref("browser.in-content.dark-mode") {
-@media (prefers-color-scheme: dark) {
-  :host {
-    --success-color: #86DE74;
-  }
-}
-}
-
-:host(:not([data-copied])) .copied-button-text,
-:host([data-copied]) .copy-button-text {
-  display: none;
-}
-
-:host([data-copied]) {
-  color: var(--success-color);
-}
-
-:host([data-copied]) button {
-  background-color: transparent;
-  opacity: 1; /* override common.css fading out disabled buttons */
-}
deleted file mode 100644
--- a/browser/components/aboutlogins/content/components/copy-to-clipboard-button.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-import {recordTelemetryEvent} from "../aboutLoginsUtils.js";
-import ReflectedFluentElement from "./reflected-fluent-element.js";
-
-export default class CopyToClipboardButton extends ReflectedFluentElement {
-  /**
-   * The number of milliseconds to display the "Copied" success message
-   * before reverting to the normal "Copy" button.
-   */
-  static get BUTTON_RESET_TIMEOUT() {
-    return 5000;
-  }
-
-  constructor() {
-    super();
-
-    this._relatedInput = null;
-  }
-
-  connectedCallback() {
-    if (this.shadowRoot) {
-      return;
-    }
-
-    let CopyToClipboardButtonTemplate = document.querySelector("#copy-to-clipboard-button-template");
-    this.attachShadow({mode: "open"})
-        .appendChild(CopyToClipboardButtonTemplate.content.cloneNode(true));
-
-    this._copyButton = this.shadowRoot.querySelector(".copy-button");
-    this._copyButton.addEventListener("click", this);
-
-    super.connectedCallback();
-  }
-
-  static get reflectedFluentIDs() {
-    return ["copy-button-text", "copied-button-text"];
-  }
-
-  static get observedAttributes() {
-    return CopyToClipboardButton.reflectedFluentIDs;
-  }
-
-  handleSpecialCaseFluentString(attrName) {
-    if (attrName != "copied-button-text" &&
-        attrName != "copy-button-text") {
-      return false;
-    }
-
-    let span = this.shadowRoot.querySelector("." + attrName);
-    span.textContent = this.getAttribute(attrName);
-    return true;
-  }
-
-  handleEvent(event) {
-    if (event.type != "click" || event.currentTarget != this._copyButton) {
-      return;
-    }
-
-    this._copyButton.disabled = true;
-    navigator.clipboard.writeText(this._relatedInput.value).then(() => {
-      this.dataset.copied = true;
-      setTimeout(() => {
-        this._copyButton.disabled = false;
-        delete this.dataset.copied;
-      }, CopyToClipboardButton.BUTTON_RESET_TIMEOUT);
-    }, () => this._copyButton.disabled = false);
-
-    if (this.dataset.telemetryObject) {
-      recordTelemetryEvent({object: this.dataset.telemetryObject, method: "copy"});
-    }
-  }
-
-  /**
-   * @param {Element} val A reference to the input element whose value will
-   *                      be placed on the clipboard.
-   */
-  set relatedInput(val) {
-    this._relatedInput = val;
-  }
-}
-customElements.define("copy-to-clipboard-button", CopyToClipboardButton);
--- a/browser/components/aboutlogins/content/components/login-filter.js
+++ b/browser/components/aboutlogins/content/components/login-filter.js
@@ -1,68 +1,48 @@
 /* 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/. */
 
 import {recordTelemetryEvent} from "../aboutLoginsUtils.js";
-import ReflectedFluentElement from "./reflected-fluent-element.js";
 
-export default class LoginFilter extends ReflectedFluentElement {
+export default class LoginFilter extends HTMLElement {
   connectedCallback() {
     if (this.shadowRoot) {
       return;
     }
 
     let loginFilterTemplate = document.querySelector("#login-filter-template");
-    this.attachShadow({mode: "open"})
-        .appendChild(loginFilterTemplate.content.cloneNode(true));
+    let shadowRoot = this.attachShadow({mode: "open"});
+    document.l10n.connectRoot(shadowRoot);
+    shadowRoot.appendChild(loginFilterTemplate.content.cloneNode(true));
 
     this._input = this.shadowRoot.querySelector("input");
 
     this.addEventListener("input", this);
-
-    super.connectedCallback();
   }
 
   handleEvent(event) {
     switch (event.type) {
       case "input": {
         this._dispatchFilterEvent(event.originalTarget.value);
         break;
       }
     }
   }
 
-  static get reflectedFluentIDs() {
-    return ["placeholder"];
-  }
-
-  static get observedAttributes() {
-    return this.reflectedFluentIDs;
-  }
-
   get value() {
     return this._input.value;
   }
 
   set value(val) {
     this._input.value = val;
     this._dispatchFilterEvent(val);
   }
 
-  handleSpecialCaseFluentString(attrName) {
-    if (!this.shadowRoot ||
-        attrName != "placeholder") {
-      return false;
-    }
-
-    this._input.placeholder = this.getAttribute(attrName);
-    return true;
-  }
-
   _dispatchFilterEvent(value) {
     this.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
       bubbles: true,
       composed: true,
       detail: value,
     }));
 
     recordTelemetryEvent({object: "list", method: "filter"});
--- a/browser/components/aboutlogins/content/components/login-item.css
+++ b/browser/components/aboutlogins/content/components/login-item.css
@@ -3,24 +3,35 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 :host {
   padding: 18px;
 
   --reveal-checkbox-opacity: .8;
   --reveal-checkbox-opacity-hover: .6;
   --reveal-checkbox-opacity-active: 1;
+  --success-color: #00c100;
+}
+
+@supports -moz-bool-pref("browser.in-content.dark-mode") {
+@media (prefers-color-scheme: dark) {
+  :host {
+    --success-color: #86DE74;
+  }
+}
 }
 
 :host([data-editing]) .edit-button,
 :host([data-is-new-login]) .delete-button,
 :host([data-is-new-login]) .origin-saved-value,
 :host([data-is-new-login]) copy-to-clipboard-button,
 :host([data-is-new-login]) .open-site-button,
 :host([data-is-new-login]) .meta-info,
+:host([data-is-new-login]) .login-item-title,
+:host(:not([data-is-new-login])) .new-login-title,
 :host(:not([data-editing])) .cancel-button,
 :host(:not([data-editing])) .save-changes-button {
   display: none;
 }
 
 :host(:not([data-editing])) input[type="password"],
 :host(:not([data-editing])) input[type="text"],
 :host(:not([data-editing])) input[type="url"] {
@@ -85,16 +96,27 @@
 
 .field-label {
   display: block;
   font-size: smaller;
   color: var(--in-content-deemphasized-text);
   margin-bottom: 5px;
 }
 
+.copy-button:not([data-copied]) .copied-button-text,
+.copy-button[data-copied] .copy-button-text {
+  display: none;
+}
+
+.copy-button[data-copied] {
+  color: var(--success-color) !important; /* override common.css */
+  background-color: transparent;
+  opacity: 1; /* override common.css fading out disabled buttons */
+}
+
 .meta-info {
   font-size: smaller;
 }
 
 .meta-info:first-of-type {
   padding-top: 1em;
   border-top: 1px solid var(--in-content-box-border-color);
   width: 40px;
--- a/browser/components/aboutlogins/content/components/login-item.js
+++ b/browser/components/aboutlogins/content/components/login-item.js
@@ -1,143 +1,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/. */
 
 import {recordTelemetryEvent} from "../aboutLoginsUtils.js";
-import ReflectedFluentElement from "./reflected-fluent-element.js";
 
-export default class LoginItem extends ReflectedFluentElement {
+export default class LoginItem extends HTMLElement {
+  /**
+   * The number of milliseconds to display the "Copied" success message
+   * before reverting to the normal "Copy" button.
+   */
+  static get COPY_BUTTON_RESET_TIMEOUT() {
+    return 5000;
+  }
+
   constructor() {
     super();
     this._login = {};
   }
 
   connectedCallback() {
     if (this.shadowRoot) {
       this.render();
       return;
     }
 
     let loginItemTemplate = document.querySelector("#login-item-template");
-    this.attachShadow({mode: "open"})
-        .appendChild(loginItemTemplate.content.cloneNode(true));
+    let shadowRoot = this.attachShadow({mode: "open"});
+    document.l10n.connectRoot(shadowRoot);
+    shadowRoot.appendChild(loginItemTemplate.content.cloneNode(true));
 
     for (let selector of [
+      ".copy-password-button",
+      ".copy-username-button",
       ".delete-button",
       ".edit-button",
       ".open-site-button",
+      ".reveal-password-checkbox",
       ".save-changes-button",
       ".cancel-button",
     ]) {
       let button = this.shadowRoot.querySelector(selector);
       button.addEventListener("click", this);
     }
 
+    this._confirmDeleteDialog = document.querySelector("confirm-delete-dialog");
     this._copyPasswordButton = this.shadowRoot.querySelector(".copy-password-button");
     this._copyUsernameButton = this.shadowRoot.querySelector(".copy-username-button");
     this._deleteButton = this.shadowRoot.querySelector(".delete-button");
     this._editButton = this.shadowRoot.querySelector(".edit-button");
     this._form = this.shadowRoot.querySelector("form");
     this._originInput = this.shadowRoot.querySelector("input[name='origin']");
     this._usernameInput = this.shadowRoot.querySelector("input[name='username']");
     this._passwordInput = this.shadowRoot.querySelector("input[name='password']");
     this._revealCheckbox = this.shadowRoot.querySelector(".reveal-password-checkbox");
-    this._title = this.shadowRoot.querySelector(".title");
-
-    this._copyUsernameButton.relatedInput = this._usernameInput;
-    this._copyPasswordButton.relatedInput = this._passwordInput;
+    this._title = this.shadowRoot.querySelector(".login-item-title");
+    this._timeCreated = this.shadowRoot.querySelector(".time-created");
+    this._timeChanged = this.shadowRoot.querySelector(".time-changed");
+    this._timeUsed = this.shadowRoot.querySelector(".time-used");
 
     this.render();
 
     this._originInput.addEventListener("blur", this);
-    this._revealCheckbox.addEventListener("click", this);
     window.addEventListener("AboutLoginsLoginSelected", this);
-
-    super.connectedCallback();
-  }
-
-  static get reflectedFluentIDs() {
-    return [
-      "cancel-button",
-      "copied-password-button",
-      "copied-username-button",
-      "copy-password-button",
-      "copy-username-button",
-      "delete-button",
-      "edit-button",
-      "new-login-title",
-      "open-site-button",
-      "origin-label",
-      "origin-placeholder",
-      "password-hide-title",
-      "password-label",
-      "password-show-title",
-      "save-changes-button",
-      "time-created",
-      "time-changed",
-      "time-used",
-      "username-label",
-      "username-placeholder",
-    ];
-  }
-
-  static get observedAttributes() {
-    return this.reflectedFluentIDs;
-  }
-
-  handleSpecialCaseFluentString(attrName) {
-    switch (attrName) {
-      case "copied-password-button":
-      case "copy-password-button": {
-        let newAttrName = attrName.substr(0, attrName.indexOf("-")) + "-button-text";
-        this._copyPasswordButton.setAttribute(newAttrName, this.getAttribute(attrName));
-        break;
-      }
-      case "copied-username-button":
-      case "copy-username-button": {
-        let newAttrName = attrName.substr(0, attrName.indexOf("-")) + "-button-text";
-        this._copyUsernameButton.setAttribute(newAttrName, this.getAttribute(attrName));
-        break;
-      }
-      case "new-login-title": {
-        this._title.setAttribute(attrName, this.getAttribute(attrName));
-        if (!this._login.title) {
-          this._title.textContent = this.getAttribute(attrName);
-        }
-        break;
-      }
-      case "origin-placeholder": {
-        this._originInput.setAttribute("placeholder", this.getAttribute(attrName));
-        break;
-      }
-      case "password-hide-title":
-      case "password-show-title": {
-        this._updatePasswordRevealState();
-        break;
-      }
-      case "username-placeholder": {
-        this._usernameInput.setAttribute("placeholder", this.getAttribute(attrName));
-        break;
-      }
-      default:
-        return false;
-    }
-    return true;
   }
 
   render() {
-    let l10nArgs = {
-      timeCreated: this._login.timeCreated || "",
-      timeChanged: this._login.timePasswordChanged || "",
-      timeUsed: this._login.timeLastUsed || "",
-    };
-    document.l10n.setAttributes(this, "login-item", l10nArgs);
+    document.l10n.setAttributes(this._timeCreated, "login-item-time-created", {timeCreated: this._login.timeCreated || ""});
+    document.l10n.setAttributes(this._timeChanged, "login-item-time-changed", {timeChanged: this._login.timePasswordChanged || ""});
+    document.l10n.setAttributes(this._timeUsed, "login-item-time-used", {timeUsed: this._login.timeLastUsed || ""});
 
-    this._title.textContent = this._login.title || this._title.getAttribute("new-login-title");
+    this._title.textContent = this._login.title;
     this._originInput.defaultValue = this._login.origin || "";
     this._usernameInput.defaultValue = this._login.username || "";
     this._passwordInput.defaultValue = this._login.password || "";
     this._updatePasswordRevealState();
   }
 
   handleEvent(event) {
     switch (event.type) {
@@ -152,17 +89,17 @@ export default class LoginItem extends R
           return;
         }
         if (!originValue.match(/:\/\//)) {
           this._originInput.value = "https://" + originValue;
         }
         break;
       }
       case "click": {
-        let classList = event.target.classList;
+        let classList = event.currentTarget.classList;
         if (classList.contains("reveal-password-checkbox")) {
           this._updatePasswordRevealState();
 
           let method = this._revealCheckbox.checked ? "show" : "hide";
           recordTelemetryEvent({object: "password", method});
           return;
         }
 
@@ -179,23 +116,34 @@ export default class LoginItem extends R
           }
 
           recordTelemetryEvent({
             object: this._login.guid ? "existing_login" : "new_login",
             method: "cancel",
           });
           return;
         }
+        if (classList.contains("copy-password-button") ||
+            classList.contains("copy-username-button")) {
+          let copyButton = event.currentTarget;
+          copyButton.disabled = true;
+          let propertyToCopy = copyButton.dataset.copyLoginProperty;
+          navigator.clipboard.writeText(this._login[propertyToCopy]).then(() => {
+            copyButton.dataset.copied = true;
+            setTimeout(() => {
+              copyButton.disabled = false;
+              delete copyButton.dataset.copied;
+            }, LoginItem.COPY_BUTTON_RESET_TIMEOUT);
+          }, () => copyButton.disabled = false);
+
+          recordTelemetryEvent({object: copyButton.dataset.telemetryObject, method: "copy"});
+          return;
+        }
         if (classList.contains("delete-button")) {
-          document.dispatchEvent(new CustomEvent("AboutLoginsDeleteLogin", {
-            bubbles: true,
-            detail: this._login,
-          }));
-
-          recordTelemetryEvent({object: "existing_login", method: "delete"});
+          this.confirmDelete();
           return;
         }
         if (classList.contains("edit-button")) {
           this._toggleEditing();
 
           recordTelemetryEvent({object: "existing_login", method: "edit"});
           return;
         }
@@ -231,16 +179,31 @@ export default class LoginItem extends R
           }
         }
         break;
       }
     }
   }
 
   /**
+   * Toggles the confirm delete dialog, completing the deletion if the user
+   * agrees.
+   */
+  confirmDelete() {
+    const dialog = document.querySelector("confirm-delete-dialog");
+    dialog.show().then(() => {
+      document.dispatchEvent(new CustomEvent("AboutLoginsDeleteLogin", {
+        bubbles: true,
+        detail: this._login,
+      }));
+      recordTelemetryEvent({object: "existing_login", method: "delete"});
+    }, () => {});
+  }
+
+  /**
    * @param {login} login The login that should be displayed. The login object is
    *                      a plain JS object representation of nsILoginInfo/nsILoginMetaInfo.
    */
   setLogin(login) {
     this._login = login;
 
     this._form.reset();
 
@@ -376,19 +339,18 @@ export default class LoginItem extends R
       this.dataset.editing = true;
       this._originInput.focus();
     } else {
       delete this.dataset.editing;
     }
   }
 
   _updatePasswordRevealState() {
-    let labelAttr = this._revealCheckbox.checked ? "password-show-title"
-                                                 : "password-hide-title";
-    this._revealCheckbox.setAttribute("aria-label", this.getAttribute(labelAttr));
-    this._revealCheckbox.setAttribute("title", this.getAttribute(labelAttr));
+    let titleId = this._revealCheckbox.checked ? "login-item-password-reveal-checkbox-hide"
+                                               : "login-item-password-reveal-checkbox-show";
+    document.l10n.setAttributes(this._revealCheckbox, titleId);
 
     let {checked} = this._revealCheckbox;
-    let inputType = checked ? "type" : "password";
+    let inputType = checked ? "text" : "password";
     this._passwordInput.setAttribute("type", inputType);
   }
 }
 customElements.define("login-item", LoginItem);
--- a/browser/components/aboutlogins/content/components/login-list-item.js
+++ b/browser/components/aboutlogins/content/components/login-list-item.js
@@ -16,39 +16,45 @@ export default class LoginListItem exten
 
   connectedCallback() {
     if (this.shadowRoot) {
       this.render();
       return;
     }
 
     let loginListItemTemplate = document.querySelector("#login-list-item-template");
-    this.attachShadow({mode: "open"})
-        .appendChild(loginListItemTemplate.content.cloneNode(true));
+    let shadowRoot = this.attachShadow({mode: "open"});
+    document.l10n.connectRoot(shadowRoot);
+    shadowRoot.appendChild(loginListItemTemplate.content.cloneNode(true));
 
     this._title = this.shadowRoot.querySelector(".title");
     this._username = this.shadowRoot.querySelector(".username");
     this.setAttribute("role", "option");
 
-    this.render();
+    this.addEventListener("click", this);
 
-    this.addEventListener("click", this);
+    this.render();
   }
 
   render() {
     if (!this._login.guid) {
       delete this.dataset.guid;
-      this._title.textContent = this.getAttribute("new-login-title");
-      this._username.textContent = this.getAttribute("new-login-subtitle");
+      document.l10n.setAttributes(this._title, "login-list-item-title-new-login");
+      document.l10n.setAttributes(this._username, "login-list-item-subtitle-new-login");
       return;
     }
 
     this.dataset.guid = this._login.guid;
     this._title.textContent = this._login.title;
-    this._username.textContent = this._login.username.trim() || this.getAttribute("missing-username");
+    if (this._login.username.trim()) {
+      this._username.removeAttribute("data-l10n-id");
+      this._username.textContent = this._login.username.trim();
+    } else {
+      document.l10n.setAttributes(this._username, "login-list-item-subtitle-missing-username");
+    }
   }
 
   handleEvent(event) {
     switch (event.type) {
       case "click": {
         this.dispatchEvent(new CustomEvent("AboutLoginsLoginSelected", {
           bubbles: true,
           composed: true,
--- a/browser/components/aboutlogins/content/components/login-list.js
+++ b/browser/components/aboutlogins/content/components/login-list.js
@@ -1,80 +1,78 @@
 /* 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/. */
 
 import LoginListItem from "./login-list-item.js";
-import ReflectedFluentElement from "./reflected-fluent-element.js";
 
 const collator = new Intl.Collator();
 const sortFnOptions = {
   name: (a, b) => collator.compare(a.title, b.title),
   "last-used": (a, b) => (a.timeLastUsed < b.timeLastUsed),
   "last-changed": (a, b) => (a.timePasswordChanged < b.timePasswordChanged),
 };
 
-export default class LoginList extends ReflectedFluentElement {
+export default class LoginList extends HTMLElement {
   constructor() {
     super();
     this._logins = [];
     this._filter = "";
     this._selectedGuid = null;
     this._blankLoginListItem = new LoginListItem({});
   }
 
   connectedCallback() {
     if (this.shadowRoot) {
       return;
     }
     let loginListTemplate = document.querySelector("#login-list-template");
-    this.attachShadow({mode: "open"})
-        .appendChild(loginListTemplate.content.cloneNode(true));
+    let shadowRoot = this.attachShadow({mode: "open"});
+    document.l10n.connectRoot(shadowRoot);
+    shadowRoot.appendChild(loginListTemplate.content.cloneNode(true));
 
     this._list = this.shadowRoot.querySelector("ol");
+    this._count = this.shadowRoot.querySelector(".count");
 
     this.render();
 
     this.shadowRoot.getElementById("login-sort")
                    .addEventListener("change", this);
     window.addEventListener("AboutLoginsLoginSelected", this);
     window.addEventListener("AboutLoginsFilterLogins", this);
     this.addEventListener("keydown", this);
-
-    super.connectedCallback();
   }
 
   render() {
     this._list.textContent = "";
 
     if (!this._logins.length) {
-      document.l10n.setAttributes(this, "login-list", {count: 0});
+      document.l10n.setAttributes(this._count, "login-list-count", {count: 0});
       return;
     }
 
     if (!this._selectedGuid) {
       this._blankLoginListItem.classList.add("selected");
       this._blankLoginListItem.setAttribute("aria-selected", "true");
       this._list.setAttribute("aria-activedescendant", this._blankLoginListItem.id);
       this._list.append(this._blankLoginListItem);
     }
 
     for (let login of this._logins) {
       let listItem = new LoginListItem(login);
-      listItem.setAttribute("missing-username", this.getAttribute("missing-username"));
       if (login.guid == this._selectedGuid) {
         listItem.classList.add("selected");
         listItem.setAttribute("aria-selected", "true");
         this._list.setAttribute("aria-activedescendant", listItem.id);
       }
       this._list.append(listItem);
     }
 
     let visibleLoginCount = this._applyFilter();
-    document.l10n.setAttributes(this, "login-list", {count: visibleLoginCount});
+    document.l10n.setAttributes(this._count, "login-list-count", {count: visibleLoginCount});
   }
 
   handleEvent(event) {
     switch (event.type) {
       case "change": {
         const sort = event.target.value;
         this._logins = this._logins.sort((a, b) => sortFnOptions[sort](a, b));
         this.render();
@@ -96,52 +94,16 @@ export default class LoginList extends R
       }
       case "keydown": {
         this._handleKeyboardNav(event);
         break;
       }
     }
   }
 
-  static get reflectedFluentIDs() {
-    return ["aria-label",
-            "count",
-            "last-used-option",
-            "last-changed-option",
-            "missing-username",
-            "name-option",
-            "new-login-subtitle",
-            "new-login-title",
-            "sort-label-text"];
-  }
-
-  static get observedAttributes() {
-    return this.reflectedFluentIDs;
-  }
-
-  handleSpecialCaseFluentString(attrName) {
-    switch (attrName) {
-      case "aria-label": {
-        this._list.setAttribute("aria-label", this.getAttribute(attrName));
-        break;
-      }
-      case "missing-username": {
-        break;
-      }
-      case "new-login-subtitle":
-      case "new-login-title": {
-        this._blankLoginListItem.setAttribute(attrName, this.getAttribute(attrName));
-        break;
-      }
-      default:
-        return false;
-    }
-    return true;
-  }
-
   /**
    * @param {login[]} logins An array of logins used for displaying in the list.
    */
   setLogins(logins) {
     this._logins = logins;
     this.render();
   }
 
--- a/browser/components/aboutlogins/content/components/menu-button.js
+++ b/browser/components/aboutlogins/content/components/menu-button.js
@@ -1,63 +1,36 @@
 /* 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/. */
 
-import ReflectedFluentElement from "chrome://browser/content/aboutlogins/components/reflected-fluent-element.js";
-
-export default class MenuButton extends ReflectedFluentElement {
+export default class MenuButton extends HTMLElement {
   connectedCallback() {
     if (this.shadowRoot) {
       return;
     }
 
     let MenuButtonTemplate = document.querySelector("#menu-button-template");
-    this.attachShadow({mode: "open"})
-        .appendChild(MenuButtonTemplate.content.cloneNode(true));
+    let shadowRoot = this.attachShadow({mode: "open"});
+    document.l10n.connectRoot(shadowRoot);
+    shadowRoot.appendChild(MenuButtonTemplate.content.cloneNode(true));
 
     for (let menuitem of this.shadowRoot.querySelectorAll(".menuitem-button[data-supported-platforms]")) {
       let supportedPlatforms = menuitem.dataset.supportedPlatforms.split(",").map(platform => platform.trim());
       if (supportedPlatforms.includes(navigator.platform)) {
         menuitem.hidden = false;
       }
     }
 
     this._menu = this.shadowRoot.querySelector(".menu");
     this._menuButton = this.shadowRoot.querySelector(".menu-button");
 
     this.addEventListener("blur", this);
     this._menuButton.addEventListener("click", this);
     this.addEventListener("keydown", this, true);
-
-    super.connectedCallback();
-  }
-
-  static get reflectedFluentIDs() {
-    return [
-      "button-title",
-      "menuitem-faq",
-      "menuitem-import",
-      "menuitem-feedback",
-      "menuitem-preferences",
-    ];
-  }
-
-  static get observedAttributes() {
-    return MenuButton.reflectedFluentIDs;
-  }
-
-  handleSpecialCaseFluentString(attrName) {
-    if (!this.shadowRoot ||
-        attrName != "button-title") {
-      return false;
-    }
-
-    this._menuButton.setAttribute("title", this.getAttribute(attrName));
-    return true;
   }
 
   handleEvent(event) {
     switch (event.type) {
       case "blur": {
         if (event.relatedTarget &&
             event.relatedTarget.closest(".menu") == this._menu) {
           // Only hide the menu if focus has left the menu-button.
deleted file mode 100644
--- a/browser/components/aboutlogins/content/components/reflected-fluent-element.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-export default class ReflectedFluentElement extends HTMLElement {
-  connectedCallback() {
-    this._reflectFluentStrings();
-  }
-
-  /*
-   * Fluent doesn't handle localizing into Shadow DOM yet so strings
-   * need to get reflected in to their targeted element.
-   */
-  attributeChangedCallback(attr, oldValue, newValue) {
-    if (!this.shadowRoot) {
-      return;
-    }
-
-    // Don't respond to attribute changes that aren't related to locale text.
-    if (!this.constructor.reflectedFluentIDs.includes(attr)) {
-      return;
-    }
-
-    if (this.handleSpecialCaseFluentString &&
-        this.handleSpecialCaseFluentString(attr)) {
-      return;
-    }
-
-    // Strings that are reflected to their shadowed element are assigned
-    // to an attribute name that matches a className on the element.
-    let shadowedElement = this.shadowRoot.querySelector("." + attr);
-    shadowedElement.textContent = newValue;
-  }
-
-  _isReflectedAttributePresent(attr) {
-    return this.constructor.reflectedFluentIDs.includes(attr.name);
-  }
-
-  /*
-   * Called to apply any localized strings that Fluent may have applied
-   * to the element before the custom element was defined.
-   */
-  _reflectFluentStrings() {
-    for (let reflectedFluentID of this.constructor.reflectedFluentIDs) {
-      if (this.hasAttribute(reflectedFluentID)) {
-        if (this.handleSpecialCaseFluentString &&
-            this.handleSpecialCaseFluentString(reflectedFluentID)) {
-          continue;
-        }
-
-        let attrValue = this.getAttribute(reflectedFluentID);
-        // Strings that are reflected to their shadowed element are assigned
-        // to an attribute name that matches a className on the element.
-        let shadowedElement = this.shadowRoot.querySelector("." + reflectedFluentID);
-        shadowedElement.textContent = attrValue;
-      }
-    }
-  }
-}
-customElements.define("reflected-fluent-element", ReflectedFluentElement);
--- a/browser/components/aboutlogins/jar.mn
+++ b/browser/components/aboutlogins/jar.mn
@@ -1,26 +1,25 @@
 # 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/.
 
 browser.jar:
-  content/browser/aboutlogins/components/copy-to-clipboard-button.css (content/components/copy-to-clipboard-button.css)
-  content/browser/aboutlogins/components/copy-to-clipboard-button.js  (content/components/copy-to-clipboard-button.js)
+  content/browser/aboutlogins/components/confirm-delete-dialog.css      (content/components/confirm-delete-dialog.css)
+  content/browser/aboutlogins/components/confirm-delete-dialog.js       (content/components/confirm-delete-dialog.js)
   content/browser/aboutlogins/components/login-filter.css      (content/components/login-filter.css)
   content/browser/aboutlogins/components/login-filter.js       (content/components/login-filter.js)
   content/browser/aboutlogins/components/login-item.css        (content/components/login-item.css)
   content/browser/aboutlogins/components/login-item.js         (content/components/login-item.js)
   content/browser/aboutlogins/components/login-list.css        (content/components/login-list.css)
   content/browser/aboutlogins/components/login-list.js         (content/components/login-list.js)
   content/browser/aboutlogins/components/login-list-item.css   (content/components/login-list-item.css)
   content/browser/aboutlogins/components/login-list-item.js    (content/components/login-list-item.js)
   content/browser/aboutlogins/components/menu-button.css       (content/components/menu-button.css)
   content/browser/aboutlogins/components/menu-button.js        (content/components/menu-button.js)
-  content/browser/aboutlogins/components/reflected-fluent-element.js  (content/components/reflected-fluent-element.js)
   content/browser/aboutlogins/icons/delete.svg        (content/icons/delete.svg)
   content/browser/aboutlogins/icons/edit.svg          (content/icons/edit.svg)
   content/browser/aboutlogins/icons/faq.svg           (content/icons/faq.svg)
   content/browser/aboutlogins/icons/favicon.svg       (content/icons/favicon.svg)
   content/browser/aboutlogins/icons/feedback.svg      (content/icons/feedback.svg)
   content/browser/aboutlogins/icons/hide-password.svg (content/icons/hide-password.svg)
   content/browser/aboutlogins/icons/show-password.svg (content/icons/show-password.svg)
   content/browser/aboutlogins/aboutLogins.css   (content/aboutLogins.css)
--- a/browser/components/aboutlogins/tests/browser/browser.ini
+++ b/browser/components/aboutlogins/tests/browser/browser.ini
@@ -3,16 +3,17 @@ prefs =
   signon.management.page.enabled=true
 support-files =
   head.js
 
 # Run first so content events from previous tests won't trickle in.
 # Skip ASAN and debug since waiting for content events is already slow.
 [browser_aaa_eventTelemetry_run_first.js]
 skip-if = asan || debug
+[browser_confirmDeleteDialog.js]
 [browser_copyToClipboardButton.js]
 [browser_createLogin.js]
 [browser_deleteLogin.js]
 [browser_loginListChanges.js]
 [browser_masterPassword.js]
 [browser_openFiltered.js]
 [browser_openImport.js]
 skip-if = (os != "win") # import is only available on Windows
--- a/browser/components/aboutlogins/tests/browser/browser_aaa_eventTelemetry_run_first.js
+++ b/browser/components/aboutlogins/tests/browser/browser_aaa_eventTelemetry_run_first.js
@@ -38,25 +38,23 @@ add_task(async function test_telemetry_e
     let loginListItem = loginList.shadowRoot.querySelector("login-list-item[data-guid]");
     loginListItem.click();
   });
   await waitForTelemetryEventCount(1);
 
   await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
     let loginItem = content.document.querySelector("login-item");
     let copyButton = loginItem.shadowRoot.querySelector(".copy-username-button");
-    copyButton = copyButton.shadowRoot.querySelector(".copy-button");
     copyButton.click();
   });
   await waitForTelemetryEventCount(2);
 
   await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
     let loginItem = content.document.querySelector("login-item");
     let copyButton = loginItem.shadowRoot.querySelector(".copy-password-button");
-    copyButton = copyButton.shadowRoot.querySelector(".copy-button");
     copyButton.click();
   });
   await waitForTelemetryEventCount(3);
 
   let promiseNewTab = BrowserTestUtils.waitForNewTab(gBrowser, TEST_LOGIN1.origin);
   await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
     let loginItem = content.document.querySelector("login-item");
     let openSiteButton = loginItem.shadowRoot.querySelector(".open-site-button");
@@ -103,16 +101,19 @@ add_task(async function test_telemetry_e
     loginListItem.click();
   });
   await waitForTelemetryEventCount(9);
 
   await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
     let loginItem = content.document.querySelector("login-item");
     let deleteButton = loginItem.shadowRoot.querySelector(".delete-button");
     deleteButton.click();
+    let confirmDeleteDialog = content.document.querySelector("confirm-delete-dialog");
+    let confirmDeleteButton = confirmDeleteDialog.shadowRoot.querySelector(".confirm-button");
+    confirmDeleteButton.click();
   });
   await waitForTelemetryEventCount(10);
 
   await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
     let loginFilter = content.document.querySelector("login-filter");
     let input = loginFilter.shadowRoot.querySelector("input");
     input.setUserInput("test");
   });
new file mode 100644
--- /dev/null
+++ b/browser/components/aboutlogins/tests/browser/browser_confirmDeleteDialog.js
@@ -0,0 +1,68 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(async function setup() {
+  await BrowserTestUtils.openNewForegroundTab({gBrowser, url: "about:logins"});
+  registerCleanupFunction(() => {
+    BrowserTestUtils.removeTab(gBrowser.selectedTab);
+  });
+});
+
+add_task(async function test() {
+  let browser = gBrowser.selectedBrowser;
+
+  await ContentTask.spawn(browser, null, async () => {
+    let dialog = Cu.waiveXrays(content.document.querySelector("confirm-delete-dialog"));
+
+    let cancelButton = dialog.shadowRoot.querySelector(".cancel-button");
+    let confirmDeleteButton = dialog.shadowRoot.querySelector(".confirm-button");
+    let dismissButton = dialog.shadowRoot.querySelector(".dismiss-button");
+    let message = dialog.shadowRoot.querySelector(".message");
+    let title = dialog.shadowRoot.querySelector(".title");
+
+    is(title.textContent, "Confirm Deletion",
+       "Title contents should match l10n attribute set on outer element");
+    is(message.textContent, "Are you sure you want to delete this login?",
+       "Message contents should match l10n attribute set on outer element");
+    is(cancelButton.textContent, "Cancel",
+       "Cancel button contents should match l10n attribute set on outer element");
+    is(confirmDeleteButton.textContent, "Delete login",
+       "Delete button contents should match l10n attribute set on outer element");
+
+    let showPromise = dialog.show();
+    cancelButton.click();
+    try {
+      await showPromise;
+      ok(false, "Promise returned by show() should not resolve after clicking cancel button");
+    } catch (ex) {
+      ok(true, "Promise returned by show() should reject after clicking cancel button");
+    }
+    await ContentTaskUtils.waitForCondition(() => dialog.hidden,
+      "Waiting for the dialog to be hidden");
+    ok(dialog.hidden, "Dialog should be hidden after clicking cancel button");
+
+    showPromise = dialog.show();
+    dismissButton.click();
+    try {
+      await showPromise;
+      ok(false, "Promise returned by show() should not resolve after clicking dismiss button");
+    } catch (ex) {
+      ok(true, "Promise returned by show() should reject after clicking dismiss button");
+    }
+    await ContentTaskUtils.waitForCondition(() => dialog.hidden,
+      "Waiting for the dialog to be hidden");
+    ok(dialog.hidden, "Dialog should be hidden after clicking dismiss button");
+
+    showPromise = dialog.show();
+    confirmDeleteButton.click();
+    try {
+      await showPromise;
+      ok(true, "Promise returned by show() should resolve after clicking confirm button");
+    } catch (ex) {
+      ok(false, "Promise returned by show() should not reject after clicking confirm button");
+    }
+    await ContentTaskUtils.waitForCondition(() => dialog.hidden,
+      "Waiting for the dialog to be hidden");
+    ok(dialog.hidden, "Dialog should be hidden after clicking confirm button");
+  });
+});
--- a/browser/components/aboutlogins/tests/browser/browser_copyToClipboardButton.js
+++ b/browser/components/aboutlogins/tests/browser/browser_copyToClipboardButton.js
@@ -14,18 +14,17 @@ add_task(async function test() {
 
     await ContentTask.spawn(browser, TEST_LOGIN, async function(login) {
       let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
 
       // The login object needs to be cloned into the content global.
       loginItem.setLogin(Cu.cloneInto(login, content));
 
       // Lower the timeout for the test.
-      let copyButton = loginItem.shadowRoot.querySelector(".copy-username-button");
-      Object.defineProperty(copyButton.constructor, "BUTTON_RESET_TIMEOUT", {
+      Object.defineProperty(loginItem.constructor, "COPY_BUTTON_RESET_TIMEOUT", {
           configurable: true,
           writable: true,
           value: 1000,
       });
     });
 
     for (let testCase of [
       [TEST_LOGIN.username, ".copy-username-button"],
@@ -35,19 +34,18 @@ add_task(async function test() {
         expectedValue: testCase[0],
         copyButtonSelector: testCase[1],
       };
       info("waiting for " + testObj.expectedValue + " to be placed on clipboard");
       await SimpleTest.promiseClipboardChange(testObj.expectedValue, async () => {
         await ContentTask.spawn(browser, testObj, async function(aTestObj) {
           let loginItem = content.document.querySelector("login-item");
           let copyButton = loginItem.shadowRoot.querySelector(aTestObj.copyButtonSelector);
-          let innerButton = copyButton.shadowRoot.querySelector("button");
           info("Clicking 'copy' button");
-          innerButton.click();
+          copyButton.click();
         });
       });
       ok(true, testObj.expectedValue + " is on clipboard now");
 
       await ContentTask.spawn(browser, testObj, async function(aTestObj) {
         let loginItem = content.document.querySelector("login-item");
         let copyButton = loginItem.shadowRoot.querySelector(aTestObj.copyButtonSelector);
         ok(copyButton.dataset.copied, "Success message should be shown");
--- a/browser/components/aboutlogins/tests/browser/browser_deleteLogin.js
+++ b/browser/components/aboutlogins/tests/browser/browser_deleteLogin.js
@@ -40,12 +40,16 @@ add_task(async function test_login_item(
     let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
     let loginItemPopulated = await ContentTaskUtils.waitForCondition(() => {
       return loginItem._login.guid == loginListItem.dataset.guid;
     }, "Waiting for login item to get populated");
     ok(loginItemPopulated, "The login item should get populated");
 
     let deleteButton = loginItem.shadowRoot.querySelector(".delete-button");
     deleteButton.click();
+
+    let confirmDeleteDialog = Cu.waiveXrays(content.document.querySelector("confirm-delete-dialog"));
+    let confirmButton = confirmDeleteDialog.shadowRoot.querySelector(".confirm-button");
+    confirmButton.click();
   });
   ok(deleteLoginMessageReceived,
      "Clicking the delete button should send the AboutLogins:DeleteLogin messsage");
 });
--- a/browser/components/aboutlogins/tests/browser/browser_updateLogin.js
+++ b/browser/components/aboutlogins/tests/browser/browser_updateLogin.js
@@ -75,16 +75,19 @@ add_task(async function test_login_item(
     ok(!loginItem.dataset.editing, "LoginItem should not be in 'edit' mode after saving");
 
     editButton.click();
     await Promise.resolve();
 
     ok(loginItem.dataset.editing, "LoginItem should be in 'edit' mode");
     let deleteButton = loginItem.shadowRoot.querySelector(".delete-button");
     deleteButton.click();
+    let confirmDeleteDialog = Cu.waiveXrays(content.document.querySelector("confirm-delete-dialog"));
+    let confirmDeleteButton = confirmDeleteDialog.shadowRoot.querySelector(".confirm-button");
+    confirmDeleteButton.click();
 
     await ContentTaskUtils.waitForCondition(() => {
       loginListItem = Cu.waiveXrays(loginList.shadowRoot.querySelector("login-list-item"));
       return !loginListItem;
     }, "Waiting for login to be removed from list");
 
     ok(!loginItem.dataset.editing, "LoginItem should not be in 'edit' mode after deleting");
   });
--- a/browser/components/aboutlogins/tests/chrome/aboutlogins_common.js
+++ b/browser/components/aboutlogins/tests/chrome/aboutlogins_common.js
@@ -1,11 +1,11 @@
 "use strict";
 
-/* exported asyncElementRendered, importDependencies, stubFluentL10n */
+/* exported asyncElementRendered, importDependencies */
 
 /**
  * A helper to await on while waiting for an asynchronous rendering of a Custom
  * Element.
  * @returns {Promise}
  */
 function asyncElementRendered() {
   return Promise.resolve();
@@ -20,23 +20,29 @@ function importDependencies(templateFram
   let templates = templateFrame.contentDocument.querySelectorAll("template");
   isnot(templates, null, "Check some templates found");
   for (let template of templates) {
     let imported = document.importNode(template, true);
     destinationEl.appendChild(imported);
   }
 }
 
-function stubFluentL10n(argsMap) {
-  Object.defineProperty(document, "l10n", {
-    configurable: true,
-    writable: true,
-    value: {
-      setAttributes(element, id, args) {
-        element.setAttribute("data-l10n-id", id);
-        for (let attrName of Object.keys(argsMap)) {
-          let varName = argsMap[attrName];
-          element.setAttribute(attrName, args[varName]);
-        }
-      },
+Object.defineProperty(document, "l10n", {
+  configurable: true,
+  writable: true,
+  value: {
+    connectRoot() {
+    },
+    translateElements() {
+      return Promise.resolve();
     },
-  });
-}
+    getAttributes(element) {
+      return {
+        id: element.getAttribute("data-l10n-id"),
+        args: JSON.parse(element.getAttribute("data-l10n-args")),
+      };
+    },
+    setAttributes(element, id, args) {
+      element.setAttribute("data-l10n-id", id);
+      element.setAttribute("data-l10n-args", JSON.stringify(args));
+    },
+  },
+});
--- a/browser/components/aboutlogins/tests/chrome/chrome.ini
+++ b/browser/components/aboutlogins/tests/chrome/chrome.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
 scheme = https
 support-files =
    aboutlogins_common.js
 
+[test_confirm_delete_dialog.html]
 [test_login_filter.html]
 [test_login_item.html]
 [test_login_list.html]
 [test_menu_button.html]
-[test_reflected_fluent_element.html]
new file mode 100644
--- /dev/null
+++ b/browser/components/aboutlogins/tests/chrome/test_confirm_delete_dialog.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test the confirm-delete-dialog component
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test the confirm-delete-dialog component</title>
+  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+  <script type="module" src="chrome://browser/content/aboutlogins/components/confirm-delete-dialog.js"></script>
+  <script src="aboutlogins_common.js"></script>
+
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+  <p id="display">
+  </p>
+<div id="content" style="display: none">
+  <iframe id="templateFrame" src="chrome://browser/content/aboutlogins/aboutLogins.html"
+          sandbox="allow-same-origin"></iframe>
+</div>
+<pre id="test">
+</pre>
+<script>
+/** Test the confirm-delete-dialog component **/
+
+let cancelButton, confirmButton, gConfirmDeleteDialog;
+add_task(async function setup() {
+  let templateFrame = document.getElementById("templateFrame");
+  let displayEl = document.getElementById("display");
+  importDependencies(templateFrame, displayEl);
+
+  gConfirmDeleteDialog = document.createElement("confirm-delete-dialog");
+  displayEl.appendChild(gConfirmDeleteDialog);
+  ok(gConfirmDeleteDialog, "The dialog should exist");
+
+  cancelButton = gConfirmDeleteDialog.shadowRoot.querySelector(".cancel-button");
+  confirmButton = gConfirmDeleteDialog.shadowRoot.querySelector(".confirm-button");
+  ok(cancelButton, "The cancel button should exist");
+  ok(confirmButton, "The confirm button should exist");
+});
+
+add_task(async function test_escape_key_to_cancel() {
+  gConfirmDeleteDialog.show();
+  ok(!gConfirmDeleteDialog.hidden, "The dialog should be visible");
+  sendKey("ESCAPE");
+  ok(gConfirmDeleteDialog.hidden, "The dialog should be hidden after hitting Escape");
+  gConfirmDeleteDialog.hide();
+});
+
+add_task(async function test_initial_focus() {
+  gConfirmDeleteDialog.show();
+  ok(!gConfirmDeleteDialog.hidden, "The dialog should be visible");
+  is(gConfirmDeleteDialog.shadowRoot.activeElement, cancelButton,
+     "After initially opening the dialog, the cancel button should be focused");
+  gConfirmDeleteDialog.hide();
+});
+
+add_task(async function test_tab_focus() {
+  gConfirmDeleteDialog.show();
+  ok(!gConfirmDeleteDialog.hidden, "The dialog should be visible");
+  sendKey("TAB");
+  is(gConfirmDeleteDialog.shadowRoot.activeElement, confirmButton,
+     "After opening the dialog and tabbing once, the confirm delete button should be focused");
+  gConfirmDeleteDialog.hide();
+});
+
+add_task(async function test_enter_key_to_cancel() {
+  let showPromise = gConfirmDeleteDialog.show();
+  ok(!gConfirmDeleteDialog.hidden, "The dialog should be visible");
+  sendKey("RETURN");
+  try {
+    await showPromise;
+    ok(false, "The dialog Promise should not resolve after hitting Return with the cancel button focused");
+  } catch (ex) {
+    ok(true, "The dialog Promise should reject after hitting Return with the cancel button focused");
+  }
+});
+
+add_task(async function test_enter_key_to_confirm() {
+  let showPromise = gConfirmDeleteDialog.show();
+  ok(!gConfirmDeleteDialog.hidden, "The dialog should be visible");
+  sendKey("TAB");
+  sendKey("RETURN");
+  try {
+    await showPromise;
+    ok(true, "The dialog Promise should resolve after hitting Return with the confirm button focused");
+  } catch (ex) {
+    ok(false, "The dialog Promise should not reject after hitting Return with the confirm button focused");
+  }
+});
+</script>
+</body>
+</html>
--- a/browser/components/aboutlogins/tests/chrome/test_login_filter.html
+++ b/browser/components/aboutlogins/tests/chrome/test_login_filter.html
@@ -24,20 +24,16 @@ Test the login-filter component
 <pre id="test">
 </pre>
 <script>
 /** Test the login-filter component **/
 
 let gLoginFilter;
 let gLoginList;
 add_task(async function setup() {
-  stubFluentL10n({
-    "count": "count",
-  });
-
   let templateFrame = document.getElementById("templateFrame");
   let displayEl = document.getElementById("display");
   importDependencies(templateFrame, displayEl);
 
   gLoginFilter = document.createElement("login-filter");
   displayEl.appendChild(gLoginFilter);
 
   gLoginList = document.createElement("login-list");
@@ -108,20 +104,18 @@ add_task(async function test_list_filter
 
     let filterLength = loginFilterInput.value.length;
     while (filterLength-- > 0) {
       sendKey("BACK_SPACE");
     }
     sendString(testObj.query);
 
     await SimpleTest.promiseWaitForCondition(() => {
-      return gLoginList.hasAttribute("count") &&
-             +gLoginList.getAttribute("count") == testObj.resultExpectedCount;
+      let countElement = gLoginList.shadowRoot.querySelector(".count");
+      return countElement.hasAttribute("data-l10n-args") &&
+             JSON.parse(countElement.getAttribute("data-l10n-args")).count == testObj.resultExpectedCount;
     }, `Waiting for the search result count to update to ${testObj.resultExpectedCount} (tc#${testObj.testCase})`);
-    let count = +gLoginList.getAttribute("count");
-    is(count, testObj.resultExpectedCount,
-       `The login list count should match the expected result (tc#${testObj.testCase})`);
   }
 });
 </script>
 
 </body>
 </html>
--- a/browser/components/aboutlogins/tests/chrome/test_login_item.html
+++ b/browser/components/aboutlogins/tests/chrome/test_login_item.html
@@ -42,70 +42,64 @@ const TEST_LOGIN_2 = {
   username: "user2",
   password: "pass2",
   timeCreated: "2000",
   timePasswordChanged: "4000",
   timeLastUsed: "8000",
 };
 
 add_task(async function setup() {
-  stubFluentL10n({
-    "time-created": "timeCreated",
-    "time-changed": "timeChanged",
-    "time-used": "timeUsed",
-  });
-
   let templateFrame = document.getElementById("templateFrame");
   let displayEl = document.getElementById("display");
   importDependencies(templateFrame, displayEl);
 
   gLoginItem = document.createElement("login-item");
   displayEl.appendChild(gLoginItem);
 });
 
 add_task(async function test_empty_item() {
   ok(gLoginItem, "loginItem exists");
   is(gLoginItem.shadowRoot.querySelector("input[name='origin']").value, "", "origin should be blank");
   is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, "", "username should be blank");
   is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, "", "password should be blank");
-  is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, "", "time-created should be blank when undefined");
-  is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, "", "time-changed should be blank when undefined");
-  is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, "", "time-used should be blank when undefined");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-created")).args.timeCreated, "", "time-created should be blank when undefined");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-changed")).args.timeChanged, "", "time-changed should be blank when undefined");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-used")).args.timeUsed, "", "time-used should be blank when undefined");
 });
 
 add_task(async function test_set_login() {
   gLoginItem.setLogin(TEST_LOGIN_1);
   await asyncElementRendered();
 
   ok(!gLoginItem.dataset.editing, "loginItem should not be in 'edit' mode");
   ok(!gLoginItem.dataset.isNewLogin, "loginItem should not be in 'isNewLogin' mode");
   is(gLoginItem.shadowRoot.querySelector("input[name='origin']").value, TEST_LOGIN_1.origin, "origin should be populated");
   is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, TEST_LOGIN_1.username, "username should be populated");
   is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, TEST_LOGIN_1.password, "password should be populated");
-  is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, TEST_LOGIN_1.timeCreated, "time-created should be populated");
-  is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, TEST_LOGIN_1.timePasswordChanged, "time-changed should be populated");
-  is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, TEST_LOGIN_1.timeLastUsed, "time-used should be populated");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-created")).args.timeCreated, TEST_LOGIN_1.timeCreated, "time-created should be populated");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-changed")).args.timeChanged, TEST_LOGIN_1.timePasswordChanged, "time-changed should be populated");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-used")).args.timeUsed, TEST_LOGIN_1.timeLastUsed, "time-used should be populated");
 });
 
 add_task(async function test_edit_login() {
   gLoginItem.setLogin(TEST_LOGIN_1);
   gLoginItem.shadowRoot.querySelector(".edit-button").click();
   await asyncElementRendered();
 
   ok(gLoginItem.dataset.editing, "loginItem should be in 'edit' mode");
   ok(isHidden(gLoginItem.shadowRoot.querySelector(".edit-button")), "edit button should be hidden in 'edit' mode");
   ok(!gLoginItem.dataset.isNewLogin, "loginItem should not be in 'isNewLogin' mode");
   let deleteButton = gLoginItem.shadowRoot.querySelector(".delete-button");
   ok(!deleteButton.disabled, "Delete button should be enabled when editing a login");
   is(gLoginItem.shadowRoot.querySelector("input[name='origin']").value, TEST_LOGIN_1.origin, "origin should be populated");
   is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, TEST_LOGIN_1.username, "username should be populated");
   is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, TEST_LOGIN_1.password, "password should be populated");
-  is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, TEST_LOGIN_1.timeCreated, "time-created should be populated");
-  is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, TEST_LOGIN_1.timePasswordChanged, "time-changed should be populated");
-  is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, TEST_LOGIN_1.timeLastUsed, "time-used should be populated");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-created")).args.timeCreated, TEST_LOGIN_1.timeCreated, "time-created should be populated");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-changed")).args.timeChanged, TEST_LOGIN_1.timePasswordChanged, "time-changed should be populated");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-used")).args.timeUsed, TEST_LOGIN_1.timeLastUsed, "time-used should be populated");
 
   gLoginItem.shadowRoot.querySelector("input[name='username']").value = "newUsername";
   gLoginItem.shadowRoot.querySelector("input[name='password']").value = "newPassword";
 
   let updateEventDispatched = false;
   document.addEventListener("AboutLoginsUpdateLogin", event => {
     is(event.detail.guid, TEST_LOGIN_1.guid, "event should include guid");
     is(event.detail.origin, TEST_LOGIN_1.origin, "event should include origin");
@@ -153,19 +147,19 @@ add_task(async function test_set_login_e
   ok(gLoginItem.dataset.editing, "loginItem should be in 'edit' mode");
   ok(isHidden(gLoginItem.shadowRoot.querySelector(".edit-button")), "edit button should be hidden in 'edit' mode");
   ok(gLoginItem.dataset.isNewLogin, "loginItem should be in 'isNewLogin' mode");
   let deleteButton = gLoginItem.shadowRoot.querySelector(".delete-button");
   ok(deleteButton.disabled, "Delete button should be disabled when creating a login");
   is(gLoginItem.shadowRoot.querySelector("input[name='origin']").value, "", "origin should be empty");
   is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, "", "username should be empty");
   is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, "", "password should be empty");
-  is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, "", "time-created should be blank when undefined");
-  is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, "", "time-changed should be blank when undefined");
-  is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, "", "time-used should be blank when undefined");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-created")).args.timeCreated, "", "time-created should be blank when undefined");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-changed")).args.timeChanged, "", "time-changed should be blank when undefined");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-used")).args.timeUsed, "", "time-used should be blank when undefined");
 
   let createEventDispatched = false;
   document.addEventListener("AboutLoginsCreateLogin", event => {
     createEventDispatched = true;
   }, {once: true});
   gLoginItem.shadowRoot.querySelector(".save-changes-button").click();
   ok(!createEventDispatched, "Clicking the .save-changes-button shouldn't dispatch the event when fields are invalid");
   let originInput = gLoginItem.shadowRoot.querySelector("input[name='origin']");
@@ -206,58 +200,58 @@ add_task(async function test_different_l
   gLoginItem.setLogin(TEST_LOGIN_1);
   let otherLogin = Object.assign({}, TEST_LOGIN_1, {username: "fakeuser", guid: "fakeguid"});
   gLoginItem.loginModified(otherLogin);
   await asyncElementRendered();
 
   is(gLoginItem.shadowRoot.querySelector("input[name='origin']").value, TEST_LOGIN_1.origin, "origin should be unchanged");
   is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, TEST_LOGIN_1.username, "username should be unchanged");
   is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, TEST_LOGIN_1.password, "password should be unchanged");
-  is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, TEST_LOGIN_1.timeCreated, "time-created should be unchanged");
-  is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, TEST_LOGIN_1.timePasswordChanged, "time-changed should be unchanged");
-  is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, TEST_LOGIN_1.timeLastUsed, "time-used should be unchanged");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-created")).args.timeCreated, TEST_LOGIN_1.timeCreated, "time-created should be unchanged");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-changed")).args.timeChanged, TEST_LOGIN_1.timePasswordChanged, "time-changed should be unchanged");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-used")).args.timeUsed, TEST_LOGIN_1.timeLastUsed, "time-used should be unchanged");
 });
 
 add_task(async function test_different_login_removed() {
   gLoginItem.setLogin(TEST_LOGIN_1);
   let otherLogin = Object.assign({}, TEST_LOGIN_1, {username: "fakeuser", guid: "fakeguid"});
   gLoginItem.loginRemoved(otherLogin);
   await asyncElementRendered();
 
   is(gLoginItem.shadowRoot.querySelector("input[name='origin']").value, TEST_LOGIN_1.origin, "origin should be unchanged");
   is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, TEST_LOGIN_1.username, "username should be unchanged");
   is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, TEST_LOGIN_1.password, "password should be unchanged");
-  is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, TEST_LOGIN_1.timeCreated, "time-created should be unchanged");
-  is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, TEST_LOGIN_1.timePasswordChanged, "time-changed should be unchanged");
-  is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, TEST_LOGIN_1.timeLastUsed, "time-used should be unchanged");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-created")).args.timeCreated, TEST_LOGIN_1.timeCreated, "time-created should be unchanged");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-changed")).args.timeChanged, TEST_LOGIN_1.timePasswordChanged, "time-changed should be unchanged");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-used")).args.timeUsed, TEST_LOGIN_1.timeLastUsed, "time-used should be unchanged");
 });
 
 add_task(async function test_login_modified() {
   gLoginItem.setLogin(TEST_LOGIN_1);
   let modifiedLogin = Object.assign({}, TEST_LOGIN_1, {username: "updateduser"});
   gLoginItem.loginModified(modifiedLogin);
   await asyncElementRendered();
 
   is(gLoginItem.shadowRoot.querySelector("input[name='origin']").value, modifiedLogin.origin, "origin should be updated");
   is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, modifiedLogin.username, "username should be updated");
   is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, modifiedLogin.password, "password should be updated");
-  is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, modifiedLogin.timeCreated, "time-created should be updated");
-  is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, modifiedLogin.timePasswordChanged, "time-changed should be updated");
-  is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, modifiedLogin.timeLastUsed, "time-used should be updated");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-created")).args.timeCreated, modifiedLogin.timeCreated, "time-created should be updated");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-changed")).args.timeChanged, modifiedLogin.timePasswordChanged, "time-changed should be updated");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-used")).args.timeUsed, modifiedLogin.timeLastUsed, "time-used should be updated");
 });
 
 add_task(async function test_login_removed() {
   gLoginItem.setLogin(TEST_LOGIN_1);
   gLoginItem.loginRemoved(TEST_LOGIN_1);
   await asyncElementRendered();
 
   is(gLoginItem.shadowRoot.querySelector("input[name='origin']").value, "", "origin should be cleared");
   is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, "", "username should be cleared");
   is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, "", "password should be cleared");
-  is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, "", "time-created should be blank when undefined");
-  is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, "", "time-changed should be blank when undefined");
-  is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, "", "time-used should be blank when undefined");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-created")).args.timeCreated, "", "time-created should be blank when undefined");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-changed")).args.timeChanged, "", "time-changed should be blank when undefined");
+  is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-used")).args.timeUsed, "", "time-used should be blank when undefined");
 });
 
 </script>
 
 </body>
 </html>
--- a/browser/components/aboutlogins/tests/chrome/test_login_list.html
+++ b/browser/components/aboutlogins/tests/chrome/test_login_list.html
@@ -53,20 +53,16 @@ const TEST_LOGIN_3 = {
   password: "pass3",
   title: "def.example.com",
   // new Date("June 1, 2019").getTime()
   timeLastUsed: 1559361600000,
   timePasswordChanged: 1559361600000,
 };
 
 add_task(async function setup() {
-  stubFluentL10n({
-    "count": "count",
-  });
-
   let templateFrame = document.getElementById("templateFrame");
   let displayEl = document.getElementById("display");
   importDependencies(templateFrame, displayEl);
 
   gLoginList = document.createElement("login-list");
   displayEl.appendChild(gLoginList);
 });
 
@@ -129,20 +125,19 @@ add_task(async function test_empty_login
   }));
 
   gLoginList.setLogins([TEST_LOGIN_3]);
   let loginListItems = gLoginList.shadowRoot.querySelectorAll("login-list-item");
   is(loginListItems.length, 2, "A blank login and the one stored login should be displayed");
   ok(!loginListItems[0].dataset.guid, "first login-list-item should be the 'new' item");
   is(loginListItems[1].dataset.guid, TEST_LOGIN_3.guid, "login-list-item should have correct guid attribute");
 
-  loginListItems[1].setAttribute("missing-username", "(no username)");
   loginListItems[1].render();
   let loginUsername = loginListItems[1].shadowRoot.querySelector(".username");
-  is(loginUsername.textContent, "(no username)", "login should show missing username text");
+  is(loginUsername.getAttribute("data-l10n-id"), "login-list-item-subtitle-missing-username", "login should show missing username text");
 });
 
 add_task(async function test_populated_list() {
   gLoginList.setLogins([TEST_LOGIN_1, TEST_LOGIN_2]);
   let loginListItems = gLoginList.shadowRoot.querySelectorAll("login-list-item");
   is(loginListItems.length, 3, "A blank login and the two stored logins should be displayed");
   ok(!loginListItems[0].dataset.guid, "first login-list-item should be the 'new' item");
   is(loginListItems[1].dataset.guid, TEST_LOGIN_1.guid, "login-list-item should have correct guid attribute");
@@ -158,55 +153,55 @@ add_task(async function test_populated_l
   is(loginListItems.length, 2, "After selecting one, only the two stored logins should be displayed");
   ok(loginListItems[0].classList.contains("selected"), "The first item should be selected");
   ok(!loginListItems[1].classList.contains("selected"), "The second item should still not be selected");
 });
 
 add_task(async function test_filtered_list() {
   is(gLoginList.shadowRoot.querySelectorAll("login-list-item:not([hidden])").length, 2, "Both logins should be visible");
   let countSpan = gLoginList.shadowRoot.querySelector(".count");
-  is(countSpan.textContent, "2", "Count should match full list length");
+  is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 2, "Count should match full list length");
   window.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
     bubbles: true,
     detail: "user1",
   }));
-  is(countSpan.textContent, "1", "Count should match result amount");
+  is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 1, "Count should match result amount");
   let loginListItems = gLoginList.shadowRoot.querySelectorAll("login-list-item");
   is(loginListItems[0].shadowRoot.querySelector(".username").textContent, "user1", "user1 is expected first");
   ok(!loginListItems[0].hidden, "user1 should remain visible");
   ok(loginListItems[1].hidden, "user2 should be hidden");
   window.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
     bubbles: true,
     detail: "user2",
   }));
-  is(countSpan.textContent, "1", "Count should match result amount");
+  is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 1, "Count should match result amount");
   loginListItems = gLoginList.shadowRoot.querySelectorAll("login-list-item");
   ok(loginListItems[0].hidden, "user1 should be hidden");
   ok(!loginListItems[1].hidden, "user2 should be visible");
   window.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
     bubbles: true,
     detail: "user",
   }));
-  is(countSpan.textContent, "2", "Count should match result amount");
+  is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 2, "Count should match result amount");
   loginListItems = gLoginList.shadowRoot.querySelectorAll("login-list-item");
   ok(!loginListItems[0].hidden, "user1 should be visible");
   ok(!loginListItems[1].hidden, "user2 should be visible");
   window.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
     bubbles: true,
     detail: "foo",
   }));
-  is(countSpan.textContent, "0", "Count should match result amount");
+  is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 0, "Count should match result amount");
   loginListItems = gLoginList.shadowRoot.querySelectorAll("login-list-item");
   ok(loginListItems[0].hidden, "user1 should be hidden");
   ok(loginListItems[1].hidden, "user2 should be hidden");
   window.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
     bubbles: true,
     detail: "",
   }));
-  is(countSpan.textContent, "2", "Count should be reset to full list length");
+  is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 2, "Count should be reset to full list length");
   loginListItems = gLoginList.shadowRoot.querySelectorAll("login-list-item");
   ok(!loginListItems[0].hidden, "user1 should be visible");
   ok(!loginListItems[1].hidden, "user2 should be visible");
 });
 
 add_task(async function test_login_modified() {
   let modifiedLogin = Object.assign(TEST_LOGIN_1, {username: "user11"});
   gLoginList.loginModified(modifiedLogin);
@@ -243,36 +238,36 @@ add_task(async function test_login_remov
   let loginListItems = gLoginList.shadowRoot.querySelectorAll("login-list-item");
   is(loginListItems.length, 2, "New login should be removed from the list");
   is(loginListItems[0].dataset.guid, TEST_LOGIN_1.guid, "login-list-item1 should have correct guid attribute");
   is(loginListItems[1].dataset.guid, TEST_LOGIN_2.guid, "login-list-item2 should have correct guid attribute");
 });
 
 add_task(async function test_login_added_filtered() {
   let countSpan = gLoginList.shadowRoot.querySelector(".count");
-  is(countSpan.textContent, "2", "Count should match full list length");
+  is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 2, "Count should match full list length");
   window.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
     bubbles: true,
     composed: true,
     detail: "user1",
   }));
-  is(countSpan.textContent, "1", "Count should match result amount");
+  is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 1, "Count should match result amount");
 
   let newLogin = Object.assign({}, TEST_LOGIN_1, {username: "user22", guid: "111222"});
   gLoginList.loginAdded(newLogin);
   await asyncElementRendered();
   let loginListItems = gLoginList.shadowRoot.querySelectorAll("login-list-item");
   is(loginListItems.length, 3, "New login should be added to the list");
   is(loginListItems[0].dataset.guid, TEST_LOGIN_1.guid, "login-list-item1 should have correct guid attribute");
   is(loginListItems[1].dataset.guid, TEST_LOGIN_2.guid, "login-list-item2 should have correct guid attribute");
   is(loginListItems[2].dataset.guid, newLogin.guid, "login-list-item3 should have correct guid attribute");
   ok(!loginListItems[0].hidden, "login-list-item1 should be visible");
   ok(loginListItems[1].hidden, "login-list-item2 should be hidden");
   ok(loginListItems[2].hidden, "login-list-item3 should be hidden");
-  is(countSpan.textContent, "1", "Count should remain unchanged");
+  is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 1, "Count should remain unchanged");
 });
 
 add_task(async function test_sorted_list() {
   // Clear the selection so the 'new' login will be in the list too.
   window.dispatchEvent(new CustomEvent("AboutLoginsLoginSelected", {
     detail: {},
   }));
 
deleted file mode 100644
--- a/browser/components/aboutlogins/tests/chrome/test_reflected_fluent_element.html
+++ /dev/null
@@ -1,117 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-Test the reflected-fluent-element component
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test the reflected-fluent-element component</title>
-  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script src="aboutlogins_common.js"></script>
-
-  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-  <p id="display">
-  </p>
-<div id="content" style="display: none">
-  <iframe id="templateFrame" src="chrome://browser/content/aboutlogins/aboutLogins.html"
-          sandbox="allow-same-origin"></iframe>
-</div>
-<pre id="test">
-</pre>
-<script>
-/** Test the reflected-fluent-element component **/
-
-const TEST_STRINGS = {
-  loginFilter: {
-    placeholder: "Sample placeholder",
-  },
-  loginItem: {
-    "cancel-button": "Cancel",
-    "delete-button": "Delete",
-    "origin-label": "Website Address",
-    "password-label": "Password",
-    "save-changes-button": "Save Changes",
-    // See stubFluentL10n for the following three
-    "time-created": "",
-    "time-changed": "",
-    "time-used": "",
-    "username-label": "Username",
-  },
-};
-
-let gLoginFilter;
-let gLoginItem;
-add_task(async function setup() {
-  stubFluentL10n({
-    "time-created": "timeCreated",
-    "time-changed": "timeChanged",
-    "time-used": "timeUsed",
-  });
-
-  let displayEl = document.getElementById("display");
-
-  // Create and append the login-filter element before its template
-  // is cloned the custom element defined.
-  gLoginFilter = document.createElement("login-filter");
-  gLoginFilter.setAttribute("placeholder", TEST_STRINGS.loginFilter.placeholder);
-  displayEl.appendChild(gLoginFilter);
-
-  // ... and do the same with the login-item.
-  gLoginItem = document.createElement("login-item");
-  for (let attrKey of Object.keys(TEST_STRINGS.loginItem)) {
-    gLoginItem.setAttribute(attrKey, TEST_STRINGS.loginItem[attrKey]);
-  }
-  displayEl.appendChild(gLoginItem);
-
-  let templateFrame = document.getElementById("templateFrame");
-  importDependencies(templateFrame, displayEl);
-
-  // The script needs to be inserted after the element and template are appended
-  // to match the environment of the locale text being applied before the custom
-  // element is defined.
-  for (let scriptSrc of ["login-filter.js", "login-item.js", "login-list.js"]) {
-    let scriptEl = document.createElement("script");
-    scriptEl.setAttribute("src", `chrome://browser/content/aboutlogins/components/${scriptSrc}`);
-    scriptEl.setAttribute("type", "module");
-    document.head.appendChild(scriptEl);
-  }
-});
-
-add_task(async function test_placeholder_on_login_filter() {
-  ok(gLoginFilter, "loginFilter exists");
-  await SimpleTest.promiseWaitForCondition(() => !!gLoginFilter.shadowRoot, "Wait for shadowRoot");
-  is(gLoginFilter.shadowRoot.querySelector("input").placeholder,
-     TEST_STRINGS.loginFilter.placeholder,
-     "Placeholder text should be present when set before the element is defined");
-});
-
-add_task(async function test_login_item() {
-  ok(gLoginItem, "loginItem exists");
-  await SimpleTest.promiseWaitForCondition(() => !!gLoginItem.shadowRoot, "Wait for shadowRoot");
-
-  for (let attrKey of Object.keys(TEST_STRINGS.loginItem)) {
-    let selector = "." + attrKey;
-    is(gLoginItem.shadowRoot.querySelector(selector).textContent,
-       TEST_STRINGS.loginItem[attrKey],
-       selector + " textContent should be present when set before the element is defined");
-  }
-});
-
-add_task(async function test_attribute_changed_callback() {
-  let displayEl = document.getElementById("display");
-  let loginList = document.createElement("login-list");
-  displayEl.appendChild(loginList);
-  await SimpleTest.promiseWaitForCondition(() => !!loginList.shadowRoot, "Wait for element to get templated");
-
-  loginList.setAttribute("count", "1234");
-  await SimpleTest.promiseWaitForCondition(() => loginList.shadowRoot.querySelector(".count").textContent.includes("1234"),
-                                           "Wait for text to get localized");
-  ok(loginList.shadowRoot.querySelector(".count").textContent.includes("1234"),
-     "The count attribute should be inherited by the .count span");
-});
-</script>
-
-</body>
-</html>
--- a/browser/components/controlcenter/content/identityPanel.inc.xul
+++ b/browser/components/controlcenter/content/identityPanel.inc.xul
@@ -341,13 +341,13 @@
         <vbox id="identity-popup-breakageReportView-footer"
               class="panel-footer">
           <button id="identity-popup-breakageReportView-cancel"
                   label="&contentBlocking.breakageReportView.cancel.label;"
                   oncommand="ContentBlocking.backToMainView();"/>
           <button id="identity-popup-breakageReportView-submit"
                   default="true"
                   label="&contentBlocking.breakageReportView.sendReport.label;"
-                  oncommand="ContentBlocking.submitBreakageReport();"/>
+                  oncommand="ContentBlocking.onSubmitBreakageReportClicked();"/>
         </vbox>
     </panelview>
   </panelmultiview>
 </panel>
--- a/browser/components/controlcenter/content/protectionsPanel.inc.xul
+++ b/browser/components/controlcenter/content/protectionsPanel.inc.xul
@@ -20,29 +20,31 @@
         <label id="protections-popup-main-header-label">
           <html:span id="protections-popup-mainView-panel-header-span"/>
         </label>
         <description id="protections-popup-toast-panel-tp-on-desc">Enhanced Tracking Protection is ON for this site</description>
         <description id="protections-popup-toast-panel-tp-off-desc">Enhanced Tracking Protection is OFF for this site</description>
       </hbox>
 
       <hbox id="protections-popup-tp-switch-section" class="identity-popup-section">
-        <vbox id="protections-popup-tp-switch-label-box" flex="1">
-          <label id="protections-popup-tp-switch-on-header"
+        <vbox class="protections-popup-tp-switch-label-box" flex="1">
+          <label class="protections-popup-tp-switch-on-header"
                  hidden="true">Tracking protection is ON for this site</label>
-          <label id="protections-popup-tp-switch-off-header"
+          <label class="protections-popup-tp-switch-off-header"
                  hidden="true">Tracking protection is OFF for this site</label>
           <label id="protections-popup-tp-switch-breakage-link"
                  class="text-link"
+                 onclick="gProtectionsHandler.showSiteNotWorkingView();"
                  hidden="true">Site not working?</label>
         </vbox>
-        <vbox id="protections-popup-tp-switch-box">
+        <vbox class="protections-popup-tp-switch-box">
           <toolbarbutton id="protections-popup-tp-switch"
-              enabled="false"
-              oncommand="gProtectionsHandler.onTPSwitchCommand();" />
+                         class="protections-popup-tp-switch"
+                         enabled="false"
+                         oncommand="gProtectionsHandler.onTPSwitchCommand();" />
         </vbox>
       </hbox>
 
       <vbox id="protections-popup-settings-section"
             class="identity-popup-section">
         <toolbarbutton id="protections-popup-settings-button"
                        oncommand="ContentBlocking.openPreferences();">
           <image class="protection-settings-icon"/>
@@ -54,10 +56,82 @@
         <description id="protections-popup-trackers-blocked-counter-description"
                      flex="1"/>
         <label id="protections-popup-show-full-report-link"
                is="text-link"
                useoriginprincipal="true"
                href="about:protections">Show Full Report</label>
       </hbox>
     </panelview>
+
+    <!-- Site Not Working? SubView -->
+    <panelview id="protections-popup-siteNotWorkingView"
+               title="Site Not Working?"
+               descriptionheightworkaround="true"
+               flex="1">
+        <hbox id="protections-popup-siteNotWorkingView-header">
+          <vbox class="protections-popup-tp-switch-label-box" flex="1">
+            <label class="protections-popup-tp-switch-on-header"
+              hidden="true">Tracking protection is ON for this site</label>
+            <label class="protections-popup-tp-switch-off-header"
+              hidden="true">Tracking protection is OFF for this site</label>
+          </vbox>
+          <vbox class="protections-popup-tp-switch-box">
+            <toolbarbutton id="protections-popup-siteNotWorking-tp-switch"
+                           class="protections-popup-tp-switch"
+                           enabled="false"
+                           oncommand="gProtectionsHandler.onTPSwitchCommand();" />
+          </vbox>
+        </hbox>
+        <vbox id="protections-popup-siteNotWorkingView-body" flex="1">
+          <label>Turn off Tracking Protection if you're having issues with:</label>
+          <label>
+            <html:ul id="protections-popup-siteNotWorkingView-body-issue-list">
+              <html:li>Log in fields</html:li>
+              <html:li>Forms</html:li>
+              <html:li>Payments</html:li>
+              <html:li>Comments</html:li>
+              <html:li>Videos</html:li>
+            </html:ul>
+          </label>
+        </vbox>
+        <hbox id="protections-popup-siteNotWorkingView-footer"
+              class="panel-footer">
+          <label id="protections-popup-siteNotWorkingView-siteStillBroken" flex="1">Site Still Broken?</label>
+          <label id="protections-popup-siteNotWorkingView-sendReport"
+            onclick="gProtectionsHandler.showSendReportView();"
+            class="text-link">Send Report</label>
+        </hbox>
+    </panelview>
+
+
+    <!-- Send Report SubView -->
+    <panelview id="protections-popup-sendReportView"
+               title="Send Report"
+               descriptionheightworkaround="true">
+        <vbox id="protections-popup-sendReportView-heading">
+          <description>&contentBlocking.breakageReportView2.description;</description>
+          <label id="protections-popup-sendReportView-learn-more"
+                 is="text-link">&contentBlocking.breakageReportView.learnMore;</label>
+        </vbox>
+        <vbox id="protections-popup-sendReportView-body" class="panel-view-body-unscrollable">
+          <vbox class="protections-popup-sendReportView-collection-section">
+            <label>&contentBlocking.breakageReportView.collection.url.label;</label>
+            <html:input readonly="readonly" id="protections-popup-sendReportView-collection-url"/>
+          </vbox>
+          <vbox class="protections-popup-sendReportView-collection-section">
+            <label>&contentBlocking.breakageReportView.collection.comments.label;</label>
+            <html:textarea id="protections-popup-sendReportView-collection-comments"/>
+          </vbox>
+        </vbox>
+        <vbox id="protections-popup-sendReportView-footer"
+              class="panel-footer">
+          <button id="protections-popup-sendReportView-cancel"
+                  label="&contentBlocking.breakageReportView.cancel.label;"
+                  oncommand="gProtectionsHandler._protectionsPopupMultiView.goBack();"/>
+          <button id="protections-popup-sendReportView-submit"
+                  default="true"
+                  label="&contentBlocking.breakageReportView.sendReport.label;"
+                  oncommand="gProtectionsHandler.onSendReportClicked();"/>
+        </vbox>
+    </panelview>
   </panelmultiview>
 </panel>
--- a/browser/components/extensions/ext-browser.json
+++ b/browser/components/extensions/ext-browser.json
@@ -193,16 +193,24 @@
     "url": "chrome://browser/content/parent/ext-tabs.js",
     "schema": "chrome://browser/content/schemas/tabs.json",
     "scopes": ["addon_parent"],
     "events": ["update", "disable"],
     "paths": [
       ["tabs"]
     ]
   },
+  "topSites": {
+    "url": "chrome://extensions/content/parent/ext-topSites.js",
+    "schema": "chrome://extensions/content/schemas/top_sites.json",
+    "scopes": ["addon_parent"],
+    "paths": [
+      ["topSites"]
+    ]
+  },
   "urlbar": {
     "url": "chrome://browser/content/parent/ext-urlbar.js",
     "schema": "chrome://browser/content/schemas/urlbar.json",
     "scopes": ["addon_parent"],
     "paths": [
       ["urlbar"]
     ]
   },
--- a/browser/components/newtab/AboutNewTabService.jsm
+++ b/browser/components/newtab/AboutNewTabService.jsm
@@ -14,17 +14,17 @@ ChromeUtils.defineModuleGetter(this, "Ab
                                "resource:///modules/AboutNewTab.jsm");
 
 const TOPIC_APP_QUIT = "quit-application-granted";
 const TOPIC_LOCALES_CHANGE = "intl:app-locales-changed";
 const TOPIC_CONTENT_DOCUMENT_INTERACTIVE = "content-document-interactive";
 
 // Automated tests ensure packaged locales are in this list. Copied output of:
 // https://github.com/mozilla/activity-stream/blob/master/bin/render-activity-stream-html.js
-const ACTIVITY_STREAM_BCP47 = "en-US ach an ar ast az be bg bn br bs ca cak crh cs cy da de dsb el en-CA en-GB eo es-AR es-CL es-ES es-MX et eu fa ff fi fr fy-NL ga-IE gd gl gn gu-IN he hi-IN hr hsb hu hy-AM ia id is it ja ja-JP-macos ka kab kk km kn ko lij lo lt ltg lv mk mr ms my nb-NO ne-NP nl nn-NO oc pa-IN pl pt-BR pt-PT rm ro ru si sk sl sq sr sv-SE ta te th tl tr trs uk ur uz vi zh-CN zh-TW".split(" ");
+const ACTIVITY_STREAM_BCP47 = "en-US ach an ar ast az be bg bn br bs ca cak crh cs cy da de dsb el en-CA en-GB eo es-AR es-CL es-ES es-MX et eu fa ff fi fr fy-NL ga-IE gd gl gn gu-IN he hi-IN hr hsb hu hy-AM ia id is it ja ka kab kk km kn ko lij lo lt ltg lv mk mr ms my nb-NO ne-NP nl nn-NO oc pa-IN pl pt-BR pt-PT rm ro ru si sk sl sq sr sv-SE ta te th tl tr trs uk ur uz vi zh-CN zh-TW".split(" ");
 
 const ABOUT_URL = "about:newtab";
 const BASE_URL = "resource://activity-stream/";
 const ACTIVITY_STREAM_PAGES = new Set(["home", "newtab", "welcome"]);
 
 const IS_MAIN_PROCESS = Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_DEFAULT;
 const IS_PRIVILEGED_PROCESS = Services.appinfo.remoteType === E10SUtils.PRIVILEGEDABOUT_REMOTE_TYPE;
 
--- a/browser/components/urlbar/UrlbarView.jsm
+++ b/browser/components/urlbar/UrlbarView.jsm
@@ -115,19 +115,21 @@ class UrlbarView {
 
   /**
    * @returns {number}
    *   The number of visible results in the view.  Note that this may be larger
    *   than the number of results in the current query context since the view
    *   may be showing stale results.
    */
   get visibleItemCount() {
-    return Array.reduce(this._rows.children, (sum, r) => {
-      return sum + Number(this._isRowVisible(r));
-    }, 0);
+    let sum = 0;
+    for (let row of this._rows.children) {
+      sum += Number(this._isRowVisible(row));
+    }
+    return sum;
   }
 
   /**
    * Moves the view selection forward or backward.
    *
    * @param {number} amount
    *   The number of steps to move.
    * @param {boolean} options.reverse
--- a/browser/components/urlbar/tests/browser/browser_inputHistory.js
+++ b/browser/components/urlbar/tests/browser/browser_inputHistory.js
@@ -284,24 +284,24 @@ add_task(async function test_adaptive_mo
 
   let url1 = "http://site.tld/1";
   let url2 = "http://site.tld/2";
 
   info("Same visit count, different picks");
   await PlacesUtils.history.clear();
   await bumpScore(url1, "site", {visits: 3, picks: 3}, true);
   await bumpScore(url2, "site", {visits: 3, picks: 1}, true);
-  await promiseAutocompleteResultPopup("");
-  let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
+  await promiseAutocompleteResultPopup("si");
+  let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
   Assert.equal(result.url, url1, "Check first result");
-  result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
+  result = await UrlbarTestUtils.getDetailsOfResultAt(window, 2);
   Assert.equal(result.url, url2, "Check second result");
 
   info("Same visit count, different picks, invert");
   await PlacesUtils.history.clear();
   await bumpScore(url1, "site", {visits: 3, picks: 1}, true);
   await bumpScore(url2, "site", {visits: 3, picks: 3}, true);
-  await promiseAutocompleteResultPopup("");
-  result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
+  await promiseAutocompleteResultPopup("si");
+  result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
   Assert.equal(result.url, url2, "Check first result");
-  result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
+  result = await UrlbarTestUtils.getDetailsOfResultAt(window, 2);
   Assert.equal(result.url, url1, "Check second result");
 });
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -4,22 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 %endif
 
 /* Hide all conditional elements by default. */
 :-moz-any([when-connection],[when-customroot],[when-mixedcontent],[when-ciphers],[when-loginforms]) {
   display: none;
 }
 
-#identity-popup {
-  --identity-popup-width: 33rem;
-}
-
+#identity-popup,
 #protections-popup {
-  --protections-popup-width: 33rem;
+  --popup-width: 33rem;
 }
 
 /* This is used by screenshots tests to hide intermittently different
  * identity popup shadows (see bug 1425253). */
 #identity-popup.no-shadow {
   -moz-window-shadow: none;
 }
 
@@ -73,23 +70,23 @@
   padding: 0;
   /* Set default fill for icons in the identity popup.
      Individual icons can override this. */
   fill: currentColor;
   fill-opacity: .6;
 }
 
 #identity-popup-mainView {
-  min-width: var(--identity-popup-width);
-  max-width: var(--identity-popup-width);
+  min-width: var(--popup-width);
+  max-width: var(--popup-width);
 }
 
 #protections-popup-mainView {
-  min-width: var(--protections-popup-width);
-  max-width: var(--protections-popup-width);
+  min-width: var(--popup-width);
+  max-width: var(--popup-width);
 }
 
 #protections-popup[toast] #protections-popup-mainView > :not(#protections-popup-mainView-panel-header),
 #protections-popup[toast] #protections-popup-main-header-label {
   display: none;
 }
 
 #protections-popup[toast] #protections-popup-mainView-panel-header {
@@ -187,16 +184,17 @@
 .identity-popup-cookiesView-list-header,
 .identity-popup-content-blocking-list-item > label,
 #identity-popup-mainView-panel-header > label,
 #protections-popup-mainView-panel-header > label,
 #protections-popup-mainView-panel-header > description,
 #identity-popup-trackersView > .panel-header,
 #identity-popup-securityView > .panel-header,
 #identity-popup-breakageReportView > .panel-header,
+#protections-popup-sendReportView > .panel-header,
 #identity-popup-content-blocking-report-breakage,
 .identity-popup-content-blocking-category-label,
 .identity-popup-content-blocking-category-state-label,
 .identity-popup-permission-label,
 .identity-popup-permission-state-label,
 .identity-popup-security-content > description,
 #identity-popup-security-descriptions > description,
 #identity-popup-securityView-body > description,
@@ -205,17 +203,18 @@
 .protections-popup-settings-label,
 #protections-popup-footer > description,
 #protections-popup-footer > label {
   font-size: 110%;
   margin: 0;
 }
 
 #identity-popup-mainView-panel-header,
-#protections-popup-mainView-panel-header {
+#protections-popup-mainView-panel-header,
+#protections-popup-siteNotWorkingView-footer {
   padding: 4px 1em;
   min-height: 40px;
   -moz-box-pack: center;
   -moz-box-align: center;
 }
 
 #protections-popup > .panel-arrowcontainer > .panel-arrowbox > .panel-arrow {
   fill: rgb(100, 70, 228);
@@ -235,17 +234,23 @@
 #protections-popup-toast-panel-tp-on-desc,
 #protections-popup-toast-panel-tp-off-desc {
   display: inline-block;
   font-weight: 600;
   text-align: center;
   overflow-wrap: break-word;
   /* This is needed for the overflow-wrap to work correctly.
    * 33em is the panel width, panel-header has 1em padding on each side. */
-  max-width: calc(var(--identity-popup-width) - 2em);
+  max-width: calc(var(--popup-width) - 2em);
+}
+
+#protections-popup-mainView-panel-header-span,
+#protections-popup-toast-panel-tp-on-desc,
+#protections-popup-toast-panel-tp-off-desc {
+  max-width: calc(var(--popup-width) - 2em);
 }
 
 #identity-popup-permissions-content > description,
 #identity-popup-content-blocking-content > description {
   color: var(--panel-disabled-color);
 }
 
 /* This element needs the pre-wrap because we add newlines to it in the code. */
@@ -258,17 +263,17 @@
   font-size: 150%;
 }
 
 #identity-popup-host {
   overflow-wrap: break-word;
   /* This is needed for the overflow-wrap to work correctly.
    * 1em + 2em + 24px is .identity-popup-security-content padding
    * 33em is the panel width */
-  max-width: calc(var(--identity-popup-width) - 3rem - 24px);
+  max-width: calc(var(--popup-width) - 3rem - 24px);
 }
 
 .identity-popup-warning-gray {
   padding-inline-start: 24px;
   background: url(chrome://browser/skin/controlcenter/warning.svg) no-repeat 0 50%;
   fill: #808080;
   stroke: #fff;
   -moz-context-properties: fill, stroke;
@@ -366,43 +371,51 @@ description#identity-popup-content-verif
 
 #identity-popup-securityView-body > button {
   margin-inline-start: 0;
   margin-inline-end: 0;
 }
 
 /* CONTENT BLOCKING / TRACKING PROTECTION */
 
-#identity-popup-breakageReportView-footer {
+#identity-popup-breakageReportView-footer,
+#protections-popup-sendReportView-footer {
   display: flex;
 }
 
-#identity-popup-breakageReportView-footer > button {
+#identity-popup-breakageReportView-footer > button,
+#protections-popup-sendReportView-footer > button {
   flex: 1;
 }
 
 #identity-popup-breakageReportView-heading,
-#identity-popup-breakageReportView-body {
+#identity-popup-breakageReportView-body,
+#protections-popup-sendReportView-heading,
+#protections-popup-sendReportView-body {
   padding: 16px;
   font-size: 110%;
 }
 
-.identity-popup-breakageReportView-collection-section {
+.identity-popup-breakageReportView-collection-section,
+.protections-popup-sendReportView-collection-section {
   margin-bottom: 16px;
 }
 
-#identity-popup-breakageReportView-body {
+#identity-popup-breakageReportView-body,
+#protections-popup-sendReportView-body {
   border-top: 1px solid var(--panel-separator-color);
 }
 
-#identity-popup-breakageReportView-collection-url {
+#identity-popup-breakageReportView-collection-url,
+#protections-popup-sendReportView-collection-url {
   font: inherit;
 }
 
-#identity-popup-breakageReportView-collection-comments {
+#identity-popup-breakageReportView-collection-comments,
+#protections-popup-sendReportView-collection-comments {
   height: 120px;
 }
 
 #identity-popup-content-blocking-content {
   background-image: url("chrome://browser/skin/controlcenter/tracking-protection.svg");
 }
 
 .identity-popup-content-blocking-category {
@@ -540,18 +553,18 @@ description#identity-popup-content-verif
 
 .identity-popup-cryptominersView-icon.allowed {
   list-style-image: url(chrome://browser/skin/controlcenter/cryptominers.svg);
 }
 
 #identity-popup-trackersView-strict-info {
   min-height: 40px;
   /* Limit to full width - margin */
-  max-width: calc(var(--identity-popup-width) - 12px);
-  min-width: calc(var(--identity-popup-width) - 12px);
+  max-width: calc(var(--popup-width) - 12px);
+  min-width: calc(var(--popup-width) - 12px);
   background-color: #45a1ff80;
   margin: 6px;
   text-align: center;
   -moz-box-align: center;
   -moz-box-pack: center;
   padding: 5px 15px;
   border-radius: 3px;
 }
@@ -561,17 +574,17 @@ description#identity-popup-content-verif
   -moz-context-properties: fill;
   fill: currentColor;
   margin-inline-end: 10px;
 }
 
 #identity-popup-trackersView-strict-info > label {
   overflow-wrap: break-word;
   /* Limit to full width - container margin - container padding - icon width - icon margin */
-  max-width: calc(var(--identity-popup-width) - 12px - 20px - 16px - 10px);
+  max-width: calc(var(--popup-width) - 12px - 20px - 16px - 10px);
 }
 
 /* Content Blocking categories */
 
 #identity-popup-content-blocking-category-list {
   margin-top: 10px;
 }
 
@@ -806,18 +819,18 @@ description#identity-popup-content-verif
 .identity-popup-permission-remove-button:not(:-moz-focusring):hover:active {
   opacity: 0.8;
 }
 
 #protections-popup-mainView-panel-header > description {
   display: none;
 }
 
-#protections-popup:not([hasException]) #protections-popup-tp-switch-on-header,
-#protections-popup[hasException] #protections-popup-tp-switch-off-header,
+#protections-popup:not([hasException]) .protections-popup-tp-switch-on-header,
+#protections-popup[hasException] .protections-popup-tp-switch-off-header,
 #protections-popup:not([hasException])[toast] #protections-popup-toast-panel-tp-on-desc,
 #protections-popup[hasException][toast] #protections-popup-toast-panel-tp-off-desc {
   display: unset;
 }
 
 #protections-popup-tp-switch-section {
   padding: 4px;
 }
@@ -827,73 +840,82 @@ description#identity-popup-content-verif
     -56deg,
     var(--arrowpanel-dimmed),
     var(--arrowpanel-dimmed) 10px,
     transparent 10px,
     transparent 20px
   );
 }
 
-#protections-popup-tp-switch-label-box,
-#protections-popup-tp-switch-box {
+#protections-popup-siteNotWorkingView-body,
+.protections-popup-tp-switch-label-box,
+.protections-popup-tp-switch-box {
   padding: 4px 1em;
   min-height: 40px;
   -moz-box-pack: center;
   /* This is needed in order to make 'position' working for the badge alongside
      the TP switch toggle.*/
   position: relative;
 }
 
-#protections-popup-tp-switch-on-header,
-#protections-popup-tp-switch-off-header {
+.protections-popup-tp-switch-on-header,
+.protections-popup-tp-switch-off-header {
   font-weight: 600;
 }
 
-#protections-popup-tp-switch {
+.protections-popup-tp-switch {
   -moz-appearance: none;
   box-sizing: border-box;
   min-width: 26px;
   border-radius: 10px;
   background-color: var(--arrowpanel-dimmed-even-further);
   border: 1px solid transparent;
   margin-top: 4px;
   margin-bottom: 4px;
   margin-inline-start: 1px;
-  margin-inline-end: 7px;
   padding: 2px;
+  padding-inline-end: 0;
   transition: padding .2s ease;
 }
 
-#protections-popup-tp-switch::before {
+.protections-popup-tp-switch::before {
   position: relative;
   display: block;
   content: "";
   width: 10px;
   height: 10px;
   border-radius: 10px;
   background: white;
 }
 
-#protections-popup-tp-switch[enabled] {
+.protections-popup-tp-switch[enabled] {
   background-color: #0a84ff;
   border: 1px solid #0a84ff;
   /* Push the toggle to the right. */
   padding-inline-start: 12px;
 }
 
-#protections-popup-tp-switch:hover,
-#protections-popup-tp-switch:-moz-focusring {
+.protections-popup-tp-switch:hover,
+.protections-popup-tp-switch:-moz-focusring {
   border: 1px solid var(--panel-separator-color);
 }
 
-#protections-popup-tp-switch[enabled=true]:hover,
-#protections-popup-tp-switch[enabled=true]:-moz-focusring {
+.protections-popup-tp-switch[enabled=true]:hover,
+.protections-popup-tp-switch[enabled=true]:-moz-focusring {
   background-color: #45a1ff;
 }
 
+#protections-popup-siteNotWorkingView-body-issue-list {
+  padding-inline-start: 1em;
+}
+
+#protections-popup-siteNotWorkingView-footer {
+  border-top: 1px solid var(--panel-separator-color);
+}
+
 #protections-popup-settings-section {
   padding: 4px;
   -moz-context-properties: fill, fill-opacity;
 }
 
 #protections-popup-settings-button {
   /* We need to align the setting button with the labels in the tp switch
      section. So we add 6px to offset the margin of labels. */
--- a/devtools/client/aboutdebugging/aboutdebugging.css
+++ b/devtools/client/aboutdebugging/aboutdebugging.css
@@ -199,17 +199,17 @@ button {
 }
 
 .warning {
   display: inline-block;
   width: 12px;
   height: 12px;
   vertical-align: 0;
   margin-inline-end: 8px;
-  background-image: url(chrome://devtools/skin/images/alert.svg);
+  background-image: url(chrome://devtools/skin/images/alert-small.svg);
   background-repeat: no-repeat;
   background-size: contain;
 }
 
 .addons-install-error__additional-errors {
   font-family: monospace;
   font-size: 13px;
   margin-block: 8px;
--- a/devtools/client/accessibility/accessibility-view.js
+++ b/devtools/client/accessibility/accessibility-view.js
@@ -47,28 +47,29 @@ AccessibilityView.prototype = {
    * @param {Object} accessibility  front that can initialize accessibility
    *                                walker and enable/disable accessibility
    *                                services.
    * @param {Object} walker         front for accessibility walker actor responsible for
    *                                managing accessible objects actors/fronts.
    * @param {JSON}   supports       a collection of flags indicating which accessibility
    *                                panel features are supported by the current serverside
    *                                version.
+   * @param {Array}  fluentBundles  array of FluentBundles elements for localization
    */
-  async initialize(accessibility, walker, supports) {
+  async initialize(accessibility, walker, supports, fluentBundles) {
     // Make sure state is reset every time accessibility panel is initialized.
     await this.store.dispatch(reset(accessibility, supports));
     const container = document.getElementById("content");
 
     if (!supports.enableDisable) {
       ReactDOM.render(OldVersionDescription(), container);
       return;
     }
 
-    const mainFrame = MainFrame({ accessibility, walker });
+    const mainFrame = MainFrame({ accessibility, walker, fluentBundles });
     // Render top level component
     const provider = createElement(Provider, { store: this.store }, mainFrame);
     this.mainFrame = ReactDOM.render(provider, container);
   },
 
   async selectAccessible(walker, accessible) {
     await this.store.dispatch(select(walker, accessible));
     window.emit(EVENTS.NEW_ACCESSIBLE_FRONT_INSPECTED);
--- a/devtools/client/accessibility/accessibility.css
+++ b/devtools/client/accessibility/accessibility.css
@@ -23,30 +23,32 @@
   --badge-active-background-color: var(--blue-50);
   --badge-active-border-color: #FFFFFFB3;
   --badge-interactive-background-color: var(--grey-20);
   --accessible-label-background-color: white;
   --accessible-label-border-color: #CACAD1;
   --accessible-label-color: var(--grey-60);
   /* Similarly to webconsole, add more padding before the toolbar group. */
   --separator-inline-margin: 5px;
+  --accessibility-code-background: var(--grey-20);
 }
 
 :root.theme-dark {
   --accessibility-unfocused-tree-focused-node-background: var(--grey-70);
   --accessibility-unfocused-tree-focused-node-twisty-fill: var(--theme-selection-color);
   --accessibility-link-color: var(--theme-highlight-blue);
   --accessibility-link-color-active: var(--blue-40);
   --accessibility-body-background-a90: rgba(42, 42, 46, 0.9);
   --badge-active-background-color: var(--blue-60);
   --badge-active-border-color: #FFF6;
   --badge-interactive-background-color: var(--grey-70);
   --accessible-label-background-color: var(--grey-80);
   --accessible-label-border-color: var(--grey-50);
   --accessible-label-color: var(--grey-40);
+  --accessibility-code-background: var(--grey-70);
 }
 
 /* General */
 html,
 body {
   height: 100%;
   margin: 0;
   padding: 0;
@@ -655,66 +657,90 @@ body {
 .checks-empty {
   font-style: italic;
   padding: 0.5em 20px;
   -moz-user-select: none;
   font-size: 12px;
   white-space: initial;
 }
 
-/* Color Contrast */
-.accessibility-color-contrast-check,
+/* Checks */
+.accessibility-check code {
+  background-color: var(--accessibility-code-background);
+  border-radius: 2px;
+  box-decoration-break: clone;
+  padding: 0 4px;
+}
+
+.accessibility-text-label-check .icon {
+  display: inline;
+  -moz-context-properties: fill;
+  vertical-align: top;
+  margin-block-start: 2px;
+  margin-inline-end: 4px;
+}
+
+.accessibility-text-label-check .icon.fail {
+  fill: var(--theme-icon-error-color);
+}
+
+.accessibility-text-label-check .icon.WARNING {
+  fill: var(--theme-icon-warning-color);
+}
+
+.accessibility-check,
 .accessibility-color-contrast {
   position: relative;
   display: flex;
   cursor: default;
   height: inherit;
 }
 
-.accessibility-color-contrast-check {
+.accessibility-check {
   flex-direction: column;
   padding: 4px var(--accessibility-horizontal-indent);
   line-height: 20px;
 }
 
 .accessibility-color-contrast {
   align-items: baseline;
 }
 
-.accessibility-color-contrast-header {
+.accessibility-check-header {
   margin: 0;
   font-weight: bold;
   font-size: var(--accessibility-font-size);
   line-height: var(--accessibility-toolbar-height);
 }
 
-.accessibility-color-contrast-annotation {
+.accessibility-check-annotation {
+  display: inline;
   margin: 0;
   white-space: normal;
   color: var(--accessible-label-color);
 }
 
-.accessibility-color-contrast-annotation .link {
+.accessibility-check-annotation .link {
   color: var(--accessibility-link-color);
   cursor: pointer;
   outline: 0;
   white-space: nowrap;
   font-style: normal;
 }
 
-.accessibility-color-contrast-annotation .link:hover:not(:focus) {
+.accessibility-check-annotation .link:hover:not(:focus) {
   text-decoration: underline;
 }
 
-.accessibility-color-contrast-annotation .link:focus:not(:active) {
+.accessibility-check-annotation .link:focus:not(:active) {
   box-shadow: 0 0 0 2px var(--accessibility-toolbar-focus), 0 0 0 4px var(--accessibility-toolbar-focus-alpha30);
   border-radius: 2px;
 }
 
-.accessibility-color-contrast-annotation .link:active {
+.accessibility-check-annotation .link:active {
   color: var(--accessibility-link-color-active);
   text-decoration: underline;
 }
 
 .accessibility-color-contrast-large-text {
   background-color: var(--accessible-label-background-color);
   color: var(--accessible-label-color);
   outline: 1px solid var(--accessible-label-border-color);
--- a/devtools/client/accessibility/components/Checks.js
+++ b/devtools/client/accessibility/components/Checks.js
@@ -7,16 +7,17 @@
 const { Component, createFactory } = require("devtools/client/shared/vendor/react");
 const { connect } = require("devtools/client/shared/vendor/react-redux");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 const { div } = require("devtools/client/shared/vendor/react-dom-factories");
 
 const List = createFactory(require("devtools/client/shared/components/List").List);
 const ColorContrastCheck =
   createFactory(require("./ColorContrastAccessibility").ColorContrastCheck);
+const TextLabelCheck = createFactory(require("./TextLabelCheck"));
 const { L10N } = require("../utils/l10n");
 
 const { accessibility: { AUDIT_TYPE } } = require("devtools/shared/constants");
 
 function EmptyChecks() {
   return (
     div({
       className: "checks-empty",
@@ -34,16 +35,20 @@ class Checks extends Component {
       labelledby: PropTypes.string.isRequired,
     };
   }
 
   [AUDIT_TYPE.CONTRAST](contrastRatio) {
     return ColorContrastCheck(contrastRatio);
   }
 
+  [AUDIT_TYPE.TEXT_LABEL](textLabelCheck) {
+    return TextLabelCheck(textLabelCheck);
+  }
+
   render() {
     const { audit, labelledby } = this.props;
     if (!audit) {
       return EmptyChecks();
     }
 
     const items = [];
     for (const name in audit) {
--- a/devtools/client/accessibility/components/ColorContrastAccessibility.js
+++ b/devtools/client/accessibility/components/ColorContrastAccessibility.js
@@ -147,17 +147,17 @@ class ContrastAnnotationClass extends Co
   }
 
   render() {
     const { score } = this.props;
 
     return (
       LearnMoreLink(
         {
-          className: "accessibility-color-contrast-annotation",
+          className: "accessibility-check-annotation",
           href: A11Y_CONTRAST_LEARN_MORE_LINK,
           learnMoreStringKey: "accessibility.learnMore",
           l10n: L10N,
           messageStringKey: `accessibility.contrast.annotation.${score}`,
         }
       )
     );
   }
@@ -173,20 +173,20 @@ class ColorContrastCheck extends Compone
   }
 
   render() {
     const { error } = this.props;
 
     return (
       div({
         role: "presentation",
-        className: "accessibility-color-contrast-check",
+        className: "accessibility-check",
       },
         h3({
-          className: "accessibility-color-contrast-header",
+          className: "accessibility-check-header",
         }, L10N.getStr("accessibility.contrast.header")),
         ColorContrastAccessibility(this.props),
         !error && ContrastAnnotation(this.props)
       )
     );
   }
 }
 
--- a/devtools/client/accessibility/components/MainFrame.js
+++ b/devtools/client/accessibility/components/MainFrame.js
@@ -7,16 +7,20 @@
 
 // React & Redux
 const { Component, createFactory } = require("devtools/client/shared/vendor/react");
 const { span, div } = require("devtools/client/shared/vendor/react-dom-factories");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 const { connect } = require("devtools/client/shared/vendor/react-redux");
 const { reset } = require("../actions/ui");
 
+// Localization
+const FluentReact = require("devtools/client/shared/vendor/fluent-react");
+const LocalizationProvider = createFactory(FluentReact.LocalizationProvider);
+
 // Constants
 const { SIDEBAR_WIDTH, PORTRAIT_MODE_WIDTH } = require("../constants");
 
 // Accessibility Panel
 const AccessibilityTree = createFactory(require("./AccessibilityTree"));
 const AuditProgressOverlay = createFactory(require("./AuditProgressOverlay"));
 const Description = createFactory(require("./Description").Description);
 const RightSidebar = createFactory(require("./RightSidebar"));
@@ -26,16 +30,17 @@ const SplitBox = createFactory(require("
 /**
  * Renders basic layout of the Accessibility panel. The Accessibility panel
  * content consists of two main parts: tree and sidebar.
  */
 class MainFrame extends Component {
   static get propTypes() {
     return {
       accessibility: PropTypes.object.isRequired,
+      fluentBundles: PropTypes.array.isRequired,
       walker: PropTypes.object.isRequired,
       enabled: PropTypes.bool.isRequired,
       dispatch: PropTypes.func.isRequired,
       auditing: PropTypes.array.isRequired,
     };
   }
 
   constructor(props) {
@@ -86,26 +91,26 @@ class MainFrame extends Component {
       this.refs.splitBox.setState({ vert: this.useLandscapeMode });
     }
   }
 
   /**
    * Render Accessibility panel content
    */
   render() {
-    const { accessibility, walker, enabled, auditing } = this.props;
+    const { accessibility, walker, fluentBundles, enabled, auditing } = this.props;
 
     if (!enabled) {
       return Description({ accessibility });
     }
 
     // Audit is currently running.
     const isAuditing = auditing.length > 0;
 
-    return (
+    return LocalizationProvider({ messages: fluentBundles },
       div({ className: "mainFrame", role: "presentation" },
         Toolbar({ accessibility, walker }),
         isAuditing && AuditProgressOverlay(),
         span({
           "aria-hidden": isAuditing,
           role: "presentation",
           style: { display: "contents" },
         },
@@ -117,18 +122,20 @@ class MainFrame extends Component {
             splitterSize: 1,
             endPanelControl: true,
             startPanel: div({
               className: "main-panel",
               role: "presentation",
             }, AccessibilityTree({ walker })),
             endPanel: RightSidebar({ walker }),
             vert: this.useLandscapeMode,
-          })),
-      ));
+          })
+        ),
+      )
+    );
   }
 }
 
 const mapStateToProps = ({ ui, audit: { auditing } }) => ({
   enabled: ui.enabled,
   auditing,
 });
 
new file mode 100644
--- /dev/null
+++ b/devtools/client/accessibility/components/TextLabelCheck.js
@@ -0,0 +1,335 @@
+/* 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/. */
+"use strict";
+
+// React
+const { Component, createFactory } = require("devtools/client/shared/vendor/react");
+const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+const ReactDOM = require("devtools/client/shared/vendor/react-dom-factories");
+
+const FluentReact = require("devtools/client/shared/vendor/fluent-react");
+const Localized = createFactory(FluentReact.Localized);
+
+const { openDocLink } = require("devtools/client/shared/link");
+
+const { A11Y_TEXT_LABEL_LINKS } = require("../constants");
+
+const {
+  accessibility: {
+    AUDIT_TYPE: { TEXT_LABEL },
+    ISSUE_TYPE: {
+      [TEXT_LABEL]: {
+        AREA_NO_NAME_FROM_ALT,
+        DIALOG_NO_NAME,
+        DOCUMENT_NO_TITLE,
+        EMBED_NO_NAME,
+        FIGURE_NO_NAME,
+        FORM_FIELDSET_NO_NAME,
+        FORM_FIELDSET_NO_NAME_FROM_LEGEND,
+        FORM_NO_NAME,
+        FORM_NO_VISIBLE_NAME,
+        FORM_OPTGROUP_NO_NAME,
+        FORM_OPTGROUP_NO_NAME_FROM_LABEL,
+        FRAME_NO_NAME,
+        HEADING_NO_CONTENT,
+        HEADING_NO_NAME,
+        IFRAME_NO_NAME_FROM_TITLE,
+        IMAGE_NO_NAME,
+        INTERACTIVE_NO_NAME,
+        MATHML_GLYPH_NO_NAME,
+        TOOLBAR_NO_NAME,
+      },
+    },
+    SCORES: { BEST_PRACTICES, FAIL, WARNING },
+  },
+} = require("devtools/shared/constants");
+
+/**
+ * A map from text label issues to annotation component properties.
+ */
+const ISSUE_TO_ANNOTATION_MAP = {
+  [AREA_NO_NAME_FROM_ALT]: {
+    href: A11Y_TEXT_LABEL_LINKS.AREA_NO_NAME_FROM_ALT,
+    l10nId: "accessibility-text-label-issue-area",
+    args: {
+      get code() {
+        return ReactDOM.code({}, "alt");
+      },
+      // Note: there is no way right now to use custom elements in privileged
+      // content. We have to use something like <div> since we can't provide
+      // three args with the same name.
+      get div() {
+        return ReactDOM.code({}, "area");
+      },
+      // Note: there is no way right now to use custom elements in privileged
+      // content. We have to use something like <span> since we can't provide
+      // three args with the same name.
+      get span() {
+        return ReactDOM.code({}, "href");
+      },
+    },
+  },
+  [DIALOG_NO_NAME]: {
+    href: A11Y_TEXT_LABEL_LINKS.DIALOG_NO_NAME,
+    l10nId: "accessibility-text-label-issue-dialog",
+  },
+  [DOCUMENT_NO_TITLE]: {
+    href: A11Y_TEXT_LABEL_LINKS.DOCUMENT_NO_TITLE,
+    l10nId: "accessibility-text-label-issue-document-title",
+    args: {
+      get code() {
+        return ReactDOM.code({}, "title");
+      },
+    },
+  },
+  [EMBED_NO_NAME]: {
+    href: A11Y_TEXT_LABEL_LINKS.EMBED_NO_NAME,
+    l10nId: "accessibility-text-label-issue-embed",
+  },
+  [FIGURE_NO_NAME]: {
+    href: A11Y_TEXT_LABEL_LINKS.FIGURE_NO_NAME,
+    l10nId: "accessibility-text-label-issue-figure",
+  },
+  [FORM_FIELDSET_NO_NAME]: {
+    href: A11Y_TEXT_LABEL_LINKS.FORM_FIELDSET_NO_NAME,
+    l10nId: "accessibility-text-label-issue-fieldset",
+    args: {
+      get code() {
+        return ReactDOM.code({}, "fieldset");
+      },
+    },
+  },
+  [FORM_FIELDSET_NO_NAME_FROM_LEGEND]: {
+    href: A11Y_TEXT_LABEL_LINKS.FORM_FIELDSET_NO_NAME_FROM_LEGEND,
+    l10nId: "accessibility-text-label-issue-fieldset-legend",
+    args: {
+      get code() {
+        return ReactDOM.code({}, "legend");
+      },
+      // Note: there is no way right now to use custom elements in privileged
+      // content. We have to use something like <span> since we can't provide
+      // two args with the same name.
+      get span() {
+        return ReactDOM.code({}, "fieldset");
+      },
+    },
+  },
+  [FORM_NO_NAME]: {
+    href: A11Y_TEXT_LABEL_LINKS.FORM_NO_NAME,
+    l10nId: "accessibility-text-label-issue-form",
+  },
+  [FORM_NO_VISIBLE_NAME]: {
+    href: A11Y_TEXT_LABEL_LINKS.FORM_NO_VISIBLE_NAME,
+    l10nId: "accessibility-text-label-issue-form-visible",
+  },
+  [FORM_OPTGROUP_NO_NAME]: {
+    href: A11Y_TEXT_LABEL_LINKS.FORM_OPTGROUP_NO_NAME,
+    l10nId: "accessibility-text-label-issue-optgroup",
+    args: {
+      get code() {
+        return ReactDOM.code({}, "optgroup");
+      },
+    },
+  },
+  [FORM_OPTGROUP_NO_NAME_FROM_LABEL]: {
+    href: A11Y_TEXT_LABEL_LINKS.FORM_OPTGROUP_NO_NAME_FROM_LABEL,
+    l10nId: "accessibility-text-label-issue-optgroup-label",
+    args: {
+      get code() {
+        return ReactDOM.code({}, "label");
+      },
+      // Note: there is no way right now to use custom elements in privileged
+      // content. We have to use something like <span> since we can't provide
+      // two args with the same name.
+      get span() {
+        return ReactDOM.code({}, "optgroup");
+      },
+    },
+  },
+  [FRAME_NO_NAME]: {
+    href: A11Y_TEXT_LABEL_LINKS.FRAME_NO_NAME,
+    l10nId: "accessibility-text-label-issue-frame",
+    args: {
+      get code() {
+        return ReactDOM.code({}, "frame");
+      },
+    },
+  },
+  [HEADING_NO_CONTENT]: {
+    href: A11Y_TEXT_LABEL_LINKS.HEADING_NO_CONTENT,
+    l10nId: "accessibility-text-label-issue-heading-content",
+  },
+  [HEADING_NO_NAME]: {
+    href: A11Y_TEXT_LABEL_LINKS.HEADING_NO_NAME,
+    l10nId: "accessibility-text-label-issue-heading",
+  },
+  [IFRAME_NO_NAME_FROM_TITLE]: {
+    href: A11Y_TEXT_LABEL_LINKS.IFRAME_NO_NAME_FROM_TITLE,
+    l10nId: "accessibility-text-label-issue-iframe",
+    args: {
+      get code() {
+        return ReactDOM.code({}, "title");
+      },
+      // Note: there is no way right now to use custom elements in privileged
+      // content. We have to use something like <span> since we can't provide
+      // two args with the same name.
+      get span() {
+        return ReactDOM.code({}, "iframe");
+      },
+    },
+  },
+  [IMAGE_NO_NAME]: {
+    href: A11Y_TEXT_LABEL_LINKS.IMAGE_NO_NAME,
+    l10nId: "accessibility-text-label-issue-image",
+  },
+  [INTERACTIVE_NO_NAME]: {
+    href: A11Y_TEXT_LABEL_LINKS.INTERACTIVE_NO_NAME,
+    l10nId: "accessibility-text-label-issue-interactive",
+  },
+  [MATHML_GLYPH_NO_NAME]: {
+    href: A11Y_TEXT_LABEL_LINKS.MATHML_GLYPH_NO_NAME,
+    l10nId: "accessibility-text-label-issue-glyph",
+    args: {
+      get code() {
+        return ReactDOM.code({}, "alt");
+      },
+      // Note: there is no way right now to use custom elements in privileged
+      // content. We have to use something like <span> since we can't provide
+      // two args with the same name.
+      get span() {
+        return ReactDOM.code({}, "mglyph");
+      },
+    },
+  },
+  [TOOLBAR_NO_NAME]: {
+    href: A11Y_TEXT_LABEL_LINKS.TOOLBAR_NO_NAME,
+    l10nId: "accessibility-text-label-issue-toolbar",
+  },
+};
+
+/**
+ * A map of accessibility scores to the text descriptions of check icons.
+ */
+const SCORE_TO_ICON_MAP = {
+  [BEST_PRACTICES]: {
+    l10nId: "accessibility-best-practices",
+    src: "chrome://devtools/skin/images/info.svg",
+
+  },
+  [FAIL]: {
+    l10nId: "accessibility-fail",
+    src: "chrome://devtools/skin/images/error.svg",
+  },
+  [WARNING]: {
+    l10nId: "accessibility-warning",
+    src: "chrome://devtools/skin/images/alert.svg",
+  },
+};
+
+/**
+ * Localized "Learn more" link that opens a new tab with relevant documentation.
+ */
+class LearnMoreClass extends Component {
+  static get propTypes() {
+    return {
+      href: PropTypes.string,
+      l10nId: PropTypes.string.isRequired,
+      onClick: PropTypes.func,
+    };
+  }
+
+  static get defaultProps() {
+    return {
+      href: "#",
+      l10nId: null,
+      onClick: LearnMoreClass.openDocOnClick,
+    };
+  }
+
+  static openDocOnClick(event) {
+    event.preventDefault();
+    openDocLink(event.target.href);
+  }
+
+  render() {
+    const { href, l10nId, onClick } = this.props;
+    const className = "link";
+
+    return Localized({ id: l10nId }, ReactDOM.a({ className, href, onClick }));
+  }
+}
+
+const LearnMore = createFactory(LearnMoreClass);
+
+/**
+ * Renders icon with text description for the text label accessibility check.
+ *
+ * @param {Object}
+ *        Options:
+ *          - score: value from SCORES from "devtools/shared/constants"
+ */
+function Icon({ score }) {
+  const { l10nId, src } = SCORE_TO_ICON_MAP[score];
+
+  return Localized({ id: l10nId, attrs: { alt: true } },
+    ReactDOM.img({ src, className: `icon ${score}` })
+  );
+}
+
+/**
+ * Renders text description of the text label accessibility check.
+ *
+ * @param {Object}
+ *        Options:
+ *          - issue: value from ISSUE_TYPE[AUDIT_TYPE.TEXT_LABEL] from
+ *                   "devtools/shared/constants"
+ */
+function Annotation({ issue }) {
+  const { args, href, l10nId } = ISSUE_TO_ANNOTATION_MAP[issue];
+
+  return Localized({
+    id: l10nId,
+    a: LearnMore({ l10nId: "accessibility-learn-more", href }),
+    ...args,
+  },
+    ReactDOM.p({ className: "accessibility-check-annotation" })
+  );
+}
+
+/**
+ * Component for rendering a check for text label accessibliity check failures,
+ * warnings and best practices suggestions association with a given
+ * accessibility object in the accessibility tree.
+ */
+class TextLabelCheck extends Component {
+  static get propTypes() {
+    return {
+      issue: PropTypes.string.isRequired,
+      score: PropTypes.string.isRequired,
+    };
+  }
+
+  render() {
+    const { issue, score } = this.props;
+
+    return ReactDOM.div({
+      role: "presentation",
+      className: "accessibility-check",
+    },
+      Localized({
+        id: "accessibility-text-label-header",
+      },
+        ReactDOM.h3({ className: "accessibility-check-header" })),
+      ReactDOM.div({
+        role: "presentation",
+        className: "accessibility-text-label-check",
+      },
+        Icon({ score }),
+        Annotation({ issue })
+      )
+    );
+  }
+}
+
+module.exports = TextLabelCheck;
--- a/devtools/client/accessibility/components/moz.build
+++ b/devtools/client/accessibility/components/moz.build
@@ -17,10 +17,11 @@ DevToolsModules(
     'Checks.js',
     'ColorContrastAccessibility.js',
     'ContrastBadge.js',
     'Description.js',
     'LearnMoreLink.js',
     'MainFrame.js',
     'RightSidebar.js',
     'TextLabelBadge.js',
+    'TextLabelCheck.js',
     'Toolbar.js'
 )
--- a/devtools/client/accessibility/constants.js
+++ b/devtools/client/accessibility/constants.js
@@ -1,14 +1,41 @@
 /* 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/. */
 "use strict";
 
-const { accessibility: { AUDIT_TYPE } } = require("devtools/shared/constants");
+const {
+  accessibility: {
+    AUDIT_TYPE,
+    ISSUE_TYPE: {
+      [AUDIT_TYPE.TEXT_LABEL]: {
+        AREA_NO_NAME_FROM_ALT,
+        DIALOG_NO_NAME,
+        DOCUMENT_NO_TITLE,
+        EMBED_NO_NAME,
+        FIGURE_NO_NAME,
+        FORM_FIELDSET_NO_NAME,
+        FORM_FIELDSET_NO_NAME_FROM_LEGEND,
+        FORM_NO_NAME,
+        FORM_NO_VISIBLE_NAME,
+        FORM_OPTGROUP_NO_NAME,
+        FORM_OPTGROUP_NO_NAME_FROM_LABEL,
+        FRAME_NO_NAME,
+        HEADING_NO_CONTENT,
+        HEADING_NO_NAME,
+        IFRAME_NO_NAME_FROM_TITLE,
+        IMAGE_NO_NAME,
+        INTERACTIVE_NO_NAME,
+        MATHML_GLYPH_NO_NAME,
+        TOOLBAR_NO_NAME,
+      },
+    },
+  },
+} = require("devtools/shared/constants");
 
 // Used in accessible component for properties tree rendering.
 exports.TREE_ROW_HEIGHT = 21;
 
 // Initial sidebar width.
 exports.SIDEBAR_WIDTH = "350px";
 
 // When value is updated either in the tree or sidebar.
@@ -79,8 +106,46 @@ exports.A11Y_SERVICE_DURATION = "DEVTOOL
 exports.A11Y_SERVICE_ENABLED_COUNT = "devtools.accessibility.service_enabled_count";
 
 // URL constants
 exports.A11Y_LEARN_MORE_LINK =
   "https://developer.mozilla.org/docs/Tools/Accessibility_inspector";
 exports.A11Y_CONTRAST_LEARN_MORE_LINK =
   "https://developer.mozilla.org/docs/Web/Accessibility/Understanding_WCAG/Perceivable/" +
   "Color_contrast?utm_source=devtools&utm_medium=a11y-panel-checks-color-contrast";
+
+const A11Y_TEXT_LABEL_LINK_BASE =
+  "https://developer.mozilla.org/docs/Web/Accessibility/Understanding_WCAG/Text_labels_and_names" +
+  "?utm_source=devtools&utm_medium=a11y-panel-checks-text-label";
+
+const A11Y_TEXT_LABEL_LINK_IDS = {
+  [AREA_NO_NAME_FROM_ALT]:
+    "Use_alt_attribute_to_provide_a_name_for_areas_that_have_the_href_attribute",
+  [DIALOG_NO_NAME]: "Dialogs_should_have_a_name",
+  [DOCUMENT_NO_TITLE]: "Documents_must_have_a_title",
+  [EMBED_NO_NAME]: "Embedded_content_must_have_a_name",
+  [FIGURE_NO_NAME]: "Figures_with_optional_captions_should_have_a_name",
+  [FORM_FIELDSET_NO_NAME]: "Form_element_groups_must_have_a_name",
+  [FORM_FIELDSET_NO_NAME_FROM_LEGEND]:
+    "Use_legend_element_to_provide_a_name_for_form_element_groups",
+  [FORM_NO_NAME]: "Form_elements_must_have_a_name",
+  [FORM_NO_VISIBLE_NAME]: "Form_elements_should_have_a_visible_text_label",
+  [FORM_OPTGROUP_NO_NAME]: "Groupings_of_options_must_have_a_name",
+  [FORM_OPTGROUP_NO_NAME_FROM_LABEL]:
+    "Use_label_attribute_to_provide_a_name_for_groupings_of_options",
+  [FRAME_NO_NAME]: "Frames_must_have_a_name",
+  [HEADING_NO_NAME]: "Headings_must_have_a_name",
+  [HEADING_NO_CONTENT]: "Headings_must_have_visible_text_content",
+  [IFRAME_NO_NAME_FROM_TITLE]: "Use_title_attribute_to_describe_iframe_content",
+  [IMAGE_NO_NAME]: "Content_with_images_must_have_a_name",
+  [INTERACTIVE_NO_NAME]: "Interactive_elements_must_have_a_name",
+  [MATHML_GLYPH_NO_NAME]:
+    "Use_alt_attribute_to_provide_a_name_for_MathML_glyphs",
+  [TOOLBAR_NO_NAME]:
+    "Toolbars_must_have_a_name_when_there_is_more_than_one_toolbar",
+};
+
+const A11Y_TEXT_LABEL_LINKS = {};
+for (const key in A11Y_TEXT_LABEL_LINK_IDS) {
+  A11Y_TEXT_LABEL_LINKS[key] =
+    `${A11Y_TEXT_LABEL_LINK_BASE}#${A11Y_TEXT_LABEL_LINK_IDS[key]}`;
+}
+exports.A11Y_TEXT_LABEL_LINKS = A11Y_TEXT_LABEL_LINKS;
--- a/devtools/client/accessibility/panel.js
+++ b/devtools/client/accessibility/panel.js
@@ -1,13 +1,16 @@
 /* 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/. */
 "use strict";
 
+const Services = require("Services");
+const { L10nRegistry } = require("resource://gre/modules/L10nRegistry.jsm");
+
 const EventEmitter = require("devtools/shared/event-emitter");
 
 const Telemetry = require("devtools/client/shared/telemetry");
 
 const { Picker } = require("./picker");
 const { A11Y_SERVICE_DURATION } = require("./constants");
 
 // The panel's window global is an EventEmitter firing the following events:
@@ -76,29 +79,50 @@ AccessibilityPanel.prototype = {
     this.panelWin.gToolbox = this._toolbox;
 
     await this._toolbox.initInspector();
     await this.startup.initAccessibility();
     if (this.supports.enableDisable) {
       this.picker = new Picker(this);
     }
 
+    this.fluentBundles = await this.createFluentBundles();
+
     this.updateA11YServiceDurationTimer();
     this.front.on("init", this.updateA11YServiceDurationTimer);
     this.front.on("shutdown", this.updateA11YServiceDurationTimer);
 
     this.front.on("init", this.forceUpdatePickerButton);
     this.front.on("shutdown", this.forceUpdatePickerButton);
 
     this.isReady = true;
     this.emit("ready");
     resolver(this);
     return this._opening;
   },
 
+  /**
+   * Retrieve message contexts for the current locales, and return them as an
+   * array of FluentBundles elements.
+   */
+  async createFluentBundles() {
+    const locales = Services.locale.appLocalesAsBCP47;
+    const generator =
+      L10nRegistry.generateBundles(locales, ["devtools/accessibility.ftl"]);
+
+    // Return value of generateBundles is a generator and should be converted to
+    // a sync iterable before using it with React.
+    const contexts = [];
+    for await (const message of generator) {
+      contexts.push(message);
+    }
+
+    return contexts;
+  },
+
   onNewAccessibleFrontSelected(selected) {
     this.emit("new-accessible-front-selected", selected);
   },
 
   onAccessibilityInspectorUpdated() {
     this.emit("accessibility-inspector-updated");
   },
 
@@ -128,17 +152,18 @@ AccessibilityPanel.prototype = {
     }
 
     // Do not refresh if it isn't necessary.
     if (!this.shouldRefresh) {
       return;
     }
     // Alright reset the flag we are about to refresh the panel.
     this.shouldRefresh = false;
-    this.postContentMessage("initialize", this.front, this.walker, this.supports);
+    this.postContentMessage("initialize", this.front, this.walker, this.supports,
+                            this.fluentBundles);
   },
 
   updateA11YServiceDurationTimer() {
     if (this.front.enabled) {
       this._telemetry.start(A11Y_SERVICE_DURATION, this);
     } else {
       this._telemetry.finish(A11Y_SERVICE_DURATION, this, true);
     }
new file mode 100644
--- /dev/null
+++ b/devtools/client/accessibility/test/jest/babel.config.js
@@ -0,0 +1,9 @@
+/* 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/. */
+
+"use strict";
+
+module.exports = {
+  "plugins": ["@babel/plugin-proposal-async-generator-functions"],
+};
--- a/devtools/client/accessibility/test/jest/components/__snapshots__/audit-filter.test.js.snap
+++ b/devtools/client/accessibility/test/jest/components/__snapshots__/audit-filter.test.js.snap
@@ -1,13 +1,13 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`AuditController component: audit filter filtered contrast checks fail 1`] = `"<span></span>"`;
 
 exports[`AuditController component: audit filter filtered contrast checks fail range 1`] = `"<span></span>"`;
 
-exports[`AuditController component: audit filter filtered contrast checks success 1`] = `null`;
+exports[`AuditController component: audit filter filtered contrast checks success 1`] = `""`;
 
-exports[`AuditController component: audit filter filtered no checks 1`] = `null`;
+exports[`AuditController component: audit filter filtered no checks 1`] = `""`;
 
-exports[`AuditController component: audit filter filtered unknown checks 1`] = `null`;
+exports[`AuditController component: audit filter filtered unknown checks 1`] = `""`;
 
 exports[`AuditController component: audit filter not filtered 1`] = `"<span></span>"`;
--- a/devtools/client/accessibility/test/jest/components/__snapshots__/audit-progress-overlay.test.js.snap
+++ b/devtools/client/accessibility/test/jest/components/__snapshots__/audit-progress-overlay.test.js.snap
@@ -5,9 +5,9 @@ exports[`AuditProgressOverlay component:
 exports[`AuditProgressOverlay component: render auditing initializing 1`] = `"<span id=\\"audit-progress-container\\" role=\\"progressbar\\" aria-valuetext=\\"accessibility.progress.initializing\\">accessibility.progress.initializing</span>"`;
 
 exports[`AuditProgressOverlay component: render auditing progress 1`] = `"<span id=\\"audit-progress-container\\">accessibility.progress.progressbar<progress max=\\"100\\" value=\\"0\\" class=\\"audit-progress-progressbar\\" aria-labelledby=\\"audit-progress-container\\"></progress></span>"`;
 
 exports[`AuditProgressOverlay component: render auditing progress 2`] = `"<span id=\\"audit-progress-container\\">accessibility.progress.progressbar<progress max=\\"100\\" value=\\"50\\" class=\\"audit-progress-progressbar\\" aria-labelledby=\\"audit-progress-container\\"></progress></span>"`;
 
 exports[`AuditProgressOverlay component: render auditing progress 3`] = `"<span id=\\"audit-progress-container\\">accessibility.progress.progressbar<progress max=\\"100\\" value=\\"75\\" class=\\"audit-progress-progressbar\\" aria-labelledby=\\"audit-progress-container\\"></progress></span>"`;
 
-exports[`AuditProgressOverlay component: render not auditing 1`] = `null`;
+exports[`AuditProgressOverlay component: render not auditing 1`] = `""`;
--- a/devtools/client/accessibility/test/jest/components/__snapshots__/badges.test.js.snap
+++ b/devtools/client/accessibility/test/jest/components/__snapshots__/badges.test.js.snap
@@ -1,15 +1,15 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`Badges component: contrast ratio fail range render 1`] = `"<span class=\\"badges\\" role=\\"group\\" aria-label=\\"accessibility.badges\\"><span class=\\"audit-badge badge\\" title=\\"accessibility.badge.contrast.tooltip\\" aria-label=\\"accessibility.badge.contrast.warning\\">accessibility.badge.contrast</span></span>"`;
 
 exports[`Badges component: contrast ratio fail render 1`] = `"<span class=\\"badges\\" role=\\"group\\" aria-label=\\"accessibility.badges\\"><span class=\\"audit-badge badge\\" title=\\"accessibility.badge.contrast.tooltip\\" aria-label=\\"accessibility.badge.contrast.warning\\">accessibility.badge.contrast</span></span>"`;
 
 exports[`Badges component: contrast ratio success render 1`] = `"<span class=\\"badges\\" role=\\"group\\" aria-label=\\"accessibility.badges\\"></span>"`;
 
-exports[`Badges component: empty checks render 1`] = `null`;
+exports[`Badges component: empty checks render 1`] = `""`;
 
-exports[`Badges component: no props render 1`] = `null`;
+exports[`Badges component: no props render 1`] = `""`;
 
-exports[`Badges component: null checks render 1`] = `null`;
+exports[`Badges component: null checks render 1`] = `""`;
 
-exports[`Badges component: unsupported checks render 1`] = `null`;
+exports[`Badges component: unsupported checks render 1`] = `""`;
new file mode 100644
--- /dev/null
+++ b/devtools/client/accessibility/test/jest/components/__snapshots__/text-label-check.test.js.snap
@@ -0,0 +1,7 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`TextLabelCheck component: BEST_PRACTICES render 1`] = `"<div role=\\"presentation\\" class=\\"accessibility-check\\"><h3 class=\\"accessibility-check-header\\"></h3><div role=\\"presentation\\" class=\\"accessibility-text-label-check\\"><img src=\\"chrome://devtools/skin/images/info.svg\\" class=\\"icon BEST_PRACTICES\\"><p class=\\"accessibility-check-annotation\\"></p></div></div>"`;
+
+exports[`TextLabelCheck component: WARNING render 1`] = `"<div role=\\"presentation\\" class=\\"accessibility-check\\"><h3 class=\\"accessibility-check-header\\"></h3><div role=\\"presentation\\" class=\\"accessibility-text-label-check\\"><img src=\\"chrome://devtools/skin/images/alert.svg\\" class=\\"icon WARNING\\"><p class=\\"accessibility-check-annotation\\"></p></div></div>"`;
+
+exports[`TextLabelCheck component: fail render 1`] = `"<div role=\\"presentation\\" class=\\"accessibility-check\\"><h3 class=\\"accessibility-check-header\\"></h3><div role=\\"presentation\\" class=\\"accessibility-text-label-check\\"><img src=\\"chrome://devtools/skin/images/error.svg\\" class=\\"icon fail\\"><p class=\\"accessibility-check-annotation\\"></p></div></div>"`;
new file mode 100644
--- /dev/null
+++ b/devtools/client/accessibility/test/jest/components/text-label-check.test.js
@@ -0,0 +1,69 @@
+/* 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/. */
+
+"use strict";
+
+const { mount } = require("enzyme");
+const { createFactory } = require("devtools/client/shared/vendor/react");
+const TextLabelCheckClass = require("devtools/client/accessibility/components/TextLabelCheck");
+const TextLabelCheck = createFactory(TextLabelCheckClass);
+
+const FluentReact = require("devtools/client/shared/vendor/fluent-react");
+const LocalizationProvider = createFactory(FluentReact.LocalizationProvider);
+
+const {
+  accessibility: {
+    AUDIT_TYPE: { TEXT_LABEL },
+    ISSUE_TYPE: {
+      [TEXT_LABEL]: {
+        AREA_NO_NAME_FROM_ALT,
+        DIALOG_NO_NAME,
+        FORM_NO_VISIBLE_NAME,
+      },
+    },
+    SCORES: { BEST_PRACTICES, FAIL, WARNING },
+  },
+} = require("devtools/shared/constants");
+
+function testTextLabelCheck(wrapper, props) {
+  expect(wrapper.html()).toMatchSnapshot();
+  expect(wrapper.children().length).toBe(1);
+  const container = wrapper.childAt(0);
+  expect(container.hasClass("accessibility-check")).toBe(true);
+  expect(container.prop("role")).toBe("presentation");
+  expect(wrapper.props()).toMatchObject(props);
+
+  const localized = wrapper.find(FluentReact.Localized);
+  expect(localized.length).toBe(3);
+
+  const heading = localized.at(0).childAt(0);
+  expect(heading.type()).toBe("h3");
+  expect(heading.hasClass("accessibility-check-header")).toBe(true);
+
+  const icon = localized.at(1).childAt(0);
+  expect(icon.type()).toBe("img");
+  expect(icon.hasClass(props.score === FAIL ? "fail" : props.score)).toBe(true);
+
+  const annotation = localized.at(2).childAt(0);
+  expect(annotation.type()).toBe("p");
+  expect(annotation.hasClass("accessibility-check-annotation")).toBe(true);
+}
+
+describe("TextLabelCheck component:", () => {
+  const testProps = [
+    { issue: AREA_NO_NAME_FROM_ALT, score: FAIL },
+    { issue: FORM_NO_VISIBLE_NAME, score: WARNING },
+    { issue: DIALOG_NO_NAME, score: BEST_PRACTICES },
+  ];
+
+  for (const props of testProps) {
+    it(`${props.score} render`, () => {
+      const wrapper = mount(LocalizationProvider({ messages: []},
+        TextLabelCheck(props)));
+
+      const textLabelCheck = wrapper.find(TextLabelCheckClass);
+      testTextLabelCheck(textLabelCheck, props);
+    });
+  }
+});
--- a/devtools/client/accessibility/test/jest/package.json
+++ b/devtools/client/accessibility/test/jest/package.json
@@ -5,17 +5,18 @@
   "engines": {
     "node": ">=8.9.4"
   },
   "scripts": {
     "test": "jest",
     "test-ci": "jest --json"
   },
   "dependencies": {
-    "jest": "^23.0.0",
+    "@babel/plugin-proposal-async-generator-functions": "^7.2.0",
+    "jest": "^24.6.0",
     "react-test-renderer": "16.4.1",
     "react": "16.4.1",
     "react-dom": "16.4.1",
-    "enzyme": "^3.3.0",
-    "enzyme-to-json": "3.3.4",
-    "enzyme-adapter-react-16": "^1.1.1"
+    "enzyme": "^3.9.0",
+    "enzyme-to-json": "^3.3.5",
+    "enzyme-adapter-react-16": "^1.13.2"
   }
 }
--- a/devtools/client/accessibility/test/jest/yarn.lock
+++ b/devtools/client/accessibility/test/jest/yarn.lock
@@ -1,33 +1,407 @@
 # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
 # yarn lockfile v1
 
 
-"@babel/code-frame@^7.0.0-beta.35":
+"@babel/code-frame@^7.0.0":
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8"
   integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==
   dependencies:
     "@babel/highlight" "^7.0.0"
 
+"@babel/core@^7.1.0":
+  version "7.4.5"
+  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.4.5.tgz#081f97e8ffca65a9b4b0fdc7e274e703f000c06a"
+  integrity sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    "@babel/generator" "^7.4.4"
+    "@babel/helpers" "^7.4.4"
+    "@babel/parser" "^7.4.5"
+    "@babel/template" "^7.4.4"
+    "@babel/traverse" "^7.4.5"
+    "@babel/types" "^7.4.4"
+    convert-source-map "^1.1.0"
+    debug "^4.1.0"
+    json5 "^2.1.0"
+    lodash "^4.17.11"
+    resolve "^1.3.2"
+    semver "^5.4.1"
+    source-map "^0.5.0"
+
+"@babel/generator@^7.4.0", "@babel/generator@^7.4.4":
+  version "7.4.4"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.4.4.tgz#174a215eb843fc392c7edcaabeaa873de6e8f041"
+  integrity sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==
+  dependencies:
+    "@babel/types" "^7.4.4"
+    jsesc "^2.5.1"
+    lodash "^4.17.11"
+    source-map "^0.5.0"
+    trim-right "^1.0.1"
+
+"@babel/helper-annotate-as-pure@^7.0.0":
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32"
+  integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==
+  dependencies:
+    "@babel/types" "^7.0.0"
+
+"@babel/helper-function-name@^7.1.0":
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53"
+  integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==
+  dependencies:
+    "@babel/helper-get-function-arity" "^7.0.0"
+    "@babel/template" "^7.1.0"
+    "@babel/types" "^7.0.0"
+
+"@babel/helper-get-function-arity@^7.0.0":
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3"
+  integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==
+  dependencies:
+    "@babel/types" "^7.0.0"
+
+"@babel/helper-plugin-utils@^7.0.0":
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250"
+  integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==
+
+"@babel/helper-remap-async-to-generator@^7.1.0":
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f"
+  integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.0.0"
+    "@babel/helper-wrap-function" "^7.1.0"
+    "@babel/template" "^7.1.0"
+    "@babel/traverse" "^7.1.0"
+    "@babel/types" "^7.0.0"
+
+"@babel/helper-split-export-declaration@^7.4.4":
+  version "7.4.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677"
+  integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==
+  dependencies:
+    "@babel/types" "^7.4.4"
+
+"@babel/helper-wrap-function@^7.1.0":
+  version "7.2.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa"
+  integrity sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==
+  dependencies:
+    "@babel/helper-function-name" "^7.1.0"
+    "@babel/template" "^7.1.0"
+    "@babel/traverse" "^7.1.0"
+    "@babel/types" "^7.2.0"
+
+"@babel/helpers@^7.4.4":
+  version "7.4.4"
+  resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.4.4.tgz#868b0ef59c1dd4e78744562d5ce1b59c89f2f2a5"
+  integrity sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==
+  dependencies:
+    "@babel/template" "^7.4.4"
+    "@babel/traverse" "^7.4.4"
+    "@babel/types" "^7.4.4"
+
 "@babel/highlight@^7.0.0":
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4"
   integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==
   dependencies:
     chalk "^2.0.0"
     esutils "^2.0.2"
     js-tokens "^4.0.0"
 
+"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.4.4", "@babel/parser@^7.4.5":
+  version "7.4.5"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.5.tgz#04af8d5d5a2b044a2a1bffacc1e5e6673544e872"
+  integrity sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==
+
+"@babel/plugin-proposal-async-generator-functions@^7.2.0":
+  version "7.2.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e"
+  integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-remap-async-to-generator" "^7.1.0"
+    "@babel/plugin-syntax-async-generators" "^7.2.0"
+
+"@babel/plugin-syntax-async-generators@^7.2.0":
+  version "7.2.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f"
+  integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-object-rest-spread@^7.0.0":
+  version "7.2.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e"
+  integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4":
+  version "7.4.4"
+  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237"
+  integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    "@babel/parser" "^7.4.4"
+    "@babel/types" "^7.4.4"
+
+"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.4.5":
+  version "7.4.5"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.5.tgz#4e92d1728fd2f1897dafdd321efbff92156c3216"
+  integrity sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    "@babel/generator" "^7.4.4"
+    "@babel/helper-function-name" "^7.1.0"
+    "@babel/helper-split-export-declaration" "^7.4.4"
+    "@babel/parser" "^7.4.5"
+    "@babel/types" "^7.4.4"
+    debug "^4.1.0"
+    globals "^11.1.0"
+    lodash "^4.17.11"
+
+"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4":
+  version "7.4.4"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0"
+  integrity sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==
+  dependencies:
+    esutils "^2.0.2"
+    lodash "^4.17.11"
+    to-fast-properties "^2.0.0"
+
+"@cnakazawa/watch@^1.0.3":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef"
+  integrity sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==
+  dependencies:
+    exec-sh "^0.3.2"
+    minimist "^1.2.0"
+
+"@jest/console@^24.7.1":
+  version "24.7.1"
+  resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.7.1.tgz#32a9e42535a97aedfe037e725bd67e954b459545"
+  integrity sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg==
+  dependencies:
+    "@jest/source-map" "^24.3.0"
+    chalk "^2.0.1"
+    slash "^2.0.0"
+
+"@jest/core@^24.8.0":
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.8.0.tgz#fbbdcd42a41d0d39cddbc9f520c8bab0c33eed5b"
+  integrity sha512-R9rhAJwCBQzaRnrRgAdVfnglUuATXdwTRsYqs6NMdVcAl5euG8LtWDe+fVkN27YfKVBW61IojVsXKaOmSnqd/A==
+  dependencies:
+    "@jest/console" "^24.7.1"
+    "@jest/reporters" "^24.8.0"
+    "@jest/test-result" "^24.8.0"
+    "@jest/transform" "^24.8.0"
+    "@jest/types" "^24.8.0"
+    ansi-escapes "^3.0.0"
+    chalk "^2.0.1"
+    exit "^0.1.2"
+    graceful-fs "^4.1.15"
+    jest-changed-files "^24.8.0"
+    jest-config "^24.8.0"
+    jest-haste-map "^24.8.0"
+    jest-message-util "^24.8.0"
+    jest-regex-util "^24.3.0"
+    jest-resolve-dependencies "^24.8.0"
+    jest-runner "^24.8.0"
+    jest-runtime "^24.8.0"
+    jest-snapshot "^24.8.0"
+    jest-util "^24.8.0"
+    jest-validate "^24.8.0"
+    jest-watcher "^24.8.0"
+    micromatch "^3.1.10"
+    p-each-series "^1.0.0"
+    pirates "^4.0.1"
+    realpath-native "^1.1.0"
+    rimraf "^2.5.4"
+    strip-ansi "^5.0.0"
+
+"@jest/environment@^24.8.0":
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.8.0.tgz#0342261383c776bdd652168f68065ef144af0eac"
+  integrity sha512-vlGt2HLg7qM+vtBrSkjDxk9K0YtRBi7HfRFaDxoRtyi+DyVChzhF20duvpdAnKVBV6W5tym8jm0U9EfXbDk1tw==
+  dependencies:
+    "@jest/fake-timers" "^24.8.0"
+    "@jest/transform" "^24.8.0"
+    "@jest/types" "^24.8.0"
+    jest-mock "^24.8.0"
+
+"@jest/fake-timers@^24.8.0":
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.8.0.tgz#2e5b80a4f78f284bcb4bd5714b8e10dd36a8d3d1"
+  integrity sha512-2M4d5MufVXwi6VzZhJ9f5S/wU4ud2ck0kxPof1Iz3zWx6Y+V2eJrES9jEktB6O3o/oEyk+il/uNu9PvASjWXQw==
+  dependencies:
+    "@jest/types" "^24.8.0"
+    jest-message-util "^24.8.0"
+    jest-mock "^24.8.0"
+
+"@jest/reporters@^24.8.0":
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.8.0.tgz#075169cd029bddec54b8f2c0fc489fd0b9e05729"
+  integrity sha512-eZ9TyUYpyIIXfYCrw0UHUWUvE35vx5I92HGMgS93Pv7du+GHIzl+/vh8Qj9MCWFK/4TqyttVBPakWMOfZRIfxw==
+  dependencies:
+    "@jest/environment" "^24.8.0"
+    "@jest/test-result" "^24.8.0"
+    "@jest/transform" "^24.8.0"
+    "@jest/types" "^24.8.0"
+    chalk "^2.0.1"
+    exit "^0.1.2"
+    glob "^7.1.2"
+    istanbul-lib-coverage "^2.0.2"
+    istanbul-lib-instrument "^3.0.1"
+    istanbul-lib-report "^2.0.4"
+    istanbul-lib-source-maps "^3.0.1"
+    istanbul-reports "^2.1.1"
+    jest-haste-map "^24.8.0"
+    jest-resolve "^24.8.0"
+    jest-runtime "^24.8.0"
+    jest-util "^24.8.0"
+    jest-worker "^24.6.0"
+    node-notifier "^5.2.1"
+    slash "^2.0.0"
+    source-map "^0.6.0"
+    string-length "^2.0.0"
+
+"@jest/source-map@^24.3.0":
+  version "24.3.0"
+  resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.3.0.tgz#563be3aa4d224caf65ff77edc95cd1ca4da67f28"
+  integrity sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag==
+  dependencies:
+    callsites "^3.0.0"
+    graceful-fs "^4.1.15"
+    source-map "^0.6.0"
+
+"@jest/test-result@^24.8.0":
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.8.0.tgz#7675d0aaf9d2484caa65e048d9b467d160f8e9d3"
+  integrity sha512-+YdLlxwizlfqkFDh7Mc7ONPQAhA4YylU1s529vVM1rsf67vGZH/2GGm5uO8QzPeVyaVMobCQ7FTxl38QrKRlng==
+  dependencies:
+    "@jest/console" "^24.7.1"
+    "@jest/types" "^24.8.0"
+    "@types/istanbul-lib-coverage" "^2.0.0"
+
+"@jest/test-sequencer@^24.8.0":
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.8.0.tgz#2f993bcf6ef5eb4e65e8233a95a3320248cf994b"
+  integrity sha512-OzL/2yHyPdCHXEzhoBuq37CE99nkme15eHkAzXRVqthreWZamEMA0WoetwstsQBCXABhczpK03JNbc4L01vvLg==
+  dependencies:
+    "@jest/test-result" "^24.8.0"
+    jest-haste-map "^24.8.0"
+    jest-runner "^24.8.0"
+    jest-runtime "^24.8.0"
+
+"@jest/transform@^24.8.0":
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.8.0.tgz#628fb99dce4f9d254c6fd9341e3eea262e06fef5"
+  integrity sha512-xBMfFUP7TortCs0O+Xtez2W7Zu1PLH9bvJgtraN1CDST6LBM/eTOZ9SfwS/lvV8yOfcDpFmwf9bq5cYbXvqsvA==
+  dependencies:
+    "@babel/core" "^7.1.0"
+    "@jest/types" "^24.8.0"
+    babel-plugin-istanbul "^5.1.0"
+    chalk "^2.0.1"
+    convert-source-map "^1.4.0"
+    fast-json-stable-stringify "^2.0.0"
+    graceful-fs "^4.1.15"
+    jest-haste-map "^24.8.0"
+    jest-regex-util "^24.3.0"
+    jest-util "^24.8.0"
+    micromatch "^3.1.10"
+    realpath-native "^1.1.0"
+    slash "^2.0.0"
+    source-map "^0.6.1"
+    write-file-atomic "2.4.1"
+
+"@jest/types@^24.8.0":
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.8.0.tgz#f31e25948c58f0abd8c845ae26fcea1491dea7ad"
+  integrity sha512-g17UxVr2YfBtaMUxn9u/4+siG1ptg9IGYAYwvpwn61nBg779RXnjE/m7CxYcIzEt0AbHZZAHSEZNhkE2WxURVg==
+  dependencies:
+    "@types/istanbul-lib-coverage" "^2.0.0"
+    "@types/istanbul-reports" "^1.1.1"
+    "@types/yargs" "^12.0.9"
+
+"@types/babel__core@^7.1.0":
+  version "7.1.2"
+  resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.2.tgz#608c74f55928033fce18b99b213c16be4b3d114f"
+  integrity sha512-cfCCrFmiGY/yq0NuKNxIQvZFy9kY/1immpSpTngOnyIbD4+eJOG5mxphhHDv3CHL9GltO4GcKr54kGBg3RNdbg==
+  dependencies:
+    "@babel/parser" "^7.1.0"
+    "@babel/types" "^7.0.0"
+    "@types/babel__generator" "*"
+    "@types/babel__template" "*"
+    "@types/babel__traverse" "*"
+
+"@types/babel__generator@*":
+  version "7.0.2"
+  resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.0.2.tgz#d2112a6b21fad600d7674274293c85dce0cb47fc"
+  integrity sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ==
+  dependencies:
+    "@babel/types" "^7.0.0"
+
+"@types/babel__template@*":
+  version "7.0.2"
+  resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307"
+  integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==
+  dependencies:
+    "@babel/parser" "^7.1.0"
+    "@babel/types" "^7.0.0"
+
+"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6":
+  version "7.0.7"
+  resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.7.tgz#2496e9ff56196cc1429c72034e07eab6121b6f3f"
+  integrity sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw==
+  dependencies:
+    "@babel/types" "^7.3.0"
+
+"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
+  integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==
+
+"@types/istanbul-lib-report@*":
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c"
+  integrity sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==
+  dependencies:
+    "@types/istanbul-lib-coverage" "*"
+
+"@types/istanbul-reports@^1.1.1":
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a"
+  integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==
+  dependencies:
+    "@types/istanbul-lib-coverage" "*"
+    "@types/istanbul-lib-report" "*"
+
 "@types/node@*":
   version "11.13.2"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-11.13.2.tgz#dc85dde46aa8740bb4aed54b8104250f8f849503"
   integrity sha512-HOtU5KqROKT7qX/itKHuTtt5fV0iXbheQvrgbLNXFJQBY/eh+VS5vmmTAVlo3qIGMsypm0G4N1t2AXjy1ZicaQ==
 
+"@types/stack-utils@^1.0.1":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
+  integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
+
+"@types/yargs@^12.0.2", "@types/yargs@^12.0.9":
+  version "12.0.12"
+  resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.12.tgz#45dd1d0638e8c8f153e87d296907659296873916"
+  integrity sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==
+
 abab@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f"
   integrity sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==
 
 abbrev@1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
@@ -51,20 +425,20 @@ acorn@^5.5.3:
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
   integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
 
 acorn@^6.0.1:
   version "6.1.1"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f"
   integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==
 
-airbnb-prop-types@^2.12.0:
-  version "2.13.1"
-  resolved "https://registry.yarnpkg.com/airbnb-prop-types/-/airbnb-prop-types-2.13.1.tgz#abcae3f683c0c918aae5e0a1df6232e39e0abfa5"
-  integrity sha512-imXx6ssLTp1IJ6TgOH+8X04VgNXLjjHDz72PfhrovwFYwVHOmoklMpPAeB45VxxP5+wi1Ztxwl+xHBIZLEEmRQ==
+airbnb-prop-types@^2.13.2:
+  version "2.13.2"
+  resolved "https://registry.yarnpkg.com/airbnb-prop-types/-/airbnb-prop-types-2.13.2.tgz#43147a5062dd2a4a5600e748a47b64004cc5f7fc"
+  integrity sha512-2FN6DlHr6JCSxPPi25EnqGaXC4OC3/B3k1lCd6MMYrZ51/Gf/1qDfaR+JElzWa+Tl7cY2aYOlsYJGFeQyVHIeQ==
   dependencies:
     array.prototype.find "^2.0.4"
     function.prototype.name "^1.1.0"
     has "^1.0.3"
     is-regex "^1.0.4"
     object-is "^1.0.1"
     object.assign "^4.1.0"
     object.entries "^1.1.0"
@@ -92,76 +466,55 @@ ansi-regex@^2.0.0:
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
   integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
 
 ansi-regex@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
   integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
 
-ansi-styles@^2.2.1:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
-  integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
+ansi-regex@^4.0.0, ansi-regex@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
+  integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
 
 ansi-styles@^3.2.0, ansi-styles@^3.2.1:
   version "3.2.1"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
   integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
   dependencies:
     color-convert "^1.9.0"
 
 anymatch@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
   integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==
   dependencies:
     micromatch "^3.1.4"
     normalize-path "^2.1.1"
 
-append-transform@^0.4.0:
-  version "0.4.0"
-  resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991"
-  integrity sha1-126/jKlNJ24keja61EpLdKthGZE=
-  dependencies:
-    default-require-extensions "^1.0.0"
-
 aproba@^1.0.3:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
   integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
 
 are-we-there-yet@~1.1.2:
   version "1.1.5"
   resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
   integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==
   dependencies:
     delegates "^1.0.0"
     readable-stream "^2.0.6"
 
-argparse@^1.0.7:
-  version "1.0.10"
-  resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
-  integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
-  dependencies:
-    sprintf-js "~1.0.2"
-
-arr-diff@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
-  integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=
-  dependencies:
-    arr-flatten "^1.0.1"
-
 arr-diff@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
   integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=
 
-arr-flatten@^1.0.1, arr-flatten@^1.1.0:
+arr-flatten@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
   integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
 
 arr-union@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
   integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
@@ -171,21 +524,16 @@ array-equal@^1.0.0:
   resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
   integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=
 
 array-filter@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83"
   integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=
 
-array-unique@^0.2.1:
-  version "0.2.1"
-  resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
-  integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=
-
 array-unique@^0.3.2:
   version "0.3.2"
   resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
   integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
 
 array.prototype.find@^2.0.4:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.0.4.tgz#556a5c5362c08648323ddaeb9de9d14bc1864c90"
@@ -198,21 +546,16 @@ array.prototype.flat@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz#812db8f02cad24d3fab65dd67eabe3b8903494a4"
   integrity sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw==
   dependencies:
     define-properties "^1.1.2"
     es-abstract "^1.10.0"
     function-bind "^1.1.1"
 
-arrify@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
-  integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
-
 asap@~2.0.3:
   version "2.0.6"
   resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
   integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
 
 asn1@~0.2.3:
   version "0.2.4"
   resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
@@ -235,23 +578,16 @@ astral-regex@^1.0.0:
   resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
   integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
 
 async-limiter@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
   integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==
 
-async@^2.1.4:
-  version "2.6.2"
-  resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381"
-  integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==
-  dependencies:
-    lodash "^4.17.11"
-
 asynckit@^0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
   integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
 
 atob@^2.1.1:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
@@ -262,176 +598,52 @@ aws-sign2@~0.7.0:
   resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
   integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
 
 aws4@^1.8.0:
   version "1.8.0"
   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
   integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
 
-babel-code-frame@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
-  integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=
-  dependencies:
-    chalk "^1.1.3"
-    esutils "^2.0.2"
-    js-tokens "^3.0.2"
-
-babel-core@^6.0.0, babel-core@^6.26.0:
-  version "6.26.3"
-  resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
-  integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==
-  dependencies:
-    babel-code-frame "^6.26.0"
-    babel-generator "^6.26.0"
-    babel-helpers "^6.24.1"
-    babel-messages "^6.23.0"
-    babel-register "^6.26.0"
-    babel-runtime "^6.26.0"
-    babel-template "^6.26.0"
-    babel-traverse "^6.26.0"
-    babel-types "^6.26.0"
-    babylon "^6.18.0"
-    convert-source-map "^1.5.1"
-    debug "^2.6.9"
-    json5 "^0.5.1"
-    lodash "^4.17.4"
-    minimatch "^3.0.4"
-    path-is-absolute "^1.0.1"
-    private "^0.1.8"
-    slash "^1.0.0"
-    source-map "^0.5.7"
-
-babel-generator@^6.18.0, babel-generator@^6.26.0:
-  version "6.26.1"
-  resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
-  integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==
-  dependencies:
-    babel-messages "^6.23.0"
-    babel-runtime "^6.26.0"
-    babel-types "^6.26.0"
-    detect-indent "^4.0.0"
-    jsesc "^1.3.0"
-    lodash "^4.17.4"
-    source-map "^0.5.7"
-    trim-right "^1.0.1"
-
-babel-helpers@^6.24.1:
-  version "6.24.1"
-  resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
-  integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=
-  dependencies:
-    babel-runtime "^6.22.0"
-    babel-template "^6.24.1"
-
-babel-jest@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1"
-  integrity sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==
-  dependencies:
-    babel-plugin-istanbul "^4.1.6"
-    babel-preset-jest "^23.2.0"
-
-babel-messages@^6.23.0:
-  version "6.23.0"
-  resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
-  integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=
-  dependencies:
-    babel-runtime "^6.22.0"
-
-babel-plugin-istanbul@^4.1.6:
-  version "4.1.6"
-  resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45"
-  integrity sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==
-  dependencies:
-    babel-plugin-syntax-object-rest-spread "^6.13.0"
-    find-up "^2.1.0"
-    istanbul-lib-instrument "^1.10.1"
-    test-exclude "^4.2.1"
-
-babel-plugin-jest-hoist@^23.2.0:
-  version "23.2.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167"
-  integrity sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=
-
-babel-plugin-syntax-object-rest-spread@^6.13.0:
-  version "6.13.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
-  integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=
-
-babel-preset-jest@^23.2.0:
-  version "23.2.0"
-  resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46"
-  integrity sha1-jsegOhOPABoaj7HoETZSvxpV2kY=
-  dependencies:
-    babel-plugin-jest-hoist "^23.2.0"
-    babel-plugin-syntax-object-rest-spread "^6.13.0"
-
-babel-register@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
-  integrity sha1-btAhFz4vy0htestFxgCahW9kcHE=
-  dependencies:
-    babel-core "^6.26.0"
-    babel-runtime "^6.26.0"
-    core-js "^2.5.0"
-    home-or-tmp "^2.0.0"
-    lodash "^4.17.4"
-    mkdirp "^0.5.1"
-    source-map-support "^0.4.15"
-
-babel-runtime@^6.22.0, babel-runtime@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
-  integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
-  dependencies:
-    core-js "^2.4.0"
-    regenerator-runtime "^0.11.0"
-
-babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
-  integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=
-  dependencies:
-    babel-runtime "^6.26.0"
-    babel-traverse "^6.26.0"
-    babel-types "^6.26.0"
-    babylon "^6.18.0"
-    lodash "^4.17.4"
-
-babel-traverse@^6.0.0, babel-traverse@^6.18.0, babel-traverse@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
-  integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=
-  dependencies:
-    babel-code-frame "^6.26.0"
-    babel-messages "^6.23.0"
-    babel-runtime "^6.26.0"
-    babel-types "^6.26.0"
-    babylon "^6.18.0"
-    debug "^2.6.8"
-    globals "^9.18.0"
-    invariant "^2.2.2"
-    lodash "^4.17.4"
-
-babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.26.0:
-  version "6.26.0"
-  resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
-  integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
-  dependencies:
-    babel-runtime "^6.26.0"
-    esutils "^2.0.2"
-    lodash "^4.17.4"
-    to-fast-properties "^1.0.3"
-
-babylon@^6.18.0:
-  version "6.18.0"
-  resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
-  integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
+babel-jest@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.8.0.tgz#5c15ff2b28e20b0f45df43fe6b7f2aae93dba589"
+  integrity sha512-+5/kaZt4I9efoXzPlZASyK/lN9qdRKmmUav9smVc0ruPQD7IsfucQ87gpOE8mn2jbDuS6M/YOW6n3v9ZoIfgnw==
+  dependencies:
+    "@jest/transform" "^24.8.0"
+    "@jest/types" "^24.8.0"
+    "@types/babel__core" "^7.1.0"
+    babel-plugin-istanbul "^5.1.0"
+    babel-preset-jest "^24.6.0"
+    chalk "^2.4.2"
+    slash "^2.0.0"
+
+babel-plugin-istanbul@^5.1.0:
+  version "5.1.4"
+  resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.4.tgz#841d16b9a58eeb407a0ddce622ba02fe87a752ba"
+  integrity sha512-dySz4VJMH+dpndj0wjJ8JPs/7i1TdSPb1nRrn56/92pKOF9VKC1FMFJmMXjzlGGusnCAqujP6PBCiKq0sVA+YQ==
+  dependencies:
+    find-up "^3.0.0"
+    istanbul-lib-instrument "^3.3.0"
+    test-exclude "^5.2.3"
+
+babel-plugin-jest-hoist@^24.6.0:
+  version "24.6.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.6.0.tgz#f7f7f7ad150ee96d7a5e8e2c5da8319579e78019"
+  integrity sha512-3pKNH6hMt9SbOv0F3WVmy5CWQ4uogS3k0GY5XLyQHJ9EGpAT9XWkFd2ZiXXtkwFHdAHa5j7w7kfxSP5lAIwu7w==
+  dependencies:
+    "@types/babel__traverse" "^7.0.6"
+
+babel-preset-jest@^24.6.0:
+  version "24.6.0"
+  resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.6.0.tgz#66f06136eefce87797539c0d63f1769cc3915984"
+  integrity sha512-pdZqLEdmy1ZK5kyRUfvBb2IfTPb2BUvIJczlPspS8fWmBQslNNDBqVfh7BW5leOVJMDZKzjD8XEyABTk6gQ5yw==
+  dependencies:
+    "@babel/plugin-syntax-object-rest-spread" "^7.0.0"
+    babel-plugin-jest-hoist "^24.6.0"
 
 balanced-match@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
   integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
 
 base@^0.11.1:
   version "0.11.2"
@@ -461,25 +673,16 @@ boolbase@~1.0.0:
 brace-expansion@^1.1.7:
   version "1.1.11"
   resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
   integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
   dependencies:
     balanced-match "^1.0.0"
     concat-map "0.0.1"
 
-braces@^1.8.2:
-  version "1.8.5"
-  resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
-  integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=
-  dependencies:
-    expand-range "^1.8.1"
-    preserve "^0.2.0"
-    repeat-element "^1.1.2"
-
 braces@^2.3.1:
   version "2.3.2"
   resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
   integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
   dependencies:
     arr-flatten "^1.1.0"
     array-unique "^0.3.2"
     extend-shallow "^2.0.1"
@@ -525,50 +728,39 @@ cache-base@^1.0.1:
     get-value "^2.0.6"
     has-value "^1.0.0"
     isobject "^3.0.1"
     set-value "^2.0.0"
     to-object-path "^0.3.0"
     union-value "^1.0.0"
     unset-value "^1.0.0"
 
-callsites@^2.0.0:
+callsites@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
+  integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+
+camelcase@^5.0.0:
+  version "5.3.1"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+  integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
+capture-exit@^2.0.0:
   version "2.0.0"
-  resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
-  integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=
-
-camelcase@^4.1.0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
-  integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
-
-capture-exit@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f"
-  integrity sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=
-  dependencies:
-    rsvp "^3.3.3"
+  resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4"
+  integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==
+  dependencies:
+    rsvp "^4.8.4"
 
 caseless@~0.12.0:
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
   integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
 
-chalk@^1.1.3:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
-  integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
-  dependencies:
-    ansi-styles "^2.2.1"
-    escape-string-regexp "^1.0.2"
-    has-ansi "^2.0.0"
-    strip-ansi "^3.0.0"
-    supports-color "^2.0.0"
-
-chalk@^2.0.0, chalk@^2.0.1:
+chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.2:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
   integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
   dependencies:
     ansi-styles "^3.2.1"
     escape-string-regexp "^1.0.5"
     supports-color "^5.3.0"
 
@@ -584,20 +776,20 @@ cheerio@^1.0.0-rc.2:
     lodash "^4.15.0"
     parse5 "^3.0.1"
 
 chownr@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
   integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==
 
-ci-info@^1.5.0:
-  version "1.6.0"
-  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
-  integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
+ci-info@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
+  integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
 
 class-utils@^0.3.5:
   version "0.3.6"
   resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
   integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==
   dependencies:
     arr-union "^3.1.0"
     define-property "^0.2.5"
@@ -670,49 +862,46 @@ concat-map@0.0.1:
   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
   integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
 
 console-control-strings@^1.0.0, console-control-strings@~1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
   integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
 
-convert-source-map@^1.4.0, convert-source-map@^1.5.1:
+convert-source-map@^1.1.0, convert-source-map@^1.4.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20"
   integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==
   dependencies:
     safe-buffer "~5.1.1"
 
 copy-descriptor@^0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
   integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
 
 core-js@^1.0.0:
   version "1.2.7"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
   integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=
 
-core-js@^2.4.0, core-js@^2.5.0:
-  version "2.6.5"
-  resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895"
-  integrity sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==
-
 core-util-is@1.0.2, core-util-is@~1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
   integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
 
-cross-spawn@^5.0.1:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
-  integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=
-  dependencies:
-    lru-cache "^4.0.1"
+cross-spawn@^6.0.0:
+  version "6.0.5"
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
+  integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
+  dependencies:
+    nice-try "^1.0.4"
+    path-key "^2.0.1"
+    semver "^5.5.0"
     shebang-command "^1.2.0"
     which "^1.2.9"
 
 css-select@~1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
   integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=
   dependencies:
@@ -749,31 +938,31 @@ data-urls@^1.0.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe"
   integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==
   dependencies:
     abab "^2.0.0"
     whatwg-mimetype "^2.2.0"
     whatwg-url "^7.0.0"
 
-debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
+debug@^2.1.2, debug@^2.2.0, debug@^2.3.3:
   version "2.6.9"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
   integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
   dependencies:
     ms "2.0.0"
 
-debug@^3.1.0:
-  version "3.2.6"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
-  integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
+debug@^4.1.0, debug@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
+  integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
   dependencies:
     ms "^2.1.1"
 
-decamelize@^1.1.1:
+decamelize@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
   integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
 
 decode-uri-component@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
   integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
@@ -783,23 +972,16 @@ deep-extend@^0.6.0:
   resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
   integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
 
 deep-is@~0.1.3:
   version "0.1.3"
   resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
   integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
 
-default-require-extensions@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8"
-  integrity sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=
-  dependencies:
-    strip-bom "^2.0.0"
-
 define-properties@^1.1.2, define-properties@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
   integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
   dependencies:
     object-keys "^1.0.12"
 
 define-property@^0.2.5:
@@ -829,37 +1011,30 @@ delayed-stream@~1.0.0:
   resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
   integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
 
 delegates@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
   integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
 
-detect-indent@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
-  integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg=
-  dependencies:
-    repeating "^2.0.0"
-
 detect-libc@^1.0.2:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
   integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
 
 detect-newline@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
   integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=
 
-diff@^3.2.0:
-  version "3.5.0"
-  resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
-  integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
+diff-sequences@^24.3.0:
+  version "24.3.0"
+  resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.3.0.tgz#0f20e8a1df1abddaf4d9c226680952e64118b975"
+  integrity sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==
 
 discontinuous-range@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
   integrity sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=
 
 dom-serializer@0, dom-serializer@~0.1.1:
   version "0.1.1"
@@ -914,57 +1089,65 @@ ecc-jsbn@~0.1.1:
 
 encoding@^0.1.11:
   version "0.1.12"
   resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
   integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
   dependencies:
     iconv-lite "~0.4.13"
 
+end-of-stream@^1.1.0:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
+  integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
+  dependencies:
+    once "^1.4.0"
+
 entities@^1.1.1, entities@~1.1.1:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
   integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
 
-enzyme-adapter-react-16@^1.1.1:
-  version "1.12.1"
-  resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.12.1.tgz#6a2d74c80559d35ac0a91ca162fa45f4186290cf"
-  integrity sha512-GB61gvY97XvrA6qljExGY+lgI6BBwz+ASLaRKct9VQ3ozu0EraqcNn3CcrUckSGIqFGa1+CxO5gj5is5t3lwrw==
-  dependencies:
-    enzyme-adapter-utils "^1.11.0"
+enzyme-adapter-react-16@^1.13.2:
+  version "1.14.0"
+  resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.14.0.tgz#204722b769172bcf096cb250d33e6795c1f1858f"
+  integrity sha512-7PcOF7pb4hJUvjY7oAuPGpq3BmlCig3kxXGi2kFx0YzJHppqX1K8IIV9skT1IirxXlu8W7bneKi+oQ10QRnhcA==
+  dependencies:
+    enzyme-adapter-utils "^1.12.0"
+    has "^1.0.3"
     object.assign "^4.1.0"
     object.values "^1.1.0"
     prop-types "^15.7.2"
     react-is "^16.8.6"
     react-test-renderer "^16.0.0-0"
-    semver "^5.6.0"
-
-enzyme-adapter-utils@^1.11.0:
-  version "1.11.0"
-  resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.11.0.tgz#6ffff782b1b57dd46c72a845a91fc4103956a117"
-  integrity sha512-0VZeoE9MNx+QjTfsjmO1Mo+lMfunucYB4wt5ficU85WB/LoetTJrbuujmHP3PJx6pSoaAuLA+Mq877x4LoxdNg==
-  dependencies:
-    airbnb-prop-types "^2.12.0"
+    semver "^5.7.0"
+
+enzyme-adapter-utils@^1.12.0:
+  version "1.12.0"
+  resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.12.0.tgz#96e3730d76b872f593e54ce1c51fa3a451422d93"
+  integrity sha512-wkZvE0VxcFx/8ZsBw0iAbk3gR1d9hK447ebnSYBf95+r32ezBq+XDSAvRErkc4LZosgH8J7et7H7/7CtUuQfBA==
+  dependencies:
+    airbnb-prop-types "^2.13.2"
     function.prototype.name "^1.1.0"
     object.assign "^4.1.0"
     object.fromentries "^2.0.0"
     prop-types "^15.7.2"
     semver "^5.6.0"
 
-enzyme-to-json@3.3.4:
-  version "3.3.4"
-  resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.3.4.tgz#67c6040e931182f183418af2eb9f4323258aa77f"
-  integrity sha1-Z8YEDpMRgvGDQYry659DIyWKp38=
+enzyme-to-json@^3.3.5:
+  version "3.3.5"
+  resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.3.5.tgz#f8eb82bd3d5941c9d8bc6fd9140030777d17d0af"
+  integrity sha512-DmH1wJ68HyPqKSYXdQqB33ZotwfUhwQZW3IGXaNXgR69Iodaoj8TF/D9RjLdz4pEhGq2Tx2zwNUIjBuqoZeTgA==
   dependencies:
     lodash "^4.17.4"
 
-enzyme@^3.3.0:
-  version "3.9.0"
-  resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.9.0.tgz#2b491f06ca966eb56b6510068c7894a7e0be3909"
-  integrity sha512-JqxI2BRFHbmiP7/UFqvsjxTirWoM1HfeaJrmVSZ9a1EADKkZgdPcAuISPMpoUiHlac9J4dYt81MC5BBIrbJGMg==
+enzyme@^3.9.0:
+  version "3.10.0"
+  resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.10.0.tgz#7218e347c4a7746e133f8e964aada4a3523452f6"
+  integrity sha512-p2yy9Y7t/PFbPoTvrWde7JIYB2ZyGC+NgTNbVEGvZ5/EyoYSr9aG/2rSbVvyNvMHEhw9/dmGUJHWtfQIEiX9pg==
   dependencies:
     array.prototype.flat "^1.2.1"
     cheerio "^1.0.0-rc.2"
     function.prototype.name "^1.1.0"
     has "^1.0.3"
     html-element-map "^1.0.0"
     is-boolean-object "^1.0.0"
     is-callable "^1.1.4"
@@ -978,17 +1161,17 @@ enzyme@^3.3.0:
     object-is "^1.0.1"
     object.assign "^4.1.0"
     object.entries "^1.0.4"
     object.values "^1.0.4"
     raf "^3.4.0"
     rst-selector-parser "^2.2.3"
     string.prototype.trim "^1.1.2"
 
-error-ex@^1.2.0:
+error-ex@^1.3.1:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
   integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
   dependencies:
     is-arrayish "^0.2.1"
 
 es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.7.0:
   version "1.13.0"
@@ -1006,17 +1189,17 @@ es-to-primitive@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377"
   integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==
   dependencies:
     is-callable "^1.1.4"
     is-date-object "^1.0.1"
     is-symbol "^1.0.2"
 
-escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+escape-string-regexp@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
   integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
 
 escodegen@^1.9.1:
   version "1.11.1"
   resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.1.tgz#c485ff8d6b4cdb89e27f4a856e91f118401ca510"
   integrity sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==
@@ -1028,94 +1211,73 @@ escodegen@^1.9.1:
   optionalDependencies:
     source-map "~0.6.1"
 
 esprima@^3.1.3:
   version "3.1.3"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
   integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=
 
-esprima@^4.0.0:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
-  integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-
 estraverse@^4.2.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
   integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=
 
 esutils@^2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
   integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=
 
-exec-sh@^0.2.0:
-  version "0.2.2"
-  resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36"
-  integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==
-  dependencies:
-    merge "^1.2.0"
-
-execa@^0.7.0:
-  version "0.7.0"
-  resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
-  integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=
-  dependencies:
-    cross-spawn "^5.0.1"
-    get-stream "^3.0.0"
+exec-sh@^0.3.2:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.2.tgz#6738de2eb7c8e671d0366aea0b0db8c6f7d7391b"
+  integrity sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==
+
+execa@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
+  integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
+  dependencies:
+    cross-spawn "^6.0.0"
+    get-stream "^4.0.0"
     is-stream "^1.1.0"
     npm-run-path "^2.0.0"
     p-finally "^1.0.0"
     signal-exit "^3.0.0"
     strip-eof "^1.0.0"
 
 exit@^0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
   integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=
 
-expand-brackets@^0.1.4:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
-  integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=
-  dependencies:
-    is-posix-bracket "^0.1.0"
-
 expand-brackets@^2.1.4:
   version "2.1.4"
   resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
   integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI=
   dependencies:
     debug "^2.3.3"
     define-property "^0.2.5"
     extend-shallow "^2.0.1"
     posix-character-classes "^0.1.0"
     regex-not "^1.0.0"
     snapdragon "^0.8.1"
     to-regex "^3.0.1"
 
-expand-range@^1.8.1:
-  version "1.8.2"
-  resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
-  integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=
-  dependencies:
-    fill-range "^2.1.0"
-
-expect@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/expect/-/expect-23.6.0.tgz#1e0c8d3ba9a581c87bd71fb9bc8862d443425f98"
-  integrity sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==
-  dependencies:
+expect@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/expect/-/expect-24.8.0.tgz#471f8ec256b7b6129ca2524b2a62f030df38718d"
+  integrity sha512-/zYvP8iMDrzaaxHVa724eJBCKqSHmO0FA7EDkBiRHxg6OipmMn1fN+C8T9L9K8yr7UONkOifu6+LLH+z76CnaA==
+  dependencies:
+    "@jest/types" "^24.8.0"
     ansi-styles "^3.2.0"
-    jest-diff "^23.6.0"
-    jest-get-type "^22.1.0"
-    jest-matcher-utils "^23.6.0"
-    jest-message-util "^23.4.0"
-    jest-regex-util "^23.3.0"
+    jest-get-type "^24.8.0"
+    jest-matcher-utils "^24.8.0"
+    jest-message-util "^24.8.0"
+    jest-regex-util "^24.3.0"
 
 extend-shallow@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
   integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=
   dependencies:
     is-extendable "^0.1.0"
 
@@ -1127,23 +1289,16 @@ extend-shallow@^3.0.0, extend-shallow@^3
     assign-symbols "^1.0.0"
     is-extendable "^1.0.1"
 
 extend@~3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
   integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
 
-extglob@^0.3.1:
-  version "0.3.2"
-  resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
-  integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=
-  dependencies:
-    is-extglob "^1.0.0"
-
 extglob@^2.0.4:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
   integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==
   dependencies:
     array-unique "^0.3.2"
     define-property "^1.0.0"
     expand-brackets "^2.1.4"
@@ -1193,77 +1348,38 @@ fbjs@^0.8.16:
     core-js "^1.0.0"
     isomorphic-fetch "^2.1.1"
     loose-envify "^1.0.0"
     object-assign "^4.1.0"
     promise "^7.1.1"
     setimmediate "^1.0.5"
     ua-parser-js "^0.7.18"
 
-filename-regex@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
-  integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=
-
-fileset@^2.0.2:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0"
-  integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=
-  dependencies:
-    glob "^7.0.3"
-    minimatch "^3.0.3"
-
-fill-range@^2.1.0:
-  version "2.2.4"
-  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565"
-  integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==
-  dependencies:
-    is-number "^2.1.0"
-    isobject "^2.0.0"
-    randomatic "^3.0.0"
-    repeat-element "^1.1.2"
-    repeat-string "^1.5.2"
-
 fill-range@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
   integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=
   dependencies:
     extend-shallow "^2.0.1"
     is-number "^3.0.0"
     repeat-string "^1.6.1"
     to-regex-range "^2.1.0"
 
-find-up@^1.0.0:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
-  integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
-  dependencies:
-    path-exists "^2.0.0"
-    pinkie-promise "^2.0.0"
-
-find-up@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
-  integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c=
-  dependencies:
-    locate-path "^2.0.0"
-
-for-in@^1.0.1, for-in@^1.0.2:
+find-up@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
+  integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+  dependencies:
+    locate-path "^3.0.0"
+
+for-in@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
   integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
 
-for-own@^0.1.4:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce"
-  integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=
-  dependencies:
-    for-in "^1.0.1"
-
 forever-agent@~0.6.1:
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
   integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
 
 form-data@~2.3.2:
   version "2.3.3"
   resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
@@ -1287,23 +1403,23 @@ fs-minipass@^1.2.5:
   dependencies:
     minipass "^2.2.1"
 
 fs.realpath@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
   integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
 
-fsevents@^1.2.3:
-  version "1.2.7"
-  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.7.tgz#4851b664a3783e52003b3c66eb0eee1074933aa4"
-  integrity sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==
-  dependencies:
-    nan "^2.9.2"
-    node-pre-gyp "^0.10.0"
+fsevents@^1.2.7:
+  version "1.2.9"
+  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f"
+  integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==
+  dependencies:
+    nan "^2.12.1"
+    node-pre-gyp "^0.12.0"
 
 function-bind@^1.0.2, function-bind@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
   integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
 
 function.prototype.name@^1.1.0:
   version "1.1.0"
@@ -1328,79 +1444,66 @@ gauge@~2.7.3:
     strip-ansi "^3.0.1"
     wide-align "^1.1.0"
 
 get-caller-file@^1.0.1:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
   integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
 
-get-stream@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
-  integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
+get-stream@^4.0.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
+  integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
+  dependencies:
+    pump "^3.0.0"
 
 get-value@^2.0.3, get-value@^2.0.6:
   version "2.0.6"
   resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
   integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
 
 getpass@^0.1.1:
   version "0.1.7"
   resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
   integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
   dependencies:
     assert-plus "^1.0.0"
 
-glob-base@^0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
-  integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=
-  dependencies:
-    glob-parent "^2.0.0"
-    is-glob "^2.0.0"
-
-glob-parent@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
-  integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=
-  dependencies:
-    is-glob "^2.0.0"
-
-glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3:
+glob@^7.1.1, glob@^7.1.2, glob@^7.1.3:
   version "7.1.3"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
   integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
   dependencies:
     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@^9.18.0:
-  version "9.18.0"
-  resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
-  integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
-
-graceful-fs@^4.1.11, graceful-fs@^4.1.2:
+globals@^11.1.0:
+  version "11.12.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
+  integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2:
   version "4.1.15"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
   integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
 
 growly@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
   integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
 
-handlebars@^4.0.3:
-  version "4.1.1"
-  resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.1.tgz#6e4e41c18ebe7719ae4d38e5aca3d32fa3dd23d3"
-  integrity sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==
+handlebars@^4.1.2:
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67"
+  integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==
   dependencies:
     neo-async "^2.6.0"
     optimist "^0.6.1"
     source-map "^0.6.1"
   optionalDependencies:
     uglify-js "^3.1.4"
 
 har-schema@^2.0.0:
@@ -1411,28 +1514,16 @@ har-schema@^2.0.0:
 har-validator@~5.1.0:
   version "5.1.3"
   resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
   integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
   dependencies:
     ajv "^6.5.5"
     har-schema "^2.0.0"
 
-has-ansi@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
-  integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
-  dependencies:
-    ansi-regex "^2.0.0"
-
-has-flag@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
-  integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
-
 has-flag@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
   integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
 
 has-symbols@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44"
@@ -1476,24 +1567,16 @@ has-values@^1.0.0:
 
 has@^1.0.1, has@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
   integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
   dependencies:
     function-bind "^1.1.1"
 
-home-or-tmp@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
-  integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg=
-  dependencies:
-    os-homedir "^1.0.0"
-    os-tmpdir "^1.0.1"
-
 hosted-git-info@^2.1.4:
   version "2.7.1"
   resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047"
   integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==
 
 html-element-map@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/html-element-map/-/html-element-map-1.0.1.tgz#3c4fcb4874ebddfe4283b51c8994e7713782b592"
@@ -1538,22 +1621,22 @@ iconv-lite@0.4.24, iconv-lite@^0.4.4, ic
 
 ignore-walk@^3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8"
   integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==
   dependencies:
     minimatch "^3.0.4"
 
-import-local@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc"
-  integrity sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==
-  dependencies:
-    pkg-dir "^2.0.0"
+import-local@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d"
+  integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==
+  dependencies:
+    pkg-dir "^3.0.0"
     resolve-cwd "^2.0.0"
 
 imurmurhash@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
   integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
 
 inflight@^1.0.4:
@@ -1569,27 +1652,27 @@ inherits@2, inherits@^2.0.1, inherits@^2
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
   integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
 
 ini@~1.3.0:
   version "1.3.5"
   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
   integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
 
-invariant@^2.2.2, invariant@^2.2.4:
+invariant@^2.2.4:
   version "2.2.4"
   resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
   integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
   dependencies:
     loose-envify "^1.0.0"
 
-invert-kv@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
-  integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY=
+invert-kv@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
+  integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
 
 is-accessor-descriptor@^0.1.6:
   version "0.1.6"
   resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
   integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=
   dependencies:
     kind-of "^3.0.2"
 
@@ -1615,22 +1698,22 @@ is-buffer@^1.1.5:
   resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
   integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
 
 is-callable@^1.1.3, is-callable@^1.1.4:
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
   integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==
 
-is-ci@^1.0.10:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
-  integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==
-  dependencies:
-    ci-info "^1.5.0"
+is-ci@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
+  integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==
+  dependencies:
+    ci-info "^2.0.0"
 
 is-data-descriptor@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
   integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=
   dependencies:
     kind-of "^3.0.2"
 
@@ -1659,117 +1742,64 @@ is-descriptor@^1.0.0, is-descriptor@^1.0
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec"
   integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==
   dependencies:
     is-accessor-descriptor "^1.0.0"
     is-data-descriptor "^1.0.0"
     kind-of "^6.0.2"
 
-is-dotfile@^1.0.0:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1"
-  integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=
-
-is-equal-shallow@^0.1.3:
-  version "0.1.3"
-  resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
-  integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=
-  dependencies:
-    is-primitive "^2.0.0"
-
 is-extendable@^0.1.0, is-extendable@^0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
   integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=
 
 is-extendable@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4"
   integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==
   dependencies:
     is-plain-object "^2.0.4"
 
-is-extglob@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
-  integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=
-
-is-finite@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
-  integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=
-  dependencies:
-    number-is-nan "^1.0.0"
-
 is-fullwidth-code-point@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
   integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
   dependencies:
     number-is-nan "^1.0.0"
 
 is-fullwidth-code-point@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
   integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
 
-is-generator-fn@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a"
-  integrity sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=
-
-is-glob@^2.0.0, is-glob@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
-  integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=
-  dependencies:
-    is-extglob "^1.0.0"
+is-generator-fn@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
+  integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
 
 is-number-object@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.3.tgz#f265ab89a9f445034ef6aff15a8f00b00f551799"
   integrity sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=
 
-is-number@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
-  integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=
-  dependencies:
-    kind-of "^3.0.2"
-
 is-number@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
   integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=
   dependencies:
     kind-of "^3.0.2"
 
-is-number@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
-  integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
-
 is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
   integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
   dependencies:
     isobject "^3.0.1"
 
-is-posix-bracket@^0.1.0:
-  version "0.1.1"
-  resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
-  integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=
-
-is-primitive@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
-  integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU=
-
 is-regex@^1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
   integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=
   dependencies:
     has "^1.0.1"
 
 is-stream@^1.0.1, is-stream@^1.1.0:
@@ -1794,21 +1824,16 @@ is-symbol@^1.0.2:
   dependencies:
     has-symbols "^1.0.0"
 
 is-typedarray@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
   integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
 
-is-utf8@^0.2.0:
-  version "0.2.1"
-  resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
-  integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
-
 is-windows@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
   integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
 
 is-wsl@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
@@ -1844,421 +1869,418 @@ isomorphic-fetch@^2.1.1:
     node-fetch "^1.0.1"
     whatwg-fetch ">=0.10.0"
 
 isstream@~0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
   integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
 
-istanbul-api@^1.3.1:
-  version "1.3.7"
-  resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.3.7.tgz#a86c770d2b03e11e3f778cd7aedd82d2722092aa"
-  integrity sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==
-  dependencies:
-    async "^2.1.4"
-    fileset "^2.0.2"
-    istanbul-lib-coverage "^1.2.1"
-    istanbul-lib-hook "^1.2.2"
-    istanbul-lib-instrument "^1.10.2"
-    istanbul-lib-report "^1.1.5"
-    istanbul-lib-source-maps "^1.2.6"
-    istanbul-reports "^1.5.1"
-    js-yaml "^3.7.0"
-    mkdirp "^0.5.1"
-    once "^1.4.0"
-
-istanbul-lib-coverage@^1.2.0, istanbul-lib-coverage@^1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0"
-  integrity sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==
-
-istanbul-lib-hook@^1.2.2:
-  version "1.2.2"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz#bc6bf07f12a641fbf1c85391d0daa8f0aea6bf86"
-  integrity sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==
-  dependencies:
-    append-transform "^0.4.0"
-
-istanbul-lib-instrument@^1.10.1, istanbul-lib-instrument@^1.10.2:
-  version "1.10.2"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca"
-  integrity sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==
-  dependencies:
-    babel-generator "^6.18.0"
-    babel-template "^6.16.0"
-    babel-traverse "^6.18.0"
-    babel-types "^6.18.0"
-    babylon "^6.18.0"
-    istanbul-lib-coverage "^1.2.1"
-    semver "^5.3.0"
-
-istanbul-lib-report@^1.1.5:
-  version "1.1.5"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz#f2a657fc6282f96170aaf281eb30a458f7f4170c"
-  integrity sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==
-  dependencies:
-    istanbul-lib-coverage "^1.2.1"
-    mkdirp "^0.5.1"
-    path-parse "^1.0.5"
-    supports-color "^3.1.2"
-
-istanbul-lib-source-maps@^1.2.4, istanbul-lib-source-maps@^1.2.6:
-  version "1.2.6"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz#37b9ff661580f8fca11232752ee42e08c6675d8f"
-  integrity sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==
-  dependencies:
-    debug "^3.1.0"
-    istanbul-lib-coverage "^1.2.1"
-    mkdirp "^0.5.1"
-    rimraf "^2.6.1"
-    source-map "^0.5.3"
-
-istanbul-reports@^1.5.1:
-  version "1.5.1"
-  resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.1.tgz#97e4dbf3b515e8c484caea15d6524eebd3ff4e1a"
-  integrity sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==
-  dependencies:
-    handlebars "^4.0.3"
-
-jest-changed-files@^23.4.2:
-  version "23.4.2"
-  resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.4.2.tgz#1eed688370cd5eebafe4ae93d34bb3b64968fe83"
-  integrity sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==
-  dependencies:
+istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.5:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49"
+  integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==
+
+istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.3.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630"
+  integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==
+  dependencies:
+    "@babel/generator" "^7.4.0"
+    "@babel/parser" "^7.4.3"
+    "@babel/template" "^7.4.0"
+    "@babel/traverse" "^7.4.3"
+    "@babel/types" "^7.4.0"
+    istanbul-lib-coverage "^2.0.5"
+    semver "^6.0.0"
+
+istanbul-lib-report@^2.0.4:
+  version "2.0.8"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33"
+  integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==
+  dependencies:
+    istanbul-lib-coverage "^2.0.5"
+    make-dir "^2.1.0"
+    supports-color "^6.1.0"
+
+istanbul-lib-source-maps@^3.0.1:
+  version "3.0.6"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8"
+  integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==
+  dependencies:
+    debug "^4.1.1"
+    istanbul-lib-coverage "^2.0.5"
+    make-dir "^2.1.0"
+    rimraf "^2.6.3"
+    source-map "^0.6.1"
+
+istanbul-reports@^2.1.1:
+  version "2.2.6"
+  resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af"
+  integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==
+  dependencies:
+    handlebars "^4.1.2"
+
+jest-changed-files@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.8.0.tgz#7e7eb21cf687587a85e50f3d249d1327e15b157b"
+  integrity sha512-qgANC1Yrivsq+UrLXsvJefBKVoCsKB0Hv+mBb6NMjjZ90wwxCDmU3hsCXBya30cH+LnPYjwgcU65i6yJ5Nfuug==
+  dependencies:
+    "@jest/types" "^24.8.0"
+    execa "^1.0.0"
     throat "^4.0.0"
 
-jest-cli@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-23.6.0.tgz#61ab917744338f443ef2baa282ddffdd658a5da4"
-  integrity sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==
-  dependencies:
-    ansi-escapes "^3.0.0"
+jest-cli@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.8.0.tgz#b075ac914492ed114fa338ade7362a301693e989"
+  integrity sha512-+p6J00jSMPQ116ZLlHJJvdf8wbjNbZdeSX9ptfHX06/MSNaXmKihQzx5vQcw0q2G6JsdVkUIdWbOWtSnaYs3yA==
+  dependencies:
+    "@jest/core" "^24.8.0"
+    "@jest/test-result" "^24.8.0"
+    "@jest/types" "^24.8.0"
     chalk "^2.0.1"
     exit "^0.1.2"
-    glob "^7.1.2"
-    graceful-fs "^4.1.11"
-    import-local "^1.0.0"
-    is-ci "^1.0.10"
-    istanbul-api "^1.3.1"
-    istanbul-lib-coverage "^1.2.0"
-    istanbul-lib-instrument "^1.10.1"
-    istanbul-lib-source-maps "^1.2.4"
-    jest-changed-files "^23.4.2"
-    jest-config "^23.6.0"
-    jest-environment-jsdom "^23.4.0"
-    jest-get-type "^22.1.0"
-    jest-haste-map "^23.6.0"
-    jest-message-util "^23.4.0"
-    jest-regex-util "^23.3.0"
-    jest-resolve-dependencies "^23.6.0"
-    jest-runner "^23.6.0"
-    jest-runtime "^23.6.0"
-    jest-snapshot "^23.6.0"
-    jest-util "^23.4.0"
-    jest-validate "^23.6.0"
-    jest-watcher "^23.4.0"
-    jest-worker "^23.2.0"
-    micromatch "^2.3.11"
-    node-notifier "^5.2.1"
-    prompts "^0.1.9"
-    realpath-native "^1.0.0"
-    rimraf "^2.5.4"
-    slash "^1.0.0"
-    string-length "^2.0.0"
-    strip-ansi "^4.0.0"
-    which "^1.2.12"
-    yargs "^11.0.0"
-
-jest-config@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.6.0.tgz#f82546a90ade2d8c7026fbf6ac5207fc22f8eb1d"
-  integrity sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==
-  dependencies:
-    babel-core "^6.0.0"
-    babel-jest "^23.6.0"
+    import-local "^2.0.0"
+    is-ci "^2.0.0"
+    jest-config "^24.8.0"
+    jest-util "^24.8.0"
+    jest-validate "^24.8.0"
+    prompts "^2.0.1"
+    realpath-native "^1.1.0"
+    yargs "^12.0.2"
+
+jest-config@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.8.0.tgz#77db3d265a6f726294687cbbccc36f8a76ee0f4f"
+  integrity sha512-Czl3Nn2uEzVGsOeaewGWoDPD8GStxCpAe0zOYs2x2l0fZAgPbCr3uwUkgNKV3LwE13VXythM946cd5rdGkkBZw==
+  dependencies:
+    "@babel/core" "^7.1.0"
+    "@jest/test-sequencer" "^24.8.0"
+    "@jest/types" "^24.8.0"
+    babel-jest "^24.8.0"
     chalk "^2.0.1"
     glob "^7.1.1"
-    jest-environment-jsdom "^23.4.0"
-    jest-environment-node "^23.4.0"
-    jest-get-type "^22.1.0"
-    jest-jasmine2 "^23.6.0"
-    jest-regex-util "^23.3.0"
-    jest-resolve "^23.6.0"
-    jest-util "^23.4.0"
-    jest-validate "^23.6.0"
-    micromatch "^2.3.11"
-    pretty-format "^23.6.0"
-
-jest-diff@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.6.0.tgz#1500f3f16e850bb3d71233408089be099f610c7d"
-  integrity sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==
-  dependencies:
-    chalk "^2.0.1"
-    diff "^3.2.0"
-    jest-get-type "^22.1.0"
-    pretty-format "^23.6.0"
-
-jest-docblock@^23.2.0:
-  version "23.2.0"
-  resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.2.0.tgz#f085e1f18548d99fdd69b20207e6fd55d91383a7"
-  integrity sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=
-  dependencies:
-    detect-newline "^2.1.0"
-
-jest-each@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.6.0.tgz#ba0c3a82a8054387016139c733a05242d3d71575"
-  integrity sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==
+    jest-environment-jsdom "^24.8.0"
+    jest-environment-node "^24.8.0"
+    jest-get-type "^24.8.0"
+    jest-jasmine2 "^24.8.0"
+    jest-regex-util "^24.3.0"
+    jest-resolve "^24.8.0"
+    jest-util "^24.8.0"
+    jest-validate "^24.8.0"
+    micromatch "^3.1.10"
+    pretty-format "^24.8.0"
+    realpath-native "^1.1.0"
+
+jest-diff@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.8.0.tgz#146435e7d1e3ffdf293d53ff97e193f1d1546172"
+  integrity sha512-wxetCEl49zUpJ/bvUmIFjd/o52J+yWcoc5ZyPq4/W1LUKGEhRYDIbP1KcF6t+PvqNrGAFk4/JhtxDq/Nnzs66g==
   dependencies:
     chalk "^2.0.1"
-    pretty-format "^23.6.0"
-
-jest-environment-jsdom@^23.4.0:
-  version "23.4.0"
-  resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz#056a7952b3fea513ac62a140a2c368c79d9e6023"
-  integrity sha1-BWp5UrP+pROsYqFAosNox52eYCM=
-  dependencies:
-    jest-mock "^23.2.0"
-    jest-util "^23.4.0"
+    diff-sequences "^24.3.0"
+    jest-get-type "^24.8.0"
+    pretty-format "^24.8.0"
+
+jest-docblock@^24.3.0:
+  version "24.3.0"
+  resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.3.0.tgz#b9c32dac70f72e4464520d2ba4aec02ab14db5dd"
+  integrity sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg==
+  dependencies:
+    detect-newline "^2.1.0"
+
+jest-each@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.8.0.tgz#a05fd2bf94ddc0b1da66c6d13ec2457f35e52775"
+  integrity sha512-NrwK9gaL5+XgrgoCsd9svsoWdVkK4gnvyhcpzd6m487tXHqIdYeykgq3MKI1u4I+5Zf0tofr70at9dWJDeb+BA==
+  dependencies:
+    "@jest/types" "^24.8.0"
+    chalk "^2.0.1"
+    jest-get-type "^24.8.0"
+    jest-util "^24.8.0"
+    pretty-format "^24.8.0"
+
+jest-environment-jsdom@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.8.0.tgz#300f6949a146cabe1c9357ad9e9ecf9f43f38857"
+  integrity sha512-qbvgLmR7PpwjoFjM/sbuqHJt/NCkviuq9vus9NBn/76hhSidO+Z6Bn9tU8friecegbJL8gzZQEMZBQlFWDCwAQ==
+  dependencies:
+    "@jest/environment" "^24.8.0"
+    "@jest/fake-timers" "^24.8.0"
+    "@jest/types" "^24.8.0"
+    jest-mock "^24.8.0"
+    jest-util "^24.8.0"
     jsdom "^11.5.1"
 
-jest-environment-node@^23.4.0:
-  version "23.4.0"
-  resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.4.0.tgz#57e80ed0841dea303167cce8cd79521debafde10"
-  integrity sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=
-  dependencies:
-    jest-mock "^23.2.0"
-    jest-util "^23.4.0"
-
-jest-get-type@^22.1.0:
-  version "22.4.3"
-  resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4"
-  integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==
-
-jest-haste-map@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16"
-  integrity sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==
-  dependencies:
+jest-environment-node@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.8.0.tgz#d3f726ba8bc53087a60e7a84ca08883a4c892231"
+  integrity sha512-vIGUEScd1cdDgR6sqn2M08sJTRLQp6Dk/eIkCeO4PFHxZMOgy+uYLPMC4ix3PEfM5Au/x3uQ/5Tl0DpXXZsJ/Q==
+  dependencies:
+    "@jest/environment" "^24.8.0"
+    "@jest/fake-timers" "^24.8.0"
+    "@jest/types" "^24.8.0"
+    jest-mock "^24.8.0"
+    jest-util "^24.8.0"
+
+jest-get-type@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.8.0.tgz#a7440de30b651f5a70ea3ed7ff073a32dfe646fc"
+  integrity sha512-RR4fo8jEmMD9zSz2nLbs2j0zvPpk/KCEz3a62jJWbd2ayNo0cb+KFRxPHVhE4ZmgGJEQp0fosmNz84IfqM8cMQ==
+
+jest-haste-map@^24.8.0:
+  version "24.8.1"
+  resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.8.1.tgz#f39cc1d2b1d907e014165b4bd5a957afcb992982"
+  integrity sha512-SwaxMGVdAZk3ernAx2Uv2sorA7jm3Kx+lR0grp6rMmnY06Kn/urtKx1LPN2mGTea4fCT38impYT28FfcLUhX0g==
+  dependencies:
+    "@jest/types" "^24.8.0"
+    anymatch "^2.0.0"
     fb-watchman "^2.0.0"
-    graceful-fs "^4.1.11"
+    graceful-fs "^4.1.15"
     invariant "^2.2.4"
-    jest-docblock "^23.2.0"
-    jest-serializer "^23.0.1"
-    jest-worker "^23.2.0"
-    micromatch "^2.3.11"
-    sane "^2.0.0"
-
-jest-jasmine2@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz#840e937f848a6c8638df24360ab869cc718592e0"
-  integrity sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==
-  dependencies:
-    babel-traverse "^6.0.0"
+    jest-serializer "^24.4.0"
+    jest-util "^24.8.0"
+    jest-worker "^24.6.0"
+    micromatch "^3.1.10"
+    sane "^4.0.3"
+    walker "^1.0.7"
+  optionalDependencies:
+    fsevents "^1.2.7"
+
+jest-jasmine2@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.8.0.tgz#a9c7e14c83dd77d8b15e820549ce8987cc8cd898"
+  integrity sha512-cEky88npEE5LKd5jPpTdDCLvKkdyklnaRycBXL6GNmpxe41F0WN44+i7lpQKa/hcbXaQ+rc9RMaM4dsebrYong==
+  dependencies:
+    "@babel/traverse" "^7.1.0"
+    "@jest/environment" "^24.8.0"
+    "@jest/test-result" "^24.8.0"
+    "@jest/types" "^24.8.0"
     chalk "^2.0.1"
     co "^4.6.0"
-    expect "^23.6.0"
-    is-generator-fn "^1.0.0"
-    jest-diff "^23.6.0"
-    jest-each "^23.6.0"
-    jest-matcher-utils "^23.6.0"
-    jest-message-util "^23.4.0"
-    jest-snapshot "^23.6.0"
-    jest-util "^23.4.0"
-    pretty-format "^23.6.0"
-
-jest-leak-detector@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz#e4230fd42cf381a1a1971237ad56897de7e171de"
-  integrity sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==
-  dependencies:
-    pretty-format "^23.6.0"
-
-jest-matcher-utils@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz#726bcea0c5294261a7417afb6da3186b4b8cac80"
-  integrity sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==
+    expect "^24.8.0"
+    is-generator-fn "^2.0.0"
+    jest-each "^24.8.0"
+    jest-matcher-utils "^24.8.0"
+    jest-message-util "^24.8.0"
+    jest-runtime "^24.8.0"
+    jest-snapshot "^24.8.0"
+    jest-util "^24.8.0"
+    pretty-format "^24.8.0"
+    throat "^4.0.0"
+
+jest-leak-detector@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.8.0.tgz#c0086384e1f650c2d8348095df769f29b48e6980"
+  integrity sha512-cG0yRSK8A831LN8lIHxI3AblB40uhv0z+SsQdW3GoMMVcK+sJwrIIyax5tu3eHHNJ8Fu6IMDpnLda2jhn2pD/g==
+  dependencies:
+    pretty-format "^24.8.0"
+
+jest-matcher-utils@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.8.0.tgz#2bce42204c9af12bde46f83dc839efe8be832495"
+  integrity sha512-lex1yASY51FvUuHgm0GOVj7DCYEouWSlIYmCW7APSqB9v8mXmKSn5+sWVF0MhuASG0bnYY106/49JU1FZNl5hw==
   dependencies:
     chalk "^2.0.1"
-    jest-get-type "^22.1.0"
-    pretty-format "^23.6.0"
-
-jest-message-util@^23.4.0:
-  version "23.4.0"
-  resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f"
-  integrity sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=
-  dependencies:
-    "@babel/code-frame" "^7.0.0-beta.35"
+    jest-diff "^24.8.0"
+    jest-get-type "^24.8.0"
+    pretty-format "^24.8.0"
+
+jest-message-util@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.8.0.tgz#0d6891e72a4beacc0292b638685df42e28d6218b"
+  integrity sha512-p2k71rf/b6ns8btdB0uVdljWo9h0ovpnEe05ZKWceQGfXYr4KkzgKo3PBi8wdnd9OtNh46VpNIJynUn/3MKm1g==
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    "@jest/test-result" "^24.8.0"
+    "@jest/types" "^24.8.0"
+    "@types/stack-utils" "^1.0.1"
     chalk "^2.0.1"
-    micromatch "^2.3.11"
-    slash "^1.0.0"
+    micromatch "^3.1.10"
+    slash "^2.0.0"
     stack-utils "^1.0.1"
 
-jest-mock@^23.2.0:
-  version "23.2.0"
-  resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134"
-  integrity sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=
-
-jest-regex-util@^23.3.0:
-  version "23.3.0"
-  resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5"
-  integrity sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=
-
-jest-resolve-dependencies@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz#b4526af24c8540d9a3fab102c15081cf509b723d"
-  integrity sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==
-  dependencies:
-    jest-regex-util "^23.3.0"
-    jest-snapshot "^23.6.0"
-
-jest-resolve@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.6.0.tgz#cf1d1a24ce7ee7b23d661c33ba2150f3aebfa0ae"
-  integrity sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==
-  dependencies:
+jest-mock@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.8.0.tgz#2f9d14d37699e863f1febf4e4d5a33b7fdbbde56"
+  integrity sha512-6kWugwjGjJw+ZkK4mDa0Df3sDlUTsV47MSrT0nGQ0RBWJbpODDQ8MHDVtGtUYBne3IwZUhtB7elxHspU79WH3A==
+  dependencies:
+    "@jest/types" "^24.8.0"
+
+jest-pnp-resolver@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a"
+  integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==
+
+jest-regex-util@^24.3.0:
+  version "24.3.0"
+  resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.3.0.tgz#d5a65f60be1ae3e310d5214a0307581995227b36"
+  integrity sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg==
+
+jest-resolve-dependencies@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.8.0.tgz#19eec3241f2045d3f990dba331d0d7526acff8e0"
+  integrity sha512-hyK1qfIf/krV+fSNyhyJeq3elVMhK9Eijlwy+j5jqmZ9QsxwKBiP6qukQxaHtK8k6zql/KYWwCTQ+fDGTIJauw==
+  dependencies:
+    "@jest/types" "^24.8.0"
+    jest-regex-util "^24.3.0"
+    jest-snapshot "^24.8.0"
+
+jest-resolve@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.8.0.tgz#84b8e5408c1f6a11539793e2b5feb1b6e722439f"
+  integrity sha512-+hjSzi1PoRvnuOICoYd5V/KpIQmkAsfjFO71458hQ2Whi/yf1GDeBOFj8Gxw4LrApHsVJvn5fmjcPdmoUHaVKw==
+  dependencies:
+    "@jest/types" "^24.8.0"
     browser-resolve "^1.11.3"
     chalk "^2.0.1"
-    realpath-native "^1.0.0"
-
-jest-runner@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.6.0.tgz#3894bd219ffc3f3cb94dc48a4170a2e6f23a5a38"
-  integrity sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==
-  dependencies:
+    jest-pnp-resolver "^1.2.1"
+    realpath-native "^1.1.0"
+
+jest-runner@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.8.0.tgz#4f9ae07b767db27b740d7deffad0cf67ccb4c5bb"
+  integrity sha512-utFqC5BaA3JmznbissSs95X1ZF+d+4WuOWwpM9+Ak356YtMhHE/GXUondZdcyAAOTBEsRGAgH/0TwLzfI9h7ow==
+  dependencies:
+    "@jest/console" "^24.7.1"
+    "@jest/environment" "^24.8.0"
+    "@jest/test-result" "^24.8.0"
+    "@jest/types" "^24.8.0"
+    chalk "^2.4.2"
     exit "^0.1.2"
-    graceful-fs "^4.1.11"
-    jest-config "^23.6.0"
-    jest-docblock "^23.2.0"
-    jest-haste-map "^23.6.0"
-    jest-jasmine2 "^23.6.0"
-    jest-leak-detector "^23.6.0"
-    jest-message-util "^23.4.0"
-    jest-runtime "^23.6.0"
-    jest-util "^23.4.0"
-    jest-worker "^23.2.0"
+    graceful-fs "^4.1.15"
+    jest-config "^24.8.0"
+    jest-docblock "^24.3.0"
+    jest-haste-map "^24.8.0"
+    jest-jasmine2 "^24.8.0"
+    jest-leak-detector "^24.8.0"
+    jest-message-util "^24.8.0"
+    jest-resolve "^24.8.0"
+    jest-runtime "^24.8.0"
+    jest-util "^24.8.0"
+    jest-worker "^24.6.0"
     source-map-support "^0.5.6"
     throat "^4.0.0"
 
-jest-runtime@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.6.0.tgz#059e58c8ab445917cd0e0d84ac2ba68de8f23082"
-  integrity sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==
-  dependencies:
-    babel-core "^6.0.0"
-    babel-plugin-istanbul "^4.1.6"
+jest-runtime@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.8.0.tgz#05f94d5b05c21f6dc54e427cd2e4980923350620"
+  integrity sha512-Mq0aIXhvO/3bX44ccT+czU1/57IgOMyy80oM0XR/nyD5zgBcesF84BPabZi39pJVA6UXw+fY2Q1N+4BiVUBWOA==
+  dependencies:
+    "@jest/console" "^24.7.1"
+    "@jest/environment" "^24.8.0"
+    "@jest/source-map" "^24.3.0"
+    "@jest/transform" "^24.8.0"
+    "@jest/types" "^24.8.0"
+    "@types/yargs" "^12.0.2"
     chalk "^2.0.1"
-    convert-source-map "^1.4.0"
     exit "^0.1.2"
-    fast-json-stable-stringify "^2.0.0"
-    graceful-fs "^4.1.11"
-    jest-config "^23.6.0"
-    jest-haste-map "^23.6.0"
-    jest-message-util "^23.4.0"
-    jest-regex-util "^23.3.0"
-    jest-resolve "^23.6.0"
-    jest-snapshot "^23.6.0"
-    jest-util "^23.4.0"
-    jest-validate "^23.6.0"
-    micromatch "^2.3.11"
-    realpath-native "^1.0.0"
-    slash "^1.0.0"
-    strip-bom "3.0.0"
-    write-file-atomic "^2.1.0"
-    yargs "^11.0.0"
-
-jest-serializer@^23.0.1:
-  version "23.0.1"
-  resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165"
-  integrity sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=
-
-jest-snapshot@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.6.0.tgz#f9c2625d1b18acda01ec2d2b826c0ce58a5aa17a"
-  integrity sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==
-  dependencies:
-    babel-types "^6.0.0"
+    glob "^7.1.3"
+    graceful-fs "^4.1.15"
+    jest-config "^24.8.0"
+    jest-haste-map "^24.8.0"
+    jest-message-util "^24.8.0"
+    jest-mock "^24.8.0"
+    jest-regex-util "^24.3.0"
+    jest-resolve "^24.8.0"
+    jest-snapshot "^24.8.0"
+    jest-util "^24.8.0"
+    jest-validate "^24.8.0"
+    realpath-native "^1.1.0"
+    slash "^2.0.0"
+    strip-bom "^3.0.0"
+    yargs "^12.0.2"
+
+jest-serializer@^24.4.0:
+  version "24.4.0"
+  resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.4.0.tgz#f70c5918c8ea9235ccb1276d232e459080588db3"
+  integrity sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q==
+
+jest-snapshot@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.8.0.tgz#3bec6a59da2ff7bc7d097a853fb67f9d415cb7c6"
+  integrity sha512-5ehtWoc8oU9/cAPe6fez6QofVJLBKyqkY2+TlKTOf0VllBB/mqUNdARdcjlZrs9F1Cv+/HKoCS/BknT0+tmfPg==
+  dependencies:
+    "@babel/types" "^7.0.0"
+    "@jest/types" "^24.8.0"
     chalk "^2.0.1"
-    jest-diff "^23.6.0"
-    jest-matcher-utils "^23.6.0"
-    jest-message-util "^23.4.0"
-    jest-resolve "^23.6.0"
+    expect "^24.8.0"
+    jest-diff "^24.8.0"
+    jest-matcher-utils "^24.8.0"
+    jest-message-util "^24.8.0"
+    jest-resolve "^24.8.0"
     mkdirp "^0.5.1"
     natural-compare "^1.4.0"
-    pretty-format "^23.6.0"
+    pretty-format "^24.8.0"
     semver "^5.5.0"
 
-jest-util@^23.4.0:
-  version "23.4.0"
-  resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.4.0.tgz#4d063cb927baf0a23831ff61bec2cbbf49793561"
-  integrity sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=
-  dependencies:
-    callsites "^2.0.0"
+jest-util@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.8.0.tgz#41f0e945da11df44cc76d64ffb915d0716f46cd1"
+  integrity sha512-DYZeE+XyAnbNt0BG1OQqKy/4GVLPtzwGx5tsnDrFcax36rVE3lTA5fbvgmbVPUZf9w77AJ8otqR4VBbfFJkUZA==
+  dependencies:
+    "@jest/console" "^24.7.1"
+    "@jest/fake-timers" "^24.8.0"
+    "@jest/source-map" "^24.3.0"
+    "@jest/test-result" "^24.8.0"
+    "@jest/types" "^24.8.0"
+    callsites "^3.0.0"
     chalk "^2.0.1"
-    graceful-fs "^4.1.11"
-    is-ci "^1.0.10"
-    jest-message-util "^23.4.0"
+    graceful-fs "^4.1.15"
+    is-ci "^2.0.0"
     mkdirp "^0.5.1"
-    slash "^1.0.0"
+    slash "^2.0.0"
     source-map "^0.6.0"
 
-jest-validate@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474"
-  integrity sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==
-  dependencies:
+jest-validate@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.8.0.tgz#624c41533e6dfe356ffadc6e2423a35c2d3b4849"
+  integrity sha512-+/N7VOEMW1Vzsrk3UWBDYTExTPwf68tavEPKDnJzrC6UlHtUDU/fuEdXqFoHzv9XnQ+zW6X3qMZhJ3YexfeLDA==
+  dependencies:
+    "@jest/types" "^24.8.0"
+    camelcase "^5.0.0"
     chalk "^2.0.1"
-    jest-get-type "^22.1.0"
+    jest-get-type "^24.8.0"
     leven "^2.1.0"
-    pretty-format "^23.6.0"
-
-jest-watcher@^23.4.0:
-  version "23.4.0"
-  resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.4.0.tgz#d2e28ce74f8dad6c6afc922b92cabef6ed05c91c"
-  integrity sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=
-  dependencies:
+    pretty-format "^24.8.0"
+
+jest-watcher@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.8.0.tgz#58d49915ceddd2de85e238f6213cef1c93715de4"
+  integrity sha512-SBjwHt5NedQoVu54M5GEx7cl7IGEFFznvd/HNT8ier7cCAx/Qgu9ZMlaTQkvK22G1YOpcWBLQPFSImmxdn3DAw==
+  dependencies:
+    "@jest/test-result" "^24.8.0"
+    "@jest/types" "^24.8.0"
+    "@types/yargs" "^12.0.9"
     ansi-escapes "^3.0.0"
     chalk "^2.0.1"
+    jest-util "^24.8.0"
     string-length "^2.0.0"
 
-jest-worker@^23.2.0:
-  version "23.2.0"
-  resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.2.0.tgz#faf706a8da36fae60eb26957257fa7b5d8ea02b9"
-  integrity sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=
+jest-worker@^24.6.0:
+  version "24.6.0"
+  resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.6.0.tgz#7f81ceae34b7cde0c9827a6980c35b7cdc0161b3"
+  integrity sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==
   dependencies:
     merge-stream "^1.0.1"
-
-jest@^23.0.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/jest/-/jest-23.6.0.tgz#ad5835e923ebf6e19e7a1d7529a432edfee7813d"
-  integrity sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==
-  dependencies:
-    import-local "^1.0.0"
-    jest-cli "^23.6.0"
+    supports-color "^6.1.0"
+
+jest@^24.6.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/jest/-/jest-24.8.0.tgz#d5dff1984d0d1002196e9b7f12f75af1b2809081"
+  integrity sha512-o0HM90RKFRNWmAWvlyV8i5jGZ97pFwkeVoGvPW1EtLTgJc2+jcuqcbbqcSZLE/3f2S5pt0y2ZBETuhpWNl1Reg==
+  dependencies:
+    import-local "^2.0.0"
+    jest-cli "^24.8.0"
 
 "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
   integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
 
-js-tokens@^3.0.2:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
-  integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
-
-js-yaml@^3.7.0:
-  version "3.13.1"
-  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
-  integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
-  dependencies:
-    argparse "^1.0.7"
-    esprima "^4.0.0"
-
 jsbn@~0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
   integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
 
 jsdom@^11.5.1:
   version "11.12.0"
   resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8"
@@ -2286,40 +2308,47 @@ jsdom@^11.5.1:
     w3c-hr-time "^1.0.1"
     webidl-conversions "^4.0.2"
     whatwg-encoding "^1.0.3"
     whatwg-mimetype "^2.1.0"
     whatwg-url "^6.4.1"
     ws "^5.2.0"
     xml-name-validator "^3.0.0"
 
-jsesc@^1.3.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
-  integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s=
+jsesc@^2.5.1:
+  version "2.5.2"
+  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
+  integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+
+json-parse-better-errors@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
+  integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
 
 json-schema-traverse@^0.4.1:
   version "0.4.1"
   resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
   integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
 
 json-schema@0.2.3:
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
   integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
 
 json-stringify-safe@~5.0.1:
   version "5.0.1"
   resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
   integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
 
-json5@^0.5.1:
-  version "0.5.1"
-  resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
-  integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
+json5@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850"
+  integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==
+  dependencies:
+    minimist "^1.2.0"
 
 jsprim@^1.2.2:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
   integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
   dependencies:
     assert-plus "1.0.0"
     extsprintf "1.3.0"
@@ -2345,27 +2374,27 @@ kind-of@^5.0.0:
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d"
   integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==
 
 kind-of@^6.0.0, kind-of@^6.0.2:
   version "6.0.2"
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
   integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
 
-kleur@^2.0.1:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300"
-  integrity sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==
-
-lcid@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
-  integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=
-  dependencies:
-    invert-kv "^1.0.0"
+kleur@^3.0.2:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
+  integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
+
+lcid@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
+  integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==
+  dependencies:
+    invert-kv "^2.0.0"
 
 left-pad@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e"
   integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==
 
 leven@^2.1.0:
   version "2.1.0"
@@ -2375,33 +2404,32 @@ leven@^2.1.0:
 levn@~0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
   integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=
   dependencies:
     prelude-ls "~1.1.2"
     type-check "~0.3.2"
 
-load-json-file@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
-  integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
+load-json-file@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
+  integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
   dependencies:
     graceful-fs "^4.1.2"
-    parse-json "^2.2.0"
-    pify "^2.0.0"
-    pinkie-promise "^2.0.0"
-    strip-bom "^2.0.0"
-
-locate-path@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
-  integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=
-  dependencies:
-    p-locate "^2.0.0"
+    parse-json "^4.0.0"
+    pify "^3.0.0"
+    strip-bom "^3.0.0"
+
+locate-path@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
+  integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+  dependencies:
+    p-locate "^3.0.0"
     path-exists "^3.0.0"
 
 lodash.escape@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98"
   integrity sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=
 
 lodash.flattendeep@^4.4.0:
@@ -2426,87 +2454,67 @@ lodash@^4.15.0, lodash@^4.17.11, lodash@
 
 loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
   integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
   dependencies:
     js-tokens "^3.0.0 || ^4.0.0"
 
-lru-cache@^4.0.1:
-  version "4.1.5"
-  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
-  integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
-  dependencies:
-    pseudomap "^1.0.2"
-    yallist "^2.1.2"
+make-dir@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
+  integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
+  dependencies:
+    pify "^4.0.1"
+    semver "^5.6.0"
 
 makeerror@1.0.x:
   version "1.0.11"
   resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
   integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=
   dependencies:
     tmpl "1.0.x"
 
+map-age-cleaner@^0.1.1:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
+  integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
+  dependencies:
+    p-defer "^1.0.0"
+
 map-cache@^0.2.2:
   version "0.2.2"
   resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
   integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=
 
 map-visit@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
   integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=
   dependencies:
     object-visit "^1.0.0"
 
-math-random@^1.0.1:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c"
-  integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==
-
-mem@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76"
-  integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=
-  dependencies:
-    mimic-fn "^1.0.0"
+mem@^4.0.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
+  integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
+  dependencies:
+    map-age-cleaner "^0.1.1"
+    mimic-fn "^2.0.0"
+    p-is-promise "^2.0.0"
 
 merge-stream@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1"
   integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=
   dependencies:
     readable-stream "^2.0.1"
 
-merge@^1.2.0:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145"
-  integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==
-
-micromatch@^2.3.11:
-  version "2.3.11"
-  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
-  integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=
-  dependencies:
-    arr-diff "^2.0.0"
-    array-unique "^0.2.1"
-    braces "^1.8.2"
-    expand-brackets "^0.1.4"
-    extglob "^0.3.1"
-    filename-regex "^2.0.0"
-    is-extglob "^1.0.0"
-    is-glob "^2.0.1"
-    kind-of "^3.0.2"
-    normalize-path "^2.0.1"
-    object.omit "^2.0.0"
-    parse-glob "^3.0.4"
-    regex-cache "^0.4.2"
-
-micromatch@^3.1.4:
+micromatch@^3.1.10, micromatch@^3.1.4:
   version "3.1.10"
   resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
   integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
   dependencies:
     arr-diff "^4.0.0"
     array-unique "^0.3.2"
     braces "^2.3.1"
     define-property "^2.0.2"
@@ -2527,22 +2535,22 @@ mime-db@~1.38.0:
 
 mime-types@^2.1.12, mime-types@~2.1.19:
   version "2.1.22"
   resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd"
   integrity sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==
   dependencies:
     mime-db "~1.38.0"
 
-mimic-fn@^1.0.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
-  integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
-
-minimatch@^3.0.3, minimatch@^3.0.4:
+mimic-fn@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+  integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+
+minimatch@^3.0.4:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
   integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
   dependencies:
     brace-expansion "^1.1.7"
 
 minimist@0.0.8:
   version "0.0.8"
@@ -2599,20 +2607,20 @@ ms@2.0.0:
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
   integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
 
 ms@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
   integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
 
-nan@^2.9.2:
-  version "2.13.2"
-  resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7"
-  integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==
+nan@^2.12.1:
+  version "2.14.0"
+  resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
+  integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
 
 nanomatch@^1.2.9:
   version "1.2.13"
   resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
   integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==
   dependencies:
     arr-diff "^4.0.0"
     array-unique "^0.3.2"
@@ -2651,44 +2659,54 @@ needle@^2.2.1:
     iconv-lite "^0.4.4"
     sax "^1.2.4"
 
 neo-async@^2.6.0:
   version "2.6.0"
   resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835"
   integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==
 
+nice-try@^1.0.4:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
+  integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+
 node-fetch@^1.0.1:
   version "1.7.3"
   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
   integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
   dependencies:
     encoding "^0.1.11"
     is-stream "^1.0.1"
 
 node-int64@^0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
   integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=
 
+node-modules-regexp@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40"
+  integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
+
 node-notifier@^5.2.1:
   version "5.4.0"
   resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.0.tgz#7b455fdce9f7de0c63538297354f3db468426e6a"
   integrity sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ==
   dependencies:
     growly "^1.3.0"
     is-wsl "^1.1.0"
     semver "^5.5.0"
     shellwords "^0.1.1"
     which "^1.3.0"
 
-node-pre-gyp@^0.10.0:
-  version "0.10.3"
-  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc"
-  integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==
+node-pre-gyp@^0.12.0:
+  version "0.12.0"
+  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149"
+  integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==
   dependencies:
     detect-libc "^1.0.2"
     mkdirp "^0.5.1"
     needle "^2.2.1"
     nopt "^4.0.1"
     npm-packlist "^1.1.6"
     npmlog "^4.0.2"
     rc "^1.2.7"
@@ -2709,17 +2727,17 @@ normalize-package-data@^2.3.2:
   resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
   integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
   dependencies:
     hosted-git-info "^2.1.4"
     resolve "^1.10.0"
     semver "2 || 3 || 4 || 5"
     validate-npm-package-license "^3.0.1"
 
-normalize-path@^2.0.1, normalize-path@^2.1.1:
+normalize-path@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
   integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=
   dependencies:
     remove-trailing-separator "^1.0.1"
 
 npm-bundled@^1.0.1:
   version "1.0.6"
@@ -2842,24 +2860,16 @@ object.fromentries@^2.0.0:
 object.getownpropertydescriptors@^2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
   integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=
   dependencies:
     define-properties "^1.1.2"
     es-abstract "^1.5.1"
 
-object.omit@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
-  integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=
-  dependencies:
-    for-own "^0.1.4"
-    is-extendable "^0.1.1"
-
 object.pick@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
   integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=
   dependencies:
     isobject "^3.0.1"
 
 object.values@^1.0.4, object.values@^1.1.0:
@@ -2867,17 +2877,17 @@ object.values@^1.0.4, object.values@^1.1
   resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9"
   integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==
   dependencies:
     define-properties "^1.1.3"
     es-abstract "^1.12.0"
     function-bind "^1.1.1"
     has "^1.0.3"
 
-once@^1.3.0, once@^1.4.0:
+once@^1.3.0, once@^1.3.1, once@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
   integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
   dependencies:
     wrappy "1"
 
 optimist@^0.6.1:
   version "0.6.1"
@@ -2899,78 +2909,91 @@ optionator@^0.8.1:
     type-check "~0.3.2"
     wordwrap "~1.0.0"
 
 os-homedir@^1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
   integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
 
-os-locale@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2"
-  integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==
-  dependencies:
-    execa "^0.7.0"
-    lcid "^1.0.0"
-    mem "^1.1.0"
-
-os-tmpdir@^1.0.0, os-tmpdir@^1.0.1:
+os-locale@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
+  integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
+  dependencies:
+    execa "^1.0.0"
+    lcid "^2.0.0"
+    mem "^4.0.0"
+
+os-tmpdir@^1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
   integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
 
 osenv@^0.1.4:
   version "0.1.5"
   resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
   integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
   dependencies:
     os-homedir "^1.0.0"
     os-tmpdir "^1.0.0"
 
+p-defer@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
+  integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
+
+p-each-series@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71"
+  integrity sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=
+  dependencies:
+    p-reduce "^1.0.0"
+
 p-finally@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
   integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
 
-p-limit@^1.1.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
-  integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==
-  dependencies:
-    p-try "^1.0.0"
-
-p-locate@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
-  integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=
-  dependencies:
-    p-limit "^1.1.0"
-
-p-try@^1.0.0:
+p-is-promise@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
+  integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
+
+p-limit@^2.0.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2"
+  integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==
+  dependencies:
+    p-try "^2.0.0"
+
+p-locate@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
+  integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+  dependencies:
+    p-limit "^2.0.0"
+
+p-reduce@^1.0.0:
   version "1.0.0"
-  resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
-  integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
-
-parse-glob@^3.0.4:
-  version "3.0.4"
-  resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
-  integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw=
-  dependencies:
-    glob-base "^0.3.0"
-    is-dotfile "^1.0.0"
-    is-extglob "^1.0.0"
-    is-glob "^2.0.0"
-
-parse-json@^2.2.0:
+  resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa"
+  integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=
+
+p-try@^2.0.0:
   version "2.2.0"
-  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
-  integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
-  dependencies:
-    error-ex "^1.2.0"
+  resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+  integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+parse-json@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
+  integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
+  dependencies:
+    error-ex "^1.3.1"
+    json-parse-better-errors "^1.0.1"
 
 parse5@4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
   integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==
 
 parse5@^3.0.1:
   version "3.0.3"
@@ -2979,133 +3002,116 @@ parse5@^3.0.1:
   dependencies:
     "@types/node" "*"
 
 pascalcase@^0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
   integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
 
-path-exists@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
-  integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
-  dependencies:
-    pinkie-promise "^2.0.0"
-
 path-exists@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
   integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
 
-path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
+path-is-absolute@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
   integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
 
-path-key@^2.0.0:
+path-key@^2.0.0, path-key@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
   integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
 
-path-parse@^1.0.5, path-parse@^1.0.6:
+path-parse@^1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
   integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
 
-path-type@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
-  integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
-  dependencies:
-    graceful-fs "^4.1.2"
-    pify "^2.0.0"
-    pinkie-promise "^2.0.0"
+path-type@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
+  integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
+  dependencies:
+    pify "^3.0.0"
 
 performance-now@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
   integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
 
-pify@^2.0.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
-  integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
-
-pinkie-promise@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
-  integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
-  dependencies:
-    pinkie "^2.0.0"
-
-pinkie@^2.0.0:
-  version "2.0.4"
-  resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
-  integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
-
-pkg-dir@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
-  integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=
-  dependencies:
-    find-up "^2.1.0"
+pify@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
+  integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
+
+pify@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
+  integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
+
+pirates@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"
+  integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==
+  dependencies:
+    node-modules-regexp "^1.0.0"
+
+pkg-dir@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
+  integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==
+  dependencies:
+    find-up "^3.0.0"
 
 pn@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
   integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==
 
 posix-character-classes@^0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
   integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
 
 prelude-ls@~1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
   integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
 
-preserve@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
-  integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
-
-pretty-format@^23.6.0:
-  version "23.6.0"
-  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760"
-  integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==
-  dependencies:
-    ansi-regex "^3.0.0"
+pretty-format@^24.8.0:
+  version "24.8.0"
+  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2"
+  integrity sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw==
+  dependencies:
+    "@jest/types" "^24.8.0"
+    ansi-regex "^4.0.0"
     ansi-styles "^3.2.0"
-
-private@^0.1.8:
-  version "0.1.8"
-  resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
-  integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
+    react-is "^16.8.4"
 
 process-nextick-args@~2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
   integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
 
 promise@^7.1.1:
   version "7.3.1"
   resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
   integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
   dependencies:
     asap "~2.0.3"
 
-prompts@^0.1.9:
-  version "0.1.14"
-  resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.14.tgz#a8e15c612c5c9ec8f8111847df3337c9cbd443b2"
-  integrity sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==
-  dependencies:
-    kleur "^2.0.1"
-    sisteransi "^0.1.1"
+prompts@^2.0.1:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.1.0.tgz#bf90bc71f6065d255ea2bdc0fe6520485c1b45db"
+  integrity sha512-+x5TozgqYdOwWsQFZizE/Tra3fKvAoy037kOyU6cgz84n8f6zxngLOV4O32kTwt9FcLCxAqw0P/c8rOr9y+Gfg==
+  dependencies:
+    kleur "^3.0.2"
+    sisteransi "^1.0.0"
 
 prop-types-exact@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/prop-types-exact/-/prop-types-exact-1.2.0.tgz#825d6be46094663848237e3925a98c6e944e9869"
   integrity sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==
   dependencies:
     has "^1.0.3"
     object.assign "^4.1.0"
@@ -3115,26 +3121,29 @@ prop-types@^15.6.0, prop-types@^15.6.2, 
   version "15.7.2"
   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
   integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
   dependencies:
     loose-envify "^1.4.0"
     object-assign "^4.1.1"
     react-is "^16.8.1"
 
-pseudomap@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
-  integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
-
 psl@^1.1.24, psl@^1.1.28:
   version "1.1.31"
   resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184"
   integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==
 
+pump@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
+  integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
+  dependencies:
+    end-of-stream "^1.1.0"
+    once "^1.3.1"
+
 punycode@^1.4.1:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
   integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
 
 punycode@^2.1.0, punycode@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
@@ -3160,25 +3169,16 @@ railroad-diagrams@^1.0.0:
 randexp@0.4.6:
   version "0.4.6"
   resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3"
   integrity sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==
   dependencies:
     discontinuous-range "1.0.0"
     ret "~0.1.10"
 
-randomatic@^3.0.0:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed"
-  integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==
-  dependencies:
-    is-number "^4.0.0"
-    kind-of "^6.0.0"
-    math-random "^1.0.1"
-
 rc@^1.2.7:
   version "1.2.8"
   resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
   integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
   dependencies:
     deep-extend "^0.6.0"
     ini "~1.3.0"
     minimist "^1.2.0"
@@ -3189,17 +3189,17 @@ react-dom@16.4.1:
   resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.4.1.tgz#7f8b0223b3a5fbe205116c56deb85de32685dad6"
   integrity sha512-1Gin+wghF/7gl4Cqcvr1DxFX2Osz7ugxSwl6gBqCMpdrxHjIFUS7GYxrFftZ9Ln44FHw0JxCFD9YtZsrbR5/4A==
   dependencies:
     fbjs "^0.8.16"
     loose-envify "^1.1.0"
     object-assign "^4.1.1"
     prop-types "^15.6.0"
 
-react-is@^16.4.1, react-is@^16.8.1, react-is@^16.8.6:
+react-is@^16.4.1, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
   version "16.8.6"
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
   integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
 
 react-test-renderer@16.4.1:
   version "16.4.1"
   resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.4.1.tgz#f2fb30c2c7b517db6e5b10ed20bb6b0a7ccd8d70"
   integrity sha512-wyyiPxRZOTpKnNIgUBOB6xPLTpIzwcQMIURhZvzUqZzezvHjaGNsDPBhMac5fIY3Jf5NuKxoGvV64zDSOECPPQ==
@@ -3224,32 +3224,32 @@ react@16.4.1:
   resolved "https://registry.yarnpkg.com/react/-/react-16.4.1.tgz#de51ba5764b5dbcd1f9079037b862bd26b82fe32"
   integrity sha512-3GEs0giKp6E0Oh/Y9ZC60CmYgUPnp7voH9fbjWsvXtYFb4EWtgQub0ADSq0sJR0BbHc4FThLLtzlcFaFXIorwg==
   dependencies:
     fbjs "^0.8.16"
     loose-envify "^1.1.0"
     object-assign "^4.1.1"
     prop-types "^15.6.0"
 
-read-pkg-up@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
-  integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
-  dependencies:
-    find-up "^1.0.0"
-    read-pkg "^1.0.0"
-
-read-pkg@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
-  integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
-  dependencies:
-    load-json-file "^1.0.0"
+read-pkg-up@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978"
+  integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==
+  dependencies:
+    find-up "^3.0.0"
+    read-pkg "^3.0.0"
+
+read-pkg@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
+  integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=
+  dependencies:
+    load-json-file "^4.0.0"
     normalize-package-data "^2.3.2"
-    path-type "^1.0.0"
+    path-type "^3.0.0"
 
 readable-stream@^2.0.1, readable-stream@^2.0.6:
   version "2.3.6"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
   integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
   dependencies:
     core-util-is "~1.0.0"
     inherits "~2.0.3"
@@ -3263,40 +3263,28 @@ readable-stream@^3.1.1:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.3.0.tgz#cb8011aad002eb717bf040291feba8569c986fb9"
   integrity sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==
   dependencies:
     inherits "^2.0.3"
     string_decoder "^1.1.1"
     util-deprecate "^1.0.1"
 
-realpath-native@^1.0.0:
+realpath-native@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
   integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==
   dependencies:
     util.promisify "^1.0.0"
 
 reflect.ownkeys@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460"
   integrity sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=
 
-regenerator-runtime@^0.11.0:
-  version "0.11.1"
-  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
-  integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
-
-regex-cache@^0.4.2:
-  version "0.4.4"
-  resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd"
-  integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==
-  dependencies:
-    is-equal-shallow "^0.1.3"
-
 regex-not@^1.0.0, regex-not@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
   integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==
   dependencies:
     extend-shallow "^3.0.2"
     safe-regex "^1.1.0"
 
@@ -3305,28 +3293,21 @@ remove-trailing-separator@^1.0.1:
   resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
   integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
 
 repeat-element@^1.1.2:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce"
   integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==
 
-repeat-string@^1.5.2, repeat-string@^1.6.1:
+repeat-string@^1.6.1:
   version "1.6.1"
   resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
   integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
 
-repeating@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
-  integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=
-  dependencies:
-    is-finite "^1.0.0"
-
 request-promise-core@1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346"
   integrity sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==
   dependencies:
     lodash "^4.17.11"
 
 request-promise-native@^1.0.5:
@@ -3369,16 +3350,21 @@ require-directory@^2.1.1:
   resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
   integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
 
 require-main-filename@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
   integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
 
+require-main-filename@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
+  integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+
 resolve-cwd@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
   integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=
   dependencies:
     resolve-from "^3.0.0"
 
 resolve-from@^3.0.0:
@@ -3398,40 +3384,47 @@ resolve@1.1.7:
 
 resolve@^1.10.0:
   version "1.10.0"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba"
   integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==
   dependencies:
     path-parse "^1.0.6"
 
+resolve@^1.3.2:
+  version "1.11.0"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.0.tgz#4014870ba296176b86343d50b60f3b50609ce232"
+  integrity sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==
+  dependencies:
+    path-parse "^1.0.6"
+
 ret@~0.1.10:
   version "0.1.15"
   resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
   integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
 
-rimraf@^2.5.4, rimraf@^2.6.1:
+rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3:
   version "2.6.3"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
   integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
   dependencies:
     glob "^7.1.3"
 
 rst-selector-parser@^2.2.3:
   version "2.2.3"
   resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91"
   integrity sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=
   dependencies:
     lodash.flattendeep "^4.4.0"
     nearley "^2.7.10"
 
-rsvp@^3.3.3:
-  version "3.6.2"
-  resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
-  integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==
+rsvp@^4.8.4:
+  version "4.8.5"
+  resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
+  integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==
 
 safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
   version "5.1.2"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
   integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
 
 safe-regex@^1.1.0:
   version "1.1.0"
@@ -3440,50 +3433,54 @@ safe-regex@^1.1.0:
   dependencies:
     ret "~0.1.10"
 
 "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
   integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
 
-sane@^2.0.0:
-  version "2.5.2"
-  resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa"
-  integrity sha1-tNwYYcIbQn6SlQej51HiosuKs/o=
-  dependencies:
+sane@^4.0.3:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded"
+  integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==
+  dependencies:
+    "@cnakazawa/watch" "^1.0.3"
     anymatch "^2.0.0"
-    capture-exit "^1.2.0"
-    exec-sh "^0.2.0"
+    capture-exit "^2.0.0"
+    exec-sh "^0.3.2"
+    execa "^1.0.0"
     fb-watchman "^2.0.0"
     micromatch "^3.1.4"
     minimist "^1.1.1"
     walker "~1.0.5"
-    watch "~0.18.0"
-  optionalDependencies:
-    fsevents "^1.2.3"
 
 sax@^1.2.4:
   version "1.2.4"
   resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
   integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
 
 scheduler@^0.13.6:
   version "0.13.6"
   resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889"
   integrity sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==
   dependencies:
     loose-envify "^1.1.0"
     object-assign "^4.1.1"
 
-"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0:
+"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0:
   version "5.7.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
   integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
 
+semver@^6.0.0:
+  version "6.1.1"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-6.1.1.tgz#53f53da9b30b2103cd4f15eab3a18ecbcb210c9b"
+  integrity sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==
+
 set-blocking@^2.0.0, set-blocking@~2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
   integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
 
 set-value@^0.4.3:
   version "0.4.3"
   resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1"
@@ -3526,25 +3523,25 @@ shellwords@^0.1.1:
   resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
   integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
 
 signal-exit@^3.0.0, signal-exit@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
   integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
 
-sisteransi@^0.1.1:
-  version "0.1.1"
-  resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce"
-  integrity sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==
-
-slash@^1.0.0:
+sisteransi@^1.0.0:
   version "1.0.0"
-  resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
-  integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
+  resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.0.tgz#77d9622ff909080f1c19e5f4a1df0c1b0a27b88c"
+  integrity sha512-N+z4pHB4AmUv0SjveWRd6q1Nj5w62m5jodv+GD8lvmbY/83T/rpbJGZOnK5T149OldDj4Db07BSv9xY4K6NTPQ==
+
+slash@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
+  integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
 
 snapdragon-node@^2.0.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
   integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==
   dependencies:
     define-property "^1.0.0"
     isobject "^3.0.0"
@@ -3577,37 +3574,30 @@ source-map-resolve@^0.5.0:
   integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==
   dependencies:
     atob "^2.1.1"
     decode-uri-component "^0.2.0"
     resolve-url "^0.2.1"
     source-map-url "^0.4.0"
     urix "^0.1.0"
 
-source-map-support@^0.4.15:
-  version "0.4.18"
-  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
-  integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==
-  dependencies:
-    source-map "^0.5.6"
-
 source-map-support@^0.5.6:
   version "0.5.12"
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"
   integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==
   dependencies:
     buffer-from "^1.0.0"
     source-map "^0.6.0"
 
 source-map-url@^0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
   integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
 
-source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7:
+source-map@^0.5.0, source-map@^0.5.6:
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
   integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
 
 source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
   integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
@@ -3640,21 +3630,16 @@ spdx-license-ids@^3.0.0:
 
 split-string@^3.0.1, split-string@^3.0.2:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
   integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==
   dependencies:
     extend-shallow "^3.0.0"
 
-sprintf-js@~1.0.2:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
-  integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
-
 sshpk@^1.7.0:
   version "1.16.1"
   resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
   integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
   dependencies:
     asn1 "~0.2.3"
     assert-plus "^1.0.0"
     bcrypt-pbkdf "^1.0.0"
@@ -3740,57 +3725,52 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1:
 
 strip-ansi@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
   integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
   dependencies:
     ansi-regex "^3.0.0"
 
-strip-bom@3.0.0:
+strip-ansi@^5.0.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
+  integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
+  dependencies:
+    ansi-regex "^4.1.0"
+
+strip-bom@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
   integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
 
-strip-bom@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
-  integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
-  dependencies:
-    is-utf8 "^0.2.0"
-
 strip-eof@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
   integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
 
 strip-json-comments@~2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
   integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
 
-supports-color@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
-  integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
-
-supports-color@^3.1.2:
-  version "3.2.3"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
-  integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=
-  dependencies:
-    has-flag "^1.0.0"
-
 supports-color@^5.3.0:
   version "5.5.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
   integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
   dependencies:
     has-flag "^3.0.0"
 
+supports-color@^6.1.0:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
+  integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
+  dependencies:
+    has-flag "^3.0.0"
+
 symbol-tree@^3.2.2:
   version "3.2.2"
   resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
   integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=
 
 tar@^4:
   version "4.4.8"
   resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d"
@@ -3799,41 +3779,40 @@ tar@^4:
     chownr "^1.1.1"
     fs-minipass "^1.2.5"
     minipass "^2.3.4"
     minizlib "^1.1.1"
     mkdirp "^0.5.0"
     safe-buffer "^5.1.2"
     yallist "^3.0.2"
 
-test-exclude@^4.2.1:
-  version "4.2.3"
-  resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.3.tgz#a9a5e64474e4398339245a0a769ad7c2f4a97c20"
-  integrity sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==
-  dependencies:
-    arrify "^1.0.1"
-    micromatch "^2.3.11"
-    object-assign "^4.1.0"
-    read-pkg-up "^1.0.1"
-    require-main-filename "^1.0.1"
+test-exclude@^5.2.3:
+  version "5.2.3"
+  resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0"
+  integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==
+  dependencies:
+    glob "^7.1.3"
+    minimatch "^3.0.4"
+    read-pkg-up "^4.0.0"
+    require-main-filename "^2.0.0"
 
 throat@^4.0.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a"
   integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=
 
 tmpl@1.0.x:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
   integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
 
-to-fast-properties@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
-  integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=
+to-fast-properties@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+  integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
 
 to-object-path@^0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
   integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=
   dependencies:
     kind-of "^3.0.2"
 
@@ -3987,31 +3966,23 @@ verror@1.10.0:
 
 w3c-hr-time@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045"
   integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=
   dependencies:
     browser-process-hrtime "^0.1.2"
 
-walker@~1.0.5:
+walker@^1.0.7, walker@~1.0.5:
   version "1.0.7"
   resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
   integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=
   dependencies:
     makeerror "1.0.x"
 
-watch@~0.18.0:
-  version "0.18.0"
-  resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986"
-  integrity sha1-KAlUdsbffJDJYxOJkMClQj60uYY=
-  dependencies:
-    exec-sh "^0.2.0"
-    minimist "^1.2.0"
-
 webidl-conversions@^4.0.2:
   version "4.0.2"
   resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
   integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
 
 whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
@@ -4047,17 +4018,17 @@ whatwg-url@^7.0.0:
     tr46 "^1.0.1"
     webidl-conversions "^4.0.2"
 
 which-module@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
   integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
 
-which@^1.2.12, which@^1.2.9, which@^1.3.0:
+which@^1.2.9, which@^1.3.0:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
   integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
   dependencies:
     isexe "^2.0.0"
 
 wide-align@^1.1.0:
   version "1.1.3"
@@ -4084,20 +4055,20 @@ wrap-ansi@^2.0.0:
     string-width "^1.0.1"
     strip-ansi "^3.0.1"
 
 wrappy@1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
   integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
 
-write-file-atomic@^2.1.0:
-  version "2.4.2"
-  resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.2.tgz#a7181706dfba17855d221140a9c06e15fcdd87b9"
-  integrity sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g==
+write-file-atomic@2.4.1:
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.1.tgz#d0b05463c188ae804396fd5ab2a370062af87529"
+  integrity sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==
   dependencies:
     graceful-fs "^4.1.11"
     imurmurhash "^0.1.4"
     signal-exit "^3.0.2"
 
 ws@^5.2.0:
   version "5.2.2"
   resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"
@@ -4105,47 +4076,43 @@ ws@^5.2.0:
   dependencies:
     async-limiter "~1.0.0"
 
 xml-name-validator@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
   integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
 
-y18n@^3.2.1:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
-  integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
-
-yallist@^2.1.2:
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
-  integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
+"y18n@^3.2.1 || ^4.0.0":
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
+  integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
 
 yallist@^3.0.0, yallist@^3.0.2:
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
   integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==
 
-yargs-parser@^9.0.2:
-  version "9.0.2"
-  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
-  integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=
-  dependencies:
-    camelcase "^4.1.0"
-
-yargs@^11.0.0:
-  version "11.1.0"
-  resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77"
-  integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==
+yargs-parser@^11.1.1:
+  version "11.1.1"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4"
+  integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==
+  dependencies:
+    camelcase "^5.0.0"
+    decamelize "^1.2.0"
+
+yargs@^12.0.2:
+  version "12.0.5"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
+  integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==
   dependencies:
     cliui "^4.0.0"
-    decamelize "^1.1.1"
-    find-up "^2.1.0"
+    decamelize "^1.2.0"
+    find-up "^3.0.0"
     get-caller-file "^1.0.1"
-    os-locale "^2.0.0"
+    os-locale "^3.0.0"
     require-directory "^2.1.1"
     require-main-filename "^1.0.1"
     set-blocking "^2.0.0"
     string-width "^2.0.0"
     which-module "^2.0.0"
-    y18n "^3.2.1"
-    yargs-parser "^9.0.2"
+    y18n "^3.2.1 || ^4.0.0"
+    yargs-parser "^11.1.1"
--- a/devtools/client/accessibility/test/mochitest/contrast.snapshots.js
+++ b/devtools/client/accessibility/test/mochitest/contrast.snapshots.js
@@ -3,23 +3,23 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 window._snapshots = {
   "ColorContrastAccessibility error render.": {
     "type": "div",
     "props": {
       "role": "presentation",
-      "className": "accessibility-color-contrast-check",
+      "className": "accessibility-check",
     },
     "children": [
       {
         "type": "h3",
         "props": {
-          "className": "accessibility-color-contrast-header",
+          "className": "accessibility-check-header",
         },
         "children": [
           "Color and Contrast",
         ],
       },
       {
         "type": "div",
         "props": {
@@ -40,23 +40,23 @@ window._snapshots = {
         ],
       },
     ],
   },
   "ColorContrastAccessibility basic render.": {
     "type": "div",
     "props": {
       "role": "presentation",
-      "className": "accessibility-color-contrast-check",
+      "className": "accessibility-check",
     },
     "children": [
       {
         "type": "h3",
         "props": {
-          "className": "accessibility-color-contrast-header",
+          "className": "accessibility-check-header",
         },
         "children": [
           "Color and Contrast",
         ],
       },
       {
         "type": "div",
         "props": {
@@ -78,17 +78,17 @@ window._snapshots = {
               "4.00",
             ],
           },
         ],
       },
       {
         "type": "p",
         "props": {
-          "className": "accessibility-color-contrast-annotation",
+          "className": "accessibility-check-annotation",
         },
         "children": [
           "Does not meet WCAG standards for accessible text. ",
           {
             "type": "a",
             "props": {
               "className": "link",
               "href": "https://developer.mozilla.org/docs/Web/Accessibility/" +
@@ -105,23 +105,23 @@ window._snapshots = {
         ],
       },
     ],
   },
   "ColorContrastAccessibility range render.": {
     "type": "div",
     "props": {
       "role": "presentation",
-      "className": "accessibility-color-contrast-check",
+      "className": "accessibility-check",
     },
     "children": [
       {
         "type": "h3",
         "props": {
-          "className": "accessibility-color-contrast-header",
+          "className": "accessibility-check-header",
         },
         "children": [
           "Color and Contrast",
         ],
       },
       {
         "type": "div",
         "props": {
@@ -165,17 +165,17 @@ window._snapshots = {
               "1.39",
             ],
           },
         ],
       },
       {
         "type": "p",
         "props": {
-          "className": "accessibility-color-contrast-annotation",
+          "className": "accessibility-check-annotation",
         },
         "children": [
           "Does not meet WCAG standards for accessible text. ",
           {
             "type": "a",
             "props": {
               "className": "link",
               "href": "https://developer.mozilla.org/docs/Web/Accessibility/" +
@@ -192,23 +192,23 @@ window._snapshots = {
         ],
       },
     ],
   },
   "ColorContrastAccessibility large text render.": {
     "type": "div",
     "props": {
       "role": "presentation",
-      "className": "accessibility-color-contrast-check",
+      "className": "accessibility-check",
     },
     "children": [
       {
         "type": "h3",
         "props": {
-          "className": "accessibility-color-contrast-header",
+          "className": "accessibility-check-header",
         },
         "children": [
           "Color and Contrast",
         ],
       },
       {
         "type": "div",
         "props": {
@@ -241,17 +241,17 @@ window._snapshots = {
               "large text",
             ],
           },
         ],
       },
       {
         "type": "p",
         "props": {
-          "className": "accessibility-color-contrast-annotation",
+          "className": "accessibility-check-annotation",
         },
         "children": [
           "Meets WCAG AA standards for accessible text. ",
           {
             "type": "a",
             "props": {
               "className": "link",
               "href": "https://developer.mozilla.org/docs/Web/Accessibility/" +
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -64,17 +64,22 @@ devtools.jar:
     skin/dark-theme.css (themes/dark-theme.css)
     skin/light-theme.css (themes/light-theme.css)
     skin/toolbars.css (themes/toolbars.css)
     skin/toolbox.css (themes/toolbox.css)
     skin/tooltips.css (themes/tooltips.css)
     skin/images/accessibility.svg (themes/images/accessibility.svg)
     skin/images/add.svg (themes/images/add.svg)
     skin/images/alert.svg (themes/images/alert.svg)
+    skin/images/alert-small.svg (themes/images/alert-small.svg)
     skin/images/alert-tiny.svg (themes/images/alert-tiny.svg)
+    skin/images/error.svg (themes/images/error.svg)
+    skin/images/error-small.svg (themes/images/error-small.svg)
+    skin/images/info.svg (themes/images/info.svg)
+    skin/images/info-small.svg (themes/images/info-small.svg)
     skin/images/arrow.svg (themes/images/arrow.svg)
     skin/images/arrow-big.svg (themes/images/arrow-big.svg)
     skin/images/arrowhead-left.svg (themes/images/arrowhead-left.svg)
     skin/images/arrowhead-right.svg (themes/images/arrowhead-right.svg)
     skin/images/arrowhead-down.svg (themes/images/arrowhead-down.svg)
     skin/images/arrowhead-up.svg (themes/images/arrowhead-up.svg)
     skin/images/breadcrumbs-divider.svg (themes/images/breadcrumbs-divider.svg)
     skin/images/checkbox.svg (themes/images/checkbox.svg)
@@ -117,18 +122,16 @@ devtools.jar:
     skin/images/command-eyedropper.svg (themes/images/command-eyedropper.svg)
     skin/images/command-rulers.svg (themes/images/command-rulers.svg)
     skin/images/command-measure.svg (themes/images/command-measure.svg)
     skin/images/command-noautohide.svg (themes/images/command-noautohide.svg)
     skin/images/command-chevron.svg (themes/images/command-chevron.svg)
     skin/images/rules-view-print-simulation.svg (themes/images/rules-view-print-simulation.svg)
     skin/markup.css (themes/markup.css)
     skin/webconsole.css (themes/webconsole.css)
-    skin/images/webconsole/error.svg (themes/images/webconsole/error.svg)
-    skin/images/webconsole/info.svg (themes/images/webconsole/info.svg)
     skin/images/webconsole/input.svg (themes/images/webconsole/input.svg)
     skin/images/webconsole/navigation.svg (themes/images/webconsole/navigation.svg)
     skin/images/webconsole/return.svg (themes/images/webconsole/return.svg)
     skin/images/breadcrumbs-scrollbutton.svg (themes/images/breadcrumbs-scrollbutton.svg)
     skin/animation.css (themes/animation.css)
     skin/perf.css (themes/perf.css)
     skin/performance.css (themes/performance.css)
     skin/memory.css (themes/memory.css)
new file mode 100644
--- /dev/null
+++ b/devtools/client/locales/en-US/accessibility.ftl
@@ -0,0 +1,62 @@
+# 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/.
+
+### These strings are used inside the Accessibility panel.
+
+accessibility-learn-more = Learn more
+
+accessibility-text-label-header = Text Labels and Names
+
+## Text entries that are used as text alternative for icons that depict accessibility isses.
+
+accessibility-warning =
+  .alt = Warning
+
+accessibility-fail =
+  .alt = Error
+
+accessibility-best-practices =
+  .alt = Best Practices
+
+## Text entries for a paragraph used in the accessibility panel sidebar's checks section
+## that describe that currently selected accessible object has an accessibility issue
+## with its text label or accessible name.
+
+accessibility-text-label-issue-area = Use <code>alt</code> attribute to label <div>area</div> elements that have the <span>href</span> attribute. <a>Learn more</a>
+
+accessibility-text-label-issue-dialog = Dialogs should be labeled. <a>Learn more</a>
+
+accessibility-text-label-issue-document-title = Documents must have a <code>title</code>. <a>Learn more</a>
+
+accessibility-text-label-issue-embed = Embedded content must be labeled. <a>Learn more</a>
+
+accessibility-text-label-issue-figure = Figures with optional captions should be labeled. <a>Learn more</a>
+
+accessibility-text-label-issue-fieldset = <code>fieldset</code> elements must be labeled. <a>Learn more</a>
+
+accessibility-text-label-issue-fieldset-legend = Use <code>legend</code> element to label <span>fieldset</span> elements. <a>Learn more</a>
+
+accessibility-text-label-issue-form = Form elements must be labeled. <a>Learn more</a>
+
+accessibility-text-label-issue-form-visible = Form elements should have a visible text label. <a>Learn more</a>
+
+accessibility-text-label-issue-frame = <code>frame</code> elements must be labeled. <a>Learn more</a>
+
+accessibility-text-label-issue-glyph = Use <code>alt</code> attribute to label <span>mglyph</span> elements. <a>Learn more</a>
+
+accessibility-text-label-issue-heading = Headings must be labeled. <a>Learn more</a>
+
+accessibility-text-label-issue-heading-content = Headings should have visible text content. <a>Learn more</a>
+
+accessibility-text-label-issue-iframe = Use <code>title</code> attribute to describe <span>iframe</span> content. <a>Learn more</a>
+
+accessibility-text-label-issue-image = Content with images must be labeled. <a>Learn more</a>
+
+accessibility-text-label-issue-interactive = Interactive elements must be labeled. <a>Learn more</a>
+
+accessibility-text-label-issue-optgroup = <code>optgroup</code> elements must be labeled. <a>Learn more</a>
+
+accessibility-text-label-issue-optgroup-label = Use <code>label</code> attribute to label <span>optgroup</span> elements. <a>Learn more</a>
+
+accessibility-text-label-issue-toolbar = Toolbars must be labeled when there is more than one toolbar. <a>Learn more</a>
--- a/devtools/client/netmonitor/src/assets/styles/NetworkDetailsPanel.css
+++ b/devtools/client/netmonitor/src/assets/styles/NetworkDetailsPanel.css
@@ -470,17 +470,17 @@
   display: flex;
 }
 
 .network-monitor .security-warning-icon {
   width: 12px;
   height: 12px;
   vertical-align: -1px;
   margin-inline-start: 5px;
-  background-image: url(chrome://devtools/skin/images/alert.svg);
+  background-image: url(chrome://devtools/skin/images/alert-small.svg);
   background-size: cover;
   -moz-context-properties: fill;
   fill: var(--yellow-60);
 }
 
 /* Custom request panel */
 
 .network-monitor .custom-request-panel {
--- a/devtools/client/preferences/devtools-client.js
+++ b/devtools/client/preferences/devtools-client.js
@@ -277,17 +277,24 @@ pref("devtools.webconsole.timestampMessa
 pref("devtools.webconsole.sidebarToggle", true);
 #else
 pref("devtools.webconsole.sidebarToggle", false);
 #endif
 
 // Enable CodeMirror in the JsTerm
 pref("devtools.webconsole.jsterm.codeMirror", true);
 
-// Enable editor mode in the console.
+// Enable editor mode in the console in Nightly builds.
+#if defined(NIGHTLY_BUILD)
+pref("devtools.webconsole.features.editor", true);
+#else
+pref("devtools.webconsole.features.editor", false);
+#endif
+
+// Saved editor mode state in the console.
 pref("devtools.webconsole.input.editor", false);
 
 // Disable the new performance recording panel by default
 pref("devtools.performance.new-panel-enabled", false);
 
 // Enable message grouping in the console, true by default
 pref("devtools.webconsole.groupWarningMessages", true);
 
copy from devtools/client/themes/images/alert.svg
copy to devtools/client/themes/images/alert-small.svg
--- a/devtools/client/themes/images/alert.svg
+++ b/devtools/client/themes/images/alert.svg
@@ -1,6 +1,6 @@
 <!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" width="12" height="12">
-  <path fill="context-fill" d="M6 0a1 1 0 0 1 .89.54l5 9.6A1 1 0 0 1 11 11.6H1a1 1 0 0 1-.89-1.46l5-9.6A1 1 0 0 1 6 0zm-.25 8a.75.75 0 0 0-.75.75v.5c0 .41.34.75.75.75h.5c.41 0 .75-.34.75-.75v-.5A.75.75 0 0 0 6.25 8h-.5zM7 3.7a1 1 0 1 0-2 0v2.6a1 1 0 1 0 2 0V3.7z" />
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" d="M14.742 12.106L9.789 2.2a2 2 0 0 0-3.578 0l-4.953 9.91A2 2 0 0 0 3.047 15h9.905a2 2 0 0 0 1.79-2.894zM7 5a1 1 0 0 1 2 0v4a1 1 0 0 1-2 0zm1 8.25A1.25 1.25 0 1 1 9.25 12 1.25 1.25 0 0 1 8 13.25z" />
 </svg>
rename from devtools/client/themes/images/webconsole/error.svg
rename to devtools/client/themes/images/error-small.svg
new file mode 100644
--- /dev/null
+++ b/devtools/client/themes/images/error.svg
@@ -0,0 +1,6 @@
+<!-- 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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16">
+  <path fill="context-fill" fill-rule="evenodd" d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm0-3.429a1.143 1.143 0 1 0 0-2.285 1.143 1.143 0 0 0 0 2.285zm0-3.428c.631 0 1.143-.512 1.143-1.143V4.571a1.143 1.143 0 0 0-2.286 0V8c0 .631.512 1.143 1.143 1.143z"/>
+</svg>
rename from devtools/client/themes/images/webconsole/info.svg
rename to devtools/client/themes/images/info-small.svg
new file mode 100644
--- /dev/null
+++ b/devtools/client/themes/images/info.svg
@@ -0,0 +1,6 @@
+<!-- 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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" d="M8 1a7 7 0 1 0 7 7 7.008 7.008 0 0 0-7-7zm0 13a6 6 0 1 1 6-6 6.007 6.007 0 0 1-6 6zm0-7a1 1 0 0 0-1 1v3a1 1 0 1 0 2 0V8a1 1 0 0 0-1-1zm0-3.188A1.188 1.188 0 1 0 9.188 5 1.188 1.188 0 0 0 8 3.812z" />
+</svg>
--- a/devtools/client/themes/jit-optimizations.css
+++ b/devtools/client/themes/jit-optimizations.css
@@ -78,24 +78,24 @@
 .opt-icon::before {
   content: "";
   display: inline-block;
   vertical-align: -2px;
   width: 12px;
   height: 12px;
   max-height: 12px;
   margin-inline-end: 5px;
-  background-image: url(chrome://devtools/skin/images/webconsole/info.svg);
+  background-image: url(chrome://devtools/skin/images/info-small.svg);
   background-repeat: no-repeat;
   background-size: contain;
   -moz-context-properties: fill;
   fill: #808080;
 }
 
 .opt-icon.warning::before {
-  background-image: url(chrome://devtools/skin/images/alert.svg);
+  background-image: url(chrome://devtools/skin/images/alert-small.svg);
   fill: var(--yellow-60);
 }
 
 /* Frame Component */
 .frame-link {
   margin-inline-start: 7px;
 }
--- a/devtools/client/themes/memory.css
+++ b/devtools/client/themes/memory.css
@@ -575,17 +575,17 @@ html, body, #app, #memory-tool {
 .error::before {
   content: "";
   display: inline-block;
   vertical-align: -2px;
   width: 12px;
   height: 12px;
   max-height: 12px;
   margin-inline-end: 5px;
-  background-image: url(chrome://devtools/skin/images/alert.svg);
+  background-image: url(chrome://devtools/skin/images/alert-small.svg);
   background-repeat: no-repeat;
   background-size: contain;
   -moz-context-properties: fill;
   fill: var(--yellow-60);
 }
 
 /**
  * Frame View components
--- a/devtools/client/themes/performance.css
+++ b/devtools/client/themes/performance.css
@@ -770,17 +770,17 @@ menuitem.marker-color-graphs-grey .menu-
 menuitem.experimental-option::before {
   content: "";
   display: inline-block;
   width: 12px;
   height: 12px;
   max-height: 12px;
   margin-top: 2px;
   margin-inline-end: 5px;
-  background-image: url(chrome://devtools/skin/images/alert.svg);
+  background-image: url(chrome://devtools/skin/images/alert-small.svg);
   background-repeat: no-repeat;
   background-size: contain;
   -moz-context-properties: fill;
   fill: currentColor;
 }
 
 #performance-options-menupopup:not(.experimental-enabled) .experimental-option,
 #performance-options-menupopup:not(.experimental-enabled) .experimental-option::before {
--- a/devtools/client/themes/rules.css
+++ b/devtools/client/themes/rules.css
@@ -366,24 +366,24 @@
   width: 12px;
   height: 12px;
   background-size: 12px;
   background-repeat: no-repeat;
   -moz-context-properties: fill;
 }
 
 .ruleview-warning {
-  background-image: url(chrome://devtools/skin/images/alert.svg);
+  background-image: url(chrome://devtools/skin/images/alert-small.svg);
   fill: var(--yellow-60);
 }
 
 .ruleview-unused-warning {
-  background-image: url(chrome://devtools/skin/images/webconsole/info.svg);
+  background-image: url(chrome://devtools/skin/images/info-small.svg);
   background-color: var(--theme-sidebar-background);
-  fill: var(--theme-icon-dimmed-color);  
+  fill: var(--theme-icon-dimmed-color);
 }
 
 .ruleview-unused-warning:hover {
   fill: var(--theme-icon-color);
   stroke: var(--theme-icon-color);
 }
 
 .ruleview-rule:not(:hover) .ruleview-enableproperty {
--- a/devtools/client/themes/variables.css
+++ b/devtools/client/themes/variables.css
@@ -45,16 +45,18 @@
   --theme-splitter-color: var(--grey-25);
   --theme-emphasized-splitter-color: var(--grey-30);
   --theme-emphasized-splitter-color-hover: var(--grey-40);
 
   /* Icon colors */
   --theme-icon-color: rgba(12, 12, 13, 0.8);
   --theme-icon-dimmed-color: rgba(135, 135, 137, 0.9);
   --theme-icon-checked-color: var(--blue-60);
+  --theme-icon-error-color: var(--red-60);
+  --theme-icon-warning-color: var(--yellow-65);
 
   /* Text color */
   --theme-comment: var(--grey-50);
   --theme-body-color: var(--grey-70);
   --theme-text-color-alt: var(--grey-50);
   --theme-text-color-inactive: var(--grey-40);
   --theme-text-color-strong: var(--grey-90);
 
@@ -146,16 +148,18 @@
   --theme-splitter-color: var(--grey-70);
   --theme-emphasized-splitter-color: var(--grey-60);
   --theme-emphasized-splitter-color-hover: var(--grey-50);
 
   /* Icon colors */
   --theme-icon-color: rgba(249, 249, 250, 0.7);
   --theme-icon-dimmed-color: rgba(147, 147, 149, 0.9);
   --theme-icon-checked-color: var(--blue-30);
+  --theme-icon-error-color: var(--red-40);
+  --theme-icon-warning-color: var(--yellow-60);
 
   /* Text color */
   --theme-comment: var(--grey-45);
   --theme-body-color: var(--grey-40);
   --theme-text-color-alt: var(--grey-45);
   --theme-text-color-inactive: var(--grey-50);
   --theme-text-color-strong: var(--grey-30);
 
--- a/devtools/client/themes/webconsole.css
+++ b/devtools/client/themes/webconsole.css
@@ -16,21 +16,19 @@
 .theme-dark {
   --console-input-background: var(--theme-tab-toolbar-background);
   --console-message-background: var(--theme-body-background);
   --console-message-border: var(--theme-splitter-color);
   --console-message-color: var(--theme-text-color-strong);
   --console-error-background: hsl(345, 23%, 24%);
   --console-error-border: hsl(345, 30%, 35%);
   --console-error-color: var(--red-20);
-  --console-error-icon-color: var(--red-40);
   --console-warning-background: hsl(42, 37%, 19%);
   --console-warning-border: hsl(60, 30%, 26%);
   --console-warning-color: hsl(43, 94%, 81%);
-  --console-warning-icon-color: var(--yellow-60);
   --console-navigation-color: var(--theme-highlight-blue);
   --console-navigation-border: var(--blue-60);
   --console-indent-border-color: var(--theme-highlight-blue);
   --console-repeat-bubble-background: var(--blue-60);
 
   /* TODO in bug 1549195: colors used in shared components (e.g. Reps) should
      be renamed and/or moved to variables.css so they work everywhere */
   --error-color: var(--red-20);
@@ -40,21 +38,19 @@
 .theme-light {
   --console-input-background: var(--theme-body-background);
   --console-message-background: var(--theme-body-background);
   --console-message-border: #f2f2f4; /* between Grey 10 and Grey 20 */
   --console-message-color: var(--theme-text-color-strong);
   --console-error-background: hsl(344, 73%, 97%);
   --console-error-border: rgba(215, 0, 34, 0.12); /* Red 60 + opacity */
   --console-error-color: var(--red-70);
-  --console-error-icon-color: var(--red-60);
   --console-warning-background: hsl(54, 100%, 92%);
   --console-warning-border: rgba(215, 182, 0, 0.28); /* Yellow 60 + opacity */
   --console-warning-color: var(--yellow-80);
-  --console-warning-icon-color: var(--yellow-65);
   --console-navigation-color: var(--theme-highlight-blue);
   --console-navigation-border: var(--blue-30);
   --console-indent-border-color: var(--theme-highlight-blue);
   --console-repeat-bubble-background: var(--theme-highlight-blue);
 
   /* TODO in bug 1549195: colors used in shared components (e.g. Reps) should
      be renamed and/or moved to variables.css so they work everywhere */
   --error-color: var(--red-70);
@@ -275,27 +271,27 @@ a {
 
 .message.result > .icon {
   color: var(--theme-icon-dimmed-color);
   background-image: url(chrome://devtools/skin/images/webconsole/return.svg);
 }
 
 .message.info > .icon {
   color: var(--theme-icon-color);
-  background-image: url(chrome://devtools/skin/images/webconsole/info.svg);
+  background-image: url(chrome://devtools/skin/images/info-small.svg);
 }
 
 .message.error > .icon {
-  color: var(--console-error-icon-color);
-  background-image: url(chrome://devtools/skin/images/webconsole/error.svg);
+  color: var(--theme-icon-error-color);
+  background-image: url(chrome://devtools/skin/images/error-small.svg);
 }
 
 .message.warn > .icon {
-  color: var(--console-warning-icon-color);
-  background-image: url(chrome://devtools/skin/images/alert.svg);
+  color: var(--theme-icon-warning-color);
+  background-image: url(chrome://devtools/skin/images/alert-small.svg);
 }
 
 .message.navigationMarker > .icon {
   color: var(--console-navigation-color);
   background-image: url(chrome://devtools/skin/images/webconsole/navigation.svg);
 }
 
 .message:hover > .icon.rewindable {
--- a/devtools/client/webconsole/components/App.js
+++ b/devtools/client/webconsole/components/App.js
@@ -54,46 +54,51 @@ class App extends Component {
       currentReverseSearchEntry: PropTypes.string,
       reverseSearchInputVisible: PropTypes.bool,
       reverseSearchInitialValue: PropTypes.string,
       editorMode: PropTypes.bool,
       hideShowContentMessagesCheckbox: PropTypes.bool,
       sidebarVisible: PropTypes.bool.isRequired,
       filterBarDisplayMode:
         PropTypes.oneOf([...Object.values(FILTERBAR_DISPLAY_MODES)]).isRequired,
+      editorFeatureEnabled: PropTypes.bool.isRequired,
     };
   }
 
   constructor(props) {
     super(props);
 
     this.onClick = this.onClick.bind(this);
     this.onPaste = this.onPaste.bind(this);
     this.onKeyDown = this.onKeyDown.bind(this);
   }
 
   onKeyDown(event) {
     const {
       dispatch,
       webConsoleUI,
+      editorFeatureEnabled,
     } = this.props;
 
     if (
       (!isMacOS && event.key === "F9") ||
       (isMacOS && event.key === "r" && event.ctrlKey === true)
     ) {
       const initialValue = webConsoleUI.jsterm && webConsoleUI.jsterm.getSelectedText();
       dispatch(actions.reverseSearchInputToggle({initialValue}));
       event.stopPropagation();
     }
 
-    if (event.key.toLowerCase() === "b" && (
-      isMacOS && event.metaKey ||
-      !isMacOS && event.ctrlKey
-    )) {
+    if (
+      editorFeatureEnabled &&
+      event.key.toLowerCase() === "b" && (
+        isMacOS && event.metaKey ||
+        !isMacOS && event.ctrlKey
+      )
+    ) {
       event.stopPropagation();
       event.preventDefault();
       dispatch(actions.editorToggle());
     }
   }
 
   onClick(event) {
     const target = event.originalTarget || event.target;
--- a/devtools/client/webconsole/components/FilterBar/FilterBar.js
+++ b/devtools/client/webconsole/components/FilterBar/FilterBar.js
@@ -323,19 +323,21 @@ class FilterBar extends Component {
         }),
       ),
     ];
 
     if (this.props.closeButtonVisible) {
       children.push(dom.div(
         {
           className: "devtools-toolbar split-console-close-button-wrapper",
+          key: "wrapper",
         },
         dom.button({
           id: "split-console-close-button",
+          key: "split-console-close-button",
           className: "devtools-button",
           title: l10n.getStr("webconsole.closeSplitConsoleButton.tooltip"),
           onClick: () => {
             closeSplitConsole();
           },
         })
       ));
     }
--- a/devtools/client/webconsole/constants.js
+++ b/devtools/client/webconsole/constants.js
@@ -76,16 +76,17 @@ const prefs = {
       MESSAGE_TIMESTAMP: "devtools.webconsole.timestampMessages",
     },
     FEATURES: {
       // We use the same pref to enable the sidebar on webconsole and browser console.
       SIDEBAR_TOGGLE: "devtools.webconsole.sidebarToggle",
       JSTERM_CODE_MIRROR: "devtools.webconsole.jsterm.codeMirror",
       AUTOCOMPLETE: "devtools.webconsole.input.autocomplete",
       GROUP_WARNINGS: "devtools.webconsole.groupWarningMessages",
+      EDITOR: "devtools.webconsole.features.editor",
     },
   },
 };
 
 const FILTERS = {
   CSS: "css",
   DEBUG: "debug",
   ERROR: "error",
--- a/devtools/client/webconsole/reducers/prefs.js
+++ b/devtools/client/webconsole/reducers/prefs.js
@@ -10,16 +10,17 @@ const {
 } = require("devtools/client/webconsole/constants");
 
 const PrefState = (overrides) => Object.freeze(Object.assign({
   logLimit: 1000,
   sidebarToggle: false,
   jstermCodeMirror: false,
   groupWarnings: false,
   historyCount: 50,
+  editor: false,
 }, overrides));
 
 function prefs(state = PrefState(), action) {
   if (action.type === WARNING_GROUPS_TOGGLE) {
     return {
       ...state,
       groupWarnings: action.value,
     };
--- a/devtools/client/webconsole/store.js
+++ b/devtools/client/webconsole/store.js
@@ -46,26 +46,28 @@ function configureStore(webConsoleUI, op
   } = prefsService;
 
   const logLimit = options.logLimit
     || Math.max(getIntPref("devtools.hud.loglimit"), 1);
   const sidebarToggle = getBoolPref(PREFS.FEATURES.SIDEBAR_TOGGLE);
   const jstermCodeMirror = getBoolPref(PREFS.FEATURES.JSTERM_CODE_MIRROR);
   const autocomplete = getBoolPref(PREFS.FEATURES.AUTOCOMPLETE);
   const groupWarnings = getBoolPref(PREFS.FEATURES.GROUP_WARNINGS);
+  const editor = getBoolPref(PREFS.FEATURES.EDITOR);
   const historyCount = getIntPref(PREFS.UI.INPUT_HISTORY_COUNT);
 
   const initialState = {
     prefs: PrefState({
       logLimit,
       sidebarToggle,
       jstermCodeMirror,
       autocomplete,
       historyCount,
       groupWarnings,
+      editor,
     }),
     filters: FilterState({
       error: getBoolPref(PREFS.FILTER.ERROR),
       warn: getBoolPref(PREFS.FILTER.WARN),
       info: getBoolPref(PREFS.FILTER.INFO),
       debug: getBoolPref(PREFS.FILTER.DEBUG),
       log: getBoolPref(PREFS.FILTER.LOG),
       css: getBoolPref(PREFS.FILTER.CSS),
--- a/devtools/client/webconsole/test/mocha-test-setup.js
+++ b/devtools/client/webconsole/test/mocha-test-setup.js
@@ -23,16 +23,17 @@ pref("devtools.webconsole.inputHistoryCo
 pref("devtools.webconsole.persistlog", false);
 pref("devtools.webconsole.timestampMessages", false);
 pref("devtools.webconsole.sidebarToggle", true);
 pref("devtools.webconsole.jsterm.codeMirror", true);
 pref("devtools.webconsole.groupWarningMessages", false);
 pref("devtools.webconsole.input.editor", false);
 pref("devtools.webconsole.input.autocomplete", true);
 pref("devtools.browserconsole.contentMessages", true);
+pref("devtools.webconsole.features.editor", true);
 
 global.loader = {
   lazyServiceGetter: () => {},
   lazyGetter: (context, name, fn) => {
 
   },
   lazyRequireGetter: (context, name, path, destruct) => {
     if (path === "devtools/shared/async-storage") {
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_editor.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_editor.js
@@ -3,16 +3,17 @@
 
 // Check that the editor is displayed as expected.
 
 "use strict";
 
 const TEST_URI = "data:text/html;charset=utf8,<p>Test editor";
 
 add_task(async function() {
+  await pushPref("devtools.webconsole.features.editor", true);
   // Run test with legacy JsTerm
   await pushPref("devtools.webconsole.jsterm.codeMirror", false);
   await performTests();
 
   // And then run it with the CodeMirror-powered one.
   await pushPref("devtools.webconsole.jsterm.codeMirror", true);
   await performTests();
 });
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_enter.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_enter.js
@@ -5,16 +5,17 @@
 // and Enter does not when in editor mode.
 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1519314
 
 "use strict";
 
 const TEST_URI = "data:text/html;charset=utf-8,Web Console test for bug 1519314";
 
 add_task(async function() {
+  await pushPref("devtools.webconsole.features.editor", true);
   await pushPref("devtools.webconsole.input.editor", true);
   // Run test with legacy JsTerm
   await pushPref("devtools.webconsole.jsterm.codeMirror", false);
   await performEditorEnabledTests();
   // And then run it with the CodeMirror-powered one.
   await pushPref("devtools.webconsole.jsterm.codeMirror", true);
   await performEditorEnabledTests();
 });
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_execute.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_execute.js
@@ -5,16 +5,17 @@
 // is set to true.
 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1519313
 
 "use strict";
 
 const TEST_URI = "data:text/html;charset=utf-8,Web Console test for bug 1519313";
 
 add_task(async function() {
+  await pushPref("devtools.webconsole.features.editor", true);
   await pushPref("devtools.webconsole.input.editor", true);
   // Run test with legacy JsTerm
   await pushPref("devtools.webconsole.jsterm.codeMirror", false);
   await performTests();
   // And then run it with the CodeMirror-powered one.
   await pushPref("devtools.webconsole.jsterm.codeMirror", true);
   await performTests();
 });
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_gutter.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_gutter.js
@@ -5,16 +5,17 @@
 // 'devtools.webconsole.input.editor' is true.
 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1519315
 
 "use strict";
 
 const TEST_URI = "data:text/html;charset=utf-8,Test JsTerm editor line gutters";
 
 add_task(async function() {
+  await pushPref("devtools.webconsole.features.editor", true);
   await pushPref("devtools.webconsole.input.editor", true);
 
   const hud = await openNewTabAndConsole(TEST_URI);
 
   info("Check that the line numbers gutter is rendered when in editor layout");
   ok(getLineNumbersGutterElement(hud),
     "line numbers gutter is rendered on the input when in editor mode.");
 
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_toggle_keyboard_shortcut.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_toggle_keyboard_shortcut.js
@@ -5,16 +5,17 @@
 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1519105
 
 "use strict";
 
 const TEST_URI = "data:text/html;charset=utf-8,Test editor mode toggle keyboard shortcut";
 const EDITOR_PREF = "devtools.webconsole.input.editor";
 
 add_task(async function() {
+  await pushPref("devtools.webconsole.features.editor", true);
   await pushPref("devtools.webconsole.input.editor", true);
   // Run test with legacy JsTerm
   info("Test legacy JsTerm");
   await pushPref("devtools.webconsole.jsterm.codeMirror", false);
   await performTest();
 
   // And then run it with the CodeMirror-powered one.
   info("Test codeMirror JsTerm");
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_toolbar.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_toolbar.js
@@ -3,16 +3,17 @@
 
 // Check that the editor toolbar works as expected when in editor mode.
 
 "use strict";
 
 const TEST_URI = "data:text/html;charset=utf8,<p>Test editor toolbar";
 
 add_task(async function() {
+  await pushPref("devtools.webconsole.features.editor", true);
   // Run test with legacy JsTerm
   await pushPref("devtools.webconsole.jsterm.codeMirror", false);
   await performTests();
 
   // And then run it with the CodeMirror-powered one.
   await pushPref("devtools.webconsole.jsterm.codeMirror", true);
   await performTests();
 });
--- a/devtools/client/webconsole/webconsole-wrapper.js
+++ b/devtools/client/webconsole/webconsole-wrapper.js
@@ -353,16 +353,17 @@ class WebConsoleWrapper {
         telemetry: this.telemetry,
         services: serviceContainer,
       });
 
       const {prefs} = store.getState();
       const jstermCodeMirror = prefs.jstermCodeMirror
         && !Services.appinfo.accessibilityEnabled;
       const autocomplete = prefs.autocomplete;
+      const editorFeatureEnabled = prefs.editor;
 
       this.prefsObservers = new Map();
       this.prefsObservers.set(PREFS.UI.MESSAGE_TIMESTAMP, () => {
         const enabled = Services.prefs.getBoolPref(PREFS.UI.MESSAGE_TIMESTAMP);
         store.dispatch(actions.timestampsToggle(enabled));
       });
 
       this.prefsObservers.set(PREFS.FEATURES.GROUP_WARNINGS, () => {
@@ -376,16 +377,17 @@ class WebConsoleWrapper {
 
       const app = App({
         serviceContainer,
         webConsoleUI,
         onFirstMeaningfulPaint: resolve,
         closeSplitConsole: this.closeSplitConsole.bind(this),
         jstermCodeMirror,
         autocomplete,
+        editorFeatureEnabled,
         hideShowContentMessagesCheckbox: !webConsoleUI.isBrowserConsole,
       });
 
       // Render the root Application component.
       if (this.parentNode) {
         const provider = createElement(Provider, { store }, app);
         this.body = ReactDOM.render(provider, this.parentNode);
       } else {
--- a/devtools/server/actors/highlighters.css
+++ b/devtools/server/actors/highlighters.css
@@ -34,16 +34,18 @@
   --highlighter-bubble-border-color: rgba(255, 255, 255, 0.2);
   --highlighter-bubble-arrow-size: 8px;
   --highlighter-font-family: message-box;
   --highlighter-font-size: 11px;
   --highlighter-infobar-color: hsl(210, 30%, 85%);
   --highlighter-marker-color: #000;
 
   --grey-40: #b1b1b3;
+  --red-40: #ff3b6b;
+  --yellow-60: #d7b600;
 }
 
 /**
  * Highlighters are asbolute positioned in the page by default.
  * A single highlighter can have fixed position in its css class if needed (see below the
  * eye dropper or rulers highlighter, for example); but if it has to handle the
  * document's scrolling (as rulers does), it would lag a bit behind due the APZ (Async
  * Pan/Zoom module), that performs asynchronously panning and zooming on the compositor
@@ -732,13 +734,41 @@
   margin-inline-end: 3px;
 }
 
 :-moz-native-anonymous .accessible-infobar-audit .accessible-contrast-ratio-separator:before {
   content: "-";
   margin-inline-start: 3px;
 }
 
+:-moz-native-anonymous .accessible-infobar-audit .accessible-text-label:before {
+  display: inline-block;
+  width: 12px;
+  height: 12px;
+  content: "";
+  margin-inline-end: 4px;
+  vertical-align: -2px;
+  background-image: none;
+  background-position: center;
+  background-repeat: no-repeat;
+  -moz-context-properties: fill;
+  fill: currentColor;
+}
+
+:-moz-native-anonymous .accessible-infobar-audit .accessible-text-label.fail:before {
+  background-image: url(chrome://devtools/skin/images/error-small.svg);
+  fill: var(--red-40);
+}
+
+:-moz-native-anonymous .accessible-infobar-audit .accessible-text-label.WARNING:before {
+  background-image: url(chrome://devtools/skin/images/alert-small.svg);
+  fill: var(--yellow-60);
+}
+
+:-moz-native-anonymous .accessible-infobar-audit .accessible-text-label.BEST_PRACTICES:before {
+  background-image: url(chrome://devtools/skin/images/info-small.svg);
+}
+
 :-moz-native-anonymous .accessible-infobar-name:not(:empty) {
   border-inline-start: 1px solid #5a6169;
   margin-inline-start: 6px;
   padding-inline-start: 6px;
 }
--- a/devtools/server/actors/highlighters/utils/accessibility.js
+++ b/devtools/server/actors/highlighters/utils/accessibility.js