merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sat, 27 May 2017 10:00:59 +0200
changeset 360970 ebad93e117700d8e2d65573b824beb18a8cc2030
parent 360946 1c1bf54915bbf8cda82dbf7985e87b1c0ff30e4c (current diff)
parent 360969 6c2e66552c700573e7f2f4de0af9e33532114fe6 (diff)
child 360971 3de27eb37023c2513eee0c20774f92e70a3c6cf5
child 360980 fa869ff5ecf6259451b656d879dde8371a6a4483
child 361010 d6e64cc963fafad4df113608b2d8d8ae357f6c19
push id43565
push userarchaeopteryx@coole-files.de
push dateSat, 27 May 2017 08:16:39 +0000
treeherderautoland@3de27eb37023 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone55.0a1
first release with
nightly linux32
ebad93e11770 / 55.0a1 / 20170527100132 / files
nightly linux64
ebad93e11770 / 55.0a1 / 20170527100132 / files
nightly mac
ebad93e11770 / 55.0a1 / 20170527030204 / files
nightly win32
ebad93e11770 / 55.0a1 / 20170527030204 / files
nightly win64
ebad93e11770 / 55.0a1 / 20170527030204 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: CEadD9RweN4
browser/components/preferences/in-content/findInPage.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -58,19 +58,16 @@ pref("extensions.update.autoUpdateDefaul
 pref("extensions.hotfix.id", "firefox-hotfix@mozilla.org");
 pref("extensions.hotfix.cert.checkAttributes", true);
 pref("extensions.hotfix.certs.1.sha1Fingerprint", "91:53:98:0C:C1:86:DF:47:8F:35:22:9E:11:C9:A7:31:04:49:A1:AA");
 pref("extensions.hotfix.certs.2.sha1Fingerprint", "39:E7:2B:7A:5B:CF:37:78:F9:5D:4A:E0:53:2D:2F:3D:68:53:C5:60");
 
 // Check AUS for system add-on updates.
 pref("extensions.systemAddon.update.url", "https://aus5.mozilla.org/update/3/SystemAddons/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
 
-// Disable screenshots for now, Shield will enable this.
-pref("extensions.screenshots.system-disabled", true);
-
 // Disable add-ons that are not installed by the user in all scopes by default.
 // See the SCOPE constants in AddonManager.jsm for values to use here.
 pref("extensions.autoDisableScopes", 15);
 // Scopes to scan for changes at startup.
 pref("extensions.startupScanScopes", 0);
 
 // This is where the profiler WebExtension API will look for breakpad symbols.
 // NOTE: deliberately http right now since https://symbols.mozilla.org is not supported.
--- a/browser/components/preferences/in-content/advanced.xul
+++ b/browser/components/preferences/in-content/advanced.xul
@@ -67,17 +67,18 @@
     </vbox>
 #ifdef MOZ_UPDATER
     <spacer flex="1"/>
     <vbox>
       <button id="showUpdateHistory"
               class="accessory-button"
               label="&updateHistory2.label;"
               accesskey="&updateHistory2.accesskey;"
-              preference="app.update.disable_button.showUpdateHistory"/>
+              preference="app.update.disable_button.showUpdateHistory"
+              searchkeywords="&history.title; &history.intro;"/>
     </vbox>
 #endif
   </hbox>
 #ifdef MOZ_UPDATER
   <vbox id="updateBox">
     <deck id="updateDeck" orient="vertical">
       <hbox id="checkForUpdates" align="center">
         <spacer flex="1"/>
--- a/browser/components/preferences/in-content/findInPage.js
+++ b/browser/components/preferences/in-content/findInPage.js
@@ -39,17 +39,17 @@ var gSearchResultsPane = {
    *    to search for filter words in.
    * @param String filter
    *    is a string containing all of the words to filter on.
    * @returns boolean
    *    true when match in string else false
    */
   stringMatchesFilters(str, filter) {
     if (!filter || !str) {
-      return true;
+      return false;
     }
     let searchStr = str.toLowerCase();
     let filterStrings = filter.toLowerCase().split(/\s+/);
     return !filterStrings.some(f => searchStr.indexOf(f) == -1);
   },
 
   categoriesInitialized: false,
 
@@ -279,55 +279,56 @@ var gSearchResultsPane = {
         let result = this.highlightMatches([node], [node.length], node.textContent.toLowerCase(), searchPhrase);
         matchesFound = matchesFound || result;
       }
 
       // Collecting data from boxObject
       let nodeSizes = [];
       let allNodeText = "";
       let runningSize = 0;
-      let labelResult = false;
-      let valueResult = false;
       let accessKeyTextNodes = this.textNodeDescendants(nodeObject.boxObject);
 
       for (let node of accessKeyTextNodes) {
         runningSize += node.textContent.length;
         allNodeText += node.textContent;
         nodeSizes.push(runningSize);
       }
 
       // Access key are presented
       let complexTextNodesResult = this.highlightMatches(accessKeyTextNodes, nodeSizes, allNodeText.toLowerCase(), searchPhrase);
 
       // Searching some elements, such as xul:button, have a 'label' attribute that contains the user-visible text.
-      if (nodeObject.getAttribute("label")) {
-        labelResult = this.stringMatchesFilters(nodeObject.getAttribute("label"), searchPhrase);
-      }
+      let labelResult = this.stringMatchesFilters(nodeObject.getAttribute("label"), searchPhrase);
 
       // Creating tooltips for buttons
       if (labelResult && nodeObject.tagName === "button") {
         this.listSearchTooltips.push(nodeObject);
       }
 
       // Searching some elements, such as xul:label, store their user-visible text in a "value" attribute.
-      if (nodeObject.getAttribute("value")) {
-        valueResult = this.stringMatchesFilters(nodeObject.getAttribute("value"), searchPhrase);
-      }
-
-      if ((nodeObject.tagName == "button" || nodeObject.tagName == "menulist" || nodeObject.tagName == "menuitem") &&
-          (labelResult || valueResult)) {
-        nodeObject.setAttribute("highlightable", "true");
-      }
+      let valueResult = this.stringMatchesFilters(nodeObject.getAttribute("value"), searchPhrase);
 
       // Creating tooltips for buttons
       if (valueResult && nodeObject.tagName === "button") {
         this.listSearchTooltips.push(nodeObject);
       }
 
-      matchesFound = matchesFound || complexTextNodesResult || labelResult || valueResult;
+      // Searching some elements, such as xul:button, buttons to open subdialogs.
+      let keywordsResult = this.stringMatchesFilters(nodeObject.getAttribute("searchkeywords"), searchPhrase);
+
+      // Creating tooltips for buttons
+      if (keywordsResult && nodeObject.tagName === "button") {
+        this.listSearchTooltips.push(nodeObject);
+      }
+
+      if (nodeObject.tagName == "button" && (labelResult || valueResult || keywordsResult)) {
+        nodeObject.setAttribute("highlightable", "true");
+      }
+
+      matchesFound = matchesFound || complexTextNodesResult || labelResult || valueResult || keywordsResult;
     }
 
     for (let i = 0; i < nodeObject.childNodes.length; i++) {
       // Search only if child node is not hidden
       if (!nodeObject.childNodes[i].hidden && nodeObject.getAttribute("data-hidden-from-search") !== "true") {
         let result = this.searchWithinNode(nodeObject.childNodes[i], searchPhrase);
         // Creating tooltips for menulist element
         if (result && nodeObject.tagName === "menulist") {
--- a/browser/components/preferences/in-content/main.xul
+++ b/browser/components/preferences/in-content/main.xul
@@ -310,17 +310,18 @@
                 accesskey="&useCurrentPage.accesskey;"
                 label1="&useCurrentPage.label;"
                 label2="&useMultiple.label;"
                 preference="pref.browser.homepage.disable_button.current_page"/>
         <button id="useBookmark"
                 class="content-cell-item"
                 label="&chooseBookmark.label;"
                 accesskey="&chooseBookmark.accesskey;"
-                preference="pref.browser.homepage.disable_button.bookmark_page"/>
+                preference="pref.browser.homepage.disable_button.bookmark_page"
+                searchkeywords="&selectBookmark.title; &selectBookmark.label;"/>
         <button id="restoreDefaultHomePage"
                 class="content-cell-item"
                 label="&restoreDefault.label;"
                 accesskey="&restoreDefault.accesskey;"
                 preference="pref.browser.homepage.disable_button.restore_default"/>
       </html:td>
     </html:tr>
   </html:table>
@@ -447,17 +448,24 @@
 <groupbox id="languagesGroup" data-category="paneGeneral" hidden="true">
   <caption><label>&languages.label;</label></caption>
 
   <hbox id="languagesBox" align="center">
     <description flex="1" control="chooseLanguage">&chooseLanguage.label;</description>
     <button id="chooseLanguage"
             class="accessory-button"
             label="&chooseButton.label;"
-            accesskey="&chooseButton.accesskey;"/>
+            accesskey="&chooseButton.accesskey;"
+            searchkeywords="&languages.customize.Header;
+                            &languages.customize.description;
+                            &languages.customize.moveUp.label;
+                            &languages.customize.moveDown.label;
+                            &languages.customize.deleteButton.label;
+                            &languages.customize.selectLanguage.label;
+                            &languages.customize.addButton.label;"/>
   </hbox>
 
   <hbox id="translationBox" hidden="true">
     <hbox align="center" flex="1">
       <checkbox id="translate" preference="browser.translation.detectLanguage"
                 label="&translateWebPages.label;." accesskey="&translateWebPages.accesskey;"
                 onsyncfrompreference="return gMainPane.updateButtons('translateButton',
                                               'browser.translation.detectLanguage');"/>
@@ -524,25 +532,93 @@
           </menupopup>
         </menulist>
       </hbox>
       <spacer flex="1" />
       <button id="advancedFonts"
               class="accessory-button"
               icon="select-font"
               label="&advancedFonts.label;"
-              accesskey="&advancedFonts.accesskey;"/>
+              accesskey="&advancedFonts.accesskey;"
+              searchkeywords="&fontsDialog.title;
+                              &language.label;
+                              &size.label;
+                              &proportional.label;
+                              &serif.label;
+                              &sans-serif.label;
+                              &monospace.label;
+                              &font.langGroup.latin;
+                              &font.langGroup.japanese;
+                              &font.langGroup.trad-chinese;
+                              &font.langGroup.simpl-chinese;
+                              &font.langGroup.trad-chinese-hk;
+                              &font.langGroup.korean;
+                              &font.langGroup.cyrillic;
+                              &font.langGroup.el;
+                              &font.langGroup.other;
+                              &font.langGroup.thai;
+                              &font.langGroup.hebrew;
+                              &font.langGroup.arabic;
+                              &font.langGroup.devanagari;
+                              &font.langGroup.tamil;
+                              &font.langGroup.armenian;
+                              &font.langGroup.bengali;
+                              &font.langGroup.canadian;
+                              &font.langGroup.ethiopic;
+                              &font.langGroup.georgian;
+                              &font.langGroup.gujarati;
+                              &font.langGroup.gurmukhi;
+                              &font.langGroup.khmer;
+                              &font.langGroup.malayalam;
+                              &font.langGroup.math;
+                              &font.langGroup.odia;
+                              &font.langGroup.telugu;
+                              &font.langGroup.kannada;
+                              &font.langGroup.sinhala;
+                              &font.langGroup.tibetan;
+                              &minSize.label;
+                              &minSize.none;
+                              &useDefaultFontSerif.label;
+                              &useDefaultFontSansSerif.label;
+                              &allowPagesToUseOwn.label;
+                              &languages.customize.Fallback2.grouplabel;
+                              &languages.customize.Fallback2.label;
+                              &languages.customize.Fallback2.desc;
+                              &languages.customize.Fallback.auto;
+                              &languages.customize.Fallback.arabic;
+                              &languages.customize.Fallback.baltic;
+                              &languages.customize.Fallback.ceiso;
+                              &languages.customize.Fallback.cewindows;
+                              &languages.customize.Fallback.simplified;
+                              &languages.customize.Fallback.traditional;
+                              &languages.customize.Fallback.cyrillic;
+                              &languages.customize.Fallback.greek;
+                              &languages.customize.Fallback.hebrew;
+                              &languages.customize.Fallback.japanese;
+                              &languages.customize.Fallback.korean;
+                              &languages.customize.Fallback.thai;
+                              &languages.customize.Fallback.turkish;
+                              &languages.customize.Fallback.vietnamese;
+                              &languages.customize.Fallback.other;"/>
     </hbox>
     <hbox id="colorsSettings">
       <spacer flex="1" />
       <button id="colors"
               class="accessory-button"
               icon="select-color"
               label="&colors.label;"
-              accesskey="&colors.accesskey;"/>
+              accesskey="&colors.accesskey;"
+              searchkeywords="&overrideDefaultPageColors.label;
+                              &overrideDefaultPageColors.always.label;
+                              &overrideDefaultPageColors.auto.label;
+                              &overrideDefaultPageColors.never.label;
+                              &useSystemColors.label;
+                              &underlineLinks.label;
+                              &linkColor.label;
+                              &visitedLinkColor.label;"/>
     </hbox>
   </vbox>
 </groupbox>
 
 <!-- Browsing -->
 <groupbox id="browsingGroup" data-category="paneGeneral">
   <caption><label>&browsing.label;</label></caption>
 
--- a/browser/components/preferences/in-content/preferences.xul
+++ b/browser/components/preferences/in-content/preferences.xul
@@ -15,16 +15,29 @@
 <?xml-stylesheet href="chrome://browser/skin/preferences/in-content/search.css"?>
 <?xml-stylesheet href="chrome://browser/skin/preferences/in-content/containers.css"?>
 
 <!DOCTYPE page [
 <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
 <!ENTITY % globalPreferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
 <!ENTITY % preferencesDTD SYSTEM
   "chrome://browser/locale/preferences/preferences.dtd">
+<!ENTITY % selectBookmarkDTD SYSTEM
+  "chrome://browser/locale/preferences/selectBookmark.dtd">
+<!ENTITY % languagesDTD SYSTEM "chrome://browser/locale/preferences/languages.dtd">
+<!ENTITY % fontDTD SYSTEM "chrome://browser/locale/preferences/fonts.dtd">
+<!ENTITY % colorsDTD SYSTEM "chrome://browser/locale/preferences/colors.dtd">
+<!ENTITY % permissionsDTD SYSTEM "chrome://browser/locale/preferences/permissions.dtd">
+<!ENTITY % passwordManagerDTD SYSTEM "chrome://passwordmgr/locale/passwordManager.dtd">
+<!ENTITY % historyDTD SYSTEM "chrome://mozapps/locale/update/history.dtd">
+<!ENTITY % certManagerDTD SYSTEM "chrome://pippki/locale/certManager.dtd">
+<!ENTITY % deviceManangerDTD SYSTEM "chrome://pippki/locale/deviceManager.dtd">
+<!ENTITY % connectionDTD SYSTEM "chrome://browser/locale/preferences/connection.dtd">
+<!ENTITY % siteDataSettingsDTD SYSTEM
+  "chrome://browser/locale/preferences/siteDataSettings.dtd" >
 <!ENTITY % privacyDTD SYSTEM "chrome://browser/locale/preferences/privacy.dtd">
 <!ENTITY % tabsDTD SYSTEM "chrome://browser/locale/preferences/tabs.dtd">
 <!ENTITY % searchDTD SYSTEM "chrome://browser/locale/preferences/search.dtd">
 <!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
 <!ENTITY % syncDTD SYSTEM "chrome://browser/locale/preferences/sync.dtd">
 <!ENTITY % securityDTD SYSTEM
   "chrome://browser/locale/preferences/security.dtd">
 <!ENTITY % containersDTD SYSTEM
@@ -37,16 +50,27 @@
   "chrome://browser/locale/preferences/applications.dtd">
 <!ENTITY % advancedDTD SYSTEM
   "chrome://browser/locale/preferences/advanced.dtd">
 <!ENTITY % aboutDialogDTD SYSTEM "chrome://browser/locale/aboutDialog.dtd" >
 %aboutDialogDTD;
 %brandDTD;
 %globalPreferencesDTD;
 %preferencesDTD;
+%selectBookmarkDTD;
+%languagesDTD;
+%fontDTD;
+%colorsDTD;
+%permissionsDTD;
+%passwordManagerDTD;
+%historyDTD;
+%certManagerDTD;
+%deviceManangerDTD;
+%connectionDTD;
+%siteDataSettingsDTD;
 %privacyDTD;
 %tabsDTD;
 %searchDTD;
 %syncBrandDTD;
 %syncDTD;
 %securityDTD;
 %containersDTD;
 %sanitizeDTD;
@@ -79,16 +103,20 @@
           src="chrome://browser/content/preferences/in-content/preferences.js"/>
   <script src="chrome://browser/content/preferences/in-content/findInPage.js"/>
   <script src="chrome://browser/content/preferences/in-content/subdialogs.js"/>
 
   <stringbundle id="bundleBrand"
                 src="chrome://branding/locale/brand.properties"/>
   <stringbundle id="bundlePreferences"
                 src="chrome://browser/locale/preferences/preferences.properties"/>
+  <stringbundle id="pkiBundle"
+                src="chrome://pippki/locale/pippki.properties"/>
+  <stringbundle id="browserBundle"
+                src="chrome://browser/locale/browser.properties"/>
 
   <stringbundleset id="appManagerBundleset">
     <stringbundle id="appManagerBundle"
                   src="chrome://browser/locale/preferences/applicationManager.properties"/>
   </stringbundleset>
 
   <stack flex="1">
   <hbox flex="1">
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -145,16 +145,23 @@ var gPrivacyPane = {
    * label of the "Clear Now..." button.
    */
   init() {
     function setEventListener(aId, aEventType, aCallback) {
       document.getElementById(aId)
               .addEventListener(aEventType, aCallback.bind(gPrivacyPane));
     }
 
+    function appendSearchKeywords(aId, keywords) {
+      let element = document.getElementById(aId);
+      let searchKeywords = element.getAttribute("searchkeywords");
+      searchKeywords && keywords.push(searchKeywords);
+      element.setAttribute("searchkeywords", keywords.join(" "));
+    }
+
     this._updateSanitizeSettingsButton();
     this.initializeHistoryMode();
     this.updateHistoryModePane();
     this.updatePrivacyMicroControls();
     this.initAutoStartPrivateBrowsingReverter();
     this._initTrackingProtection();
     this._initTrackingProtectionPBM();
     this._initAutocomplete();
@@ -314,16 +321,63 @@ var gPrivacyPane = {
       this.initSubmitCrashes();
     }
     this.initTelemetry();
     if (AppConstants.MOZ_TELEMETRY_REPORTING) {
       this.initSubmitHealthReport();
       setEventListener("submitHealthReportBox", "command",
                        gPrivacyPane.updateSubmitHealthReport);
     }
+
+    // Append search keywords into the elements could open subdialogs.
+    let bundlePrefs = document.getElementById("bundlePreferences");
+    let signonBundle = document.getElementById("signonBundle");
+    let pkiBundle = document.getElementById("pkiBundle");
+    let browserBundle = document.getElementById("browserBundle");
+    appendSearchKeywords("passwordExceptions", [
+      bundlePrefs.getString("savedLoginsExceptions_title"),
+      bundlePrefs.getString("savedLoginsExceptions_desc"),
+    ]);
+    appendSearchKeywords("showPasswords", [
+      signonBundle.getString("loginsDescriptionAll"),
+    ]);
+    appendSearchKeywords("trackingProtectionExceptions", [
+      bundlePrefs.getString("trackingprotectionpermissionstitle"),
+      bundlePrefs.getString("trackingprotectionpermissionstext"),
+    ]);
+    appendSearchKeywords("changeBlockList", [
+      bundlePrefs.getString("blockliststitle"),
+      bundlePrefs.getString("blockliststext"),
+    ]);
+    appendSearchKeywords("popupPolicyButton", [
+      bundlePrefs.getString("popuppermissionstitle"),
+      bundlePrefs.getString("popuppermissionstext"),
+    ]);
+    appendSearchKeywords("notificationsPolicyButton", [
+      bundlePrefs.getString("notificationspermissionstitle"),
+      bundlePrefs.getString("notificationspermissionstext4"),
+    ]);
+    appendSearchKeywords("addonExceptions", [
+      bundlePrefs.getString("addons_permissions_title"),
+      bundlePrefs.getString("addonspermissionstext"),
+    ]);
+    appendSearchKeywords("viewSecurityDevicesButton", [
+      pkiBundle.getString("enable_fips"),
+    ]);
+    appendSearchKeywords("browserContainersSettings", [
+      browserBundle.getString("userContextPersonal.label"),
+      browserBundle.getString("userContextWork.label"),
+      browserBundle.getString("userContextBanking.label"),
+      browserBundle.getString("userContextShopping.label"),
+    ]);
+    appendSearchKeywords("siteDataSettings", [
+      bundlePrefs.getString("siteDataSettings.description"),
+      bundlePrefs.getString("removeAllCookies.label"),
+      bundlePrefs.getString("removeSelectedCookies.label"),
+    ]);
   },
 
   // TRACKING PROTECTION MODE
 
   /**
    * Selects the right item of the Tracking Protection radiogroup.
    */
   trackingProtectionReadPrefs() {
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -166,16 +166,17 @@
   <preference id="browser.crashReports.unsubmittedCheck.autoSubmit"
               name="browser.crashReports.unsubmittedCheck.autoSubmit"
               type="bool"/>
 #endif
 
 </preferences>
 
 <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
+<stringbundle id="signonBundle" src="chrome://passwordmgr/locale/passwordmgr.properties"/>
 
 <hbox id="header-privacy"
       class="header"
       hidden="true"
       data-category="panePrivacy">
   <label class="header-name" flex="1">&panePrivacySecurity.title;</label>
 </hbox>
 
@@ -312,30 +313,32 @@
                 label="&rememberLogins1.label;" accesskey="&rememberLogins1.accesskey;"
                 preference="signon.rememberSignons"
                 onsyncfrompreference="return gPrivacyPane.readSavePasswords();"
                 flex="1" />
       <button id="passwordExceptions"
               class="accessory-button"
               label="&passwordExceptions.label;"
               accesskey="&passwordExceptions.accesskey;"
-              preference="pref.privacy.disable_button.view_passwords_exceptions"/>
+              preference="pref.privacy.disable_button.view_passwords_exceptions"
+              searchkeywords="&address.label;"/>
     </hbox>
     <hbox id="showPasswordBox" pack="end">
       <button id="showPasswords"
               class="accessory-button"
               label="&savedLogins.label;" accesskey="&savedLogins.accesskey;"
-              preference="pref.privacy.disable_button.view_passwords"/>
+              preference="pref.privacy.disable_button.view_passwords"
+              searchkeywords="&savedLogins.title;"/>
     </hbox>
   </vbox>
   <hbox id="masterPasswordRow">
     <checkbox id="useMasterPassword"
               label="&useMasterPassword.label;"
               accesskey="&useMasterPassword.accesskey;"
-              flex="1" />
+              flex="1"/>
     <button id="changeMasterPassword"
             class="accessory-button"
             label="&changeMasterPassword.label;"
             accesskey="&changeMasterPassword.accesskey;"/>
   </hbox>
 </groupbox>
 
 <!-- Tracking -->
@@ -354,22 +357,27 @@
         </description>
       </vbox>
       <spacer flex="1"/>
       <vbox id="trackingProtectionAdvancedSettings">
         <button id="trackingProtectionExceptions"
                 class="accessory-button"
                 label="&trackingProtectionExceptions.label;"
                 accesskey="&trackingProtectionExceptions.accesskey;"
-                preference="pref.privacy.disable_button.tracking_protection_exceptions"/>
+                preference="pref.privacy.disable_button.tracking_protection_exceptions"
+                searchkeywords="&removepermission.label;
+                                &removeallpermissions.label;
+                                &button.cancel.label;
+                                &button.ok.label;"/>
         <button id="changeBlockList"
                 class="accessory-button"
                 label="&changeBlockList.label;"
                 accesskey="&changeBlockList.accesskey;"
-                preference="pref.privacy.disable_button.change_blocklist"/>
+                preference="pref.privacy.disable_button.change_blocklist"
+                searchkeywords="&button.cancel.label; &button.ok.label;"/>
       </vbox>
     </hbox>
     <radiogroup id="trackingProtectionRadioGroup" aria-labelledby="trackingProtectionDesc">
       <radio value="always"
              label="&trackingProtectionAlways.label;"
              accesskey="&trackingProtectionAlways.accesskey;"/>
       <radio value="private"
              label="&trackingProtectionPrivate.label;"
@@ -408,17 +416,18 @@
     <checkbox id="popupPolicy" preference="dom.disable_open_during_load"
               label="&blockPopups.label;" accesskey="&blockPopups.accesskey;"
               onsyncfrompreference="return gPrivacyPane.updateButtons('popupPolicyButton',
                                          'dom.disable_open_during_load');"
               flex="1" />
     <button id="popupPolicyButton"
             class="accessory-button"
             label="&popupExceptions.label;"
-            accesskey="&popupExceptions.accesskey;"/>
+            accesskey="&popupExceptions.accesskey;"
+            searchkeywords="&address.label; &button.cancel.label; &button.ok.label;"/>
   </hbox>
 </groupbox>
 
 <!-- Notifications -->
 <groupbox id="notificationsGroup" data-category="panePrivacy" hidden="true">
   <caption><label>&notificationsPolicy.label;</label></caption>
   <grid>
     <columns>
@@ -431,17 +440,21 @@
           <label id="notificationsPolicy">&notificationsPolicyDesc3.label;</label>
           <label id="notificationsPolicyLearnMore"
                  class="learnMore text-link">&notificationsPolicyLearnMore.label;</label>
         </hbox>
         <hbox pack="end">
           <button id="notificationsPolicyButton"
                   class="accessory-button"
                   label="&notificationsPolicyButton.label;"
-                  accesskey="&notificationsPolicyButton.accesskey;"/>
+                  accesskey="&notificationsPolicyButton.accesskey;"
+                  searchkeywords="&removepermission.label;
+                                  &removeallpermissions.label;
+                                  &button.cancel.label;
+                                  &button.ok.label;"/>
         </hbox>
       </row>
     </rows>
   </grid>
   <vbox id="notificationsDoNotDisturbBox" hidden="true">
     <checkbox id="notificationsDoNotDisturb" label="&notificationsDoNotDisturb.label;"
               accesskey="&notificationsDoNotDisturb.accesskey;"/>
     <label id="notificationsDoNotDisturbDetails"
@@ -478,17 +491,23 @@
               label="&warnOnAddonInstall.label;"
               accesskey="&warnOnAddonInstall.accesskey;"
               preference="xpinstall.whitelist.required"
               onsyncfrompreference="return gPrivacyPane.readWarnAddonInstall();"
               flex="1" />
     <button id="addonExceptions"
             class="accessory-button"
             label="&addonExceptions.label;"
-            accesskey="&addonExceptions.accesskey;"/>
+            accesskey="&addonExceptions.accesskey;"
+            searchkeywords="&address.label;
+                            &allow.label;
+                            &removepermission.label;
+                            &removeallpermissions.label;
+                            &button.cancel.label;
+                            &button.ok.label;"/>
   </hbox>
 
   <separator class="thin"/>
   <checkbox id="enableSafeBrowsing"
             label="&enableSafeBrowsing.label;"
             accesskey="&enableSafeBrowsing.accesskey;" />
   <vbox class="indent">
     <checkbox id="blockDownloads"
@@ -529,22 +548,46 @@
               onsynctopreference="return gPrivacyPane.writeEnableOCSP();"
               preference="security.OCSP.enabled"
               flex="1" />
     <vbox>
       <button id="viewCertificatesButton"
               class="accessory-button"
               label="&viewCerts.label;"
               accesskey="&viewCerts.accesskey;"
-              preference="security.disable_button.openCertManager"/>
+              preference="security.disable_button.openCertManager"
+              searchkeywords="&certmgr.tab.mine;
+                              &certmgr.tab.others2;
+                              &certmgr.tab.websites3;
+                              &certmgr.tab.ca;
+                              &certmgr.tab.orphan2;
+                              &certmgr.mine;
+                              &certmgr.others;
+                              &certmgr.websites2;
+                              &certmgr.cas;
+                              &certmgr.orphans;
+                              &certmgr.certname;
+                              &certmgr.tokenname;
+                              &certmgr.view2.label;
+                              &certmgr.export.label;
+                              &certmgr.delete2.label;"/>
       <button id="viewSecurityDevicesButton"
               class="accessory-button"
               label="&viewSecurityDevices.label;"
               accesskey="&viewSecurityDevices.accesskey;"
-              preference="security.disable_button.openDeviceManager"/>
+              preference="security.disable_button.openDeviceManager"
+              searchkeywords="&devmgr.title;
+                              &devmgr.devlist.label;
+                              &devmgr.details.title;
+                              &devmgr.details.title2;
+                              &devmgr.button.login.label;
+                              &devmgr.button.logout.label;
+                              &devmgr.button.changepw.label;
+                              &devmgr.button.load.label;
+                              &devmgr.button.unload.label;"/>
     </vbox>
   </hbox>
 </groupbox>
 
 <!-- DRM Content -->
 <groupbox id="drmGroup" data-category="panePrivacy" hidden="true">
   <caption><label>&drmContent.label;</label></caption>
   <grid id="contentGrid2">
@@ -578,33 +621,54 @@
                 onsyncfrompreference="return gPrivacyPane.readBrowserContainersCheckbox();"/>
       <label id="browserContainersLearnMore" class="learnMore text-link">
         &browserContainersLearnMore.label;
       </label>
       <spacer flex="1"/>
       <button id="browserContainersSettings"
               class="accessory-button"
               label="&browserContainersSettings.label;"
-              accesskey="&browserContainersSettings.accesskey;"/>
+              accesskey="&browserContainersSettings.accesskey;"
+              searchkeywords="&addButton.label;
+                              &preferencesButton.label;
+                              &removeButton.label;"/>
     </hbox>
   </vbox>
 </groupbox>
 
 <!-- Network -->
 <!-- Connection -->
 <groupbox id="connectionGroup" data-category="panePrivacy" hidden="true">
   <caption><label>&connection.label;</label></caption>
 
   <hbox align="center">
     <description flex="1" control="connectionSettings">&connectionDesc.label;</description>
     <button id="connectionSettings"
             class="accessory-button"
             icon="network"
             label="&connectionSettings.label;"
-            accesskey="&connectionSettings.accesskey;"/>
+            accesskey="&connectionSettings.accesskey;"
+            searchkeywords="&connectionsDialog.title;
+                            &noProxyTypeRadio.label;
+                            &WPADTypeRadio.label;
+                            &systemTypeRadio.label;
+                            &manualTypeRadio.label;
+                            &http.label;
+                            &ssl.label;
+                            &ftp.label;
+                            &socks.label;
+                            &socks4.label;
+                            &socks5.label;
+                            &noproxy.label;
+                            &noproxyExplain.label;
+                            &shareproxy.label;
+                            &autoTypeRadio.label;
+                            &reload.label;
+                            &autologinproxy.label;
+                            &socksRemoteDNS.label2;"/>
   </hbox>
 </groupbox>
 
 <!-- Cache -->
 <groupbox id="cacheGroup" data-category="panePrivacy" hidden="true">
   <caption><label>&httpCache.label;</label></caption>
 
   <hbox align="center">
@@ -682,17 +746,21 @@
             class="accessory-button"
             icon="clear"
             label="&clearSiteData.label;" accesskey="&clearSiteData.accesskey;"/>
   </hbox>
   <vbox align="end">
     <button id="siteDataSettings"
             class="accessory-button"
             label="&siteDataSettings.label;"
-            accesskey="&siteDataSettings.accesskey;"/>
+            accesskey="&siteDataSettings.accesskey;"
+            searchkeywords="&window.title;
+                            &hostCol.label;
+                            &statusCol.label;
+                            &usageCol.label;"/>
   </vbox>
 </groupbox>
 
 <!-- Data Choices -->
 #ifdef MOZ_TELEMETRY_REPORTING
 <groupbox id="historyGroup" data-category="panePrivacy" data-subcategory="reports" hidden="true">
 <caption><label>&reports.label;</label></caption>
   <hbox align="center">
--- a/browser/components/preferences/in-content/tests/browser.ini
+++ b/browser/components/preferences/in-content/tests/browser.ini
@@ -9,16 +9,20 @@ support-files =
 [browser_applications_selection.js]
 [browser_advanced_update.js]
 skip-if = !updater
 [browser_basic_rebuild_fonts_test.js]
 [browser_bug410900.js]
 [browser_bug705422.js]
 [browser_bug731866.js]
 [browser_search_within_preferences.js]
+[browser_search_subdialogs_within_preferences_1.js]
+[browser_search_subdialogs_within_preferences_2.js]
+[browser_search_subdialogs_within_preferences_3.js]
+[browser_search_subdialogs_within_preferences_4.js]
 [browser_bug795764_cachedisabled.js]
 [browser_bug1018066_resetScrollPosition.js]
 [browser_bug1020245_openPreferences_to_paneContent.js]
 [browser_bug1184989_prevent_scrolling_when_preferences_flipped.js]
 [browser_engines.js]
 support-files =
   browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul
 [browser_change_app_handler.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_search_subdialogs_within_preferences_1.js
@@ -0,0 +1,53 @@
+/*
+* This file contains tests for the Preferences search bar.
+*/
+
+// Enabling Searching functionatily. Will display search bar form this testcase forward.
+add_task(async function() {
+  await SpecialPowers.pushPrefEnv({"set": [["browser.preferences.search", true]]});
+});
+
+/**
+ * Test for searching for the "Set Home Page" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("Set Home Page", "startupGroup");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+/**
+ * Test for searching for the "Languages" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("Choose languages", "languagesGroup");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+/**
+ * Test for searching for the "Fonts" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("Text Encoding", "fontsGroup");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+/**
+ * Test for searching for the "Colors" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("Link Colors", "fontsGroup");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+/**
+ * Test for searching for the "Exceptions - Saved Logins" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("sites will not be saved", "passwordsGroup");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_search_subdialogs_within_preferences_2.js
@@ -0,0 +1,53 @@
+/*
+* This file contains tests for the Preferences search bar.
+*/
+
+// Enabling Searching functionatily. Will display search bar form this testcase forward.
+add_task(async function() {
+  await SpecialPowers.pushPrefEnv({"set": [["browser.preferences.search", true]]});
+});
+
+/**
+ * Test for searching for the "Saved Logins" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("sites are stored", "passwordsGroup");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+/**
+ * Test for searching for the "Exceptions - Tracking Protection" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("disabled Tracking Protection", "trackingGroup");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+/**
+ * Test for searching for the "Block Lists" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("block Web elements", "trackingGroup");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+/**
+ * Test for searching for the "Allowed Sites - Pop-ups" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("open pop-up windows", "miscGroup");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+/**
+ * Test for searching for the "Notification Permissions" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("request permission again", "notificationsGroup");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_search_subdialogs_within_preferences_3.js
@@ -0,0 +1,53 @@
+/*
+* This file contains tests for the Preferences search bar.
+*/
+
+// Enabling Searching functionatily. Will display search bar form this testcase forward.
+add_task(async function() {
+  await SpecialPowers.pushPrefEnv({"set": [["browser.preferences.search", true]]});
+});
+
+/**
+ * Test for searching for the "Allowed Sites - Add-ons Installation" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("allowed to install add-ons", "addonsPhishingGroup");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+/**
+ * Test for searching for the "Certificate Manager" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("identify these certificate authorities", "certSelection");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+/**
+ * Test for searching for the "Device Manager" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("Security Modules and Devices", "certSelection");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+/**
+ * Test for searching for the "Connection Settings" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("Use system proxy settings", "connectionGroup");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+/**
+ * Test for searching for the "Settings - Site Data" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("store site data on your computer", "siteDataGroup");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_search_subdialogs_within_preferences_4.js
@@ -0,0 +1,17 @@
+/*
+* This file contains tests for the Preferences search bar.
+*/
+
+// Enabling Searching functionatily. Will display search bar form this testcase forward.
+add_task(async function() {
+  await SpecialPowers.pushPrefEnv({"set": [["browser.preferences.search", true]]});
+});
+
+/**
+ * Test for searching for the "Update History" subdialog.
+ */
+add_task(async function() {
+  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+  evaluateSearchResults("updates have been installed", "updateApp");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
--- a/browser/components/preferences/in-content/tests/browser_search_within_preferences.js
+++ b/browser/components/preferences/in-content/tests/browser_search_within_preferences.js
@@ -84,17 +84,21 @@ add_task(async function() {
   searchInput.focus();
   searchInput.value = "password";
   searchInput.doCommand();
 
   let mainPrefTag = gBrowser.contentDocument.getElementById("mainPrefPane");
 
   for (let i = 0; i < mainPrefTag.childElementCount; i++) {
     let child = mainPrefTag.children[i]
-    if (child.id == "passwordsGroup" || child.id == "weavePrefsDeck" || child.id == "header-searchResults") {
+    if (child.id == "passwordsGroup" ||
+        child.id == "weavePrefsDeck" ||
+        child.id == "header-searchResults" ||
+        child.id == "certSelection" ||
+        child.id == "connectionGroup") {
       is_element_visible(child, "Should be in search results");
     } else if (child.id) {
       is_element_hidden(child, "Should not be in search results");
     }
   }
 
   // Takes search off
   searchInput.value = "";
--- a/browser/components/preferences/in-content/tests/head.js
+++ b/browser/components/preferences/in-content/tests/head.js
@@ -213,16 +213,36 @@ function assertSitesListed(doc, hosts) {
   hosts.forEach(host => {
     let site = sitesList.querySelector(`richlistitem[host="${host}"]`);
     ok(site, `Should list the site of ${host}`);
   });
   is(removeBtn.disabled, false, "Should enable the removeSelected button");
   is(removeAllBtn.disabled, false, "Should enable the removeAllBtn button");
 }
 
+function evaluateSearchResults(keyword, searchReults) {
+  searchReults = Array.isArray(searchReults) ? searchReults : [searchReults];
+  searchReults.push("header-searchResults");
+
+  let searchInput = gBrowser.contentDocument.getElementById("searchInput");
+  searchInput.focus();
+  searchInput.value = keyword;
+  searchInput.doCommand();
+
+  let mainPrefTag = gBrowser.contentDocument.getElementById("mainPrefPane");
+  for (let i = 0; i < mainPrefTag.childElementCount; i++) {
+    let child = mainPrefTag.children[i];
+    if (searchReults.includes(child.id)) {
+      is_element_visible(child, "Should be in search results");
+    } else if (child.id) {
+      is_element_hidden(child, "Should not be in search results");
+    }
+  }
+}
+
 const mockSiteDataManager = {
 
   _SiteDataManager: null,
   _originalGetQuotaUsage: null,
   _originalRemoveQuotaUsage: null,
 
   _getQuotaUsage() {
     let results = [];
--- a/devtools/client/debugger/new/debugger.css
+++ b/devtools/client/debugger/new/debugger.css
@@ -1063,16 +1063,17 @@ html .arrow.expanded svg {
 .theme-dark .result-list {
   background-color: var(--theme-body-background);
 }
 .sources-panel {
   flex: 1;
   display: flex;
   flex-direction: column;
   overflow: hidden;
+  position: relative;
 }
 
 .sources-panel * {
   -moz-user-select: none;
   user-select: none;
 }
 
 .sources-header {
@@ -1122,16 +1123,20 @@ html .arrow.expanded svg {
 
 .no-sources-message {
   font-size: 12px;
   color: var(--theme-comment-alt);
   font-weight: lighter;
   padding-top: 5px;
   text-align: center;
 }
+
+.hidden {
+  display: none;
+}
 .outline-list {
   list-style-type: "-";
 }
 
 .outline-list__element {
   color: blue;
   padding-left: 0.5rem;
 }
@@ -1282,17 +1287,17 @@ html .toggle-button-end.vertical svg {
   background: var(--theme-toolbar-background);
   border-top: 1px solid var(--theme-splitter-color);
   position: absolute;
   display: flex;
   bottom: 0;
   left: 0;
   right: 1px;
   opacity: 1;
-  z-index: 100;
+  z-index: 1;
   -moz-user-select: none;
   user-select: none;
   height: var(--editor-footer-height);
   box-sizing: border-box;
 }
 
 .source-footer .commands {
   display: flex;
@@ -1307,17 +1312,17 @@ html .toggle-button-end.vertical svg {
 .source-footer > .commands > .action {
   cursor: pointer;
   display: flex;
   justify-content: center;
   align-items: center;
   transition: opacity 200ms;
   border: none;
   background: transparent;
-  padding: 8px 0.7em;
+  padding: 6px 0.7em;
 }
 
 .source-footer > .commands > .action i {
   height: 100%;
   display: flex;
   flex-direction: column;
   justify-content: center;
 }
@@ -1435,35 +1440,34 @@ html .toggle-button-end.vertical svg {
 .search-bottom-bar .search-modifiers button.active svg {
   fill: var(--theme-selection-background);
 }
 
 .theme-dark .search-bottom-bar .search-modifiers button.active svg {
   fill: white;
 }
 
-.search-bottom-bar .search-modifiers button.disabled svg {
-  fill: var(--theme-comment-alt);
-  cursor: default;
-}
-
 .search-bottom-bar .search-type-toggles {
   display: flex;
   align-items: center;
+  max-width: 68%;
 }
 
 .search-bottom-bar .search-type-toggles .search-toggle-title {
   color: var(--theme-body-color-inactive);
   font-size: 11px;
   font-weight: normal;
   margin: 0;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  overflow: hidden;
 }
 
 .search-bottom-bar .search-type-toggles .search-type-btn {
-  margin: 0 6px;
+  margin: 0 0 0 6px;
   border: none;
   background: transparent;
   color: var(--theme-comment-alt);
 }
 
 .search-bottom-bar .search-type-toggles .search-type-btn:hover {
   cursor: pointer;
 }
@@ -1589,17 +1593,17 @@ html .toggle-button-end.vertical svg {
 
 .tooltip {
   position: fixed;
   z-index: 100;
 }
 
 .tooltip .preview {
   background: var(--theme-toolbar-background);
-  max-width: 350px;
+  max-width: inherit;
   min-height: 80px;
   border: 1px solid var(--theme-splitter-color);
   box-shadow: 1px 2px 4px 1px var(--theme-toolbar-background-alt);
   padding: 5px;
   height: auto;
   min-height: inherit;
   max-height: 200px;
   overflow: auto;
@@ -1840,16 +1844,57 @@ html[dir="rtl"] .editor-mount {
 
 .CodeMirror-guttermarker-subtle {
   visibility: hidden;
 }
 
 .visible {
   visibility: visible;
 }
+.cm-highlight {
+  position: relative;
+}
+
+.cm-highlight::before {
+  position: absolute;
+  border-top-style: solid;
+  border-bottom-style: solid;
+  border-top-color: var(--theme-comment-alt);
+  border-bottom-color: var(--theme-comment-alt);
+  border-top-width: 1px;
+  border-bottom-width: 1px;
+  top: -1px;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  content: "";
+  margin-bottom: -1px;
+}
+
+.cm-highlight-full::before {
+  border: 1px solid var(--theme-comment-alt);
+}
+
+.cm-highlight-start::before {
+  border-left-width: 1px;
+  border-left-style: solid;
+  border-left-color: var(--theme-comment-alt);
+  margin: 0 0 -1px -1px;
+  border-top-left-radius: 2px;
+  border-bottom-left-radius: 2px;
+}
+
+.cm-highlight-end::before {
+  border-right-width: 1px;
+  border-right-style: solid;
+  border-right-color: var(--theme-comment-alt);
+  margin: 0 -1px -1px 0;
+  border-top-right-radius: 2px;
+  border-bottom-right-radius: 2px;
+}
 
 .why-paused {
   background-color: var(--theme-body-background);
   border-bottom: 1px solid var(--theme-splitter-color);
   color: var(--theme-highlight-blue);
   padding: 10px 10px 10px 20px;
   white-space: normal;
   opacity: 0.9;
--- a/devtools/client/debugger/new/debugger.js
+++ b/devtools/client/debugger/new/debugger.js
@@ -13299,31 +13299,37 @@ return /******/ (function(modules) { // 
 	  pref("devtools.debugger.scopes-visible", false);
 	  pref("devtools.debugger.start-panel-collapsed", false);
 	  pref("devtools.debugger.end-panel-collapsed", false);
 	  pref("devtools.debugger.tabs", "[]");
 	  pref("devtools.debugger.ui.framework-grouping-on", true);
 	  pref("devtools.debugger.pending-selected-location", "{}");
 	  pref("devtools.debugger.pending-breakpoints", "[]");
 	  pref("devtools.debugger.expressions", "[]");
+	  pref("devtools.debugger.file-search-case-sensitive", true);
+	  pref("devtools.debugger.file-search-whole-word", false);
+	  pref("devtools.debugger.file-search-regex-match", false);
 	}
 
 	const prefs = new PrefsHelper("devtools", {
 	  clientSourceMapsEnabled: ["Bool", "debugger.client-source-maps-enabled"],
 	  pauseOnExceptions: ["Bool", "debugger.pause-on-exceptions"],
 	  ignoreCaughtExceptions: ["Bool", "debugger.ignore-caught-exceptions"],
 	  callStackVisible: ["Bool", "debugger.call-stack-visible"],
 	  scopesVisible: ["Bool", "debugger.scopes-visible"],
 	  startPanelCollapsed: ["Bool", "debugger.start-panel-collapsed"],
 	  endPanelCollapsed: ["Bool", "debugger.end-panel-collapsed"],
 	  frameworkGroupingOn: ["Bool", "debugger.ui.framework-grouping-on"],
 	  tabs: ["Json", "debugger.tabs"],
 	  pendingSelectedLocation: ["Json", "debugger.pending-selected-location"],
 	  pendingBreakpoints: ["Json", "debugger.pending-breakpoints"],
-	  expressions: ["Json", "debugger.expressions"]
+	  expressions: ["Json", "debugger.expressions"],
+	  fileSearchCaseSensitive: ["Bool", "debugger.file-search-case-sensitive"],
+	  fileSearchWholeWord: ["Bool", "debugger.file-search-whole-word"],
+	  fileSearchRegexMatch: ["Bool", "debugger.file-search-regex-match"]
 	});
 
 	module.exports = { prefs };
 
 
 /***/ },
 /* 227 */
 /***/ function(module, exports, __webpack_require__) {
@@ -13843,17 +13849,17 @@ return /******/ (function(modules) { // 
 	}
 
 	function removeSourcesFromTabList(tabs, urls) {
 	  return urls.reduce((t, url) => removeSourceFromTabList(t, url), tabs);
 	}
 
 	function restoreTabs() {
 	  var prefsTabs = _prefs.prefs.tabs || [];
-	  if (Object.keys(prefsTabs).length == 0) {
+	  if (prefsTabs.length == 0) {
 	    return;
 	  }
 
 	  return prefsTabs;
 	}
 
 	/**
 	 * Adds the new source to the tab list if it is not already there
@@ -15007,19 +15013,19 @@ return /******/ (function(modules) { // 
 	var _constants2 = _interopRequireDefault(_constants);
 
 	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 	var State = exports.State = (0, _makeRecord2.default)({
 	  fileSearchOn: false,
 	  fileSearchQuery: "",
 	  fileSearchModifiers: (0, _makeRecord2.default)({
-	    caseSensitive: true,
-	    wholeWord: false,
-	    regexMatch: false
+	    caseSensitive: _prefs.prefs.fileSearchCaseSensitive,
+	    wholeWord: _prefs.prefs.fileSearchWholeWord,
+	    regexMatch: _prefs.prefs.fileSearchRegexMatch
 	  })(),
 	  projectSearchOn: false,
 	  symbolSearchOn: false,
 	  symbolSearchType: "functions",
 	  shownSource: "",
 	  startPanelCollapsed: _prefs.prefs.startPanelCollapsed,
 	  endPanelCollapsed: _prefs.prefs.endPanelCollapsed,
 	  frameworkGroupingOn: _prefs.prefs.frameworkGroupingOn,
@@ -15059,17 +15065,31 @@ return /******/ (function(modules) { // 
 
 	    case _constants2.default.UPDATE_FILE_SEARCH_QUERY:
 	      {
 	        return state.set("fileSearchQuery", action.query);
 	      }
 
 	    case _constants2.default.TOGGLE_FILE_SEARCH_MODIFIER:
 	      {
-	        return state.setIn(["fileSearchModifiers", action.modifier], !state.getIn(["fileSearchModifiers", action.modifier]));
+	        var actionVal = !state.getIn(["fileSearchModifiers", action.modifier]);
+
+	        if (action.modifier == "caseSensitive") {
+	          _prefs.prefs.fileSearchCaseSensitive = actionVal;
+	        }
+
+	        if (action.modifier == "wholeWord") {
+	          _prefs.prefs.fileSearchWholeWord = actionVal;
+	        }
+
+	        if (action.modifier == "regexMatch") {
+	          _prefs.prefs.fileSearchRegexMatch = actionVal;
+	        }
+
+	        return state.setIn(["fileSearchModifiers", action.modifier], actionVal);
 	      }
 
 	    case _constants2.default.SET_SYMBOL_SEARCH_TYPE:
 	      {
 	        return state.set("symbolSearchType", action.symbolType);
 	      }
 
 	    case _constants2.default.SHOW_SOURCE:
@@ -15419,17 +15439,18 @@ return /******/ (function(modules) { // 
 	        horizontal = _state.horizontal,
 	        endPanelSize = _state.endPanelSize,
 	        startPanelSize = _state.startPanelSize;
 
 	    return _react.DOM.div({ className: "editor-pane" }, _react.DOM.div({ className: "editor-container" }, EditorTabs({
 	      startPanelCollapsed,
 	      endPanelCollapsed,
 	      horizontal,
-	      endPanelSize
+	      endPanelSize,
+	      startPanelSize
 	    }), Editor({ horizontal, startPanelSize, endPanelSize }), !this.props.selectedSource ? WelcomeBox({ horizontal }) : null, ProjectSearch()));
 	  }
 
 	  renderHorizontalLayout() {
 	    var _props2 = this.props,
 	        startPanelCollapsed = _props2.startPanelCollapsed,
 	        endPanelCollapsed = _props2.endPanelCollapsed;
 	    var horizontal = this.state.horizontal;
@@ -17455,59 +17476,46 @@ return /******/ (function(modules) { // 
 	  value: true
 	});
 	exports.getMatchIndex = exports.removeOverlay = exports.findPrev = exports.findNext = exports.find = exports.countMatches = exports.clearIndex = exports.buildQuery = undefined;
 
 	var _buildQuery = __webpack_require__(258);
 
 	var _buildQuery2 = _interopRequireDefault(_buildQuery);
 
-	var _findIndex = __webpack_require__(262);
-
-	var _findIndex2 = _interopRequireDefault(_findIndex);
-
 	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 	/**
 	 * @memberof utils/source-search
 	 * @static
 	 */
 	function getSearchCursor(cm, query, pos, modifiers) {
 	  var regexQuery = (0, _buildQuery2.default)(query, modifiers, { isGlobal: true });
 	  return cm.getSearchCursor(regexQuery, pos);
 	}
 
 	/**
 	 * @memberof utils/source-search
 	 * @static
 	 */
+
+
 	function SearchState() {
 	  this.posFrom = this.posTo = this.query = null;
 	  this.overlay = null;
 	  this.results = [];
 	  this.matchIndex = -1;
 	}
 
 	/**
 	 * @memberof utils/source-search
 	 * @static
 	 */
 	function getSearchState(cm, query, modifiers) {
 	  var state = cm.state.search || (cm.state.search = new SearchState());
-
-	  // avoid generating a cursor and iterating over the results for an empty query
-	  if (query) {
-	    var cursor = getSearchCursor(cm, query, null, modifiers);
-
-	    state.results = [];
-	    while (cursor.findNext()) {
-	      state.results.push(cursor.pos);
-	    }
-	  }
-
 	  return state;
 	}
 
 	function isWhitespace(query) {
 	  return !query.match(/\S/);
 	}
 
 	/**
@@ -17608,41 +17616,34 @@ return /******/ (function(modules) { // 
 	 * result.
 	 *
 	 * @memberof utils/source-search
 	 * @static
 	 */
 	function doSearch(ctx, rev, query, keepSelection, modifiers) {
 	  var cm = ctx.cm;
 
-	  var matchIndex = 0;
+	  var matchIndex = -1;
+
 	  cm.operation(function () {
 	    if (!query || isWhitespace(query)) {
 	      return;
 	    }
 
 	    var state = getSearchState(cm, query, modifiers);
 	    var newQuery = state.query != query;
 	    state.query = query;
 
 	    updateOverlay(cm, state, query, modifiers);
 	    updateCursor(cm, state, keepSelection);
-
-	    var nextMatch = searchNext(ctx, rev, query, newQuery, modifiers);
-	    if (nextMatch) {
-	      if (state.matchIndex === -1) {
-	        matchIndex = (0, _findIndex2.default)(state.results, nextMatch);
-	      } else {
-	        var count = state.results.length;
-	        var currentIndex = state.matchIndex;
-	        matchIndex = getMatchIndex(count, currentIndex, rev);
-	      }
-
-	      state.matchIndex = matchIndex;
-	    }
+	    searchNext(ctx, rev, query, newQuery, modifiers);
+
+	    // NOTE: We would like to find the correct match index based on where the
+	    // match is in the document.
+	    state.matchIndex = matchIndex;
 	  });
 
 	  return matchIndex;
 	}
 
 	function getCursorPos(newQuery, rev, state) {
 	  if (newQuery) {
 	    return rev ? state.posFrom : state.posTo;
@@ -17660,21 +17661,26 @@ return /******/ (function(modules) { // 
 	function searchNext(ctx, rev, query, newQuery, modifiers) {
 	  var cm = ctx.cm,
 	      ed = ctx.ed;
 
 	  var nextMatch = void 0;
 	  cm.operation(function () {
 	    var state = getSearchState(cm, query, modifiers);
 	    var pos = getCursorPos(newQuery, rev, state);
+
+	    if (!state.query) {
+	      return;
+	    }
+
 	    var cursor = getSearchCursor(cm, state.query, pos, modifiers);
 
 	    var location = rev ? { line: cm.lastLine(), ch: null } : { line: cm.firstLine(), ch: 0 };
 
-	    if (!cursor.find(rev)) {
+	    if (!cursor.find(rev) && state.query) {
 	      cursor = getSearchCursor(cm, state.query, location, modifiers);
 	      if (!cursor.find(rev)) {
 	        return;
 	      }
 	    }
 
 	    // We don't want to jump the editor
 	    // when we're selecting text
@@ -21263,17 +21269,20 @@ return /******/ (function(modules) { // 
 	  togglePanes: __webpack_require__(370),
 	  "whole-word-match": __webpack_require__(371),
 	  worker: __webpack_require__(372),
 	  "sad-face": __webpack_require__(373),
 	  refresh: __webpack_require__(374),
 	  webpack: __webpack_require__(1001),
 	  node: __webpack_require__(1002),
 	  express: __webpack_require__(1003),
-	  pug: __webpack_require__(1004)
+	  pug: __webpack_require__(1004),
+	  extjs: __webpack_require__(1043),
+	  showSources: __webpack_require__(1044),
+	  showOutline: __webpack_require__(1045)
 	};
 
 	module.exports = function (name, props) {
 	  // eslint-disable-line
 	  if (!svg[name]) {
 	    throw new Error("Unknown SVG: " + name);
 	  }
 	  var className = name;
@@ -21904,18 +21913,24 @@ return /******/ (function(modules) { // 
 	var _reactRedux = __webpack_require__(151);
 
 	var _text = __webpack_require__(389);
 
 	var _actions = __webpack_require__(244);
 
 	var _actions2 = _interopRequireDefault(_actions);
 
+	var _Svg = __webpack_require__(344);
+
+	var _Svg2 = _interopRequireDefault(_Svg);
+
 	var _selectors = __webpack_require__(242);
 
+	var _devtoolsConfig = __webpack_require__(828);
+
 	__webpack_require__(424);
 
 	var _Outline2 = __webpack_require__(921);
 
 	var _Outline3 = _interopRequireDefault(_Outline2);
 
 	var _SourcesTree2 = __webpack_require__(390);
 
@@ -21926,36 +21941,83 @@ return /******/ (function(modules) { // 
 	var Outline = (0, _react.createFactory)(_Outline3.default);
 
 	var SourcesTree = (0, _react.createFactory)(_SourcesTree3.default);
 
 	class Sources extends _react.Component {
 
 	  constructor(props) {
 	    super(props);
+	    this.state = { selectedPane: "sources" };
+
 	    this.renderShortcut = this.renderShortcut.bind(this);
+	    this.togglePane = this.togglePane.bind(this);
+	    this.renderFooter = this.renderFooter.bind(this);
+	  }
+
+	  togglePane() {
+	    var selectedPane = this.state.selectedPane === "sources" ? "outline" : "sources";
+
+	    this.setState({ selectedPane });
+	  }
+
+	  renderOutlineToggleButton() {
+	    if (!(0, _devtoolsConfig.isEnabled)("outline")) {
+	      return;
+	    }
+
+	    var selectedPane = this.state.selectedPane;
+
+	    var showSourcesTooltip = L10N.getStr("sourcesPane.showSourcesTooltip");
+	    var showOutlineTooltip = L10N.getStr("sourcesPane.showOutlineTooltip");
+
+	    var isSourcesPaneSelected = selectedPane === "sources";
+	    var tooltip = isSourcesPaneSelected ? showOutlineTooltip : showSourcesTooltip;
+	    var type = isSourcesPaneSelected ? "showSources" : "showOutline";
+
+	    return _react.DOM.button({
+	      className: "action",
+	      onClick: this.togglePane,
+	      key: type,
+	      title: tooltip
+	    }, (0, _Svg2.default)(type));
+	  }
+
+	  renderFooter() {
+	    return _react.DOM.div({
+	      className: "source-footer"
+	    }, _react.DOM.div({ className: "commands" }, this.renderOutlineToggleButton()));
 	  }
 
 	  renderShortcut() {
 	    if (this.props.horizontal) {
 	      return _react.DOM.span({
 	        className: "sources-header-info",
 	        dir: "ltr",
 	        onClick: () => this.props.toggleProjectSearch()
 	      }, L10N.getFormatStr("sources.search", (0, _text.formatKeyShortcut)(L10N.getStr("sources.search.key2"))));
 	    }
 	  }
 
+	  renderHeader() {
+	    return _react.DOM.div({ className: "sources-header" }, this.renderShortcut());
+	  }
+
 	  render() {
+	    var selectedPane = this.state.selectedPane;
 	    var _props = this.props,
 	        sources = _props.sources,
 	        selectSource = _props.selectSource;
 
 
-	    return _react.DOM.div({ className: "sources-panel" }, _react.DOM.div({ className: "sources-header" }, this.renderShortcut()), SourcesTree({ sources, selectSource }), Outline({ selectSource }));
+	    return _react.DOM.div({ className: "sources-panel" }, this.renderHeader(), SourcesTree({
+	      sources,
+	      selectSource,
+	      isHidden: selectedPane === "outline"
+	    }), Outline({ selectSource, isHidden: selectedPane === "sources" }), this.renderFooter());
 	  }
 	}
 
 	Sources.propTypes = {
 	  sources: _reactImmutableProptypes2.default.map.isRequired,
 	  selectSource: _react.PropTypes.func.isRequired,
 	  horizontal: _react.PropTypes.bool.isRequired,
 	  toggleProjectSearch: _react.PropTypes.func.isRequired
@@ -22222,23 +22284,25 @@ return /******/ (function(modules) { // 
 	        this.selectItem(item);
 	        setExpanded(item, !expanded);
 	      },
 	      onContextMenu: e => this.onContextMenu(e, item)
 	    }, _react.DOM.div(null, arrow, icon, item.name));
 	  }
 
 	  render() {
+	    var isHidden = this.props.isHidden;
 	    var _state = this.state,
 	        focusedItem = _state.focusedItem,
 	        sourceTree = _state.sourceTree,
 	        parentMap = _state.parentMap,
 	        listItems = _state.listItems,
 	        highlightItems = _state.highlightItems;
 
+
 	    var isEmpty = sourceTree.contents.length === 0;
 
 	    var tree = ManagedTree({
 	      key: isEmpty ? "empty" : "full",
 	      getParent: item => {
 	        return parentMap.get(item);
 	      },
 	      getChildren: item => {
@@ -22261,27 +22325,28 @@ return /******/ (function(modules) { // 
 	    var noSourcesMessage = _react.DOM.div({
 	      className: "no-sources-message"
 	    }, L10N.getStr("sources.noSourcesAvailable"));
 
 	    if (isEmpty) {
 	      return noSourcesMessage;
 	    }
 	    return _react.DOM.div({
-	      className: "sources-list",
+	      className: (0, _classnames2.default)("sources-list", { hidden: isHidden }),
 	      onKeyDown: e => {
 	        if (e.keyCode === 13 && focusedItem) {
 	          this.selectItem(focusedItem);
 	        }
 	      }
 	    }, tree);
 	  }
 	}
 
 	SourcesTree.propTypes = {
+	  isHidden: _react.PropTypes.bool,
 	  sources: _reactImmutableProptypes2.default.map.isRequired,
 	  selectSource: _react.PropTypes.func.isRequired,
 	  shownSource: _react.PropTypes.string,
 	  selectedSource: _reactImmutableProptypes2.default.map,
 	  debuggeeUrl: _react.PropTypes.string.isRequired
 	};
 
 	SourcesTree.displayName = "SourcesTree";
@@ -23918,16 +23983,18 @@ return /******/ (function(modules) { // 
 	var _HitMarker3 = _interopRequireDefault(_HitMarker2);
 
 	var _editor = __webpack_require__(257);
 
 	var _scopes = __webpack_require__(732);
 
 	__webpack_require__(716);
 
+	__webpack_require__(1046);
+
 	var _devtoolsSourceEditor = __webpack_require__(994);
 
 	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 	function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
 
 	var Footer = (0, _react.createFactory)(_Footer3.default);
 
@@ -24627,17 +24694,17 @@ return /******/ (function(modules) { // 
 	    }
 
 	    var token = selectedToken.textContent;
 
 	    var value = (0, _editor.getExpressionValue)(selectedExpression, {
 	      getExpression: this.props.getExpression
 	    });
 
-	    if (!value || value.type == "undefined") {
+	    if (typeof value == "undefined" || value.type == "undefined") {
 	      return;
 	    }
 
 	    return Preview({
 	      value,
 	      expression: token,
 	      popoverTarget: selectedToken,
 	      onClose: () => {
@@ -25621,21 +25688,24 @@ return /******/ (function(modules) { // 
 
 	  renderSearchModifiers() {
 	    var _props11 = this.props,
 	        modifiers = _props11.modifiers,
 	        toggleFileSearchModifier = _props11.toggleFileSearchModifier,
 	        symbolSearchOn = _props11.symbolSearchOn;
 
 
+	    if (symbolSearchOn) {
+	      return null;
+	    }
+
 	    function searchModBtn(modVal, className, svgName, tooltip) {
 	      return _react.DOM.button({
 	        className: (0, _classnames2.default)(className, {
-	          active: !symbolSearchOn && modifiers && modifiers.get(modVal),
-	          disabled: symbolSearchOn
+	          active: !symbolSearchOn && modifiers && modifiers.get(modVal)
 	        }),
 	        onClick: () => !symbolSearchOn ? toggleFileSearchModifier(modVal) : null,
 	        title: tooltip
 	      }, (0, _Svg2.default)(svgName));
 	    }
 
 	    return _react.DOM.div({ className: "search-modifiers" }, searchModBtn("regexMatch", "regex-match-btn", "regex-match", L10N.getStr("symbolSearch.searchModifier.regex")), searchModBtn("caseSensitive", "case-sensitive-btn", "case-match", L10N.getStr("symbolSearch.searchModifier.caseSensitive")), searchModBtn("wholeWord", "whole-word-btn", "whole-word-match", L10N.getStr("symbolSearch.searchModifier.wholeWord")));
 	  }
@@ -25848,48 +25918,17 @@ return /******/ (function(modules) { // 
 /* 548 */,
 /* 549 */,
 /* 550 */,
 /* 551 */,
 /* 552 */,
 /* 553 */,
 /* 554 */,
 /* 555 */,
-/* 556 */
-/***/ function(module, exports) {
-
-	/**
-	 * A specialized version of `_.reduce` for arrays without support for
-	 * iteratee shorthands.
-	 *
-	 * @private
-	 * @param {Array} [array] The array to iterate over.
-	 * @param {Function} iteratee The function invoked per iteration.
-	 * @param {*} [accumulator] The initial value.
-	 * @param {boolean} [initAccum] Specify using the first element of `array` as
-	 *  the initial value.
-	 * @returns {*} Returns the accumulated value.
-	 */
-	function arrayReduce(array, iteratee, accumulator, initAccum) {
-	  var index = -1,
-	      length = array == null ? 0 : array.length;
-
-	  if (initAccum && length) {
-	    accumulator = array[++index];
-	  }
-	  while (++index < length) {
-	    accumulator = iteratee(accumulator, array[index], index, array);
-	  }
-	  return accumulator;
-	}
-
-	module.exports = arrayReduce;
-
-
-/***/ },
+/* 556 */,
 /* 557 */,
 /* 558 */,
 /* 559 */,
 /* 560 */,
 /* 561 */,
 /* 562 */,
 /* 563 */,
 /* 564 */,
@@ -26618,25 +26657,33 @@ return /******/ (function(modules) { // 
 
 	    if (value.type === "object") {
 	      return _react.DOM.div({}, this.renderObjectPreview(expression, root), this.renderAddToExpressionBar(expression, value));
 	    }
 
 	    return this.renderSimplePreview(value);
 	  }
 
+	  getPreviewType(value) {
+	    if (typeof value == "boolean" || value.class === "Function") {
+	      return "tooltip";
+	    }
+
+	    return "popover";
+	  }
+
 	  render() {
 	    var _props3 = this.props,
 	        popoverTarget = _props3.popoverTarget,
 	        onClose = _props3.onClose,
 	        value = _props3.value,
 	        expression = _props3.expression;
 
 
-	    var type = value.class === "Function" ? "tooltip" : "popover";
+	    var type = this.getPreviewType(value);
 
 	    return Popover({
 	      target: popoverTarget,
 	      onMouseLeave: onClose,
 	      type
 	    }, this.renderPreview(expression, value));
 	  }
 	}
@@ -27222,17 +27269,17 @@ return /******/ (function(modules) { // 
 	  }
 
 	  calculateLeft(target, editor, popover) {
 	    var leftOffset = target.width / 2 - popover.width / 5;
 	    var estimatedLeft = target.left + leftOffset;
 	    var estimatedRight = estimatedLeft + popover.width;
 	    var isOverflowingRight = estimatedRight > editor.right;
 	    if (isOverflowingRight) {
-	      var adjustedLeft = editor.right - popover.width;
+	      var adjustedLeft = editor.right - popover.width - 8;
 	      return adjustedLeft;
 	    }
 	    return estimatedLeft;
 	  }
 
 	  calculateVerticalOrientation(target, editor, popover) {
 	    var estimatedBottom = target.bottom + popover.height;
 
@@ -27253,28 +27300,25 @@ return /******/ (function(modules) { // 
 	    var top = orientation == "down" ? targetRect.bottom : targetRect.top - popoverRect.height;
 
 	    var targetMid = targetRect.left - popoverLeft + targetRect.width / 2 - 8;
 
 	    return { left: popoverLeft, top, orientation, targetMid };
 	  }
 
 	  getTooltipCoords() {
-	    var el = _reactDom2.default.findDOMNode(this);
-
-	    var _el$getBoundingClient = el.getBoundingClientRect(),
-	        height = _el$getBoundingClient.height;
-
-	    var _props$target$getBoun = this.props.target.getBoundingClientRect(),
-	        targetLeft = _props$target$getBoun.left,
-	        targetWidth = _props$target$getBoun.width,
-	        targetTop = _props$target$getBoun.top;
-
-	    var left = targetLeft + targetWidth / 4 - 10;
-	    var top = targetTop - height;
+	    var tooltip = _reactDom2.default.findDOMNode(this);
+	    var tooltipRect = tooltip.getBoundingClientRect();
+	    var targetRect = this.props.target.getBoundingClientRect();
+
+	    var editor = document.querySelector(".editor-wrapper");
+	    var editorRect = editor.getBoundingClientRect();
+
+	    var left = this.calculateLeft(targetRect, editorRect, tooltipRect);
+	    var top = targetRect.top - tooltipRect.height;
 
 	    return { left, top, orientation: "up", targetMid: 0 };
 	  }
 
 	  getChildren() {
 	    var children = this.props.children;
 	    var orientation = this.state.orientation;
 
@@ -27381,24 +27425,27 @@ return /******/ (function(modules) { // 
 	var _zip = __webpack_require__(704);
 
 	var _zip2 = _interopRequireDefault(_zip);
 
 	var _flatten = __webpack_require__(706);
 
 	var _flatten2 = _interopRequireDefault(_flatten);
 
+	var _frame = __webpack_require__(1014);
+
 	__webpack_require__(1005);
 
 	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
 
 	function getFunctionName(func) {
-	  return func.userDisplayName || func.displayName || func.name || func.value || "";
+	  var name = func.userDisplayName || func.displayName || func.name;
+	  return (0, _frame.simplifyDisplayName)(name);
 	}
 
 	function renderFunctionName(func) {
 	  var name = getFunctionName(func);
 	  return _react.DOM.span({ className: "function-name" }, name);
 	}
 
 	function renderParams(func) {
@@ -31482,17 +31529,17 @@ return /******/ (function(modules) { // 
 
 	    // In Firefox, we need to initially request all of the sources. This
 	    // usually fires off individual `newSource` notifications as the
 	    // debugger finds them, but there may be existing sources already in
 	    // the debugger (if it's paused already, or if loading the page from
 	    // bfcache) so explicity fire `newSource` events for all returned
 	    // sources.
 	    var sources = yield clientCommands.fetchSources();
-	    actions.newSources(sources);
+	    yield actions.newSources(sources);
 
 	    // If the threadClient is already paused, make sure to show a
 	    // paused state.
 	    var pausedPacket = threadClient.getLastPausePacket();
 	    if (pausedPacket) {
 	      clientEvents.paused("paused", pausedPacket);
 	    }
 	  });
@@ -32763,17 +32810,17 @@ return /******/ (function(modules) { // 
 	// `getExpressionValue` and `previewExpression` are utility functions
 	// for resolving which expression to show in the preview.
 	// Get ExpressionValue, knows how to get the appropriate value for each type:
 	// variable, expression, raw value.
 	function getExpressionValue(selectedExpression, _ref3) {
 	  var getExpression = _ref3.getExpression;
 
 	  var variableValue = (0, _get2.default)(selectedExpression, "contents.value");
-	  if (variableValue) {
+	  if (typeof variableValue === "boolean" || variableValue) {
 	    return variableValue;
 	  }
 
 	  var expressionValue = getExpression(selectedExpression.value);
 	  if (expressionValue) {
 	    return (0, _get2.default)(expressionValue, "value.result");
 	  }
 
@@ -33821,16 +33868,20 @@ return /******/ (function(modules) { // 
 	});
 
 	var _react = __webpack_require__(2);
 
 	var _redux = __webpack_require__(3);
 
 	var _reactRedux = __webpack_require__(151);
 
+	var _classnames = __webpack_require__(175);
+
+	var _classnames2 = _interopRequireDefault(_classnames);
+
 	var _actions = __webpack_require__(244);
 
 	var _actions2 = _interopRequireDefault(_actions);
 
 	var _selectors = __webpack_require__(242);
 
 	var _devtoolsConfig = __webpack_require__(828);
 
@@ -33845,17 +33896,23 @@ return /******/ (function(modules) { // 
 	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 	function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
 
 	class Outline extends _react.Component {
 
 	  constructor(props) {
 	    super(props);
+	    var sourceText = props.sourceText,
+	        isHidden = props.isHidden;
+
 	    this.state = {};
+	    if (!isHidden) {
+	      this.setSymbolDeclarations(sourceText);
+	    }
 	  }
 
 	  componentWillReceiveProps(_ref) {
 	    var sourceText = _ref.sourceText;
 
 	    if (sourceText) {
 	      this.setSymbolDeclarations(sourceText);
 	    }
@@ -33899,39 +33956,42 @@ return /******/ (function(modules) { // 
 
 	    if (!symbolDeclarations) {
 	      return;
 	    }
 
 	    var functions = symbolDeclarations.functions;
 
 
-	    return functions.filter(func => func.value != "anonymous").map(func => this.renderFunction(func));
+	    return functions.filter(func => func.name != "anonymous").map(func => this.renderFunction(func));
 	  }
 
 	  render() {
+	    var isHidden = this.props.isHidden;
+
 	    if (!(0, _devtoolsConfig.isEnabled)("outline")) {
 	      return null;
 	    }
 
-	    return _react.DOM.div({ className: "outline" }, _react.DOM.ul({ className: "outline-list" }, this.renderFunctions()));
+	    return _react.DOM.div({ className: (0, _classnames2.default)("outline", { hidden: isHidden }) }, _react.DOM.ul({ className: "outline-list" }, this.renderFunctions()));
 	  }
 	}
 
 	Outline.propTypes = {
+	  isHidden: _react.PropTypes.bool.isRequired,
+	  sourceText: _react.PropTypes.object,
 	  selectSource: _react.PropTypes.func.isRequired,
 	  selectedSource: _react.PropTypes.object
 	};
 
 	Outline.displayName = "Outline";
 
 	exports.default = (0, _reactRedux.connect)(state => {
 	  var selectedSource = (0, _selectors.getSelectedSource)(state);
 	  var sourceId = selectedSource ? selectedSource.get("id") : null;
-
 	  return {
 	    sourceText: (0, _selectors.getSourceText)(state, sourceId),
 	    selectedSource
 	  };
 	}, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(Outline);
 
 /***/ },
 /* 922 */
@@ -37207,17 +37267,17 @@ return /******/ (function(modules) { // 
 	  rep: wrapRender(GripMap),
 	  supportsObject
 	};
 
 /***/ },
 /* 960 */
 /***/ function(module, exports) {
 
-	module.exports = "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\n# LOCALIZATION NOTE These strings are used inside the Debugger\n# which is available from the Web Developer sub-menu -> 'Debugger'.\n# The correct localization of this file might be to keep it in\n# English, or another language commonly spoken among web developers.\n# You want to make that choice consistent across the developer tools.\n# A good criteria is the language in which you'd find the best\n# documentation on web development on the web.\n\n# LOCALIZATION NOTE (collapsePanes): This is the tooltip for the button\n# that collapses the left and right panes in the debugger UI.\ncollapsePanes=Collapse panes\n\n# LOCALIZATION NOTE (copySourceUrl): This is the text that appears in the\n# context menu to copy the source URL of file open.\ncopySourceUrl=Copy Source Url\n\n# LOCALIZATION NOTE (copySourceUrl.accesskey): Access key to copy the source URL of a file from\n# the context menu.\ncopySourceUrl.accesskey=u\n\n# LOCALIZATION NOTE (copyStackTrace): This is the text that appears in the\n# context menu to copy the stack trace methods, file names and row number.\ncopyStackTrace=Copy Stack Trace\n\n# LOCALIZATION NOTE (copyStackTrace.accesskey): Access key to copy the stack trace data from\n# the context menu.\ncopyStackTrace.accesskey=c\n\n# LOCALIZATION NOTE (expandPanes): This is the tooltip for the button\n# that expands the left and right panes in the debugger UI.\nexpandPanes=Expand panes\n\n# LOCALIZATION NOTE (pauseButtonTooltip): The tooltip that is displayed for the pause\n# button when the debugger is in a running state.\npauseButtonTooltip=Pause %S\n\n# LOCALIZATION NOTE (pausePendingButtonTooltip): The tooltip that is displayed for\n# the pause button after it's been clicked but before the next JavaScript to run.\npausePendingButtonTooltip=Waiting for next execution\n\n# LOCALIZATION NOTE (resumeButtonTooltip): The label that is displayed on the pause\n# button when the debugger is in a paused state.\nresumeButtonTooltip=Resume %S\n\n# LOCALIZATION NOTE (stepOverTooltip): The label that is displayed on the\n# button that steps over a function call.\nstepOverTooltip=Step Over %S\n\n# LOCALIZATION NOTE (stepInTooltip): The label that is displayed on the\n# button that steps into a function call.\nstepInTooltip=Step In %S\n\n# LOCALIZATION NOTE (stepOutTooltip): The label that is displayed on the\n# button that steps out of a function call.\nstepOutTooltip=Step Out %S\n\n# LOCALIZATION NOTE (noWorkersText): The text to display in the workers list\n# when there are no workers.\nnoWorkersText=This page has no workers.\n\n# LOCALIZATION NOTE (noSourcesText): The text to display in the sources list\n# when there are no sources.\nnoSourcesText=This page has no sources.\n\n# LOCALIZATION NOTE (noEventListenersText): The text to display in the events tab\n# when there are no events.\nnoEventListenersText=No event listeners to display\n\n# LOCALIZATION NOTE (eventListenersHeader): The text to display in the events\n# header.\neventListenersHeader=Event Listeners\n\n# LOCALIZATION NOTE (noStackFramesText): The text to display in the call stack tab\n# when there are no stack frames.\nnoStackFramesText=No stack frames to display\n\n# LOCALIZATION NOTE (eventCheckboxTooltip): The tooltip text to display when\n# the user hovers over the checkbox used to toggle an event breakpoint.\neventCheckboxTooltip=Toggle breaking on this event\n\n# LOCALIZATION NOTE (eventOnSelector): The text to display in the events tab\n# for every event item, between the event type and event selector.\neventOnSelector=on\n\n# LOCALIZATION NOTE (eventInSource): The text to display in the events tab\n# for every event item, between the event selector and listener's owner source.\neventInSource=in\n\n# LOCALIZATION NOTE (eventNodes): The text to display in the events tab when\n# an event is listened on more than one target node.\neventNodes=%S nodes\n\n# LOCALIZATION NOTE (eventNative): The text to display in the events tab when\n# a listener is added from plugins, thus getting translated to native code.\neventNative=[native code]\n\n# LOCALIZATION NOTE (*Events): The text to display in the events tab for\n# each group of sub-level event entries.\nanimationEvents=Animation\naudioEvents=Audio\nbatteryEvents=Battery\nclipboardEvents=Clipboard\ncompositionEvents=Composition\ndeviceEvents=Device\ndisplayEvents=Display\ndragAndDropEvents=Drag and Drop\ngamepadEvents=Gamepad\nindexedDBEvents=IndexedDB\ninteractionEvents=Interaction\nkeyboardEvents=Keyboard\nmediaEvents=HTML5 Media\nmouseEvents=Mouse\nmutationEvents=Mutation\nnavigationEvents=Navigation\npointerLockEvents=Pointer Lock\nsensorEvents=Sensor\nstorageEvents=Storage\ntimeEvents=Time\ntouchEvents=Touch\notherEvents=Other\n\n# LOCALIZATION NOTE (blackboxCheckboxTooltip2): The tooltip text to display when\n# the user hovers over the checkbox used to toggle blackboxing its associated\n# source.\nblackboxCheckboxTooltip2=Toggle blackboxing\n\n# LOCALIZATION NOTE (sources.search.key2): Key shortcut to open the search for\n# searching all the source files the debugger has seen.\nsources.search.key2=CmdOrCtrl+P\n\n# LOCALIZATION NOTE (sources.search.alt.key): A second key shortcut to open the\n# search for searching all the source files the debugger has seen.\nsources.search.alt.key=CmdOrCtrl+O\n\n# LOCALIZATION NOTE (sources.noSourcesAvailable): Text shown when the debugger\n# does not have any sources.\nsources.noSourcesAvailable=This page has no sources\n\n# LOCALIZATION NOTE (sourceSearch.search.key2): Key shortcut to open the search\n# for searching within a the currently opened files in the editor\nsourceSearch.search.key2=CmdOrCtrl+F\n\n# LOCALIZATION NOTE (sourceSearch.search.placeholder): placeholder text in\n# the source search input bar\nsourceSearch.search.placeholder=Search in file…\n\n# LOCALIZATION NOTE (sourceSearch.search.again.key2): Key shortcut to highlight\n# the next occurrence of the last search triggered from a source search\nsourceSearch.search.again.key2=CmdOrCtrl+G\n\n# LOCALIZATION NOTE (sourceSearch.search.againPrev.key2): Key shortcut to highlight\n# the previous occurrence of the last search triggered from a source search\nsourceSearch.search.againPrev.key2=CmdOrCtrl+Shift+G\n\n# LOCALIZATION NOTE (sourceSearch.resultsSummary1): Shows a summary of\n# the number of matches for autocomplete\nsourceSearch.resultsSummary1=%d results\n\n# LOCALIZATION NOTE (noMatchingStringsText): The text to display in the\n# global search results when there are no matching strings after filtering.\nnoMatchingStringsText=No matches found\n\n# LOCALIZATION NOTE (emptySearchText): This is the text that appears in the\n# filter text box when it is empty and the scripts container is selected.\nemptySearchText=Search scripts (%S)\n\n# LOCALIZATION NOTE (emptyVariablesFilterText): This is the text that\n# appears in the filter text box for the variables view container.\nemptyVariablesFilterText=Filter variables\n\n# LOCALIZATION NOTE (emptyPropertiesFilterText): This is the text that\n# appears in the filter text box for the editor's variables view bubble.\nemptyPropertiesFilterText=Filter properties\n\n# LOCALIZATION NOTE (searchPanelFilter): This is the text that appears in the\n# filter panel popup for the filter scripts operation.\nsearchPanelFilter=Filter scripts (%S)\n\n# LOCALIZATION NOTE (searchPanelGlobal): This is the text that appears in the\n# filter panel popup for the global search operation.\nsearchPanelGlobal=Search in all files (%S)\n\n# LOCALIZATION NOTE (searchPanelFunction): This is the text that appears in the\n# filter panel popup for the function search operation.\nsearchPanelFunction=Search for function definition (%S)\n\n# LOCALIZATION NOTE (searchPanelToken): This is the text that appears in the\n# filter panel popup for the token search operation.\nsearchPanelToken=Find in this file (%S)\n\n# LOCALIZATION NOTE (searchPanelGoToLine): This is the text that appears in the\n# filter panel popup for the line search operation.\nsearchPanelGoToLine=Go to line (%S)\n\n# LOCALIZATION NOTE (searchPanelVariable): This is the text that appears in the\n# filter panel popup for the variables search operation.\nsearchPanelVariable=Filter variables (%S)\n\n# LOCALIZATION NOTE (breakpointMenuItem): The text for all the elements that\n# are displayed in the breakpoints menu item popup.\nbreakpointMenuItem.setConditional=Configure conditional breakpoint\nbreakpointMenuItem.enableSelf=Enable breakpoint\nbreakpointMenuItem.disableSelf=Disable breakpoint\nbreakpointMenuItem.deleteSelf=Remove breakpoint\nbreakpointMenuItem.enableOthers=Enable others\nbreakpointMenuItem.disableOthers=Disable others\nbreakpointMenuItem.deleteOthers=Remove others\nbreakpointMenuItem.enableAll=Enable all breakpoints\nbreakpointMenuItem.disableAll=Disable all breakpoints\nbreakpointMenuItem.deleteAll=Remove all breakpoints\n\n# LOCALIZATION NOTE (breakpoints.header): Breakpoints right sidebar pane header.\nbreakpoints.header=Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.none): The text that appears when there are\n# no breakpoints present\nbreakpoints.none=No Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.enable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.enable=Enable Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.disable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.disable=Disable Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.removeBreakpointTooltip): The tooltip that is displayed\n# for remove breakpoint button in right sidebar\nbreakpoints.removeBreakpointTooltip=Remove Breakpoint\n\n# LOCALIZATION NOTE (callStack.header): Call Stack right sidebar pane header.\ncallStack.header=Call Stack\n\n# LOCALIZATION NOTE (callStack.notPaused): Call Stack right sidebar pane\n# message when not paused.\ncallStack.notPaused=Not Paused\n\n# LOCALIZATION NOTE (callStack.collapse): Call Stack right sidebar pane\n# message to hide some of the frames that are shown.\ncallStack.collapse=Collapse Rows\n\n# LOCALIZATION NOTE (callStack.expand): Call Stack right sidebar pane\n# message to show more of the frames.\ncallStack.expand=Expand Rows\n\n# LOCALIZATION NOTE (editor.searchResults): Editor Search bar message\n# for the summarizing the selected search result. e.g. 5 of 10 results.\neditor.searchResults=%d of %d results\n\n# LOCALIZATION NOTE (sourceSearch.singleResult): Copy shown when there is one result.\neditor.singleResult=1 result\n\n# LOCALIZATION NOTE (editor.noResults): Editor Search bar message\n# for when no results found.\neditor.noResults=no results\n\n# LOCALIZATION NOTE (editor.searchResults.nextResult): Editor Search bar\n# tooltip for traversing to the Next Result\neditor.searchResults.nextResult=Next Result\n\n# LOCALIZATION NOTE (editor.searchResults.prevResult): Editor Search bar\n# tooltip for traversing to the Previous Result\neditor.searchResults.prevResult=Previous Result\n\n# LOCALIZATION NOTE (editor.searchTypeToggleTitle): Search bar title for\n# toggling search type buttons(function search, variable search)\neditor.searchTypeToggleTitle=Search for:\n\n# LOCALIZATION NOTE (editor.addBreakpoint): Editor gutter context menu item\n# for adding a breakpoint on a line.\neditor.addBreakpoint=Add Breakpoint\n\n# LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item\n# for disabling a breakpoint on a line.\neditor.disableBreakpoint=Disable Breakpoint\n\n# LOCALIZATION NOTE (editor.enableBreakpoint): Editor gutter context menu item\n# for enabling a breakpoint on a line.\neditor.enableBreakpoint=Enable Breakpoint\n\n# LOCALIZATION NOTE (editor.removeBreakpoint): Editor gutter context menu item\n# for removing a breakpoint on a line.\neditor.removeBreakpoint=Remove Breakpoint\n\n# LOCALIZATION NOTE (editor.editBreakpoint): Editor gutter context menu item\n# for setting a breakpoint condition on a line.\neditor.editBreakpoint=Edit Breakpoint\n\n# LOCALIZATION NOTE (editor.addConditionalBreakpoint): Editor gutter context\n# menu item for adding a breakpoint condition on a line.\neditor.addConditionalBreakpoint=Add Conditional Breakpoint\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Placeholder text for\n# input element inside ConditionalPanel component\neditor.conditionalPanel.placeholder=This breakpoint will pause when the expression is true\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Tooltip text for\n# close button inside ConditionalPanel component\neditor.conditionalPanel.close=Cancel edit breakpoint and close\n\n# LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item\n# for navigating to a source mapped location\neditor.jumpToMappedLocation1=Jump to %S location\n\n# LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the\n# context menu to disable framework grouping.\nframework.disableGrouping=Disable Framework Grouping\n\n# LOCALIZATION NOTE (framework.enableGrouping): This is the text that appears in the\n# context menu to enable framework grouping.\nframework.enableGrouping=Enable Framework Grouping\n\n# LOCALIZATION NOTE (framework.accesskey): Access key to toggle framework grouping from\n# the context menu.\nframework.accesskey=u\n\n# LOCALIZATION NOTE (generated): Source Map term for a server source location\ngenerated=generated\n\n# LOCALIZATION NOTE (original): Source Map term for a debugger UI source location\noriginal=original\n\n# LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression\n# input element\nexpressions.placeholder=Add Watch Expression\n\n# LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item\n# for closing the selected tab below the mouse.\nsourceTabs.closeTab=Close tab\n\n# LOCALIZATION NOTE (sourceTabs.closeTab.accesskey): Access key to close the currently select\n# source tab from the editor context menu item.\nsourceTabs.closeTab.accesskey=c\n\n# LOCALIZATION NOTE (sourceTabs.closeOtherTabs): Editor source tab context menu item\n# for closing the other tabs.\nsourceTabs.closeOtherTabs=Close others\n\n# LOCALIZATION NOTE (sourceTabs.closeOtherTabs.accesskey): Access key to close other source tabs\n# from the editor context menu.\nsourceTabs.closeOtherTabs.accesskey=o\n\n# LOCALIZATION NOTE (sourceTabs.closeTabsToEnd): Editor source tab context menu item\n# for closing the tabs to the end (the right for LTR languages) of the selected tab.\nsourceTabs.closeTabsToEnd=Close tabs to the right\n\n# LOCALIZATION NOTE (sourceTabs.closeTabsToEnd.accesskey): Access key to close source tabs\n# after the selected tab from the editor context menu.\nsourceTabs.closeTabsToEnd.accesskey=e\n\n# LOCALIZATION NOTE (sourceTabs.closeAllTabs): Editor source tab context menu item\n# for closing all tabs.\nsourceTabs.closeAllTabs=Close all tabs\n\n# LOCALIZATION NOTE (sourceTabs.closeAllTabs.accesskey): Access key to close all tabs from the\n# editor context menu.\nsourceTabs.closeAllTabs.accesskey=a\n\n# LOCALIZATION NOTE (sourceTabs.revealInTree): Editor source tab context menu item\n# for revealing source in tree.\nsourceTabs.revealInTree=Reveal in Tree\n\n# LOCALIZATION NOTE (sourceTabs.revealInTree.accesskey): Access key to reveal a source in the\n# tree from the context menu.\nsourceTabs.revealInTree.accesskey=r\n\n# LOCALIZATION NOTE (sourceTabs.copyLink): Editor source tab context menu item\n# for copying a link address.\nsourceTabs.copyLink=Copy Link Address\n\n# LOCALIZATION NOTE (sourceTabs.copyLink.accesskey): Access key to copy a link addresss from the\n# editor context menu.\nsourceTabs.copyLink.accesskey=l\n\n# LOCALIZATION NOTE (sourceTabs.prettyPrint): Editor source tab context menu item\n# for pretty printing the source.\nsourceTabs.prettyPrint=Pretty Print Source\n\n# LOCALIZATION NOTE (sourceTabs.prettyPrint.accesskey): Access key to pretty print a source from\n# the editor context menu.\nsourceTabs.prettyPrint.accesskey=p\n\n# LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.blackbox=Blackbox Source\n\n# LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.unblackbox=Unblackbox Source\n\n# LOCALIZATION NOTE (sourceFooter.blackbox.accesskey): Access key to blackbox\n# an associated source\nsourceFooter.blackbox.accesskey=b\n\n# LOCALIZATION NOTE (sourceFooter.blackboxed): Text associated\n# with a blackboxed source\nsourceFooter.blackboxed=Blackboxed Source\n\n# LOCALIZATION NOTE (sourceTabs.closeTabButtonTooltip): The tooltip that is displayed\n# for close tab button in source tabs.\nsourceTabs.closeTabButtonTooltip=Close tab\n\n# LOCALIZATION NOTE (sourceTabs.newTabButtonTooltip): The tooltip that is displayed for\n# new tab button in source tabs.\nsourceTabs.newTabButtonTooltip=Search for sources (%S)\n\n# LOCALIZATION NOTE (scopes.header): Scopes right sidebar pane header.\nscopes.header=Scopes\n\n# LOCALIZATION NOTE (scopes.notAvailable): Scopes right sidebar pane message\n# for when the debugger is paused, but there isn't pause data.\nscopes.notAvailable=Scopes Unavailable\n\n# LOCALIZATION NOTE (scopes.notPaused): Scopes right sidebar pane message\n# for when the debugger is not paused.\nscopes.notPaused=Not Paused\n\n# LOCALIZATION NOTE (scopes.block): Refers to a block of code in\n# the scopes pane when the debugger is paused.\nscopes.block=Block\n\n# LOCALIZATION NOTE (sources.header): Sources left sidebar header\nsources.header=Sources\n\n# LOCALIZATION NOTE (sources.search): Sources left sidebar prompt\n# e.g. Cmd+P to search. On a mac, we use the command unicode character.\n# On windows, it's ctrl.\nsources.search=%S to search\n\n# LOCALIZATION NOTE (watchExpressions.header): Watch Expressions right sidebar\n# pane header.\nwatchExpressions.header=Watch Expressions\n\n# LOCALIZATION NOTE (watchExpressions.refreshButton): Watch Expressions header\n# button for refreshing the expressions.\nwatchExpressions.refreshButton=Refresh\n\n# LOCALIZATION NOTE (welcome.search): The center pane welcome panel's\n# search prompt. e.g. cmd+p to search for files. On windows, it's ctrl, on\n# a mac we use the unicode character.\nwelcome.search=%S to search for sources\n\n# LOCALIZATION NOTE (sourceSearch.search): The center pane Source Search\n# prompt for searching for files.\nsourceSearch.search=Search Sources…\n\n# LOCALIZATION NOTE (sourceSearch.noResults): The center pane Source Search\n# message when the query did not match any of the sources.\nsourceSearch.noResults=No files matching %S found\n\n# LOCALIZATION NOTE (ignoreExceptions): The pause on exceptions button tooltip\n# when the debugger will not pause on exceptions.\nignoreExceptions=Ignore exceptions. Click to pause on uncaught exceptions\n\n# LOCALIZATION NOTE (pauseOnUncaughtExceptions): The pause on exceptions button\n# tooltip when the debugger will pause on uncaught exceptions.\npauseOnUncaughtExceptions=Pause on uncaught exceptions. Click to pause on all exceptions\n\n# LOCALIZATION NOTE (pauseOnExceptions): The pause on exceptions button tooltip\n# when the debugger will pause on all exceptions.\npauseOnExceptions=Pause on all exceptions. Click to ignore exceptions\n\n# LOCALIZATION NOTE (loadingText): The text that is displayed in the script\n# editor when the loading process has started but there is no file to display\n# yet.\nloadingText=Loading\\u2026\n\n# LOCALIZATION NOTE (errorLoadingText2): The text that is displayed in the debugger\n# viewer when there is an error loading a file\nerrorLoadingText2=Error loading this URL: %S\n\n# LOCALIZATION NOTE (addWatchExpressionText): The text that is displayed in the\n# watch expressions list to add a new item.\naddWatchExpressionText=Add watch expression\n\n# LOCALIZATION NOTE (addWatchExpressionButton): The button that is displayed in the\n# variables view popup.\naddWatchExpressionButton=Watch\n\n# LOCALIZATION NOTE (emptyVariablesText): The text that is displayed in the\n# variables pane when there are no variables to display.\nemptyVariablesText=No variables to display\n\n# LOCALIZATION NOTE (scopeLabel): The text that is displayed in the variables\n# pane as a header for each variable scope (e.g. \"Global scope, \"With scope\",\n# etc.).\nscopeLabel=%S scope\n\n# LOCALIZATION NOTE (watchExpressionsScopeLabel): The name of the watch\n# expressions scope. This text is displayed in the variables pane as a header for\n# the watch expressions scope.\nwatchExpressionsScopeLabel=Watch expressions\n\n# LOCALIZATION NOTE (globalScopeLabel): The name of the global scope. This text\n# is added to scopeLabel and displayed in the variables pane as a header for\n# the global scope.\nglobalScopeLabel=Global\n\n# LOCALIZATION NOTE (variablesViewErrorStacktrace): This is the text that is\n# shown before the stack trace in an error.\nvariablesViewErrorStacktrace=Stack trace:\n\n# LOCALIZATION NOTE (variablesViewMoreObjects): the text that is displayed\n# when you have an object preview that does not show all of the elements. At the end of the list\n# you see \"N more...\" in the web console output.\n# This is a semi-colon list of plural forms.\n# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals\n# #1 number of remaining items in the object\n# example: 3 more…\nvariablesViewMoreObjects=#1 more…;#1 more…\n\n# LOCALIZATION NOTE (variablesEditableNameTooltip): The text that is displayed\n# in the variables list on an item with an editable name.\nvariablesEditableNameTooltip=Double click to edit\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in the variables list on an item with an editable value.\nvariablesEditableValueTooltip=Click to change value\n\n# LOCALIZATION NOTE (variablesCloseButtonTooltip): The text that is displayed\n# in the variables list on an item which can be removed.\nvariablesCloseButtonTooltip=Click to remove\n\n# LOCALIZATION NOTE (variablesEditButtonTooltip): The text that is displayed\n# in the variables list on a getter or setter which can be edited.\nvariablesEditButtonTooltip=Click to set value\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in a tooltip on the \"open in inspector\" button in the the variables list for a\n# DOMNode item.\nvariablesDomNodeValueTooltip=Click to select the node in the inspector\n\n# LOCALIZATION NOTE (configurable|...|Tooltip): The text that is displayed\n# in the variables list on certain variables or properties as tooltips.\n# Expanations of what these represent can be found at the following links:\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed\n# It's probably best to keep these in English.\nconfigurableTooltip=configurable\nenumerableTooltip=enumerable\nwritableTooltip=writable\nfrozenTooltip=frozen\nsealedTooltip=sealed\nextensibleTooltip=extensible\noverriddenTooltip=overridden\nWebIDLTooltip=WebIDL\n\n# LOCALIZATION NOTE (variablesSeparatorLabel): The text that is displayed\n# in the variables list as a separator between the name and value.\nvariablesSeparatorLabel=:\n\n# LOCALIZATION NOTE (watchExpressionsSeparatorLabel2): The text that is displayed\n# in the watch expressions list as a separator between the code and evaluation.\nwatchExpressionsSeparatorLabel2=\\u0020→\n\n# LOCALIZATION NOTE (functionSearchSeparatorLabel): The text that is displayed\n# in the functions search panel as a separator between function's inferred name\n# and its real name (if available).\nfunctionSearchSeparatorLabel=←\n\n# LOCALIZATION NOTE(symbolSearch.search.functionsPlaceholder): The placeholder\n# text displayed when the user searches for functions in a file\nsymbolSearch.search.functionsPlaceholder=Search functions…\n\n# LOCALIZATION NOTE(symbolSearch.search.variablesPlaceholder): The placeholder\n# text displayed when the user searches for variables in a file\nsymbolSearch.search.variablesPlaceholder=Search variables…\n\n# LOCALIZATION NOTE(symbolSearch.search.key2): The Key Shortcut for\n# searching for a function or variable\nsymbolSearch.search.key2=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.regex): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.regex=Regex\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.caseSensitive): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.caseSensitive=Case sensitive\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.wholeWord): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.wholeWord=Whole word\n\n# LOCALIZATION NOTE (resumptionOrderPanelTitle): This is the text that appears\n# as a description in the notification panel popup, when multiple debuggers are\n# open in separate tabs and the user tries to resume them in the wrong order.\n# The substitution parameter is the URL of the last paused window that must be\n# resumed first.\nresumptionOrderPanelTitle=There are one or more paused debuggers. Please resume the most-recently paused debugger first at: %S\n\nvariablesViewOptimizedOut=(optimized away)\nvariablesViewUninitialized=(uninitialized)\nvariablesViewMissingArgs=(unavailable)\n\nanonymousSourcesLabel=Anonymous Sources\n\nexperimental=This is an experimental feature\n\n# LOCALIZATION NOTE (whyPaused.debuggerStatement): The text that is displayed\n# in a info block explaining how the debugger is currently paused due to a `debugger`\n# statement in the code\nwhyPaused.debuggerStatement=Paused on debugger statement\n\n# LOCALIZATION NOTE (whyPaused.breakpoint): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a breakpoint\nwhyPaused.breakpoint=Paused on breakpoint\n\n# LOCALIZATION NOTE (whyPaused.exception): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an exception\nwhyPaused.exception=Paused on exception\n\n# LOCALIZATION NOTE (whyPaused.resumeLimit): The text that is displayed\n# in a info block explaining how the debugger is currently paused while stepping\n# in or out of the stack\nwhyPaused.resumeLimit=Paused while stepping\n\n# LOCALIZATION NOTE (whyPaused.pauseOnDOMEvents): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# dom event\nwhyPaused.pauseOnDOMEvents=Paused on event listener\n\n# LOCALIZATION NOTE (whyPaused.breakpointConditionThrown): The text that is displayed\n# in an info block when evaluating a conditional breakpoint throws an error\nwhyPaused.breakpointConditionThrown=Error with conditional breakpoint\n\n# LOCALIZATION NOTE (whyPaused.xhr): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# xml http request\nwhyPaused.xhr=Paused on XMLHttpRequest\n\n# LOCALIZATION NOTE (whyPaused.promiseRejection): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# promise rejection\nwhyPaused.promiseRejection=Paused on promise rejection\n\n# LOCALIZATION NOTE (whyPaused.assert): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# assert\nwhyPaused.assert=Paused on assertion\n\n# LOCALIZATION NOTE (whyPaused.debugCommand): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# debugger statement\nwhyPaused.debugCommand=Paused on debugged function\n\n# LOCALIZATION NOTE (whyPaused.other): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an event\n# listener breakpoint set\nwhyPaused.other=Debugger paused\n\n# LOCALIZATION NOTE (ctrl): The text that is used for documenting\n# keyboard shortcuts that use the control key\nctrl=Ctrl\n"
+	module.exports = "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\n# LOCALIZATION NOTE These strings are used inside the Debugger\n# which is available from the Web Developer sub-menu -> 'Debugger'.\n# The correct localization of this file might be to keep it in\n# English, or another language commonly spoken among web developers.\n# You want to make that choice consistent across the developer tools.\n# A good criteria is the language in which you'd find the best\n# documentation on web development on the web.\n\n# LOCALIZATION NOTE (collapsePanes): This is the tooltip for the button\n# that collapses the left and right panes in the debugger UI.\ncollapsePanes=Collapse panes\n\n# LOCALIZATION NOTE (copySourceUrl): This is the text that appears in the\n# context menu to copy the source URL of file open.\ncopySourceUrl=Copy Source Url\n\n# LOCALIZATION NOTE (copySourceUrl.accesskey): Access key to copy the source URL of a file from\n# the context menu.\ncopySourceUrl.accesskey=u\n\n# LOCALIZATION NOTE (copyStackTrace): This is the text that appears in the\n# context menu to copy the stack trace methods, file names and row number.\ncopyStackTrace=Copy Stack Trace\n\n# LOCALIZATION NOTE (copyStackTrace.accesskey): Access key to copy the stack trace data from\n# the context menu.\ncopyStackTrace.accesskey=c\n\n# LOCALIZATION NOTE (expandPanes): This is the tooltip for the button\n# that expands the left and right panes in the debugger UI.\nexpandPanes=Expand panes\n\n# LOCALIZATION NOTE (pauseButtonTooltip): The tooltip that is displayed for the pause\n# button when the debugger is in a running state.\npauseButtonTooltip=Pause %S\n\n# LOCALIZATION NOTE (pausePendingButtonTooltip): The tooltip that is displayed for\n# the pause button after it's been clicked but before the next JavaScript to run.\npausePendingButtonTooltip=Waiting for next execution\n\n# LOCALIZATION NOTE (resumeButtonTooltip): The label that is displayed on the pause\n# button when the debugger is in a paused state.\nresumeButtonTooltip=Resume %S\n\n# LOCALIZATION NOTE (stepOverTooltip): The label that is displayed on the\n# button that steps over a function call.\nstepOverTooltip=Step Over %S\n\n# LOCALIZATION NOTE (stepInTooltip): The label that is displayed on the\n# button that steps into a function call.\nstepInTooltip=Step In %S\n\n# LOCALIZATION NOTE (stepOutTooltip): The label that is displayed on the\n# button that steps out of a function call.\nstepOutTooltip=Step Out %S\n\n# LOCALIZATION NOTE (noWorkersText): The text to display in the workers list\n# when there are no workers.\nnoWorkersText=This page has no workers.\n\n# LOCALIZATION NOTE (noSourcesText): The text to display in the sources list\n# when there are no sources.\nnoSourcesText=This page has no sources.\n\n# LOCALIZATION NOTE (noEventListenersText): The text to display in the events tab\n# when there are no events.\nnoEventListenersText=No event listeners to display\n\n# LOCALIZATION NOTE (eventListenersHeader): The text to display in the events\n# header.\neventListenersHeader=Event Listeners\n\n# LOCALIZATION NOTE (noStackFramesText): The text to display in the call stack tab\n# when there are no stack frames.\nnoStackFramesText=No stack frames to display\n\n# LOCALIZATION NOTE (eventCheckboxTooltip): The tooltip text to display when\n# the user hovers over the checkbox used to toggle an event breakpoint.\neventCheckboxTooltip=Toggle breaking on this event\n\n# LOCALIZATION NOTE (eventOnSelector): The text to display in the events tab\n# for every event item, between the event type and event selector.\neventOnSelector=on\n\n# LOCALIZATION NOTE (eventInSource): The text to display in the events tab\n# for every event item, between the event selector and listener's owner source.\neventInSource=in\n\n# LOCALIZATION NOTE (eventNodes): The text to display in the events tab when\n# an event is listened on more than one target node.\neventNodes=%S nodes\n\n# LOCALIZATION NOTE (eventNative): The text to display in the events tab when\n# a listener is added from plugins, thus getting translated to native code.\neventNative=[native code]\n\n# LOCALIZATION NOTE (*Events): The text to display in the events tab for\n# each group of sub-level event entries.\nanimationEvents=Animation\naudioEvents=Audio\nbatteryEvents=Battery\nclipboardEvents=Clipboard\ncompositionEvents=Composition\ndeviceEvents=Device\ndisplayEvents=Display\ndragAndDropEvents=Drag and Drop\ngamepadEvents=Gamepad\nindexedDBEvents=IndexedDB\ninteractionEvents=Interaction\nkeyboardEvents=Keyboard\nmediaEvents=HTML5 Media\nmouseEvents=Mouse\nmutationEvents=Mutation\nnavigationEvents=Navigation\npointerLockEvents=Pointer Lock\nsensorEvents=Sensor\nstorageEvents=Storage\ntimeEvents=Time\ntouchEvents=Touch\notherEvents=Other\n\n# LOCALIZATION NOTE (blackboxCheckboxTooltip2): The tooltip text to display when\n# the user hovers over the checkbox used to toggle blackboxing its associated\n# source.\nblackboxCheckboxTooltip2=Toggle blackboxing\n\n# LOCALIZATION NOTE (sources.search.key2): Key shortcut to open the search for\n# searching all the source files the debugger has seen.\nsources.search.key2=CmdOrCtrl+P\n\n# LOCALIZATION NOTE (sources.search.alt.key): A second key shortcut to open the\n# search for searching all the source files the debugger has seen.\nsources.search.alt.key=CmdOrCtrl+O\n\n# LOCALIZATION NOTE (sources.noSourcesAvailable): Text shown when the debugger\n# does not have any sources.\nsources.noSourcesAvailable=This page has no sources\n\n# LOCALIZATION NOTE (sourcesPane.showOutlineTooltip): The text that may appear\n# as a tooltip when hovering over the 'toggle sources' button in\n# left sidebar\nsourcesPane.showSourcesTooltip=Show sources\nsourcesPane.showOutlineTooltip=Show outline\n\n# LOCALIZATION NOTE (sourceSearch.search.key2): Key shortcut to open the search\n# for searching within a the currently opened files in the editor\nsourceSearch.search.key2=CmdOrCtrl+F\n\n# LOCALIZATION NOTE (sourceSearch.search.placeholder): placeholder text in\n# the source search input bar\nsourceSearch.search.placeholder=Search in file…\n\n# LOCALIZATION NOTE (sourceSearch.search.again.key2): Key shortcut to highlight\n# the next occurrence of the last search triggered from a source search\nsourceSearch.search.again.key2=CmdOrCtrl+G\n\n# LOCALIZATION NOTE (sourceSearch.search.againPrev.key2): Key shortcut to highlight\n# the previous occurrence of the last search triggered from a source search\nsourceSearch.search.againPrev.key2=CmdOrCtrl+Shift+G\n\n# LOCALIZATION NOTE (sourceSearch.resultsSummary1): Shows a summary of\n# the number of matches for autocomplete\nsourceSearch.resultsSummary1=%d results\n\n# LOCALIZATION NOTE (noMatchingStringsText): The text to display in the\n# global search results when there are no matching strings after filtering.\nnoMatchingStringsText=No matches found\n\n# LOCALIZATION NOTE (emptySearchText): This is the text that appears in the\n# filter text box when it is empty and the scripts container is selected.\nemptySearchText=Search scripts (%S)\n\n# LOCALIZATION NOTE (emptyVariablesFilterText): This is the text that\n# appears in the filter text box for the variables view container.\nemptyVariablesFilterText=Filter variables\n\n# LOCALIZATION NOTE (emptyPropertiesFilterText): This is the text that\n# appears in the filter text box for the editor's variables view bubble.\nemptyPropertiesFilterText=Filter properties\n\n# LOCALIZATION NOTE (searchPanelFilter): This is the text that appears in the\n# filter panel popup for the filter scripts operation.\nsearchPanelFilter=Filter scripts (%S)\n\n# LOCALIZATION NOTE (searchPanelGlobal): This is the text that appears in the\n# filter panel popup for the global search operation.\nsearchPanelGlobal=Search in all files (%S)\n\n# LOCALIZATION NOTE (searchPanelFunction): This is the text that appears in the\n# filter panel popup for the function search operation.\nsearchPanelFunction=Search for function definition (%S)\n\n# LOCALIZATION NOTE (searchPanelToken): This is the text that appears in the\n# filter panel popup for the token search operation.\nsearchPanelToken=Find in this file (%S)\n\n# LOCALIZATION NOTE (searchPanelGoToLine): This is the text that appears in the\n# filter panel popup for the line search operation.\nsearchPanelGoToLine=Go to line (%S)\n\n# LOCALIZATION NOTE (searchPanelVariable): This is the text that appears in the\n# filter panel popup for the variables search operation.\nsearchPanelVariable=Filter variables (%S)\n\n# LOCALIZATION NOTE (breakpointMenuItem): The text for all the elements that\n# are displayed in the breakpoints menu item popup.\nbreakpointMenuItem.setConditional=Configure conditional breakpoint\nbreakpointMenuItem.enableSelf=Enable breakpoint\nbreakpointMenuItem.disableSelf=Disable breakpoint\nbreakpointMenuItem.deleteSelf=Remove breakpoint\nbreakpointMenuItem.enableOthers=Enable others\nbreakpointMenuItem.disableOthers=Disable others\nbreakpointMenuItem.deleteOthers=Remove others\nbreakpointMenuItem.enableAll=Enable all breakpoints\nbreakpointMenuItem.disableAll=Disable all breakpoints\nbreakpointMenuItem.deleteAll=Remove all breakpoints\n\n# LOCALIZATION NOTE (breakpoints.header): Breakpoints right sidebar pane header.\nbreakpoints.header=Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.none): The text that appears when there are\n# no breakpoints present\nbreakpoints.none=No Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.enable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.enable=Enable Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.disable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.disable=Disable Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.removeBreakpointTooltip): The tooltip that is displayed\n# for remove breakpoint button in right sidebar\nbreakpoints.removeBreakpointTooltip=Remove Breakpoint\n\n# LOCALIZATION NOTE (callStack.header): Call Stack right sidebar pane header.\ncallStack.header=Call Stack\n\n# LOCALIZATION NOTE (callStack.notPaused): Call Stack right sidebar pane\n# message when not paused.\ncallStack.notPaused=Not Paused\n\n# LOCALIZATION NOTE (callStack.collapse): Call Stack right sidebar pane\n# message to hide some of the frames that are shown.\ncallStack.collapse=Collapse Rows\n\n# LOCALIZATION NOTE (callStack.expand): Call Stack right sidebar pane\n# message to show more of the frames.\ncallStack.expand=Expand Rows\n\n# LOCALIZATION NOTE (editor.searchResults): Editor Search bar message\n# for the summarizing the selected search result. e.g. 5 of 10 results.\neditor.searchResults=%d of %d results\n\n# LOCALIZATION NOTE (sourceSearch.singleResult): Copy shown when there is one result.\neditor.singleResult=1 result\n\n# LOCALIZATION NOTE (editor.noResults): Editor Search bar message\n# for when no results found.\neditor.noResults=no results\n\n# LOCALIZATION NOTE (editor.searchResults.nextResult): Editor Search bar\n# tooltip for traversing to the Next Result\neditor.searchResults.nextResult=Next Result\n\n# LOCALIZATION NOTE (editor.searchResults.prevResult): Editor Search bar\n# tooltip for traversing to the Previous Result\neditor.searchResults.prevResult=Previous Result\n\n# LOCALIZATION NOTE (editor.searchTypeToggleTitle): Search bar title for\n# toggling search type buttons(function search, variable search)\neditor.searchTypeToggleTitle=Search for:\n\n# LOCALIZATION NOTE (editor.addBreakpoint): Editor gutter context menu item\n# for adding a breakpoint on a line.\neditor.addBreakpoint=Add Breakpoint\n\n# LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item\n# for disabling a breakpoint on a line.\neditor.disableBreakpoint=Disable Breakpoint\n\n# LOCALIZATION NOTE (editor.enableBreakpoint): Editor gutter context menu item\n# for enabling a breakpoint on a line.\neditor.enableBreakpoint=Enable Breakpoint\n\n# LOCALIZATION NOTE (editor.removeBreakpoint): Editor gutter context menu item\n# for removing a breakpoint on a line.\neditor.removeBreakpoint=Remove Breakpoint\n\n# LOCALIZATION NOTE (editor.editBreakpoint): Editor gutter context menu item\n# for setting a breakpoint condition on a line.\neditor.editBreakpoint=Edit Breakpoint\n\n# LOCALIZATION NOTE (editor.addConditionalBreakpoint): Editor gutter context\n# menu item for adding a breakpoint condition on a line.\neditor.addConditionalBreakpoint=Add Conditional Breakpoint\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Placeholder text for\n# input element inside ConditionalPanel component\neditor.conditionalPanel.placeholder=This breakpoint will pause when the expression is true\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Tooltip text for\n# close button inside ConditionalPanel component\neditor.conditionalPanel.close=Cancel edit breakpoint and close\n\n# LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item\n# for navigating to a source mapped location\neditor.jumpToMappedLocation1=Jump to %S location\n\n# LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the\n# context menu to disable framework grouping.\nframework.disableGrouping=Disable Framework Grouping\n\n# LOCALIZATION NOTE (framework.disableGrouping.accesskey): Access key to toggle\n# framework grouping from the context menu.\nframework.disableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (framework.enableGrouping): This is the text that appears in the\n# context menu to enable framework grouping.\nframework.enableGrouping=Enable Framework Grouping\n\n# LOCALIZATION NOTE (framework.enableGrouping.accesskey): Access key to toggle\n# framework grouping from the context menu.\nframework.enableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (generated): Source Map term for a server source location\ngenerated=generated\n\n# LOCALIZATION NOTE (original): Source Map term for a debugger UI source location\noriginal=original\n\n# LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression\n# input element\nexpressions.placeholder=Add Watch Expression\n\n# LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item\n# for closing the selected tab below the mouse.\nsourceTabs.closeTab=Close tab\n\n# LOCALIZATION NOTE (sourceTabs.closeTab.accesskey): Access key to close the currently select\n# source tab from the editor context menu item.\nsourceTabs.closeTab.accesskey=c\n\n# LOCALIZATION NOTE (sourceTabs.closeOtherTabs): Editor source tab context menu item\n# for closing the other tabs.\nsourceTabs.closeOtherTabs=Close others\n\n# LOCALIZATION NOTE (sourceTabs.closeOtherTabs.accesskey): Access key to close other source tabs\n# from the editor context menu.\nsourceTabs.closeOtherTabs.accesskey=o\n\n# LOCALIZATION NOTE (sourceTabs.closeTabsToEnd): Editor source tab context menu item\n# for closing the tabs to the end (the right for LTR languages) of the selected tab.\nsourceTabs.closeTabsToEnd=Close tabs to the right\n\n# LOCALIZATION NOTE (sourceTabs.closeTabsToEnd.accesskey): Access key to close source tabs\n# after the selected tab from the editor context menu.\nsourceTabs.closeTabsToEnd.accesskey=e\n\n# LOCALIZATION NOTE (sourceTabs.closeAllTabs): Editor source tab context menu item\n# for closing all tabs.\nsourceTabs.closeAllTabs=Close all tabs\n\n# LOCALIZATION NOTE (sourceTabs.closeAllTabs.accesskey): Access key to close all tabs from the\n# editor context menu.\nsourceTabs.closeAllTabs.accesskey=a\n\n# LOCALIZATION NOTE (sourceTabs.revealInTree): Editor source tab context menu item\n# for revealing source in tree.\nsourceTabs.revealInTree=Reveal in Tree\n\n# LOCALIZATION NOTE (sourceTabs.revealInTree.accesskey): Access key to reveal a source in the\n# tree from the context menu.\nsourceTabs.revealInTree.accesskey=r\n\n# LOCALIZATION NOTE (sourceTabs.copyLink): Editor source tab context menu item\n# for copying a link address.\nsourceTabs.copyLink=Copy Link Address\n\n# LOCALIZATION NOTE (sourceTabs.copyLink.accesskey): Access key to copy a link addresss from the\n# editor context menu.\nsourceTabs.copyLink.accesskey=l\n\n# LOCALIZATION NOTE (sourceTabs.prettyPrint): Editor source tab context menu item\n# for pretty printing the source.\nsourceTabs.prettyPrint=Pretty Print Source\n\n# LOCALIZATION NOTE (sourceTabs.prettyPrint.accesskey): Access key to pretty print a source from\n# the editor context menu.\nsourceTabs.prettyPrint.accesskey=p\n\n# LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.blackbox=Blackbox Source\n\n# LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.unblackbox=Unblackbox Source\n\n# LOCALIZATION NOTE (sourceFooter.unblackbox.accesskey): Access key to blackbox\n# an associated source\nsourceFooter.unblackbox.accesskey=b\n\n# LOCALIZATION NOTE (sourceFooter.blackbox.accesskey): Access key to blackbox\n# an associated source\nsourceFooter.blackbox.accesskey=b\n\n# LOCALIZATION NOTE (sourceFooter.blackboxed): Text associated\n# with a blackboxed source\nsourceFooter.blackboxed=Blackboxed Source\n\n# LOCALIZATION NOTE (sourceTabs.closeTabButtonTooltip): The tooltip that is displayed\n# for close tab button in source tabs.\nsourceTabs.closeTabButtonTooltip=Close tab\n\n# LOCALIZATION NOTE (sourceTabs.newTabButtonTooltip): The tooltip that is displayed for\n# new tab button in source tabs.\nsourceTabs.newTabButtonTooltip=Search for sources (%S)\n\n# LOCALIZATION NOTE (scopes.header): Scopes right sidebar pane header.\nscopes.header=Scopes\n\n# LOCALIZATION NOTE (scopes.notAvailable): Scopes right sidebar pane message\n# for when the debugger is paused, but there isn't pause data.\nscopes.notAvailable=Scopes Unavailable\n\n# LOCALIZATION NOTE (scopes.notPaused): Scopes right sidebar pane message\n# for when the debugger is not paused.\nscopes.notPaused=Not Paused\n\n# LOCALIZATION NOTE (scopes.block): Refers to a block of code in\n# the scopes pane when the debugger is paused.\nscopes.block=Block\n\n# LOCALIZATION NOTE (sources.header): Sources left sidebar header\nsources.header=Sources\n\n# LOCALIZATION NOTE (sources.search): Sources left sidebar prompt\n# e.g. Cmd+P to search. On a mac, we use the command unicode character.\n# On windows, it's ctrl.\nsources.search=%S to search\n\n# LOCALIZATION NOTE (watchExpressions.header): Watch Expressions right sidebar\n# pane header.\nwatchExpressions.header=Watch Expressions\n\n# LOCALIZATION NOTE (watchExpressions.refreshButton): Watch Expressions header\n# button for refreshing the expressions.\nwatchExpressions.refreshButton=Refresh\n\n# LOCALIZATION NOTE (welcome.search): The center pane welcome panel's\n# search prompt. e.g. cmd+p to search for files. On windows, it's ctrl, on\n# a mac we use the unicode character.\nwelcome.search=%S to search for sources\n\n# LOCALIZATION NOTE (sourceSearch.search): The center pane Source Search\n# prompt for searching for files.\nsourceSearch.search=Search Sources…\n\n# LOCALIZATION NOTE (sourceSearch.noResults): The center pane Source Search\n# message when the query did not match any of the sources.\nsourceSearch.noResults=No files matching %S found\n\n# LOCALIZATION NOTE (ignoreExceptions): The pause on exceptions button tooltip\n# when the debugger will not pause on exceptions.\nignoreExceptions=Ignore exceptions. Click to pause on uncaught exceptions\n\n# LOCALIZATION NOTE (pauseOnUncaughtExceptions): The pause on exceptions button\n# tooltip when the debugger will pause on uncaught exceptions.\npauseOnUncaughtExceptions=Pause on uncaught exceptions. Click to pause on all exceptions\n\n# LOCALIZATION NOTE (pauseOnExceptions): The pause on exceptions button tooltip\n# when the debugger will pause on all exceptions.\npauseOnExceptions=Pause on all exceptions. Click to ignore exceptions\n\n# LOCALIZATION NOTE (loadingText): The text that is displayed in the script\n# editor when the loading process has started but there is no file to display\n# yet.\nloadingText=Loading\\u2026\n\n# LOCALIZATION NOTE (errorLoadingText2): The text that is displayed in the debugger\n# viewer when there is an error loading a file\nerrorLoadingText2=Error loading this URL: %S\n\n# LOCALIZATION NOTE (addWatchExpressionText): The text that is displayed in the\n# watch expressions list to add a new item.\naddWatchExpressionText=Add watch expression\n\n# LOCALIZATION NOTE (addWatchExpressionButton): The button that is displayed in the\n# variables view popup.\naddWatchExpressionButton=Watch\n\n# LOCALIZATION NOTE (emptyVariablesText): The text that is displayed in the\n# variables pane when there are no variables to display.\nemptyVariablesText=No variables to display\n\n# LOCALIZATION NOTE (scopeLabel): The text that is displayed in the variables\n# pane as a header for each variable scope (e.g. \"Global scope, \"With scope\",\n# etc.).\nscopeLabel=%S scope\n\n# LOCALIZATION NOTE (watchExpressionsScopeLabel): The name of the watch\n# expressions scope. This text is displayed in the variables pane as a header for\n# the watch expressions scope.\nwatchExpressionsScopeLabel=Watch expressions\n\n# LOCALIZATION NOTE (globalScopeLabel): The name of the global scope. This text\n# is added to scopeLabel and displayed in the variables pane as a header for\n# the global scope.\nglobalScopeLabel=Global\n\n# LOCALIZATION NOTE (variablesViewErrorStacktrace): This is the text that is\n# shown before the stack trace in an error.\nvariablesViewErrorStacktrace=Stack trace:\n\n# LOCALIZATION NOTE (variablesViewMoreObjects): the text that is displayed\n# when you have an object preview that does not show all of the elements. At the end of the list\n# you see \"N more...\" in the web console output.\n# This is a semi-colon list of plural forms.\n# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals\n# #1 number of remaining items in the object\n# example: 3 more…\nvariablesViewMoreObjects=#1 more…;#1 more…\n\n# LOCALIZATION NOTE (variablesEditableNameTooltip): The text that is displayed\n# in the variables list on an item with an editable name.\nvariablesEditableNameTooltip=Double click to edit\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in the variables list on an item with an editable value.\nvariablesEditableValueTooltip=Click to change value\n\n# LOCALIZATION NOTE (variablesCloseButtonTooltip): The text that is displayed\n# in the variables list on an item which can be removed.\nvariablesCloseButtonTooltip=Click to remove\n\n# LOCALIZATION NOTE (variablesEditButtonTooltip): The text that is displayed\n# in the variables list on a getter or setter which can be edited.\nvariablesEditButtonTooltip=Click to set value\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in a tooltip on the \"open in inspector\" button in the the variables list for a\n# DOMNode item.\nvariablesDomNodeValueTooltip=Click to select the node in the inspector\n\n# LOCALIZATION NOTE (configurable|...|Tooltip): The text that is displayed\n# in the variables list on certain variables or properties as tooltips.\n# Expanations of what these represent can be found at the following links:\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed\n# It's probably best to keep these in English.\nconfigurableTooltip=configurable\nenumerableTooltip=enumerable\nwritableTooltip=writable\nfrozenTooltip=frozen\nsealedTooltip=sealed\nextensibleTooltip=extensible\noverriddenTooltip=overridden\nWebIDLTooltip=WebIDL\n\n# LOCALIZATION NOTE (variablesSeparatorLabel): The text that is displayed\n# in the variables list as a separator between the name and value.\nvariablesSeparatorLabel=:\n\n# LOCALIZATION NOTE (watchExpressionsSeparatorLabel2): The text that is displayed\n# in the watch expressions list as a separator between the code and evaluation.\nwatchExpressionsSeparatorLabel2=\\u0020→\n\n# LOCALIZATION NOTE (functionSearchSeparatorLabel): The text that is displayed\n# in the functions search panel as a separator between function's inferred name\n# and its real name (if available).\nfunctionSearchSeparatorLabel=←\n\n# LOCALIZATION NOTE(symbolSearch.search.functionsPlaceholder): The placeholder\n# text displayed when the user searches for functions in a file\nsymbolSearch.search.functionsPlaceholder=Search functions…\n\n# LOCALIZATION NOTE(symbolSearch.search.variablesPlaceholder): The placeholder\n# text displayed when the user searches for variables in a file\nsymbolSearch.search.variablesPlaceholder=Search variables…\n\n# LOCALIZATION NOTE(symbolSearch.search.key2): The Key Shortcut for\n# searching for a function or variable\nsymbolSearch.search.key2=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.regex): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.regex=Regex\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.caseSensitive): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.caseSensitive=Case sensitive\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.wholeWord): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.wholeWord=Whole word\n\n# LOCALIZATION NOTE (resumptionOrderPanelTitle): This is the text that appears\n# as a description in the notification panel popup, when multiple debuggers are\n# open in separate tabs and the user tries to resume them in the wrong order.\n# The substitution parameter is the URL of the last paused window that must be\n# resumed first.\nresumptionOrderPanelTitle=There are one or more paused debuggers. Please resume the most-recently paused debugger first at: %S\n\nvariablesViewOptimizedOut=(optimized away)\nvariablesViewUninitialized=(uninitialized)\nvariablesViewMissingArgs=(unavailable)\n\nanonymousSourcesLabel=Anonymous Sources\n\nexperimental=This is an experimental feature\n\n# LOCALIZATION NOTE (whyPaused.debuggerStatement): The text that is displayed\n# in a info block explaining how the debugger is currently paused due to a `debugger`\n# statement in the code\nwhyPaused.debuggerStatement=Paused on debugger statement\n\n# LOCALIZATION NOTE (whyPaused.breakpoint): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a breakpoint\nwhyPaused.breakpoint=Paused on breakpoint\n\n# LOCALIZATION NOTE (whyPaused.exception): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an exception\nwhyPaused.exception=Paused on exception\n\n# LOCALIZATION NOTE (whyPaused.resumeLimit): The text that is displayed\n# in a info block explaining how the debugger is currently paused while stepping\n# in or out of the stack\nwhyPaused.resumeLimit=Paused while stepping\n\n# LOCALIZATION NOTE (whyPaused.pauseOnDOMEvents): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# dom event\nwhyPaused.pauseOnDOMEvents=Paused on event listener\n\n# LOCALIZATION NOTE (whyPaused.breakpointConditionThrown): The text that is displayed\n# in an info block when evaluating a conditional breakpoint throws an error\nwhyPaused.breakpointConditionThrown=Error with conditional breakpoint\n\n# LOCALIZATION NOTE (whyPaused.xhr): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# xml http request\nwhyPaused.xhr=Paused on XMLHttpRequest\n\n# LOCALIZATION NOTE (whyPaused.promiseRejection): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# promise rejection\nwhyPaused.promiseRejection=Paused on promise rejection\n\n# LOCALIZATION NOTE (whyPaused.assert): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# assert\nwhyPaused.assert=Paused on assertion\n\n# LOCALIZATION NOTE (whyPaused.debugCommand): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# debugger statement\nwhyPaused.debugCommand=Paused on debugged function\n\n# LOCALIZATION NOTE (whyPaused.other): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an event\n# listener breakpoint set\nwhyPaused.other=Debugger paused\n\n# LOCALIZATION NOTE (ctrl): The text that is used for documenting\n# keyboard shortcuts that use the control key\nctrl=Ctrl\n"
 
 /***/ },
 /* 961 */,
 /* 962 */,
 /* 963 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var baseKeys = __webpack_require__(217),
@@ -47212,25 +47272,30 @@ return /******/ (function(modules) { // 
 /* 1012 */
 /***/ function(module, exports, __webpack_require__) {
 
 	"use strict";
 
 	Object.defineProperty(exports, "__esModule", {
 	  value: true
 	});
+	exports.getAndProcessFrames = getAndProcessFrames;
 
 	var _react = __webpack_require__(2);
 
 	var _redux = __webpack_require__(3);
 
 	var _reactRedux = __webpack_require__(151);
 
 	var _reselect = __webpack_require__(993);
 
+	var _get = __webpack_require__(67);
+
+	var _get2 = _interopRequireDefault(_get);
+
 	var _Frame = __webpack_require__(1013);
 
 	var _Frame2 = _interopRequireDefault(_Frame);
 
 	var _Group2 = __webpack_require__(1015);
 
 	var _Group3 = _interopRequireDefault(_Group2);
 
@@ -47243,19 +47308,16 @@ return /******/ (function(modules) { // 
 	var _clipboard = __webpack_require__(423);
 
 	var _selectors = __webpack_require__(242);
 
 	__webpack_require__(1018);
 
 	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
-	// NOTE: using require because `import get` breaks atom's syntax highlighting
-	var get = __webpack_require__(67);
-
 	var FrameComponent = (0, _react.createFactory)(_Frame2.default);
 
 	var Group = (0, _react.createFactory)(_Group3.default);
 
 	var NUM_FRAMES_SHOWN = 7;
 
 	class Frames extends _react.Component {
 
@@ -47317,38 +47379,40 @@ return /******/ (function(modules) { // 
 
 	    toggleFrameworkGrouping(!frameworkGroupingOn);
 	  }
 
 	  renderFrames(frames) {
 	    var _props3 = this.props,
 	        selectFrame = _props3.selectFrame,
 	        selectedFrame = _props3.selectedFrame,
+	        toggleBlackBox = _props3.toggleBlackBox,
 	        frameworkGroupingOn = _props3.frameworkGroupingOn;
 
 
 	    var framesOrGroups = this.truncateFrames(this.collapseFrames(frames));
 
 
 	    return _react.DOM.ul({}, framesOrGroups.map(frameOrGroup => frameOrGroup.id ? FrameComponent({
 	      frame: frameOrGroup,
 	      toggleFrameworkGrouping: this.toggleFrameworkGrouping,
 	      copyStackTrace: this.copyStackTrace,
 	      frameworkGroupingOn,
-	      frames,
 	      selectFrame,
 	      selectedFrame,
+	      toggleBlackBox,
 	      key: frameOrGroup.id
 	    }) : Group({
 	      group: frameOrGroup,
 	      toggleFrameworkGrouping: this.toggleFrameworkGrouping,
 	      copyStackTrace: this.copyStackTrace,
 	      frameworkGroupingOn,
 	      selectFrame,
 	      selectedFrame,
+	      toggleBlackBox,
 	      key: frameOrGroup[0].id
 	    })));
 	  }
 
 	  renderToggleButton(frames) {
 	    var buttonMessage = this.state.showAllFrames ? L10N.getStr("callStack.collapse") : L10N.getStr("callStack.expand");
 
 	    frames = (0, _frame.collapseFrames)(frames);
@@ -47371,43 +47435,46 @@ return /******/ (function(modules) { // 
 	  }
 	}
 
 	Frames.propTypes = {
 	  frames: _react.PropTypes.array,
 	  frameworkGroupingOn: _react.PropTypes.bool.isRequired,
 	  toggleFrameworkGrouping: _react.PropTypes.func.isRequired,
 	  selectedFrame: _react.PropTypes.object,
-	  selectFrame: _react.PropTypes.func.isRequired
+	  selectFrame: _react.PropTypes.func.isRequired,
+	  toggleBlackBox: _react.PropTypes.func
 	};
 
 	Frames.displayName = "Frames";
 
 	function getSourceForFrame(sources, frame) {
 	  return (0, _selectors.getSourceInSources)(sources, frame.location.sourceId);
 	}
 
 	function appendSource(sources, frame) {
 	  return Object.assign({}, frame, {
 	    source: getSourceForFrame(sources, frame).toJS()
 	  });
 	}
 
-	var getAndProcessFrames = (0, _reselect.createSelector)(_selectors.getFrames, _selectors.getSources, (frames, sources) => {
+	function getAndProcessFrames(frames, sources) {
 	  if (!frames) {
 	    return null;
 	  }
 
-	  frames = frames.filter(frame => getSourceForFrame(sources, frame)).filter(frame => !get(frame, "source.isBlackBoxed")).map(frame => appendSource(sources, frame)).map(_frame.annotateFrame);
-
-	  return frames;
-	});
+	  var processedFrames = frames.filter(frame => getSourceForFrame(sources, frame)).map(frame => appendSource(sources, frame)).filter(frame => !(0, _get2.default)(frame, "source.isBlackBoxed")).map(_frame.annotateFrame);
+
+	  return processedFrames;
+	}
+
+	var getAndProcessFramesSelector = (0, _reselect.createSelector)(_selectors.getFrames, _selectors.getSources, getAndProcessFrames);
 
 	exports.default = (0, _reactRedux.connect)(state => ({
-	  frames: getAndProcessFrames(state),
+	  frames: getAndProcessFramesSelector(state),
 	  frameworkGroupingOn: (0, _selectors.getFrameworkGroupingState)(state),
 	  selectedFrame: (0, _selectors.getSelectedFrame)(state)
 	}), dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(Frames);
 
 /***/ },
 /* 1013 */
 /***/ function(module, exports, __webpack_require__) {
 
@@ -47457,27 +47524,28 @@ return /******/ (function(modules) { // 
 
 	  var filename = (0, _source.getFilename)(source);
 	  return _react.DOM.div({ className: "location" }, `${filename}: ${location.line}`);
 	}
 
 	class FrameComponent extends _react.Component {
 
 	  constructor() {
-	    super(...arguments);
+	    super();
 	  }
 
 	  onContextMenu(event) {
 	    var _props = this.props,
 	        frame = _props.frame,
 	        copyStackTrace = _props.copyStackTrace,
 	        toggleFrameworkGrouping = _props.toggleFrameworkGrouping,
+	        toggleBlackBox = _props.toggleBlackBox,
 	        frameworkGroupingOn = _props.frameworkGroupingOn;
 
-	    (0, _FrameMenu2.default)(frame, frameworkGroupingOn, { copyStackTrace, toggleFrameworkGrouping }, event);
+	    (0, _FrameMenu2.default)(frame, frameworkGroupingOn, { copyStackTrace, toggleFrameworkGrouping, toggleBlackBox }, event);
 	  }
 
 	  onMouseDown(e, frame, selectedFrame) {
 	    if (e.nativeEvent.which == 3 && selectedFrame.id != frame.id) {
 	      return;
 	    }
 	    this.props.selectFrame(frame);
 	  }
@@ -47582,16 +47650,21 @@ return /******/ (function(modules) { // 
 	  );
 	}
 
 	function isPug(frame) {
 	  return (/node_modules\/pug/.test(getFrameUrl(frame))
 	  );
 	}
 
+	function isExtJs(frame) {
+	  return (/\/ext-all[\.\-]/.test(getFrameUrl(frame))
+	  );
+	}
+
 	function getLibraryFromUrl(frame) {
 	  // @TODO each of these fns calls getFrameUrl, just call it once
 	  // (assuming there's not more complex logic to identify a lib)
 
 	  if (isBackbone(frame)) {
 	    return "Backbone";
 	  }
 
@@ -47613,16 +47686,20 @@ return /******/ (function(modules) { // 
 
 	  if (isExpress(frame)) {
 	    return "Express";
 	  }
 
 	  if (isPug(frame)) {
 	    return "Pug";
 	  }
+
+	  if (isExtJs(frame)) {
+	    return "ExtJS";
+	  }
 	}
 
 	var displayNameMap = {
 	  Backbone: {
 	    "extend/child": "Create Class",
 	    ".create": "Create Model"
 	  },
 	  jQuery: {
@@ -47821,46 +47898,49 @@ return /******/ (function(modules) { // 
 	    self.toggleFrames = this.toggleFrames.bind(this);
 	  }
 
 	  onContextMenu(event) {
 	    var _props = this.props,
 	        group = _props.group,
 	        copyStackTrace = _props.copyStackTrace,
 	        toggleFrameworkGrouping = _props.toggleFrameworkGrouping,
+	        toggleBlackBox = _props.toggleBlackBox,
 	        frameworkGroupingOn = _props.frameworkGroupingOn;
 
 	    var frame = group[0];
-	    (0, _FrameMenu2.default)(frame, frameworkGroupingOn, { copyStackTrace, toggleFrameworkGrouping }, event);
+	    (0, _FrameMenu2.default)(frame, frameworkGroupingOn, { copyStackTrace, toggleFrameworkGrouping, toggleBlackBox }, event);
 	  }
 
 	  toggleFrames() {
 	    this.setState({ expanded: !this.state.expanded });
 	  }
 
 	  renderFrames() {
 	    var _props2 = this.props,
 	        group = _props2.group,
 	        selectFrame = _props2.selectFrame,
 	        selectedFrame = _props2.selectedFrame,
 	        toggleFrameworkGrouping = _props2.toggleFrameworkGrouping,
 	        frameworkGroupingOn = _props2.frameworkGroupingOn,
+	        toggleBlackBox = _props2.toggleBlackBox,
 	        copyStackTrace = _props2.copyStackTrace;
 	    var expanded = this.state.expanded;
 
 	    if (!expanded) {
 	      return null;
 	    }
 	    return _react.DOM.div({ className: "frames-list" }, group.map(frame => FrameComponent({
 	      frame,
 	      copyStackTrace,
 	      toggleFrameworkGrouping,
 	      frameworkGroupingOn,
 	      selectFrame,
 	      selectedFrame,
+	      toggleBlackBox,
 	      key: frame.id,
 	      hideLocation: true,
 	      shouldMapDisplayName: false
 	    })));
 	  }
 
 	  renderDescription() {
 	    var frame = this.props.group[0];
@@ -48200,192 +48280,207 @@ return /******/ (function(modules) { // 
 	  value: true
 	});
 	exports.default = FrameMenu;
 
 	var _devtoolsLaunchpad = __webpack_require__(131);
 
 	var _clipboard = __webpack_require__(423);
 
-	var _kebabCase = __webpack_require__(1034);
-
-	function formatMenuElement(labelString, accesskeyString, click) {
-	  var disabled = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
+	var _lodash = __webpack_require__(1048);
+
+	var _lodash2 = _interopRequireDefault(_lodash);
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+	var blackboxString = "sourceFooter.blackbox";
+
+	var unblackboxString = "sourceFooter.unblackbox";
+
+	function formatMenuElement(labelString, click) {
+	  var disabled = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
 
 	  var label = L10N.getStr(labelString);
-	  var accesskey = L10N.getStr(accesskeyString);
-	  var id = `node-menu-${(0, _kebabCase.kebabCase)(label)}`;
+	  var accesskey = L10N.getStr(`${labelString}.accesskey`);
+	  var id = `node-menu-${(0, _lodash2.default)(label)}`;
 	  return {
 	    id,
 	    label,
 	    accesskey,
 	    disabled,
 	    click
 	  };
 	}
 
-
 	function copySourceElement(url) {
-	  return formatMenuElement("copySourceUrl", "copySourceUrl.accesskey", () => (0, _clipboard.copyToTheClipboard)(url));
+	  return formatMenuElement("copySourceUrl", () => (0, _clipboard.copyToTheClipboard)(url));
 	}
 
 	function copyStackTraceElement(copyStackTrace) {
-	  return formatMenuElement("copyStackTrace", "copyStackTrace.accesskey", () => copyStackTrace());
+	  return formatMenuElement("copyStackTrace", () => copyStackTrace());
 	}
 
 	function toggleFrameworkGroupingElement(toggleFrameworkGrouping, frameworkGroupingOn) {
 	  var actionType = frameworkGroupingOn ? "framework.disableGrouping" : "framework.enableGrouping";
 
-	  return formatMenuElement(actionType, "framework.accesskey", () => toggleFrameworkGrouping());
+	  return formatMenuElement(actionType, () => toggleFrameworkGrouping());
+	}
+
+	function blackBoxSource(source, toggleBlackBox) {
+	  var toggleBlackBoxString = source.isBlackBoxed ? unblackboxString : blackboxString;
+
+	  return formatMenuElement(toggleBlackBoxString, () => toggleBlackBox(source));
 	}
 
 	function FrameMenu(frame, frameworkGroupingOn, callbacks, event) {
 	  event.stopPropagation();
 	  event.preventDefault();
 
 	  var menuOptions = [];
 
 	  var source = frame.source;
 
 	  var toggleFrameworkElement = toggleFrameworkGroupingElement(callbacks.toggleFrameworkGrouping, frameworkGroupingOn);
 	  menuOptions.push(toggleFrameworkElement);
 
 	  if (source) {
 	    var copySourceUrl = copySourceElement(source.url);
 	    menuOptions.push(copySourceUrl);
+	    menuOptions.push(blackBoxSource(source, callbacks.toggleBlackBox));
 	  }
 
 	  var copyStackTraceItem = copyStackTraceElement(callbacks.copyStackTrace);
 
 	  menuOptions.push(copyStackTraceItem);
 
 	  (0, _devtoolsLaunchpad.showMenu)(event, menuOptions);
 	}
 
 /***/ },
 /* 1033 */,
-/* 1034 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var createCompounder = __webpack_require__(1035);
-
-	/**
-	 * Converts `string` to
-	 * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
-	 *
-	 * @static
-	 * @memberOf _
-	 * @since 3.0.0
-	 * @category String
-	 * @param {string} [string=''] The string to convert.
-	 * @returns {string} Returns the kebab cased string.
-	 * @example
-	 *
-	 * _.kebabCase('Foo Bar');
-	 * // => 'foo-bar'
-	 *
-	 * _.kebabCase('fooBar');
-	 * // => 'foo-bar'
-	 *
-	 * _.kebabCase('__FOO_BAR__');
-	 * // => 'foo-bar'
-	 */
-	var kebabCase = createCompounder(function(result, word, index) {
-	  return result + (index ? '-' : '') + word.toLowerCase();
-	});
-
-	module.exports = kebabCase;
-
-
-/***/ },
-/* 1035 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var arrayReduce = __webpack_require__(556),
-	    deburr = __webpack_require__(1036),
-	    words = __webpack_require__(1039);
-
-	/** Used to compose unicode capture groups. */
-	var rsApos = "['\u2019]";
-
-	/** Used to match apostrophes. */
-	var reApos = RegExp(rsApos, 'g');
-
-	/**
-	 * Creates a function like `_.camelCase`.
-	 *
-	 * @private
-	 * @param {Function} callback The function to combine each word.
-	 * @returns {Function} Returns the new compounder function.
-	 */
-	function createCompounder(callback) {
-	  return function(string) {
-	    return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
-	  };
-	}
-
-	module.exports = createCompounder;
-
-
-/***/ },
-/* 1036 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var deburrLetter = __webpack_require__(1037),
-	    toString = __webpack_require__(108);
+/* 1034 */,
+/* 1035 */,
+/* 1036 */,
+/* 1037 */,
+/* 1038 */,
+/* 1039 */,
+/* 1040 */,
+/* 1041 */,
+/* 1042 */,
+/* 1043 */
+/***/ function(module, exports) {
+
+	module.exports = "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" id=\"svg2\" viewBox=\"0 0 34 34\"><defs id=\"defs4\"><linearGradient id=\"linearGradient4275\"><stop id=\"stop4277\" offset=\"0\" style=\"stop-color:#006e00;stop-opacity:1\"></stop><stop style=\"stop-color:#00cc00;stop-opacity:1;\" offset=\"0.55349338\" id=\"stop4283\"></stop><stop id=\"stop4279\" offset=\"1\" style=\"stop-color:#eeff2a;stop-opacity:1\"></stop></linearGradient><linearGradient gradientTransform=\"matrix(0.03267513,0,0,0.03267513,5.555801,1018.6805)\" gradientUnits=\"userSpaceOnUse\" y2=\"275.13159\" x2=\"162.84953\" y1=\"823.703\" x1=\"555.89331\" id=\"linearGradient4281\" xlink:href=\"#linearGradient4275\"></linearGradient></defs><g transform=\"translate(0,-1018.3622)\" id=\"layer1\"><path id=\"path4136\" d=\"m 13.661978,1019.0545 c -9.6447445,1.1926 -10.316754,13.2244 -4.2596149,18.1959 6.0571409,4.9714 13.9697969,9.3171 10.7466029,14.4295 9.372821,-1.0092 10.165143,-10.5469 5.793842,-15.3419 -4.371301,-4.7949 -17.4582341,-10.442 -12.28083,-17.2835 z\" style=\"opacity:1;fill:url(#linearGradient4281);fill-opacity:1;stroke:#000080;stroke-width:0.29986507;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"></path></g></svg>"
+
+/***/ },
+/* 1044 */
+/***/ function(module, exports) {
+
+	module.exports = "<svg viewBox=\"0 0 7 15\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><desc>Created with Sketch.</desc><defs></defs><g id=\"Symbols\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" stroke-linecap=\"square\"><g id=\"sources\" transform=\"translate(-1.000000, 0.000000)\" stroke=\"#DDE1E5\"><g id=\"Group\"><path d=\"M1.5,0.5 L1.5,14.5\" id=\"Line\"></path><path d=\"M4.5,0.5 L4.5,14.5\" id=\"Line\"></path><path d=\"M7.5,0.5 L7.5,14.5\" id=\"Line\"></path></g></g></g></svg>"
+
+/***/ },
+/* 1045 */
+/***/ function(module, exports) {
+
+	module.exports = "<svg viewBox=\"0 0 14 5\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><desc>Created with Sketch.</desc><defs></defs><g id=\"Symbols\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" stroke-linecap=\"square\"><g id=\"outline\" transform=\"translate(0.000000, -2.000000)\" stroke=\"#DDE1E5\"><path d=\"M1.25,2.25 L1.25,2.75\" id=\"Line\" transform=\"translate(1.250000, 2.500000) rotate(90.000000) translate(-1.250000, -2.500000) \"></path><path d=\"M1.25,4.25 L1.25,4.75\" id=\"Line\" transform=\"translate(1.250000, 4.500000) rotate(90.000000) translate(-1.250000, -4.500000) \"></path><path d=\"M8.5,-3.5 L8.5,6.5\" id=\"Line\" transform=\"translate(8.000000, 2.000000) rotate(90.000000) translate(-8.000000, -2.000000) \"></path><path d=\"M8.5,-0.5 L8.5,9.5\" id=\"Line\" transform=\"translate(8.500000, 4.500000) rotate(90.000000) translate(-8.500000, -4.500000) \"></path><path d=\"M1.25,6.25 L1.25,6.75\" id=\"Line\" transform=\"translate(1.250000, 6.500000) rotate(90.000000) translate(-1.250000, -6.500000) \"></path><path d=\"M8.5,1.5 L8.5,11.5\" id=\"Line\" transform=\"translate(8.500000, 6.500000) rotate(90.000000) translate(-8.500000, -6.500000) \"></path></g></g></svg>"
+
+/***/ },
+/* 1046 */
+/***/ function(module, exports) {
+
+	// removed by extract-text-webpack-plugin
+
+/***/ },
+/* 1047 */,
+/* 1048 */
+/***/ function(module, exports) {
+
+	/* WEBPACK VAR INJECTION */(function(global) {/**
+	 * lodash (Custom Build) <https://lodash.com/>
+	 * Build: `lodash modularize exports="npm" -o ./`
+	 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
+	 * Released under MIT license <https://lodash.com/license>
+	 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
+	 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+	 */
+
+	/** Used as references for various `Number` constants. */
+	var INFINITY = 1 / 0;
+
+	/** `Object#toString` result references. */
+	var symbolTag = '[object Symbol]';
+
+	/** Used to match words composed of alphanumeric characters. */
+	var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
 
 	/** Used to match Latin Unicode letters (excluding mathematical operators). */
 	var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
 
 	/** Used to compose unicode character classes. */
-	var rsComboMarksRange = '\\u0300-\\u036f',
-	    reComboHalfMarksRange = '\\ufe20-\\ufe2f',
-	    rsComboSymbolsRange = '\\u20d0-\\u20ff',
-	    rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange;
+	var rsAstralRange = '\\ud800-\\udfff',
+	    rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23',
+	    rsComboSymbolsRange = '\\u20d0-\\u20f0',
+	    rsDingbatRange = '\\u2700-\\u27bf',
+	    rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
+	    rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
+	    rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
+	    rsPunctuationRange = '\\u2000-\\u206f',
+	    rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000',
+	    rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
+	    rsVarRange = '\\ufe0e\\ufe0f',
+	    rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
 
 	/** Used to compose unicode capture groups. */
-	var rsCombo = '[' + rsComboRange + ']';
+	var rsApos = "['\u2019]",
+	    rsBreak = '[' + rsBreakRange + ']',
+	    rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']',
+	    rsDigits = '\\d+',
+	    rsDingbat = '[' + rsDingbatRange + ']',
+	    rsLower = '[' + rsLowerRange + ']',
+	    rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
+	    rsFitz = '\\ud83c[\\udffb-\\udfff]',
+	    rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
+	    rsNonAstral = '[^' + rsAstralRange + ']',
+	    rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
+	    rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
+	    rsUpper = '[' + rsUpperRange + ']',
+	    rsZWJ = '\\u200d';
+
+	/** Used to compose unicode regexes. */
+	var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')',
+	    rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')',
+	    rsOptLowerContr = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
+	    rsOptUpperContr = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
+	    reOptMod = rsModifier + '?',
+	    rsOptVar = '[' + rsVarRange + ']?',
+	    rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
+	    rsSeq = rsOptVar + reOptMod + rsOptJoin,
+	    rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq;
+
+	/** Used to match apostrophes. */
+	var reApos = RegExp(rsApos, 'g');
 
 	/**
 	 * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
 	 * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
 	 */
 	var reComboMark = RegExp(rsCombo, 'g');
 
-	/**
-	 * Deburrs `string` by converting
-	 * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
-	 * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
-	 * letters to basic Latin letters and removing
-	 * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
-	 *
-	 * @static
-	 * @memberOf _
-	 * @since 3.0.0
-	 * @category String
-	 * @param {string} [string=''] The string to deburr.
-	 * @returns {string} Returns the deburred string.
-	 * @example
-	 *
-	 * _.deburr('déjà vu');
-	 * // => 'deja vu'
-	 */
-	function deburr(string) {
-	  string = toString(string);
-	  return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
-	}
-
-	module.exports = deburr;
-
-
-/***/ },
-/* 1037 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var basePropertyOf = __webpack_require__(1038);
+	/** Used to match complex or compound words. */
+	var reUnicodeWord = RegExp([
+	  rsUpper + '?' + rsLower + '+' + rsOptLowerContr + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
+	  rsUpperMisc + '+' + rsOptUpperContr + '(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')',
+	  rsUpper + '?' + rsLowerMisc + '+' + rsOptLowerContr,
+	  rsUpper + '+' + rsOptUpperContr,
+	  rsDigits,
+	  rsEmoji
+	].join('|'), 'g');
+
+	/** Used to detect strings that need a more robust regexp to match words. */
+	var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
 
 	/** Used to map Latin Unicode letters to basic Latin letters. */
 	var deburredLetters = {
 	  // Latin-1 Supplement block.
 	  '\xc0': 'A',  '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
 	  '\xe0': 'a',  '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
 	  '\xc7': 'C',  '\xe7': 'c',
 	  '\xd0': 'D',  '\xf0': 'd',
@@ -48432,60 +48527,281 @@ return /******/ (function(modules) { // 
 	  '\u0168': 'U',  '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U',
 	  '\u0169': 'u',  '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u',
 	  '\u0174': 'W',  '\u0175': 'w',
 	  '\u0176': 'Y',  '\u0177': 'y', '\u0178': 'Y',
 	  '\u0179': 'Z',  '\u017b': 'Z', '\u017d': 'Z',
 	  '\u017a': 'z',  '\u017c': 'z', '\u017e': 'z',
 	  '\u0132': 'IJ', '\u0133': 'ij',
 	  '\u0152': 'Oe', '\u0153': 'oe',
-	  '\u0149': "'n", '\u017f': 's'
-	};
-
-	/**
-	 * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
-	 * letters to basic Latin letters.
-	 *
-	 * @private
-	 * @param {string} letter The matched letter to deburr.
-	 * @returns {string} Returns the deburred letter.
-	 */
-	var deburrLetter = basePropertyOf(deburredLetters);
-
-	module.exports = deburrLetter;
-
-
-/***/ },
-/* 1038 */
-/***/ function(module, exports) {
+	  '\u0149': "'n", '\u017f': 'ss'
+	};
+
+	/** Detect free variable `global` from Node.js. */
+	var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
+
+	/** Detect free variable `self`. */
+	var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
+
+	/** Used as a reference to the global object. */
+	var root = freeGlobal || freeSelf || Function('return this')();
+
+	/**
+	 * A specialized version of `_.reduce` for arrays without support for
+	 * iteratee shorthands.
+	 *
+	 * @private
+	 * @param {Array} [array] The array to iterate over.
+	 * @param {Function} iteratee The function invoked per iteration.
+	 * @param {*} [accumulator] The initial value.
+	 * @param {boolean} [initAccum] Specify using the first element of `array` as
+	 *  the initial value.
+	 * @returns {*} Returns the accumulated value.
+	 */
+	function arrayReduce(array, iteratee, accumulator, initAccum) {
+	  var index = -1,
+	      length = array ? array.length : 0;
+
+	  if (initAccum && length) {
+	    accumulator = array[++index];
+	  }
+	  while (++index < length) {
+	    accumulator = iteratee(accumulator, array[index], index, array);
+	  }
+	  return accumulator;
+	}
+
+	/**
+	 * Splits an ASCII `string` into an array of its words.
+	 *
+	 * @private
+	 * @param {string} The string to inspect.
+	 * @returns {Array} Returns the words of `string`.
+	 */
+	function asciiWords(string) {
+	  return string.match(reAsciiWord) || [];
+	}
 
 	/**
 	 * The base implementation of `_.propertyOf` without support for deep paths.
 	 *
 	 * @private
 	 * @param {Object} object The object to query.
 	 * @returns {Function} Returns the new accessor function.
 	 */
 	function basePropertyOf(object) {
 	  return function(key) {
 	    return object == null ? undefined : object[key];
 	  };
 	}
 
-	module.exports = basePropertyOf;
-
-
-/***/ },
-/* 1039 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var asciiWords = __webpack_require__(1040),
-	    hasUnicodeWord = __webpack_require__(1041),
-	    toString = __webpack_require__(108),
-	    unicodeWords = __webpack_require__(1042);
+	/**
+	 * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
+	 * letters to basic Latin letters.
+	 *
+	 * @private
+	 * @param {string} letter The matched letter to deburr.
+	 * @returns {string} Returns the deburred letter.
+	 */
+	var deburrLetter = basePropertyOf(deburredLetters);
+
+	/**
+	 * Checks if `string` contains a word composed of Unicode symbols.
+	 *
+	 * @private
+	 * @param {string} string The string to inspect.
+	 * @returns {boolean} Returns `true` if a word is found, else `false`.
+	 */
+	function hasUnicodeWord(string) {
+	  return reHasUnicodeWord.test(string);
+	}
+
+	/**
+	 * Splits a Unicode `string` into an array of its words.
+	 *
+	 * @private
+	 * @param {string} The string to inspect.
+	 * @returns {Array} Returns the words of `string`.
+	 */
+	function unicodeWords(string) {
+	  return string.match(reUnicodeWord) || [];
+	}
+
+	/** Used for built-in method references. */
+	var objectProto = Object.prototype;
+
+	/**
+	 * Used to resolve the
+	 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
+	 * of values.
+	 */
+	var objectToString = objectProto.toString;
+
+	/** Built-in value references. */
+	var Symbol = root.Symbol;
+
+	/** Used to convert symbols to primitives and strings. */
+	var symbolProto = Symbol ? Symbol.prototype : undefined,
+	    symbolToString = symbolProto ? symbolProto.toString : undefined;
+
+	/**
+	 * The base implementation of `_.toString` which doesn't convert nullish
+	 * values to empty strings.
+	 *
+	 * @private
+	 * @param {*} value The value to process.
+	 * @returns {string} Returns the string.
+	 */
+	function baseToString(value) {
+	  // Exit early for strings to avoid a performance hit in some environments.
+	  if (typeof value == 'string') {
+	    return value;
+	  }
+	  if (isSymbol(value)) {
+	    return symbolToString ? symbolToString.call(value) : '';
+	  }
+	  var result = (value + '');
+	  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
+	}
+
+	/**
+	 * Creates a function like `_.camelCase`.
+	 *
+	 * @private
+	 * @param {Function} callback The function to combine each word.
+	 * @returns {Function} Returns the new compounder function.
+	 */
+	function createCompounder(callback) {
+	  return function(string) {
+	    return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
+	  };
+	}
+
+	/**
+	 * Checks if `value` is object-like. A value is object-like if it's not `null`
+	 * and has a `typeof` result of "object".
+	 *
+	 * @static
+	 * @memberOf _
+	 * @since 4.0.0
+	 * @category Lang
+	 * @param {*} value The value to check.
+	 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+	 * @example
+	 *
+	 * _.isObjectLike({});
+	 * // => true
+	 *
+	 * _.isObjectLike([1, 2, 3]);
+	 * // => true
+	 *
+	 * _.isObjectLike(_.noop);
+	 * // => false
+	 *
+	 * _.isObjectLike(null);
+	 * // => false
+	 */
+	function isObjectLike(value) {
+	  return !!value && typeof value == 'object';
+	}
+
+	/**
+	 * Checks if `value` is classified as a `Symbol` primitive or object.
+	 *
+	 * @static
+	 * @memberOf _
+	 * @since 4.0.0
+	 * @category Lang
+	 * @param {*} value The value to check.
+	 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
+	 * @example
+	 *
+	 * _.isSymbol(Symbol.iterator);
+	 * // => true
+	 *
+	 * _.isSymbol('abc');
+	 * // => false
+	 */
+	function isSymbol(value) {
+	  return typeof value == 'symbol' ||
+	    (isObjectLike(value) && objectToString.call(value) == symbolTag);
+	}
+
+	/**
+	 * Converts `value` to a string. An empty string is returned for `null`
+	 * and `undefined` values. The sign of `-0` is preserved.
+	 *
+	 * @static
+	 * @memberOf _
+	 * @since 4.0.0
+	 * @category Lang
+	 * @param {*} value The value to process.
+	 * @returns {string} Returns the string.
+	 * @example
+	 *
+	 * _.toString(null);
+	 * // => ''
+	 *
+	 * _.toString(-0);
+	 * // => '-0'
+	 *
+	 * _.toString([1, 2, 3]);
+	 * // => '1,2,3'
+	 */
+	function toString(value) {
+	  return value == null ? '' : baseToString(value);
+	}
+
+	/**
+	 * Deburrs `string` by converting
+	 * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
+	 * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
+	 * letters to basic Latin letters and removing
+	 * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
+	 *
+	 * @static
+	 * @memberOf _
+	 * @since 3.0.0
+	 * @category String
+	 * @param {string} [string=''] The string to deburr.
+	 * @returns {string} Returns the deburred string.
+	 * @example
+	 *
+	 * _.deburr('déjà vu');
+	 * // => 'deja vu'
+	 */
+	function deburr(string) {
+	  string = toString(string);
+	  return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
+	}
+
+	/**
+	 * Converts `string` to
+	 * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
+	 *
+	 * @static
+	 * @memberOf _
+	 * @since 3.0.0
+	 * @category String
+	 * @param {string} [string=''] The string to convert.
+	 * @returns {string} Returns the kebab cased string.
+	 * @example
+	 *
+	 * _.kebabCase('Foo Bar');
+	 * // => 'foo-bar'
+	 *
+	 * _.kebabCase('fooBar');
+	 * // => 'foo-bar'
+	 *
+	 * _.kebabCase('__FOO_BAR__');
+	 * // => 'foo-bar'
+	 */
+	var kebabCase = createCompounder(function(result, word, index) {
+	  return result + (index ? '-' : '') + word.toLowerCase();
+	});
 
 	/**
 	 * Splits `string` into an array of its words.
 	 *
 	 * @static
 	 * @memberOf _
 	 * @since 3.0.0
 	 * @category String
@@ -48506,132 +48822,16 @@ return /******/ (function(modules) { // 
 	  pattern = guard ? undefined : pattern;
 
 	  if (pattern === undefined) {
 	    return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
 	  }
 	  return string.match(pattern) || [];
 	}
 
-	module.exports = words;
-
-
-/***/ },
-/* 1040 */
-/***/ function(module, exports) {
-
-	/** Used to match words composed of alphanumeric characters. */
-	var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
-
-	/**
-	 * Splits an ASCII `string` into an array of its words.
-	 *
-	 * @private
-	 * @param {string} The string to inspect.
-	 * @returns {Array} Returns the words of `string`.
-	 */
-	function asciiWords(string) {
-	  return string.match(reAsciiWord) || [];
-	}
-
-	module.exports = asciiWords;
-
-
-/***/ },
-/* 1041 */
-/***/ function(module, exports) {
-
-	/** Used to detect strings that need a more robust regexp to match words. */
-	var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
-
-	/**
-	 * Checks if `string` contains a word composed of Unicode symbols.
-	 *
-	 * @private
-	 * @param {string} string The string to inspect.
-	 * @returns {boolean} Returns `true` if a word is found, else `false`.
-	 */
-	function hasUnicodeWord(string) {
-	  return reHasUnicodeWord.test(string);
-	}
-
-	module.exports = hasUnicodeWord;
-
-
-/***/ },
-/* 1042 */
-/***/ function(module, exports) {
-
-	/** Used to compose unicode character classes. */
-	var rsAstralRange = '\\ud800-\\udfff',
-	    rsComboMarksRange = '\\u0300-\\u036f',
-	    reComboHalfMarksRange = '\\ufe20-\\ufe2f',
-	    rsComboSymbolsRange = '\\u20d0-\\u20ff',
-	    rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
-	    rsDingbatRange = '\\u2700-\\u27bf',
-	    rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
-	    rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
-	    rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
-	    rsPunctuationRange = '\\u2000-\\u206f',
-	    rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000',
-	    rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
-	    rsVarRange = '\\ufe0e\\ufe0f',
-	    rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
-
-	/** Used to compose unicode capture groups. */
-	var rsApos = "['\u2019]",
-	    rsBreak = '[' + rsBreakRange + ']',
-	    rsCombo = '[' + rsComboRange + ']',
-	    rsDigits = '\\d+',
-	    rsDingbat = '[' + rsDingbatRange + ']',
-	    rsLower = '[' + rsLowerRange + ']',
-	    rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
-	    rsFitz = '\\ud83c[\\udffb-\\udfff]',
-	    rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
-	    rsNonAstral = '[^' + rsAstralRange + ']',
-	    rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
-	    rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
-	    rsUpper = '[' + rsUpperRange + ']',
-	    rsZWJ = '\\u200d';
-
-	/** Used to compose unicode regexes. */
-	var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
-	    rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
-	    rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
-	    rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
-	    reOptMod = rsModifier + '?',
-	    rsOptVar = '[' + rsVarRange + ']?',
-	    rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
-	    rsOrdLower = '\\d*(?:(?:1st|2nd|3rd|(?![123])\\dth)\\b)',
-	    rsOrdUpper = '\\d*(?:(?:1ST|2ND|3RD|(?![123])\\dTH)\\b)',
-	    rsSeq = rsOptVar + reOptMod + rsOptJoin,
-	    rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq;
-
-	/** Used to match complex or compound words. */
-	var reUnicodeWord = RegExp([
-	  rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
-	  rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',
-	  rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,
-	  rsUpper + '+' + rsOptContrUpper,
-	  rsOrdUpper,
-	  rsOrdLower,
-	  rsDigits,
-	  rsEmoji
-	].join('|'), 'g');
-
-	/**
-	 * Splits a Unicode `string` into an array of its words.
-	 *
-	 * @private
-	 * @param {string} The string to inspect.
-	 * @returns {Array} Returns the words of `string`.
-	 */
-	function unicodeWords(string) {
-	  return string.match(reUnicodeWord) || [];
-	}
-
-	module.exports = unicodeWords;
-
+	module.exports = kebabCase;
+
+	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
 
 /***/ }
 /******/ ])
 });
 ;
\ No newline at end of file
--- a/devtools/client/debugger/new/parser-worker.js
+++ b/devtools/client/debugger/new/parser-worker.js
@@ -28925,454 +28925,41 @@ return /******/ (function(modules) { // 
 /* 958 */,
 /* 959 */,
 /* 960 */,
 /* 961 */
 /***/ function(module, exports, __webpack_require__) {
 
 	"use strict";
 
-	var _utils = __webpack_require__(962);
+	var _scopes = __webpack_require__(1049);
+
+	var _getSymbols = __webpack_require__(1050);
+
+	var _getSymbols2 = _interopRequireDefault(_getSymbols);
+
+	var _resolveToken = __webpack_require__(1054);
+
+	var _resolveToken2 = _interopRequireDefault(_resolveToken);
 
 	var _devtoolsUtils = __webpack_require__(900);
 
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
 	var workerHandler = _devtoolsUtils.workerUtils.workerHandler;
 
 
 	self.onmessage = workerHandler({
-	  getSymbols: _utils.getSymbols,
-	  getVariablesInScope: _utils.getVariablesInScope,
-	  resolveToken: _utils.resolveToken
-	});
-
-/***/ },
-/* 962 */
-/***/ function(module, exports, __webpack_require__) {
-
-	"use strict";
-
-	Object.defineProperty(exports, "__esModule", {
-	  value: true
-	});
-
-	var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
-
-	exports.getSymbols = getSymbols;
-	exports.getClosestExpression = getClosestExpression;
-	exports.resolveToken = resolveToken;
-	exports.getClosestScope = getClosestScope;
-	exports.getClosestPath = getClosestPath;
-	exports.getVariablesInLocalScope = getVariablesInLocalScope;
-	exports.getVariablesInScope = getVariablesInScope;
-	exports.isExpressionInScope = isExpressionInScope;
-
-	var _babylon = __webpack_require__(435);
-
-	var babylon = _interopRequireWildcard(_babylon);
-
-	var _babelTraverse = __webpack_require__(436);
-
-	var _babelTraverse2 = _interopRequireDefault(_babelTraverse);
-
-	var _babelTypes = __webpack_require__(493);
-
-	var t = _interopRequireWildcard(_babelTypes);
-
-	var _devtoolsConfig = __webpack_require__(828);
-
-	var _toPairs = __webpack_require__(195);
-
-	var _toPairs2 = _interopRequireDefault(_toPairs);
-
-	var _isEmpty = __webpack_require__(963);
-
-	var _isEmpty2 = _interopRequireDefault(_isEmpty);
-
-	var _uniq = __webpack_require__(561);
-
-	var _uniq2 = _interopRequireDefault(_uniq);
-
-	var _parseScriptTags = __webpack_require__(1023);
-
-	var _parseScriptTags2 = _interopRequireDefault(_parseScriptTags);
-
-	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
-
-	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
-
-	var ASTs = new Map();
-
-	var symbolDeclarations = new Map();
-
-	function _parse(code, opts) {
-	  return babylon.parse(code, Object.assign({}, opts, {
-	    sourceType: "module",
-	    plugins: ["jsx", "flow"]
-	  }));
-	}
-
-	function parse(text, opts) {
-	  var ast = void 0;
-	  if (!text) {
-	    return;
-	  }
-
-	  try {
-	    ast = _parse(text, opts);
-	  } catch (error) {
-	    if ((0, _devtoolsConfig.isDevelopment)()) {
-	      console.warn("parse failed", text);
-	    }
-
-	    ast = {};
-	  }
-
-	  return ast;
-	}
-
-	function getAst(sourceText) {
-	  if (ASTs.has(sourceText.id)) {
-	    return ASTs.get(sourceText.id);
-	  }
-
-	  var ast = {};
-	  if (sourceText.contentType == "text/html") {
-	    // Custom parser for parse-script-tags that adapts its input structure to
-	    // our parser's signature
-	    var parser = (_ref) => {
-	      var source = _ref.source,
-	          line = _ref.line;
-
-	      return parse(source, {
-	        startLine: line
-	      });
-	    };
-	    ast = (0, _parseScriptTags2.default)(sourceText.text, parser) || {};
-	  } else if (sourceText.contentType == "text/javascript") {
-	    ast = parse(sourceText.text);
-	  }
-
-	  ASTs.set(sourceText.id, ast);
-	  return ast;
-	}
-
-	function getNodeValue(node) {
-	  if (t.isThisExpression(node)) {
-	    return "this";
-	  }
-
-	  return node.name;
-	}
-
-	function getFunctionName(path) {
-	  if (path.node.id) {
-	    return path.node.id.name;
-	  }
-
-	  var parent = path.parent;
-	  if (parent.type == "ObjectProperty") {
-	    return parent.key.name;
-	  }
-
-	  if (parent.type == "ObjectExpression" || path.node.type == "ClassMethod") {
-	    return path.node.key.name;
-	  }
-
-	  if (parent.type == "VariableDeclarator") {
-	    return parent.id.name;
-	  }
-
-	  if (parent.type == "AssignmentExpression") {
-	    if (parent.left.type == "MemberExpression") {
-	      return parent.left.property.name;
-	    }
-
-	    return parent.left.name;
-	  }
-
-	  return "anonymous";
-	}
-
-	function isFunction(path) {
-	  return t.isFunction(path) || t.isArrowFunctionExpression(path) || t.isObjectMethod(path) || t.isClassMethod(path);
-	}
-
-	function getVariableNames(path) {
-	  if (t.isObjectProperty(path) && !isFunction(path.node.value)) {
-	    return [{
-	      name: path.node.key.name,
-	      location: path.node.loc
-	    }];
-	  }
-
-	  if (!path.node.declarations) {
-	    return path.node.params.map(dec => ({
-	      name: dec.name,
-	      location: dec.loc
-	    }));
-	  }
-
-	  return path.node.declarations.map(dec => ({
-	    name: dec.id.name,
-	    location: dec.loc
-	  }));
-	}
-
-	function isVariable(path) {
-	  return t.isVariableDeclaration(path) || isFunction(path) && path.node.params.length || t.isObjectProperty(path) && !isFunction(path.node.value);
-	}
-
-	function getMemberExpression(root) {
-	  function _getMemberExpression(node, expr) {
-	    if (t.isMemberExpression(node)) {
-	      expr = [node.property.name].concat(expr);
-	      return _getMemberExpression(node.object, expr);
-	    }
-
-	    if (t.isThisExpression(node)) {
-	      return ["this"].concat(expr);
-	    }
-	    return [node.name].concat(expr);
-	  }
-
-	  return _getMemberExpression(root, []);
-	}
-
-	function getScopeVariables(scope) {
-	  var bindings = scope.bindings;
-
-
-	  return (0, _toPairs2.default)(bindings).map((_ref2) => {
-	    var _ref3 = _slicedToArray(_ref2, 2),
-	        name = _ref3[0],
-	        binding = _ref3[1];
-
-	    return {
-	      name,
-	      references: binding.referencePaths
-	    };
-	  });
-	}
-
-	function getScopeChain(scope) {
-	  var scopes = [scope];
-
-	  do {
-	    scopes.push(scope);
-	  } while (scope = scope.parent);
-
-	  return scopes;
-	}
-
-	/**
-	 * helps find member expressions on one line and function scopes that are
-	 * often many lines
-	 */
-	function nodeContainsLocation(_ref4) {
-	  var node = _ref4.node,
-	      location = _ref4.location;
-	  var _node$loc = node.loc,
-	      start = _node$loc.start,
-	      end = _node$loc.end;
-	  var line = location.line,
-	      column = location.column;
-
-
-	  if (start.line === end.line) {
-	    return start.line === line && start.column <= column && end.column >= column;
-	  }
-
-	  // node is likely a function parameter
-	  if (start.line === line) {
-	    return start.column <= column;
-	  }
-
-	  // node is on the same line as the closing curly
-	  if (end.line === line) {
-	    return end.column >= column;
-	  }
-
-	  // node is either inside the block body or outside of it
-	  return start.line < line && end.line > line;
-	}
-
-	function isLexicalScope(path) {
-	  return t.isBlockStatement(path) || isFunction(path) || t.isProgram(path);
-	}
-
-	function getSymbols(source) {
-	  if (symbolDeclarations.has(source.id)) {
-	    var _symbols = symbolDeclarations.get(source.id);
-	    if (_symbols) {
-	      return _symbols;
-	    }
-	  }
-
-	  var ast = getAst(source);
-
-	  var symbols = { functions: [], variables: [] };
-
-	  if ((0, _isEmpty2.default)(ast)) {
-	    return symbols;
-	  }
-
-	  (0, _babelTraverse2.default)(ast, {
-	    enter(path) {
-	      if (isVariable(path)) {
-	        var _symbols$variables;
-
-	        (_symbols$variables = symbols.variables).push.apply(_symbols$variables, _toConsumableArray(getVariableNames(path)));
-	      }
-
-	      if (isFunction(path)) {
-	        symbols.functions.push({
-	          name: getFunctionName(path),
-	          location: path.node.loc
-	        });
-	      }
-
-	      if (t.isClassDeclaration(path)) {
-	        symbols.variables.push({
-	          name: path.node.id.name,
-	          location: path.node.loc
-	        });
-	      }
-	    }
-	  });
-
-	  symbolDeclarations.set(source.id, symbols);
-	  return symbols;
-	}
-
-	function getClosestMemberExpression(source, token, location) {
-	  var ast = getAst(source);
-	  if ((0, _isEmpty2.default)(ast)) {
-	    return null;
-	  }
-
-	  var expression = null;
-	  (0, _babelTraverse2.default)(ast, {
-	    enter(path) {
-	      var node = path.node;
-
-	      if (t.isMemberExpression(node) && node.property.name === token && nodeContainsLocation({ node, location })) {
-	        var memberExpression = getMemberExpression(node);
-	        expression = {
-	          value: memberExpression.join("."),
-	          location: node.loc
-	        };
-	      }
-	    }
-	  });
-
-	  return expression;
-	}
-
-	function getClosestExpression(source, token, location) {
-	  var memberExpression = getClosestMemberExpression(source, token, location);
-	  if (memberExpression) {
-	    return memberExpression;
-	  }
-
-	  var path = getClosestPath(source, location);
-	  if (!path || !path.node) {
-	    return;
-	  }
-
-	  var node = path.node;
-
-	  return { value: getNodeValue(node), location: node.loc };
-	}
-
-	// Resolves a token (at location) in the source to determine if it is in scope
-	// of the given frame and the expression (if any) to which it belongs
-	function resolveToken(source, token, location, frame) {
-	  var expression = getClosestExpression(source, token, location);
-	  var scope = getClosestScope(source, location);
-
-	  if (!expression || !expression.value || !scope) {
-	    return { expression: null, inScope: false };
-	  }
-
-	  var inScope = isExpressionInScope(expression.value, scope);
-
-	  return {
-	    expression,
-	    inScope
-	  };
-	}
-
-	function getClosestScope(source, location) {
-	  var ast = getAst(source);
-	  if ((0, _isEmpty2.default)(ast)) {
-	    return null;
-	  }
-
-	  var closestPath = null;
-
-	  (0, _babelTraverse2.default)(ast, {
-	    enter(path) {
-	      if (isLexicalScope(path) && nodeContainsLocation({ node: path.node, location })) {
-	        closestPath = path;
-	      }
-	    }
-	  });
-
-	  if (!closestPath) {
-	    return;
-	  }
-
-	  return closestPath.scope;
-	}
-
-	function getClosestPath(source, location) {
-	  var ast = getAst(source);
-	  if ((0, _isEmpty2.default)(ast)) {
-	    return null;
-	  }
-
-	  var closestPath = null;
-
-	  (0, _babelTraverse2.default)(ast, {
-	    enter(path) {
-	      if (nodeContainsLocation({ node: path.node, location })) {
-	        closestPath = path;
-	      }
-	    }
-	  });
-
-	  return closestPath;
-	}
-
-	function getVariablesInLocalScope(scope) {
-	  return getScopeVariables(scope);
-	}
-
-	function getVariablesInScope(scope) {
-	  var _ref5;
-
-	  var scopes = getScopeChain(scope);
-	  var scopeVars = scopes.map(getScopeVariables);
-	  var vars = (_ref5 = [{ name: "this" }, { name: "arguments" }]).concat.apply(_ref5, _toConsumableArray(scopeVars)).map(variable => variable.name);
-	  return (0, _uniq2.default)(vars);
-	}
-
-	function isExpressionInScope(expression, scope) {
-	  if (!scope) {
-	    return false;
-	  }
-
-	  var variables = getVariablesInScope(scope);
-	  var firstPart = expression.split(/\./)[0];
-	  return variables.includes(firstPart);
-	}
-
-/***/ },
+	  getSymbols: _getSymbols2.default,
+	  getVariablesInScope: _scopes.getVariablesInScope,
+	  resolveToken: _resolveToken2.default
+	});
+
+/***/ },
+/* 962 */,
 /* 963 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var baseKeys = __webpack_require__(217),
 	    getTag = __webpack_require__(198),
 	    isArguments = __webpack_require__(208),
 	    isArray = __webpack_require__(70),
 	    isArrayLike = __webpack_require__(220),
@@ -29804,12 +29391,553 @@ return /******/ (function(modules) { // 
 	  }
 	  if (ms < n * 1.5) {
 	    return Math.floor(ms / n) + ' ' + name
 	  }
 	  return Math.ceil(ms / n) + ' ' + name + 's'
 	}
 
 
+/***/ },
+/* 1025 */,
+/* 1026 */,
+/* 1027 */,
+/* 1028 */,
+/* 1029 */,
+/* 1030 */,
+/* 1031 */,
+/* 1032 */,
+/* 1033 */,
+/* 1034 */,
+/* 1035 */,
+/* 1036 */,
+/* 1037 */,
+/* 1038 */,
+/* 1039 */,
+/* 1040 */,
+/* 1041 */,
+/* 1042 */,
+/* 1043 */,
+/* 1044 */,
+/* 1045 */,
+/* 1046 */,
+/* 1047 */,
+/* 1048 */,
+/* 1049 */
+/***/ function(module, exports, __webpack_require__) {
+
+	"use strict";
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+
+	var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
+
+	exports.getVariablesInLocalScope = getVariablesInLocalScope;
+	exports.getVariablesInScope = getVariablesInScope;
+	exports.isExpressionInScope = isExpressionInScope;
+
+	var _toPairs = __webpack_require__(195);
+
+	var _toPairs2 = _interopRequireDefault(_toPairs);
+
+	var _uniq = __webpack_require__(561);
+
+	var _uniq2 = _interopRequireDefault(_uniq);
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+	function getScopeVariables(scope) {
+	  var bindings = scope.bindings;
+
+
+	  return (0, _toPairs2.default)(bindings).map((_ref) => {
+	    var _ref2 = _slicedToArray(_ref, 2),
+	        name = _ref2[0],
+	        binding = _ref2[1];
+
+	    return {
+	      name,
+	      references: binding.referencePaths
+	    };
+	  });
+	}
+
+	function getScopeChain(scope) {
+	  var scopes = [];
+
+	  do {
+	    scopes.push(scope);
+	  } while (scope = scope.parent);
+
+	  return scopes;
+	}
+
+	function getVariablesInLocalScope(scope) {
+	  return getScopeVariables(scope);
+	}
+
+	function getVariablesInScope(scope) {
+	  var _ref3;
+
+	  var scopes = getScopeChain(scope);
+	  var scopeVars = scopes.map(getScopeVariables);
+	  var vars = (_ref3 = [{ name: "this" }, { name: "arguments" }]).concat.apply(_ref3, _toConsumableArray(scopeVars)).map(variable => variable.name);
+	  return (0, _uniq2.default)(vars);
+	}
+
+	function isExpressionInScope(expression, scope) {
+	  if (!scope) {
+	    return false;
+	  }
+
+	  var variables = getVariablesInScope(scope);
+	  var firstPart = expression.split(/\./)[0];
+	  return variables.includes(firstPart);
+	}
+
+/***/ },
+/* 1050 */
+/***/ function(module, exports, __webpack_require__) {
+
+	"use strict";
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	exports.default = getSymbols;
+
+	var _ast = __webpack_require__(1051);
+
+	var _helpers = __webpack_require__(1052);
+
+	var _babelTypes = __webpack_require__(493);
+
+	var t = _interopRequireWildcard(_babelTypes);
+
+	var _getFunctionName = __webpack_require__(1053);
+
+	var _getFunctionName2 = _interopRequireDefault(_getFunctionName);
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+	var symbolDeclarations = new Map();
+
+	function getVariableNames(path) {
+	  if (t.isObjectProperty(path) && !(0, _helpers.isFunction)(path.node.value)) {
+	    return [{
+	      name: path.node.key.name,
+	      location: path.node.loc
+	    }];
+	  }
+
+	  if (!path.node.declarations) {
+	    return path.node.params.map(dec => ({
+	      name: dec.name,
+	      location: dec.loc
+	    }));
+	  }
+
+	  return path.node.declarations.map(dec => ({
+	    name: dec.id.name,
+	    location: dec.loc
+	  }));
+	}
+
+	function getSymbols(source) {
+	  if (symbolDeclarations.has(source.id)) {
+	    var _symbols = symbolDeclarations.get(source.id);
+	    if (_symbols) {
+	      return _symbols;
+	    }
+	  }
+
+	  var symbols = { functions: [], variables: [] };
+
+	  (0, _ast.traverseAst)(source, {
+	    enter(path) {
+	      if ((0, _helpers.isVariable)(path)) {
+	        var _symbols$variables;
+
+	        (_symbols$variables = symbols.variables).push.apply(_symbols$variables, _toConsumableArray(getVariableNames(path)));
+	      }
+
+	      if ((0, _helpers.isFunction)(path)) {
+	        symbols.functions.push({
+	          name: (0, _getFunctionName2.default)(path),
+	          location: path.node.loc
+	        });
+	      }
+
+	      if (t.isClassDeclaration(path)) {
+	        symbols.variables.push({
+	          name: path.node.id.name,
+	          location: path.node.loc
+	        });
+	      }
+	    }
+	  });
+
+	  symbolDeclarations.set(source.id, symbols);
+	  return symbols;
+	}
+
+/***/ },
+/* 1051 */
+/***/ function(module, exports, __webpack_require__) {
+
+	"use strict";
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	exports.getAst = getAst;
+	exports.traverseAst = traverseAst;
+
+	var _parseScriptTags = __webpack_require__(1023);
+
+	var _parseScriptTags2 = _interopRequireDefault(_parseScriptTags);
+
+	var _babylon = __webpack_require__(435);
+
+	var babylon = _interopRequireWildcard(_babylon);
+
+	var _babelTraverse = __webpack_require__(436);
+
+	var _babelTraverse2 = _interopRequireDefault(_babelTraverse);
+
+	var _isEmpty = __webpack_require__(963);
+
+	var _isEmpty2 = _interopRequireDefault(_isEmpty);
+
+	var _devtoolsConfig = __webpack_require__(828);
+
+	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+	var ASTs = new Map();
+
+	function _parse(code, opts) {
+	  return babylon.parse(code, Object.assign({}, opts, {
+	    sourceType: "module",
+	    plugins: ["jsx", "flow"]
+	  }));
+	}
+
+	function parse(text, opts) {
+	  var ast = void 0;
+	  if (!text) {
+	    return;
+	  }
+
+	  try {
+	    ast = _parse(text, opts);
+	  } catch (error) {
+	    if ((0, _devtoolsConfig.isDevelopment)()) {
+	      console.warn("parse failed", text);
+	    }
+
+	    ast = {};
+	  }
+
+	  return ast;
+	}
+
+	function getAst(sourceText) {
+	  if (ASTs.has(sourceText.id)) {
+	    return ASTs.get(sourceText.id);
+	  }
+
+	  var ast = {};
+	  if (sourceText.contentType == "text/html") {
+	    // Custom parser for parse-script-tags that adapts its input structure to
+	    // our parser's signature
+	    var parser = (_ref) => {
+	      var source = _ref.source,
+	          line = _ref.line;
+
+	      return parse(source, {
+	        startLine: line
+	      });
+	    };
+	    ast = (0, _parseScriptTags2.default)(sourceText.text, parser) || {};
+	  } else if (sourceText.contentType == "text/javascript") {
+	    ast = parse(sourceText.text);
+	  }
+
+	  ASTs.set(sourceText.id, ast);
+	  return ast;
+	}
+
+	function traverseAst(sourceText, visitor) {
+	  var ast = getAst(sourceText);
+	  if ((0, _isEmpty2.default)(ast)) {
+	    return null;
+	  }
+
+	  (0, _babelTraverse2.default)(ast, visitor);
+	}
+
+/***/ },
+/* 1052 */
+/***/ function(module, exports, __webpack_require__) {
+
+	"use strict";
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	exports.isLexicalScope = isLexicalScope;
+	exports.isFunction = isFunction;
+	exports.isVariable = isVariable;
+	exports.getMemberExpression = getMemberExpression;
+
+	var _babelTypes = __webpack_require__(493);
+
+	var t = _interopRequireWildcard(_babelTypes);
+
+	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+	function isLexicalScope(path) {
+	  return t.isBlockStatement(path) || isFunction(path) || t.isProgram(path);
+	}
+
+	function isFunction(path) {
+	  return t.isFunction(path) || t.isArrowFunctionExpression(path) || t.isObjectMethod(path) || t.isClassMethod(path);
+	}
+
+	function isVariable(path) {
+	  return t.isVariableDeclaration(path) || isFunction(path) && path.node.params.length || t.isObjectProperty(path) && !isFunction(path.node.value);
+	}
+
+	function getMemberExpression(root) {
+	  function _getMemberExpression(node, expr) {
+	    if (t.isMemberExpression(node)) {
+	      expr = [node.property.name].concat(expr);
+	      return _getMemberExpression(node.object, expr);
+	    }
+
+	    if (t.isThisExpression(node)) {
+	      return ["this"].concat(expr);
+	    }
+	    return [node.name].concat(expr);
+	  }
+
+	  return _getMemberExpression(root, []);
+	}
+
+/***/ },
+/* 1053 */
+/***/ function(module, exports) {
+
+	"use strict";
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	exports.default = getFunctionName;
+	function getFunctionName(path) {
+	  if (path.node.id) {
+	    return path.node.id.name;
+	  }
+
+	  var parent = path.parent;
+	  if (parent.type == "ObjectProperty") {
+	    return parent.key.name;
+	  }
+
+	  if (parent.type == "ObjectExpression" || path.node.type == "ClassMethod") {
+	    return path.node.key.name;
+	  }
+
+	  if (parent.type == "VariableDeclarator") {
+	    return parent.id.name;
+	  }
+
+	  if (parent.type == "AssignmentExpression") {
+	    if (parent.left.type == "MemberExpression") {
+	      return parent.left.property.name;
+	    }
+
+	    return parent.left.name;
+	  }
+
+	  return "anonymous";
+	}
+
+/***/ },
+/* 1054 */
+/***/ function(module, exports, __webpack_require__) {
+
+	"use strict";
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	exports.default = resolveToken;
+
+	var _closest = __webpack_require__(1055);
+
+	var _scopes = __webpack_require__(1049);
+
+	// Resolves a token (at location) in the source to determine if it is in scope
+	// of the given frame and the expression (if any) to which it belongs
+	function resolveToken(source, token, location, frame) {
+	  var expression = (0, _closest.getClosestExpression)(source, token, location);
+	  var scope = (0, _closest.getClosestScope)(source, location);
+
+	  if (!expression || !expression.value || !scope) {
+	    return { expression: null, inScope: false };
+	  }
+
+	  var inScope = (0, _scopes.isExpressionInScope)(expression.value, scope);
+
+	  return {
+	    expression,
+	    inScope
+	  };
+	}
+
+/***/ },
+/* 1055 */
+/***/ function(module, exports, __webpack_require__) {
+
+	"use strict";
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	exports.getClosestExpression = getClosestExpression;
+	exports.getClosestScope = getClosestScope;
+	exports.getClosestPath = getClosestPath;
+
+	var _babelTypes = __webpack_require__(493);
+
+	var t = _interopRequireWildcard(_babelTypes);
+
+	var _ast = __webpack_require__(1051);
+
+	var _helpers = __webpack_require__(1052);
+
+	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+	function getNodeValue(node) {
+	  if (t.isThisExpression(node)) {
+	    return "this";
+	  }
+
+	  return node.name;
+	}
+
+	/**
+	 * helps find member expressions on one line and function scopes that are
+	 * often many lines
+	 */
+
+
+	function nodeContainsLocation(_ref) {
+	  var node = _ref.node,
+	      location = _ref.location;
+	  var _node$loc = node.loc,
+	      start = _node$loc.start,
+	      end = _node$loc.end;
+	  var line = location.line,
+	      column = location.column;
+
+	  // node is a one line expression
+
+	  if (start.line === end.line) {
+	    return start.line === line && start.column <= column && end.column >= column;
+	  }
+
+	  // node is likely a function parameter
+	  if (start.line === line) {
+	    return start.column <= column;
+	  }
+
+	  // node is on the same line as the closing curly
+	  if (end.line === line) {
+	    return end.column >= column;
+	  }
+
+	  // node is either inside the block body or outside of it
+	  return start.line < line && end.line > line;
+	}
+
+	function getClosestMemberExpression(source, token, location) {
+	  var expression = null;
+	  (0, _ast.traverseAst)(source, {
+	    enter(path) {
+	      var node = path.node;
+
+	      if (t.isMemberExpression(node) && node.property.name === token && nodeContainsLocation({ node, location })) {
+	        var memberExpression = (0, _helpers.getMemberExpression)(node);
+	        expression = {
+	          value: memberExpression.join("."),
+	          location: node.loc
+	        };
+	      }
+	    }
+	  });
+
+	  return expression;
+	}
+
+	function getClosestExpression(source, token, location) {
+	  var memberExpression = getClosestMemberExpression(source, token, location);
+	  if (memberExpression) {
+	    return memberExpression;
+	  }
+
+	  var path = getClosestPath(source, location);
+	  if (!path || !path.node) {
+	    return;
+	  }
+
+	  var node = path.node;
+
+	  return { value: getNodeValue(node), location: node.loc };
+	}
+
+	function getClosestScope(source, location) {
+	  var closestPath = null;
+
+	  (0, _ast.traverseAst)(source, {
+	    enter(path) {
+	      if ((0, _helpers.isLexicalScope)(path) && nodeContainsLocation({ node: path.node, location })) {
+	        closestPath = path;
+	      }
+	    }
+	  });
+
+	  if (!closestPath) {
+	    return;
+	  }
+
+	  return closestPath.scope;
+	}
+
+	function getClosestPath(source, location) {
+	  var closestPath = null;
+
+	  (0, _ast.traverseAst)(source, {
+	    enter(path) {
+	      if (nodeContainsLocation({ node: path.node, location })) {
+	        closestPath = path;
+	      }
+	    }
+	  });
+
+	  return closestPath;
+	}
+
 /***/ }
 /******/ ])
 });
 ;
\ No newline at end of file
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print.js
@@ -19,13 +19,13 @@ add_task(function*() {
   yield waitForPaused(dbg);
   assertPausedLocation(dbg, ppSrc, 18);
   yield stepOver(dbg);
   assertPausedLocation(dbg, ppSrc, 27);
   yield resume(dbg);
 
   // The pretty-print button should go away in the pretty-printed
   // source.
-  ok(!findElement(dbg, "sourceFooter"), "Footer is hidden");
+  ok(!findElement(dbg, "editorFooter"), "Footer is hidden");
 
   yield selectSource(dbg, "math.min.js");
-  ok(findElement(dbg, "sourceFooter"), "Footer is hidden");
+  ok(findElement(dbg, "editorFooter"), "Footer is hidden");
 });
--- a/devtools/client/debugger/new/test/mochitest/head.js
+++ b/devtools/client/debugger/new/test/mochitest/head.js
@@ -640,17 +640,18 @@ const selectors = {
   highlightLine: ".CodeMirror-code > .highlight-line",
   codeMirror: ".CodeMirror",
   resume: ".resume.active",
   stepOver: ".stepOver.active",
   stepOut: ".stepOut.active",
   stepIn: ".stepIn.active",
   toggleBreakpoints: ".breakpoints-toggle",
   prettyPrintButton: ".prettyPrint",
-  sourceFooter: ".source-footer",
+  sourcesFooter: ".sources-panel .source-footer",
+  editorFooter: ".editor-pane .source-footer",
   sourceNode: i => `.sources-list .tree-node:nth-child(${i})`,
   sourceNodes: ".sources-list .tree-node",
   sourceArrow: i => `.sources-list .tree-node:nth-child(${i}) .arrow`
 };
 
 function getSelector(elementName, ...args) {
   let selector = selectors[elementName];
   if (!selector) {
--- a/devtools/client/locales/en-US/debugger.properties
+++ b/devtools/client/locales/en-US/debugger.properties
@@ -135,16 +135,24 @@ sources.search.key2=CmdOrCtrl+P
 # LOCALIZATION NOTE (sources.search.alt.key): A second key shortcut to open the
 # search for searching all the source files the debugger has seen.
 sources.search.alt.key=CmdOrCtrl+O
 
 # LOCALIZATION NOTE (sources.noSourcesAvailable): Text shown when the debugger
 # does not have any sources.
 sources.noSourcesAvailable=This page has no sources
 
+# LOCALIZATION NOTE (sourcesPane.showSourcesTooltip): The tooltip shown when
+# the user will navigate to the source tree view.
+sourcesPane.showSourcesTooltip=Show sources
+
+# LOCALIZATION NOTE (sourcesPane.showOutlineTooltip): The tooltip shown when
+# the user will navigate to the source outline view.
+sourcesPane.showOutlineTooltip=Show outline
+
 # LOCALIZATION NOTE (sourceSearch.search.key2): Key shortcut to open the search
 # for searching within a the currently opened files in the editor
 sourceSearch.search.key2=CmdOrCtrl+F
 
 # LOCALIZATION NOTE (sourceSearch.search.placeholder): placeholder text in
 # the source search input bar
 sourceSearch.search.placeholder=Search in file…
 
@@ -305,23 +313,27 @@ editor.conditionalPanel.close=Cancel edi
 # LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item
 # for navigating to a source mapped location
 editor.jumpToMappedLocation1=Jump to %S location
 
 # LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the
 # context menu to disable framework grouping.
 framework.disableGrouping=Disable Framework Grouping
 
+# LOCALIZATION NOTE (framework.disableGrouping.accesskey): Access key to toggle
+# framework grouping from the context menu.
+framework.disableGrouping.accesskey=u
+
 # LOCALIZATION NOTE (framework.enableGrouping): This is the text that appears in the
 # context menu to enable framework grouping.
 framework.enableGrouping=Enable Framework Grouping
 
-# LOCALIZATION NOTE (framework.accesskey): Access key to toggle framework grouping from
-# the context menu.
-framework.accesskey=u
+# LOCALIZATION NOTE (framework.enableGrouping.accesskey): Access key to toggle
+# framework grouping from the context menu.
+framework.enableGrouping.accesskey=u
 
 # LOCALIZATION NOTE (generated): Source Map term for a server source location
 generated=generated
 
 # LOCALIZATION NOTE (original): Source Map term for a debugger UI source location
 original=original
 
 # LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression
@@ -387,16 +399,20 @@ sourceTabs.prettyPrint.accesskey=p
 # LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated
 # with the blackbox button
 sourceFooter.blackbox=Blackbox Source
 
 # LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated
 # with the blackbox button
 sourceFooter.unblackbox=Unblackbox Source
 
+# LOCALIZATION NOTE (sourceFooter.unblackbox.accesskey): Access key to blackbox
+# an associated source
+sourceFooter.unblackbox.accesskey=b
+
 # LOCALIZATION NOTE (sourceFooter.blackbox.accesskey): Access key to blackbox
 # an associated source
 sourceFooter.blackbox.accesskey=b
 
 # LOCALIZATION NOTE (sourceFooter.blackboxed): Text associated
 # with a blackboxed source
 sourceFooter.blackboxed=Blackboxed Source
 
--- a/devtools/client/preferences/debugger.js
+++ b/devtools/client/preferences/debugger.js
@@ -34,8 +34,11 @@ pref("devtools.debugger.ui.framework-gro
 pref("devtools.debugger.call-stack-visible", false);
 pref("devtools.debugger.scopes-visible", false);
 pref("devtools.debugger.start-panel-collapsed", false);
 pref("devtools.debugger.end-panel-collapsed", false);
 pref("devtools.debugger.tabs", "[]");
 pref("devtools.debugger.pending-selected-location", "{}");
 pref("devtools.debugger.pending-breakpoints", "[]");
 pref("devtools.debugger.expressions", "[]");
+pref("devtools.debugger.file-search-case-sensitive", true);
+pref("devtools.debugger.file-search-whole-word", false );
+pref("devtools.debugger.file-search-regex-match", false);
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -896,16 +896,23 @@ GLContext::InitWithPrefixImpl(const char
             mNeedsTextureSizeChecks = true;
         } else if (mVendor == GLVendor::Intel) {
             // Bug 1199923. Driver seems to report a larger max size than
             // actually supported.
             mMaxTextureSize /= 2;
             mMaxRenderbufferSize /= 2;
             mNeedsTextureSizeChecks = true;
         }
+        // Bug 1367570. Explicitly set vertex attributes [1,3] to opaque
+        // black because Nvidia doesn't do it for us.
+        if (mVendor == GLVendor::NVIDIA) {
+            for (size_t i = 1; i <= 3; ++i) {
+                mSymbols.fVertexAttrib4f(i, 0, 0, 0, 1);
+            }
+        }
     }
 #endif
     if (mWorkAroundDriverBugs &&
         Renderer() == GLRenderer::AdrenoTM420) {
         // see bug 1194923. Calling glFlush before glDeleteFramebuffers
         // prevents occasional driver crash.
         mNeedsFlushBeforeDeleteFB = true;
     }
--- a/gfx/skia/skia/src/core/SkScan_AAAPath.cpp
+++ b/gfx/skia/skia/src/core/SkScan_AAAPath.cpp
@@ -1677,17 +1677,17 @@ static SK_ALWAYS_INLINE void aaa_fill_pa
         // If we're using mask, then we have to limit the bound within the path bounds.
         // Otherwise, the edge drift may access an invalid address inside the mask.
         SkIRect ir;
         path.getBounds().roundOut(&ir);
         leftBound = SkTMax(leftBound, SkIntToFixed(ir.fLeft));
         rightBound = SkTMin(rightBound, SkIntToFixed(ir.fRight));
     }
 
-    if (!path.isInverseFillType() && path.isConvex()) {
+    if (!path.isInverseFillType() && path.isConvex() && count >= 2) {
         SkASSERT(count >= 2);   // convex walker does not handle missing right edges
         aaa_walk_convex_edges(&headEdge, blitter, start_y, stop_y,
                               leftBound, rightBound, isUsingMask);
     } else {
         // Only use deferred blitting if there are many edges.
         bool useDeferred = count >
                 (SkFixedFloorToInt(tailEdge.fPrev->fLowerY - headEdge.fNext->fUpperY) + 1) * 4;
 
--- a/gfx/skia/skia/src/core/SkScan_Path.cpp
+++ b/gfx/skia/skia/src/core/SkScan_Path.cpp
@@ -462,17 +462,17 @@ void sk_fill_path(const SkPath& path, co
     PrePostProc     proc = nullptr;
 
     if (path.isInverseFillType()) {
         ib.setBlitter(blitter, clipRect, shiftEdgesUp);
         blitter = &ib;
         proc = PrePostInverseBlitterProc;
     }
 
-    if (path.isConvex() && (nullptr == proc)) {
+    if (path.isConvex() && (nullptr == proc) && count >= 2) {
         SkASSERT(count >= 2);   // convex walker does not handle missing right edges
         walk_convex_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, nullptr);
     } else {
         walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc,
                 shiftedClip.right());
     }
 }
 
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -133,16 +133,18 @@ namespace ipc {
 static const uint32_t kMinTelemetryMessageSize = 4096;
 
 // Note: we round the time we spend to the nearest millisecond. So a min value
 // of 1 ms actually captures from 500us and above.
 static const uint32_t kMinTelemetryIPCWriteLatencyMs = 1;
 
 // Note: we round the time we spend waiting for a response to the nearest
 // millisecond. So a min value of 1 ms actually captures from 500us and above.
+// This is used for both the sending and receiving side telemetry for sync IPC,
+// (IPC_SYNC_MAIN_LATENCY_MS and IPC_SYNC_RECEIVE_MS).
 static const uint32_t kMinTelemetrySyncIPCLatencyMs = 1;
 
 const int32_t MessageChannel::kNoTimeout = INT32_MIN;
 
 // static
 bool MessageChannel::sIsPumpingMessages = false;
 
 enum Direction
@@ -2014,32 +2016,41 @@ MessageChannel::DispatchMessage(Message 
     }
 }
 
 void
 MessageChannel::DispatchSyncMessage(const Message& aMsg, Message*& aReply)
 {
     AssertWorkerThread();
 
+    mozilla::TimeStamp start = TimeStamp::Now();
+
     int nestedLevel = aMsg.nested_level();
 
     MOZ_RELEASE_ASSERT(nestedLevel == IPC::Message::NOT_NESTED || NS_IsMainThread());
 #ifdef MOZ_TASK_TRACER
     AutoScopedLabel autolabel("sync message %s", aMsg.name());
 #endif
 
     MessageChannel* dummy;
     MessageChannel*& blockingVar = mSide == ChildSide && NS_IsMainThread() ? gParentProcessBlocker : dummy;
 
     Result rv;
     {
         AutoSetValue<MessageChannel*> blocked(blockingVar, this);
         rv = mListener->OnMessageReceived(aMsg, aReply);
     }
 
+    uint32_t latencyMs = round((TimeStamp::Now() - start).ToMilliseconds());
+    if (latencyMs >= kMinTelemetrySyncIPCLatencyMs) {
+        Telemetry::Accumulate(Telemetry::IPC_SYNC_RECEIVE_MS,
+                              nsDependentCString(aMsg.name()),
+                              latencyMs);
+    }
+
     if (!MaybeHandleError(rv, aMsg, "DispatchSyncMessage")) {
         aReply = new Message();
         aReply->set_sync();
         aReply->set_nested_level(aMsg.nested_level());
         aReply->set_reply();
         aReply->set_reply_error();
     }
     aReply->set_seqno(aMsg.seqno());
--- a/ipc/glue/MessageLink.cpp
+++ b/ipc/glue/MessageLink.cpp
@@ -278,34 +278,34 @@ ProcessLink::OnChannelOpened()
     AssertIOThread();
 
     {
         MonitorAutoLock lock(*mChan->mMonitor);
 
         mExistingListener = mTransport->set_listener(this);
 #ifdef DEBUG
         if (mExistingListener) {
-            queue<Message> pending;
+            std::queue<Message> pending;
             mExistingListener->GetQueuedMessages(pending);
             MOZ_ASSERT(pending.empty());
         }
 #endif  // DEBUG
 
         mChan->mChannelState = ChannelOpening;
         lock.Notify();
     }
     /*assert*/mTransport->Connect();
 }
 
 void
 ProcessLink::OnTakeConnectedChannel()
 {
     AssertIOThread();
 
-    queue<Message> pending;
+    std::queue<Message> pending;
     {
         MonitorAutoLock lock(*mChan->mMonitor);
 
         mChan->mChannelState = ChannelConnected;
 
         mExistingListener = mTransport->set_listener(this);
         if (mExistingListener) {
             mExistingListener->GetQueuedMessages(pending);
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1008,16 +1008,18 @@ nsFrame::DidSetStyleContext(nsStyleConte
   // bidi algorithm, we need to call |SetBidiEnabled| on the pres
   // context before reflow starts.  See bug 115921.
   if (StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
     PresContext()->SetBidiEnabled();
   }
 
   RemoveStateBits(NS_FRAME_SIMPLE_EVENT_REGIONS |
                   NS_FRAME_SIMPLE_DISPLAYLIST);
+
+  mMayHaveRoundedCorners = true;
 }
 
 void
 nsIFrame::ReparentFrameViewTo(nsViewManager* aViewManager,
                               nsView*        aNewParentView,
                               nsView*        aOldParentView)
 {
   if (HasView()) {
@@ -1582,32 +1584,40 @@ nsIFrame::OutsetBorderRadii(nscoord aRad
     }
   }
 }
 
 /* virtual */ bool
 nsIFrame::GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
                          Sides aSkipSides, nscoord aRadii[8]) const
 {
+  if (!mMayHaveRoundedCorners) {
+    memset(aRadii, 0, sizeof(nscoord) * 8);
+    return false;
+  }
+
   if (IsThemed()) {
     // When we're themed, the native theme code draws the border and
     // background, and therefore it doesn't make sense to tell other
     // code that's interested in border-radius that we have any radii.
     //
     // In an ideal world, we might have a way for the them to tell us an
     // border radius, but since we don't, we're better off assuming
     // zero.
     NS_FOR_CSS_HALF_CORNERS(corner) {
       aRadii[corner] = 0;
     }
     return false;
   }
-  return ComputeBorderRadii(StyleBorder()->mBorderRadius,
-                            aFrameSize, aBorderArea,
-                            aSkipSides, aRadii);
+
+  const_cast<nsIFrame*>(this)->mMayHaveRoundedCorners =
+    ComputeBorderRadii(StyleBorder()->mBorderRadius,
+                       aFrameSize, aBorderArea,
+                       aSkipSides, aRadii);
+  return mMayHaveRoundedCorners;
 }
 
 bool
 nsIFrame::GetBorderRadii(nscoord aRadii[8]) const
 {
   nsSize sz = GetSize();
   return GetBorderRadii(sz, sz, GetSkipSides(), aRadii);
 }
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -611,16 +611,17 @@ public:
     : mRect()
     , mContent(nullptr)
     , mStyleContext(nullptr)
     , mParent(nullptr)
     , mNextSibling(nullptr)
     , mPrevSibling(nullptr)
     , mState(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY)
     , mClass(aID)
+    , mMayHaveRoundedCorners(false)
   {
     mozilla::PodZero(&mOverflow);
   }
 
   nsPresContext* PresContext() const {
     return StyleContext()->PresContext();
   }
 
@@ -3916,16 +3917,19 @@ protected:
   } mOverflow;
 
   /** @see GetWritingMode() */
   mozilla::WritingMode mWritingMode;
 
   /** The ClassID of the concrete class of this instance. */
   ClassID mClass; // 1 byte
 
+  bool mMayHaveRoundedCorners : 1;
+  // There should be a 15-bit gap left here.
+
   // Helpers
   /**
    * Can we stop inside this frame when we're skipping non-rendered whitespace?
    * @param  aForward [in] Are we moving forward (or backward) in content order.
    * @param  aOffset [in/out] At what offset into the frame to start looking.
    *         on output - what offset was reached (whether or not we found a place to stop).
    * @return STOP: An appropriate offset was found within this frame,
    *         and is given by aOffset.
--- a/layout/svg/nsSVGMaskFrame.cpp
+++ b/layout/svg/nsSVGMaskFrame.cpp
@@ -162,40 +162,16 @@ ComputeLinearRGBLuminanceMask(const uint
       sourcePixel += 4;
       destPixel++;
     }
     sourcePixel += sourceOffset;
     destPixel += destOffset;
   }
 }
 
-static void
-ComputeAlphaMask(const uint8_t *aSourceData,
-                 int32_t aSourceStride,
-                 uint8_t *aDestData,
-                 int32_t aDestStride,
-                 const IntSize &aSize,
-                 float aOpacity)
-{
-  int32_t sourceOffset = aSourceStride - 4 * aSize.width;
-  const uint8_t *sourcePixel = aSourceData;
-  int32_t destOffset = aDestStride - aSize.width;
-  uint8_t *destPixel = aDestData;
-
-  for (int32_t y = 0; y < aSize.height; y++) {
-    for (int32_t x = 0; x < aSize.width; x++) {
-      *destPixel = sourcePixel[GFX_ARGB32_OFFSET_A] * aOpacity;
-      sourcePixel += 4;
-      destPixel++;
-    }
-    sourcePixel += sourceOffset;
-    destPixel += destOffset;
-  }
-}
-
 //----------------------------------------------------------------------
 // Implementation
 
 nsIFrame*
 NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsSVGMaskFrame(aContext);
 }
@@ -231,19 +207,32 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(Ma
     nsSVGUtils::ConvertToSurfaceSize(maskSurfaceRect.Size(), &resultOverflows);
 
   if (resultOverflows || maskSurfaceSize.IsEmpty()) {
     // Return value other then DrawResult::SUCCESS, so the caller can skip
     // painting the masked frame(aParams.maskedFrame).
     return nullptr;
   }
 
-  RefPtr<DrawTarget> maskDT =
-    gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
-      maskSurfaceSize, SurfaceFormat::B8G8R8A8);
+  uint8_t maskType;
+  if (aParams.maskMode == NS_STYLE_MASK_MODE_MATCH_SOURCE) {
+    maskType = StyleSVGReset()->mMaskType;
+  } else {
+    maskType = aParams.maskMode == NS_STYLE_MASK_MODE_LUMINANCE
+               ? NS_STYLE_MASK_TYPE_LUMINANCE : NS_STYLE_MASK_TYPE_ALPHA;
+  }
+
+  RefPtr<DrawTarget> maskDT;
+  if (maskType == NS_STYLE_MASK_TYPE_LUMINANCE) {
+    maskDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
+               maskSurfaceSize, SurfaceFormat::B8G8R8A8);
+  } else {
+    maskDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
+               maskSurfaceSize, SurfaceFormat::A8);
+  }
 
   if (!maskDT || !maskDT->IsValid()) {
     return nullptr;
   }
 
   gfxMatrix maskSurfaceMatrix =
     context->CurrentMatrix() * gfxMatrix::Translation(-maskSurfaceRect.TopLeft());
 
@@ -264,73 +253,71 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(Ma
     gfxMatrix m = mMatrixForChildren;
     if (kid->GetContent()->IsSVGElement()) {
       m = static_cast<nsSVGElement*>(kid->GetContent())->
             PrependLocalTransformsTo(m, eUserSpaceToParent);
     }
     nsSVGUtils::PaintFrameWithEffects(kid, *tmpCtx, m, aParams.imgParams);
   }
 
-  RefPtr<SourceSurface> maskSnapshot = maskDT->Snapshot();
-  if (!maskSnapshot) {
-    return nullptr;
-  }
-  RefPtr<DataSourceSurface> maskSurface = maskSnapshot->GetDataSurface();
-  DataSourceSurface::MappedSurface map;
-  if (!maskSurface ||
-      !maskSurface->Map(DataSourceSurface::MapType::READ, &map)) {
-    return nullptr;
-  }
+  RefPtr<SourceSurface> surface;
+  if (maskType == NS_STYLE_MASK_TYPE_LUMINANCE) {
+    RefPtr<SourceSurface> maskSnapshot = maskDT->Snapshot();
+    if (!maskSnapshot) {
+      return nullptr;
+    }
 
-  // Create alpha channel mask for output
-  RefPtr<DataSourceSurface> destMaskSurface =
-    Factory::CreateDataSourceSurface(maskSurfaceSize, SurfaceFormat::A8);
-  if (!destMaskSurface) {
-    return nullptr;
-  }
-  DataSourceSurface::MappedSurface destMap;
-  if (!destMaskSurface->Map(DataSourceSurface::MapType::WRITE, &destMap)) {
-    return nullptr;
-  }
+    RefPtr<DataSourceSurface> maskSurface = maskSnapshot->GetDataSurface();
+    DataSourceSurface::MappedSurface map;
+    if (!maskSurface->Map(DataSourceSurface::MapType::READ, &map)) {
+      return nullptr;
+    }
 
-  uint8_t maskType;
-  if (aParams.maskMode == NS_STYLE_MASK_MODE_MATCH_SOURCE) {
-    maskType = StyleSVGReset()->mMaskType;
-  } else {
-    maskType = aParams.maskMode == NS_STYLE_MASK_MODE_LUMINANCE
-               ? NS_STYLE_MASK_TYPE_LUMINANCE : NS_STYLE_MASK_TYPE_ALPHA;
-  }
+    // Create alpha channel mask for output
+    RefPtr<DataSourceSurface> destMaskSurface =
+      Factory::CreateDataSourceSurface(maskSurfaceSize, SurfaceFormat::A8);
+    if (!destMaskSurface) {
+      return nullptr;
+    }
+    DataSourceSurface::MappedSurface destMap;
+    if (!destMaskSurface->Map(DataSourceSurface::MapType::WRITE, &destMap)) {
+      return nullptr;
+    }
 
-  if (maskType == NS_STYLE_MASK_TYPE_LUMINANCE) {
     if (StyleSVG()->mColorInterpolation ==
         NS_STYLE_COLOR_INTERPOLATION_LINEARRGB) {
       ComputeLinearRGBLuminanceMask(map.mData, map.mStride,
                                     destMap.mData, destMap.mStride,
                                     maskSurfaceSize, aParams.opacity);
     } else {
       ComputesRGBLuminanceMask(map.mData, map.mStride,
                                destMap.mData, destMap.mStride,
                                maskSurfaceSize, aParams.opacity);
     }
+
+    maskSurface->Unmap();
+    destMaskSurface->Unmap();
+    surface = destMaskSurface.forget();
   } else {
-    ComputeAlphaMask(map.mData, map.mStride,
-                     destMap.mData, destMap.mStride,
-                     maskSurfaceSize, aParams.opacity);
+    maskDT->SetTransform(Matrix());
+    maskDT->FillRect(Rect(0, 0, maskSurfaceSize.width, maskSurfaceSize.height), ColorPattern(Color(1.0f, 1.0f, 1.0f, aParams.opacity)), DrawOptions(1, CompositionOp::OP_IN));
+    RefPtr<SourceSurface> maskSnapshot = maskDT->Snapshot();
+    if (!maskSnapshot) {
+      return nullptr;
+    }
+    surface = maskSnapshot.forget();
   }
 
-  maskSurface->Unmap();
-  destMaskSurface->Unmap();
-
   // Moz2D transforms in the opposite direction to Thebes
   if (!maskSurfaceMatrix.Invert()) {
     return nullptr;
   }
 
   *aParams.maskTransform = ToMatrix(maskSurfaceMatrix);
-  return destMaskSurface.forget();
+  return surface.forget();
 }
 
 gfxRect
 nsSVGMaskFrame::GetMaskArea(nsIFrame* aMaskedFrame)
 {
   SVGMaskElement *maskElem = static_cast<SVGMaskElement*>(mContent);
 
   uint16_t units =
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -1240,18 +1240,18 @@ nsHttpHandler::PrefsChanged(nsIPrefBranc
     }
 
     if (PREF_CHANGED(HTTP_PREF("referer.spoofSource"))) {
         rv = prefs->GetBoolPref(HTTP_PREF("referer.spoofSource"), &cVar);
         if (NS_SUCCEEDED(rv))
             mSpoofReferrerSource = cVar;
     }
 
-    if (PREF_CHANGED(HTTP_PREF("referer.spoofOnionSource"))) {
-        rv = prefs->GetBoolPref(HTTP_PREF("referer.spoofOnionSource"), &cVar);
+    if (PREF_CHANGED(HTTP_PREF("referer.hideOnionSource"))) {
+        rv = prefs->GetBoolPref(HTTP_PREF("referer.hideOnionSource"), &cVar);
         if (NS_SUCCEEDED(rv))
             mHideOnionReferrerSource = cVar;
     }
 
     if (PREF_CHANGED(HTTP_PREF("referer.trimmingPolicy"))) {
         rv = prefs->GetIntPref(HTTP_PREF("referer.trimmingPolicy"), &val);
         if (NS_SUCCEEDED(rv))
             mReferrerTrimmingPolicy = (uint8_t) clamped(val, 0, 2);
--- a/python/mozboot/mozboot/base.py
+++ b/python/mozboot/mozboot/base.py
@@ -259,70 +259,42 @@ class BaseBootstrapper(object):
 
         Firefox for Android Artifact Mode needs an application and an ABI set,
         and it needs paths to the Android SDK.
         '''
         raise NotImplementedError(
             '%s does not yet implement suggest_mobile_android_artifact_mode_mozconfig()'
             % __name__)
 
-    def ensure_stylo_packages(self, state_dir):
+    def ensure_stylo_packages(self, state_dir, checkout_root):
         '''
         Install any necessary packages needed for Stylo development.
         '''
         raise NotImplementedError(
             '%s does not yet implement ensure_stylo_packages()'
             % __name__)
 
-    def install_tooltool_clang_package(self, state_dir,
-                                       package_filename, package_sha512sum):
-        TOOLTOOL_API = 'https://api.pub.build.mozilla.org/tooltool/sha512/'
+    def install_tooltool_clang_package(self, state_dir, checkout_root, manifest_file):
+        abs_manifest_file = os.path.join(checkout_root, manifest_file)
 
-        # XXX this is similar to the Android NDK download.  We should unify them.
-        download_path = os.path.join(state_dir, 'mozboot')
-        try:
-            os.makedirs(download_path)
-        except OSError as e:
-            if e.errno == errno.EEXIST and os.path.isdir(download_path):
-                pass
-            else:
-                raise
-
-        try:
-            package_url = TOOLTOOL_API + package_sha512sum
-            downloaded_filename = os.path.join(download_path, package_sha512sum)
-            print('Downloading clang package from', package_url)
-            self.http_download_and_save(package_url, downloaded_filename,
-                                        package_sha512sum, 'sha512')
+        mach_binary = os.path.join(checkout_root, 'mach')
+        if not os.path.exists(mach_binary):
+            raise ValueError("mach not found at %s" % mach_binary)
 
-            # We don't have to handle a great variety of archive types here.
-            if package_filename.endswith('tar.gz'):
-                cmd = ['tar', 'zxf', downloaded_filename]
-            elif package_filename.endswith('.tar.bz2'):
-                cmd = ['tar', 'jxf', downloaded_filename]
-            elif package_filename.endswith('.tar.xz'):
-                cmd = ['tar', 'Jxf', downloaded_filename]
-            else:
-                raise NotImplementedError("Don't know how to unpack file: %s"
-                                          % package_filename)
+        # If Python can't figure out what its own executable is, there's little
+        # chance we're going to be able to execute mach on its own, particularly
+        # on Windows.
+        if not sys.executable:
+            raise ValueError("cannot determine path to Python executable")
 
-            print('Download complete!')
-            print('Unpacking %s...' % downloaded_filename)
-
-            with open(os.devnull, 'w') as stdout:
-                subprocess.check_call(cmd, stdout=stdout, cwd=state_dir)
+        cmd = [sys.executable, mach_binary, 'artifact', 'toolchain',
+               '--tooltool-manifest', abs_manifest_file,
+               'clang']
 
-            print('Unpacking %s...DONE' % downloaded_filename)
-
-        finally:
-            try:
-                os.remove(downloaded_filename)
-            except OSError as e:
-                if e.errno != errno.ENOENT:
-                    raise
+        subprocess.check_call(cmd, cwd=state_dir)
 
     def which(self, name):
         """Python implementation of which.
 
         It returns the path of an executable or None if it couldn't be found.
         """
         for path in os.environ['PATH'].split(os.pathsep):
             test = os.path.join(path, name)
--- a/python/mozboot/mozboot/bootstrap.py
+++ b/python/mozboot/mozboot/bootstrap.py
@@ -108,16 +108,22 @@ STYLO_DIRECTORY_MESSAGE = '''
 Stylo packages require a directory to store shared, persistent state.
 On this machine, that directory is:
 
   {statedir}
 
 Please restart bootstrap and create that directory when prompted.
 '''
 
+STYLO_REQUIRES_CLONE = '''
+Installing Stylo packages requires a checkout of mozilla-central. Once you
+have such a checkout, please re-run `./mach bootstrap` from the checkout
+directory.
+'''
+
 FINISHED = '''
 Your system should be ready to build %s!
 '''
 
 SOURCE_ADVERTISE = '''
 Source code can be obtained by running
 
     hg clone https://hg.mozilla.org/mozilla-unified
@@ -267,40 +273,19 @@ class Bootstrapper(object):
                     high=2)
 
                 if choice == 1:
                     print('Creating global state directory: %s' % state_dir)
                     os.makedirs(state_dir, mode=0o770)
 
         state_dir_available = os.path.exists(state_dir)
 
-        # Install the clang packages needed for developing stylo.
-        if not self.instance.no_interactive:
-            choice = self.instance.prompt_int(
-                prompt=STYLO_DEVELOPMENT_INFO,
-                low=1,
-                high=2)
-
-            # The best place to install our packages is in the state directory
-            # we have.  If the user doesn't have one, we need them to re-run
-            # bootstrap and create the directory.
-            #
-            # XXX Android bootstrap just assumes the existence of the state
-            # directory and writes the NDK into it.  Should we do the same?
-            if choice == 1:
-                if not state_dir_available:
-                    print(STYLO_DIRECTORY_MESSAGE.format(statedir=state_dir))
-                    sys.exit(1)
-
-                self.instance.stylo = True
-                self.instance.state_dir = state_dir
-                self.instance.ensure_stylo_packages(state_dir)
-
-        checkout_type = current_firefox_checkout(check_output=self.instance.check_output,
-                                                 hg=self.instance.which('hg'))
+        r = current_firefox_checkout(check_output=self.instance.check_output,
+                                     hg=self.instance.which('hg'))
+        (checkout_type, checkout_root) = r
 
         # Possibly configure Mercurial, but not if the current checkout is Git.
         # TODO offer to configure Git.
         if hg_installed and state_dir_available and checkout_type != 'git':
             configure_hg = False
             if not self.instance.no_interactive:
                 choice = self.instance.prompt_int(prompt=CONFIGURE_MERCURIAL,
                                                   low=1, high=2)
@@ -318,20 +303,47 @@ class Bootstrapper(object):
         if checkout_type:
             have_clone = True
         elif hg_installed and not self.instance.no_interactive:
             dest = raw_input(CLONE_MERCURIAL)
             dest = dest.strip()
             if dest:
                 dest = os.path.expanduser(dest)
                 have_clone = clone_firefox(self.instance.which('hg'), dest)
+                checkout_root = dest
 
         if not have_clone:
             print(SOURCE_ADVERTISE)
 
+        # Install the clang packages needed for developing stylo.
+        if not self.instance.no_interactive:
+            choice = self.instance.prompt_int(
+                prompt=STYLO_DEVELOPMENT_INFO,
+                low=1,
+                high=2)
+
+            # The best place to install our packages is in the state directory
+            # we have.  If the user doesn't have one, we need them to re-run
+            # bootstrap and create the directory.
+            #
+            # XXX Android bootstrap just assumes the existence of the state
+            # directory and writes the NDK into it.  Should we do the same?
+            wants_stylo = choice == 1
+            if wants_stylo and not state_dir_available:
+                print(STYLO_DIRECTORY_MESSAGE.format(statedir=state_dir))
+                sys.exit(1)
+
+            if wants_stylo and not have_clone:
+                print(STYLO_REQUIRES_CLONE)
+                sys.exit(1)
+
+            self.instance.stylo = True
+            self.instance.state_dir = state_dir
+            self.instance.ensure_stylo_packages(state_dir, checkout_root)
+
         print(self.finished % name)
         if not (self.instance.which('rustc') and self.instance._parse_version('rustc') >= MODERN_RUST_VERSION):
             print("To build %s, please restart the shell (Start a new terminal window)" % name)
 
         # Like 'suggest_browser_mozconfig' or 'suggest_mobile_android_mozconfig'.
         getattr(self.instance, 'suggest_%s_mozconfig' % application)()
 
 
@@ -461,24 +473,24 @@ def current_firefox_checkout(check_outpu
     while path:
         hg_dir = os.path.join(path, '.hg')
         git_dir = os.path.join(path, '.git')
         if hg and os.path.exists(hg_dir):
             # Verify the hg repo is a Firefox repo by looking at rev 0.
             try:
                 node = check_output([hg, 'log', '-r', '0', '--template', '{node}'], cwd=path)
                 if node in HG_ROOT_REVISIONS:
-                    return 'hg'
+                    return ('hg', path)
                 # Else the root revision is different. There could be nested
                 # repos. So keep traversing the parents.
             except subprocess.CalledProcessError:
                 pass
 
         # TODO check git remotes or `git rev-parse -q --verify $sha1^{commit}`
         # for signs of Firefox.
         elif os.path.exists(git_dir):
-            return 'git'
+            return ('git', path)
 
         path, child = os.path.split(path)
         if child == '':
             break
 
-    return None
+    return (None, None)
--- a/python/mozboot/mozboot/freebsd.py
+++ b/python/mozboot/mozboot/freebsd.py
@@ -65,17 +65,17 @@ class FreeBSDBootstrapper(BaseBootstrapp
 
     def install_browser_artifact_mode_packages(self):
         self.ensure_browser_packages(artifact_mode=True)
 
     def ensure_browser_packages(self, artifact_mode=False):
         # TODO: Figure out what not to install for artifact mode
         self.pkg_install(*self.browser_packages)
 
-    def ensure_stylo_packages(self, state_dir):
+    def ensure_stylo_packages(self, state_dir, checkout_root):
         self.pkg_install('llvm40')
 
     def suggest_browser_mozconfig(self):
         if self.stylo:
             print(STYLO_MOZCONFIG)
 
     def upgrade_mercurial(self, current):
         self.pkg_install('mercurial')
--- a/python/mozboot/mozboot/linux_common.py
+++ b/python/mozboot/mozboot/linux_common.py
@@ -4,11 +4,11 @@
 
 # An easy way for distribution-specific bootstrappers to share the code
 # needed to install Stylo dependencies.  This class must come before
 # BaseBootstrapper in the inheritance list.
 class StyloInstall(object):
     def __init__(self, **kwargs):
         pass
 
-    def ensure_stylo_packages(self, state_dir):
+    def ensure_stylo_packages(self, state_dir, checkout_root):
         import stylo
-        self.install_tooltool_clang_package(state_dir, **stylo.LINUX)
+        self.install_tooltool_clang_package(state_dir, checkout_root, stylo.LINUX)
--- a/python/mozboot/mozboot/mozillabuild.py
+++ b/python/mozboot/mozboot/mozillabuild.py
@@ -12,18 +12,18 @@ from mozboot.base import BaseBootstrappe
 
 STYLO_MOZCONFIG = '''
 To enable Stylo in your builds, paste the lines between the chevrons
 (>>> and <<<) into your mozconfig file:
 
 <<<
 ac_add_options --enable-stylo
 
-ac_add_options --with-libclang-path={state_dir}/clang/lib
-ac_add_options --with-clang-path={state_dir}/clang/bin/clang.exe
+ac_add_options --with-libclang-path="{state_dir}/clang/bin"
+ac_add_options --with-clang-path="{state_dir}/clang/bin/clang.exe"
 >>>
 '''
 
 class MozillaBuildBootstrapper(BaseBootstrapper):
     '''Bootstrapper for MozillaBuild to install rustup.'''
     def __init__(self, no_interactive=False):
         BaseBootstrapper.__init__(self, no_interactive=no_interactive)
         print("mach bootstrap is not fully implemented in MozillaBuild")
@@ -84,19 +84,19 @@ class MozillaBuildBootstrapper(BaseBoots
 
     def install_mobile_android_artifact_mode_packages(self):
         pass
 
     def suggest_browser_mozconfig(self):
         if self.stylo:
             print(STYLO_MOZCONFIG.format(state_dir=self.state_dir))
 
-    def ensure_stylo_packages(self, state_dir):
+    def ensure_stylo_packages(self, state_dir, checkout_root):
         import stylo
-        self.install_tooltool_clang_package(state_dir, **stylo.WINDOWS)
+        self.install_tooltool_clang_package(state_dir, checkout_root, stylo.WINDOWS)
 
     def _update_package_manager(self):
         pass
 
     def run(self, command):
         subprocess.check_call(command, stdin=sys.stdin)
 
     def pip_install(self, *packages):
--- a/python/mozboot/mozboot/osx.py
+++ b/python/mozboot/mozboot/osx.py
@@ -516,19 +516,19 @@ class OSXBootstrapper(BaseBootstrapper):
 
             for check in ('/bin', '/usr/bin'):
                 if path == check:
                     print(BAD_PATH_ORDER % (check, p_dir, p_dir, check, p_dir))
                     sys.exit(1)
 
         return active_name.lower()
 
-    def ensure_stylo_packages(self, state_dir):
+    def ensure_stylo_packages(self, state_dir, checkout_root):
         import stylo
-        self.install_tooltool_clang_package(state_dir, **stylo.OSX)
+        self.install_tooltool_clang_package(state_dir, checkout_root, stylo.OSX)
 
     def install_homebrew(self):
         print(PACKAGE_MANAGER_INSTALL % ('Homebrew', 'Homebrew', 'Homebrew', 'brew'))
         bootstrap = urlopen(url=HOMEBREW_BOOTSTRAP, timeout=20).read()
         with tempfile.NamedTemporaryFile() as tf:
             tf.write(bootstrap)
             tf.flush()
 
--- a/python/mozboot/mozboot/stylo.py
+++ b/python/mozboot/mozboot/stylo.py
@@ -1,70 +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/.
 
 from __future__ import print_function, unicode_literals
 
-# Tooltool packages generated from the script below.
-WINDOWS = {
-    'package_filename': 'clang.tar.bz2',
-    'package_sha512sum': 'cd3ed31acefd185f441632158dde73538c62bab7ebf2a8ec630985ab345938ec522983721ddb1bead1de22d5ac1571d50a958ae002364d739f2a78c6e7244222',
-}
-
-OSX = {
-    'package_filename': 'clang.tar.bz2',
-    'package_sha512sum': '0e1a556b65d6398fa812b9ceb5ce5e2dec3eda77d4a032a818182b34fc8ce602412f42388bb1fda6bea265d35c1dde3847a730b264fec01cd7e3dcfd39941660',
-}
-
-LINUX = {
-    'package_filename': 'clang.tar.xz',
-    'package_sha512sum': '52f3fc23f0f5c98050f8b0ac7c92a6752d067582a16f712a5a58074be98975d594f9e36249fc2be7f1cc2ca6d509c663faaf2bea66f949243cc1f41651638ba6',
-}
-
-if __name__ == '__main__':
-    '''Allow invoking the module as a utility to update tooltool downloads.'''
-    import json
-    import os
-    import sys
-
-    mod_path = os.path.dirname(__file__)
-    browser_config_dir = os.path.join('browser', 'config', 'tooltool-manifests')
-
-    os_map = {
-        'WINDOWS': ('win64', 'clang.manifest'),
-        'OSX': ('macosx64', 'releng.manifest'),
-        'LINUX': ('linux64', 'releng.manifest'),
-    }
-
-    for os_name, (os_dir, f) in os_map.iteritems():
-        manifest_file = os.path.join(browser_config_dir, os_dir, f)
-        abspath = os.path.join(mod_path, '..', '..', '..', manifest_file)
-        with open(abspath, 'r') as s:
-            manifest = json.load(s)
-            entries = filter(lambda x: x['filename'].startswith('clang'), manifest)
-            if not entries:
-                print('ERROR: could not find clang tooltool entry in %s' % manifest_file)
-                sys.exit(1)
-            if len(entries) > 1:
-                print('ERROR: too many clang entries in %s' % manifest_file)
-                sys.exit(1)
-
-            clang = entries[0]
-            if clang['algorithm'] != 'sha512':
-                print("ERROR: don't know how to handle digest %s in %s" % (clang['algorithm'],
-                                                                           manifest_file))
-                sys.exit(1)
-
-            FORMAT_STRING = """{os} = {{
-    'package_filename': '{filename}',
-    'package_sha512sum': '{digest}',
-}}
-"""
-            digest = clang['digest']
-            if os_name == 'WINDOWS':
-                # The only clang version we can retrieve from the tooltool manifest
-                # doesn't work with Stylo bindgen due to regressions in LLVM.  This
-                # is an older version that works.
-                digest = 'cd3ed31acefd185f441632158dde73538c62bab7ebf2a8ec630985ab345938ec522983721ddb1bead1de22d5ac1571d50a958ae002364d739f2a78c6e7244222'
-            print(FORMAT_STRING.format(os=os_name,
-                                       filename=clang['filename'],
-                                       digest=digest))
+WINDOWS = 'browser/config/tooltool-manifests/win64/clang.manifest'
+OSX = 'browser/config/tooltool-manifests/macosx64/releng.manifest'
+LINUX = 'browser/config/tooltool-manifests/linux64/clang.manifest'
--- a/python/mozboot/mozboot/windows.py
+++ b/python/mozboot/mozboot/windows.py
@@ -10,18 +10,18 @@ from mozboot.base import BaseBootstrappe
 
 STYLO_MOZCONFIG = '''
 To enable Stylo in your builds, paste the lines between the chevrons
 (>>> and <<<) into your mozconfig file:
 
 <<<
 ac_add_options --enable-stylo
 
-ac_add_options --with-libclang-path={state_dir}/clang/lib
-ac_add_options --with-clang-path={state_dir}/clang/bin/clang.exe
+ac_add_options --with-libclang-path="{state_dir}/clang/bin"
+ac_add_options --with-clang-path="{state_dir}/clang/bin/clang.exe"
 >>>
 '''
 
 
 class WindowsBootstrapper(BaseBootstrapper):
     '''Bootstrapper for msys2 based environments for building in Windows.'''
 
     SYSTEM_PACKAGES = [
@@ -79,19 +79,19 @@ class WindowsBootstrapper(BaseBootstrapp
 
     def install_mobile_android_artifact_mode_packages(self):
         raise NotImplementedError('We do not support building Android on Windows. Sorry!')
 
     def suggest_browser_mozconfig(self):
         if self.stylo:
             print(STYLO_MOZCONFIG.format(state_dir=self.state_dir))
 
-    def ensure_stylo_packages(self, state_dir):
+    def ensure_stylo_packages(self, state_dir, checkout_root):
         import stylo
-        self.install_tooltool_clang_package(state_dir, **stylo.WINDOWS)
+        self.install_tooltool_clang_package(state_dir, checkout_root, stylo.WINDOWS)
 
     def _update_package_manager(self):
         self.pacman_update()
 
     def run(self, command):
         subprocess.check_call(command, stdin=sys.stdin)
 
     def pacman_update(self):
--- a/taskcluster/ci/test/tests.yml
+++ b/taskcluster/ci/test/tests.yml
@@ -1303,16 +1303,17 @@ talos-g2:
     description: "Talos g2"
     suite: talos
     try-name: g2
     treeherder-symbol: tc-T(g2)
     max-run-time: 3600
     run-on-projects:
         by-test-platform:
             linux64-stylo/.*: ['mozilla-central', 'try']
+            linux64-stylo-sequential/.*: ['try']
             default: ['mozilla-beta', 'mozilla-aurora', 'mozilla-central', 'mozilla-inbound', 'autoland', 'try'] 
     e10s: true
     mozharness:
         script: talos_script.py
         no-read-buildbot-config: true
         config:
             by-test-platform:
                 macosx.*:
--- a/taskcluster/taskgraph/transforms/beetmover.py
+++ b/taskcluster/taskgraph/transforms/beetmover.py
@@ -10,21 +10,20 @@ from __future__ import absolute_import, 
 from taskgraph.transforms.base import TransformSequence
 from taskgraph.util.schema import validate_schema, Schema
 from taskgraph.util.scriptworker import (get_beetmover_bucket_scope,
                                          get_beetmover_action_scope)
 from taskgraph.transforms.task import task_description_schema
 from voluptuous import Any, Required, Optional
 
 
-# For developers: if you are adding any new artifacts here that need to be
-# transfered to S3, please be aware you also need to follow-up with patch in
-# the actual beetmoverscript logic that lies under
-# https://github.com/mozilla-releng/beetmoverscript/. See example in bug
-# 1348286
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US = [
     "balrog_props.json",
     "target.common.tests.zip",
     "target.cppunittest.tests.zip",
     "target.crashreporter-symbols.zip",
     "target.json",
     "target.mochitest.tests.zip",
     "target.mozinfo.json",
@@ -37,26 +36,42 @@ from voluptuous import Any, Required, Op
     "target.xpcshell.tests.zip",
     "target_info.txt",
     "target.jsshell.zip",
     "mozharness.zip",
     "target.langpack.xpi",
     "host/bin/mar",
     "host/bin/mbsdiff",
 ]
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_EN_US = [
     "update/target.complete.mar",
 ]
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_L10N = [
     "target.langpack.xpi",
     "balrog_props.json",
 ]
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_L10N = [
     "target.complete.mar",
 ]
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 _MOBILE_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US = [
     "en-US/target.common.tests.zip",
     "en-US/target.cppunittest.tests.zip",
     "en-US/target.crashreporter-symbols.zip",
     "en-US/target.json",
     "en-US/target.mochitest.tests.zip",
     "en-US/target.mozinfo.json",
     "en-US/target.reftest.tests.zip",
@@ -67,16 +82,20 @@ from voluptuous import Any, Required, Op
     "en-US/target.web-platform.tests.zip",
     "en-US/target.xpcshell.tests.zip",
     "en-US/target_info.txt",
     "en-US/bouncer.apk",
     "en-US/mozharness.zip",
     "en-US/robocop.apk",
     "en-US/target.jsshell.zip",
 ]
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 _MOBILE_UPSTREAM_ARTIFACTS_UNSIGNED_MULTI = [
     "balrog_props.json",
     "target.common.tests.zip",
     "target.cppunittest.tests.zip",
     "target.json",
     "target.mochitest.tests.zip",
     "target.mozinfo.json",
     "target.reftest.tests.zip",
@@ -87,24 +106,36 @@ from voluptuous import Any, Required, Op
     "target.web-platform.tests.zip",
     "target.xpcshell.tests.zip",
     "target_info.txt",
     "bouncer.apk",
     "mozharness.zip",
     "robocop.apk",
     "target.jsshell.zip",
 ]
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 _MOBILE_UPSTREAM_ARTIFACTS_SIGNED_EN_US = [
     "en-US/target.apk",
 ]
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 _MOBILE_UPSTREAM_ARTIFACTS_SIGNED_MULTI = [
     "target.apk",
 ]
 
 
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 UPSTREAM_ARTIFACT_UNSIGNED_PATHS = {
     'linux64-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US,
     'linux-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US,
     'linux64-devedition-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US,
     'linux-devedition-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US,
     'android-x86-nightly': _MOBILE_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US,
     'android-aarch64-nightly': _MOBILE_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US,
     'android-api-15-nightly': _MOBILE_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US,
@@ -117,16 +148,20 @@ UPSTREAM_ARTIFACT_UNSIGNED_PATHS = {
     'android-x86-nightly-multi': _MOBILE_UPSTREAM_ARTIFACTS_UNSIGNED_MULTI,
     'android-x86-old-id-nightly-multi': _MOBILE_UPSTREAM_ARTIFACTS_UNSIGNED_MULTI,
     'android-aarch64-nightly-multi': _MOBILE_UPSTREAM_ARTIFACTS_UNSIGNED_MULTI,
     'android-api-15-nightly-l10n': ["balrog_props.json"],
     'android-api-15-nightly-multi': _MOBILE_UPSTREAM_ARTIFACTS_UNSIGNED_MULTI,
     'android-api-15-old-id-nightly-multi': _MOBILE_UPSTREAM_ARTIFACTS_UNSIGNED_MULTI,
     'macosx64-nightly-l10n': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_L10N,
 }
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 UPSTREAM_ARTIFACT_SIGNED_PATHS = {
     'linux64-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_EN_US + [
         "target.tar.bz2",
         "target.tar.bz2.asc",
     ],
     'linux-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_EN_US + [
         "target.tar.bz2",
         "target.tar.bz2.asc",
--- a/taskcluster/taskgraph/transforms/beetmover_checksums.py
+++ b/taskcluster/taskgraph/transforms/beetmover_checksums.py
@@ -87,16 +87,20 @@ def make_beetmover_checksums_description
             'run-on-projects': dep_job.attributes.get('run_on_projects'),
             'treeherder': treeherder,
         }
 
         yield task
 
 
 def generate_upstream_artifacts(refs, platform, locale=None):
+    # Until bug 1331141 is fixed, if you are adding any new artifacts here that
+    # need to be transfered to S3, please be aware you also need to follow-up
+    # with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+    # See example in bug 1348286
     common_paths = [
         "public/target.checksums",
         "public/target.checksums.asc",
     ]
 
     upstream_artifacts = [{
         "taskId": {"task-reference": refs["signing"]},
         "taskType": "signing",
--- a/taskcluster/taskgraph/transforms/beetmover_repackage.py
+++ b/taskcluster/taskgraph/transforms/beetmover_repackage.py
@@ -12,21 +12,20 @@ from taskgraph.util.schema import valida
 from taskgraph.util.scriptworker import (get_beetmover_bucket_scope,
                                          get_beetmover_action_scope)
 from taskgraph.transforms.task import task_description_schema
 from voluptuous import Any, Required, Optional
 
 import logging
 logger = logging.getLogger(__name__)
 
-# For developers: if you are adding any new artifacts here that need to be
-# transfered to S3, please be aware you also need to follow-up with patch in
-# the actual beetmoverscript logic that lies under
-# https://github.com/mozilla-releng/beetmoverscript/. See example in bug
-# 1348286
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US = [
     "balrog_props.json",
     "target.common.tests.zip",
     "target.cppunittest.tests.zip",
     "target.crashreporter-symbols.zip",
     "target.json",
     "target.mochitest.tests.zip",
     "target.mozinfo.json",
@@ -39,35 +38,59 @@ logger = logging.getLogger(__name__)
     "target.xpcshell.tests.zip",
     "target_info.txt",
     "target.jsshell.zip",
     "mozharness.zip",
     "target.langpack.xpi",
     "host/bin/mar",
     "host/bin/mbsdiff",
 ]
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_EN_US = [
     "update/target.complete.mar",
 ]
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_L10N = [
     "target.langpack.xpi",
     "balrog_props.json",
 ]
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_L10N = [
     "target.complete.mar",
 ]
 
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 UPSTREAM_ARTIFACT_UNSIGNED_PATHS = {
     'macosx64-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US,
     'macosx64-nightly-l10n': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_L10N,
 }
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 UPSTREAM_ARTIFACT_SIGNED_PATHS = {
     'macosx64-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_EN_US,
     'macosx64-nightly-l10n': _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_L10N,
 }
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
 UPSTREAM_ARTIFACT_REPACKAGE_PATHS = {
     'macosx64-nightly': ["target.dmg"],
     'macosx64-nightly-l10n': ["target.dmg"],
 }
 
 # Voluptuous uses marker objects as dictionary *keys*, but they are not
 # comparable, so we cast all of the keys back to regular strings
 task_description_schema = {str(k): v for k, v in task_description_schema.schema.iteritems()}
--- a/testing/web-platform/meta/intersection-observer/display-none.html.ini
+++ b/testing/web-platform/meta/intersection-observer/display-none.html.ini
@@ -1,3 +1,5 @@
 [display-none.html]
   type: testharness
   disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1358668
+  [Intersecting notification after first rAF.]
+    disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1359318
--- a/testing/web-platform/meta/intersection-observer/multiple-thresholds.html.ini
+++ b/testing/web-platform/meta/intersection-observer/multiple-thresholds.html.ini
@@ -1,3 +1,5 @@
 [multiple-thresholds.html]
   type: testharness
-  disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1335644
+  disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1359318
+  [First rAF.]
+    https://bugzilla.mozilla.org/show_bug.cgi?id=1335644
--- a/testing/web-platform/meta/intersection-observer/root-margin.html.ini
+++ b/testing/web-platform/meta/intersection-observer/root-margin.html.ini
@@ -1,3 +1,5 @@
 [root-margin.html]
   type: testharness
-  disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1335644
+  disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1359318
+  [First rAF.]
+    https://bugzilla.mozilla.org/show_bug.cgi?id=1335644
--- a/testing/web-platform/meta/intersection-observer/same-document-no-root.html.ini
+++ b/testing/web-platform/meta/intersection-observer/same-document-no-root.html.ini
@@ -1,3 +1,5 @@
 [same-document-no-root.html]
   type: testharness
-  disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1335644
+  disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1359318
+  [First rAF.]
+    https://bugzilla.mozilla.org/show_bug.cgi?id=1335644
--- a/testing/web-platform/meta/intersection-observer/same-document-zero-size-target.html.ini
+++ b/testing/web-platform/meta/intersection-observer/same-document-zero-size-target.html.ini
@@ -1,3 +1,5 @@
 [same-document-zero-size-target.html]
   type: testharness
-  disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1335644
+  disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1359318
+  [First rAF.]
+    https://bugzilla.mozilla.org/show_bug.cgi?id=1335644
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -13228,10 +13228,22 @@
     "alert_emails": ["jwwang@mozilla.com"],
     "expires_in_version": "57",
     "kind": "exponential",
     "low": 1000,
     "high": 100000,
     "n_buckets": 100,
     "bug_numbers": [1366640],
     "description": "Time (ms) VideoFrameContainer::ClearFutureFrames spent holding a lock."
+  },
+  "IPC_SYNC_RECEIVE_MS": {
+    "record_in_processes": ["main", "content", "gpu"],
+    "alert_emails": ["michael@thelayzells.com"],
+    "bug_numbers": [1365719],
+    "expires_in_version": "60",
+    "kind": "exponential",
+    "low": 32,
+    "high": 750,
+    "n_buckets": 40,
+    "keyed": true,
+    "description": "Measures the number of milliseconds we spend processing sync IPC messages in the receiving process, keyed by message name. Note: only messages that take over 500 microseconds are included in this probe."
   }
 }