Merge inbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Fri, 08 Sep 2017 13:36:31 -0700
changeset 661689 ea7b55d65d76214f97aaae502d65cb26fc6f5659
parent 661688 dd3736e98e4e7558af2f202803bce36278a26c66 (current diff)
parent 661583 ec521bf6357cf3564d5785a66da787be53be45cd (diff)
child 661690 a8cd6b2c62e45b89b3e83ef641f2532c39c4dd43
child 661706 69fd247df26427afe8921b4732f00ef663647221
child 661723 dd9074ebc3331defeb1d3e12023ac3731b4947c7
child 661743 53c6fbfa50b11d0b187bee9eb855b76fcccc61d2
child 661751 dda67e64652da6cfc373daf14a942094f4fa1890
child 661816 e78342f09ee6e90b78dc098742f3b0bae3b9bc84
child 661851 6017b2756cd5516be9f196583f13612aa490cd15
child 661878 294285a0a5c24464c276d3240eee6af34353bc70
child 661882 a5a87cdf4563d2bda2a32e9c3e2800d1ece20742
child 661883 b72a952128d0b4aed9a142c0e4d4b30b26960f80
child 661902 9c5532c676b1ed25962a20a40d229cfd452eb272
child 661923 2dda01da1c5035906736d5aaeaa5e1529c9ef62b
child 661944 b46dcaf23326ef33c800ef48074ec03080b65889
child 662001 604549e33557bfe388e988b9ebef93f19d915c89
child 662056 2042567f90485ceb6dc4b343692cb169009893c5
child 662159 d4fd31a27e52c48d3e956a5c7a3aa7659f34db9b
child 662198 c9091c5d3b3f42c462cda529483877794fedbbad
child 662436 daf0d120a995db28f222ac0ec1723d680f0b2613
child 662621 e999acbf2b73f159c6fe0961acde7ababfa4d363
child 664076 d26ed0856af882ad52a606941685b2c91577d3bf
push id78846
push userbmo:r.f.masen@gmail.com
push dateFri, 08 Sep 2017 20:45:31 +0000
reviewersmerge
milestone57.0a1
Merge inbound to central, a=merge MozReview-Commit-ID: 4FEkd1x2GD
browser/components/nsBrowserGlue.js
browser/themes/shared/e10s-64@2x.png
dom/events/EventStateManager.cpp
layout/base/PresShell.cpp
modules/libpref/init/all.js
toolkit/components/telemetry/Histograms.json
--- a/accessible/tests/browser/bounds/browser.ini
+++ b/accessible/tests/browser/bounds/browser.ini
@@ -1,10 +1,9 @@
 [DEFAULT]
-skip-if = e10s && os == 'win' && release_or_beta
 support-files =
   head.js
   !/accessible/tests/browser/events.js
   !/accessible/tests/browser/shared-head.js
   !/accessible/tests/mochitest/*.js
   !/accessible/tests/mochitest/letters.gif
 
 [browser_test_zoom.js]
--- a/accessible/tests/browser/e10s/browser.ini
+++ b/accessible/tests/browser/e10s/browser.ini
@@ -1,10 +1,9 @@
 [DEFAULT]
-skip-if = e10s && os == 'win' && release_or_beta
 support-files =
   head.js
   doc_treeupdate_ariadialog.html
   doc_treeupdate_ariaowns.html
   doc_treeupdate_imagemap.html
   doc_treeupdate_removal.xhtml
   doc_treeupdate_visibility.html
   doc_treeupdate_whitespace.html
--- a/accessible/tests/browser/events/browser.ini
+++ b/accessible/tests/browser/events/browser.ini
@@ -1,10 +1,9 @@
 [DEFAULT]
-skip-if = e10s && os == 'win' && release_or_beta
 support-files =
   head.js
   !/accessible/tests/browser/events.js
   !/accessible/tests/browser/shared-head.js
   !/accessible/tests/mochitest/*.js
 
 [browser_test_docload.js]
 skip-if = e10s
--- a/accessible/tests/browser/scroll/browser.ini
+++ b/accessible/tests/browser/scroll/browser.ini
@@ -1,10 +1,9 @@
 [DEFAULT]
-skip-if = e10s && os == 'win' && release_or_beta
 support-files =
   head.js
   !/accessible/tests/browser/events.js
   !/accessible/tests/browser/shared-head.js
   !/accessible/tests/mochitest/*.js
 
 [browser_test_zoom_text.js]
 skip-if = e10s && os == 'win' # bug 1372296
--- a/accessible/tests/browser/states/browser.ini
+++ b/accessible/tests/browser/states/browser.ini
@@ -1,10 +1,9 @@
 [DEFAULT]
-skip-if = e10s && os == 'win' && release_or_beta
 support-files =
   head.js
   !/accessible/tests/browser/events.js
   !/accessible/tests/browser/shared-head.js
   !/accessible/tests/mochitest/*.js
 
 [browser_test_link.js]
 [browser_test_visibility.js]
--- a/accessible/tests/browser/tree/browser.ini
+++ b/accessible/tests/browser/tree/browser.ini
@@ -1,9 +1,8 @@
 [DEFAULT]
-skip-if = e10s && os == 'win' && release_or_beta
 support-files =
   head.js
   !/accessible/tests/browser/events.js
   !/accessible/tests/browser/shared-head.js
   !/accessible/tests/mochitest/*.js
 
 [browser_aria_owns.js]
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -662,19 +662,16 @@ pref("network.protocol-handler.expose.ne
 pref("network.protocol-handler.expose.snews", false);
 pref("network.protocol-handler.expose.nntp", false);
 
 pref("accessibility.typeaheadfind", false);
 pref("accessibility.typeaheadfind.timeout", 5000);
 pref("accessibility.typeaheadfind.linksonly", false);
 pref("accessibility.typeaheadfind.flashBar", 1);
 
-// Tracks when accessibility is loaded into the previous session.
-pref("accessibility.loadedInLastSession", false);
-
 pref("plugins.click_to_play", true);
 pref("plugins.testmode", false);
 
 // Should plugins that are hidden show the infobar UI?
 pref("plugins.show_infobar", false);
 
 // Should dismissing the hidden plugin infobar suppress it permanently?
 pref("plugins.remember_infobar_dismissal", true);
@@ -975,19 +972,16 @@ pref("toolkit.datacollection.infoURL",
 
 // URL for "Learn More" for Crash Reporter
 pref("toolkit.crashreporter.infoURL",
      "https://www.mozilla.org/legal/privacy/firefox.html#crash-reporter");
 
 // base URL for web-based support pages
 pref("app.support.baseURL", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/");
 
-// a11y conflicts with e10s support page
-pref("app.support.e10sAccessibilityUrl", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/accessibility-ppt");
-
 // base url for web-based feedback pages
 #ifdef MOZ_DEV_EDITION
 pref("app.feedback.baseURL", "https://input.mozilla.org/%LOCALE%/feedback/firefoxdev/%VERSION%/");
 #else
 pref("app.feedback.baseURL", "https://input.mozilla.org/%LOCALE%/feedback/%APP%/%VERSION%/");
 #endif
 
 // base URL for web-based marketing pages
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -523,23 +523,16 @@ BrowserGlue.prototype = {
     os.addObserver(this, "restart-in-safe-mode");
     os.addObserver(this, "flash-plugin-hang");
     os.addObserver(this, "xpi-signature-changed");
     os.addObserver(this, "sync-ui-state:update");
     os.addObserver(this, "handlersvc-store-initialized");
 
     this._flashHangCount = 0;
     this._firstWindowReady = new Promise(resolve => this._firstWindowLoaded = resolve);
-
-    if (AppConstants.platform == "macosx" ||
-        (AppConstants.platform == "win" && AppConstants.RELEASE_OR_BETA)) {
-      // Handles prompting to inform about incompatibilites when accessibility
-      // and e10s are active together.
-      E10SAccessibilityCheck.init();
-    }
   },
 
   // cleanup (called on application shutdown)
   _dispose: function BG__dispose() {
     let os = Services.obs;
     os.removeObserver(this, "notifications-open-settings");
     os.removeObserver(this, "prefservice:after-app-defaults");
     os.removeObserver(this, "final-ui-startup");
@@ -1004,20 +997,17 @@ BrowserGlue.prototype = {
       });
     }
 
     if (AppConstants.MOZ_CRASHREPORTER) {
       UnsubmittedCrashHandler.init();
     }
 
     this._sanitizer.onStartup();
-    E10SAccessibilityCheck.onWindowsRestored();
-
     this._scheduleStartupIdleTasks();
-
     this._lateTasksIdleObserver = (idleService, topic, data) => {
       if (topic == "idle") {
         idleService.removeIdleObserver(this._lateTasksIdleObserver,
                                        LATE_TASKS_IDLE_TIME_SEC);
         delete this._lateTasksIdleObserver;
         this._scheduleArbitrarilyLateIdleTasks();
       }
     };
@@ -2795,141 +2785,18 @@ var DefaultBrowserCheck = {
       let popup = doc.getElementById(this.OPTIONPOPUP);
       popup.removeEventListener("command", this);
       popup.remove();
       delete this._notification;
     }
   },
 };
 
-var E10SAccessibilityCheck = {
-  // tracks when an a11y init observer fires prior to the
-  // first window being opening.
-  _wantsPrompt: false,
-
-  init() {
-    Services.obs.addObserver(this, "a11y-init-or-shutdown", true);
-    Services.obs.addObserver(this, "quit-application-granted", true);
-  },
-
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
-
-  get forcedOn() {
-    try {
-      return Services.prefs.getBoolPref("browser.tabs.remote.force-enable");
-    } catch (e) {}
-    return false;
-  },
-
-  observe(subject, topic, data) {
-    switch (topic) {
-      case "quit-application-granted":
-        // Tag the profile with a11y load state. We use this in nsAppRunner
-        // checks on the next start.
-        Services.prefs.setBoolPref("accessibility.loadedInLastSession",
-                                   Services.appinfo.accessibilityEnabled);
-        break;
-      case "a11y-init-or-shutdown":
-        if (data == "1") {
-          // Update this so users can check this while still running
-          Services.prefs.setBoolPref("accessibility.loadedInLastSession", true);
-          this._showE10sAccessibilityWarning();
-        }
-        break;
-    }
-  },
-
-  onWindowsRestored() {
-    if (this._wantsPrompt) {
-      this._wantsPrompt = false;
-      this._showE10sAccessibilityWarning();
-    }
-  },
-
-  _warnedAboutAccessibility: false,
-
-  _showE10sAccessibilityWarning() {
-    // We don't prompt about a11y incompat if e10s is off.
-    if (!Services.appinfo.browserTabsRemoteAutostart) {
-      return;
-    }
-
-    // If the user set the forced pref and it's true, ignore a11y init.
-    // If the pref doesn't exist or if it's false, prompt.
-    if (this.forcedOn) {
-      return;
-    }
-
-    // Only prompt once per session
-    if (this._warnedAboutAccessibility) {
-      return;
-    }
-    this._warnedAboutAccessibility = true;
-
-    let win = RecentWindow.getMostRecentBrowserWindow();
-    if (!win || !win.gBrowser || !win.gBrowser.selectedBrowser) {
-      Services.console.logStringMessage(
-          "Accessibility support is partially disabled due to compatibility issues with new features.");
-      this._wantsPrompt = true;
-      this._warnedAboutAccessibility = false;
-      return;
-    }
-    let browser = win.gBrowser.selectedBrowser;
-
-    // We disable a11y for content and prompt on the chrome side letting
-    // a11y users know they need to disable e10s and restart.
-    let promptMessage = win.gNavigatorBundle.getFormattedString(
-                          "e10s.accessibilityNotice.mainMessage2",
-                          [gBrandBundle.GetStringFromName("brandShortName")]
-                        );
-    let notification;
-    let restartCallback  = function() {
-      let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
-      Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
-      if (cancelQuit.data) {
-        return; // somebody canceled our quit request
-      }
-      // Restart the browser
-      Services.startup.quit(Services.startup.eAttemptQuit | Services.startup.eRestart);
-    };
-    // main option: an Ok button, keeps running with content accessibility disabled
-    let mainAction = {
-      label: win.gNavigatorBundle.getString("e10s.accessibilityNotice.acceptButton.label"),
-      accessKey: win.gNavigatorBundle.getString("e10s.accessibilityNotice.acceptButton.accesskey"),
-      callback() {
-        // If the user invoked the button option remove the notification,
-        // otherwise keep the alert icon around in the address bar.
-        notification.remove();
-      },
-      dismiss: true
-    };
-    // secondary option: a restart now button. When we restart e10s will be disabled due to
-    // accessibility having been loaded in the previous session.
-    let secondaryActions = [{
-      label: win.gNavigatorBundle.getString("e10s.accessibilityNotice.enableAndRestart.label"),
-      accessKey: win.gNavigatorBundle.getString("e10s.accessibilityNotice.enableAndRestart.accesskey"),
-      callback: restartCallback,
-    }];
-    let options = {
-      popupIconURL: "chrome://browser/skin/e10s-64@2x.png",
-      learnMoreURL: Services.urlFormatter.formatURLPref("app.support.e10sAccessibilityUrl"),
-      persistent: true,
-      persistWhileVisible: true,
-    };
-
-    notification =
-      win.PopupNotifications.show(browser, "a11y_enabled_with_e10s",
-                                  promptMessage, null, mainAction,
-                                  secondaryActions, options);
-  },
-};
-
 var components = [BrowserGlue, ContentPermissionPrompt];
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
 
-
 // Listen for UITour messages.
 // Do it here instead of the UITour module itself so that the UITour module is lazy loaded
 // when the first message is received.
 var globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
 globalMM.addMessageListener("UITour:onPageEvent", function(aMessage) {
   UITour.onPageEvent(aMessage, aMessage.data);
 });
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -58,17 +58,14 @@ browser.jar:
   skin/classic/browser/preferences/preferences.css    (preferences/preferences.css)
 * skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
 * skin/classic/browser/preferences/in-content/dialog.css      (preferences/in-content/dialog.css)
   skin/classic/browser/preferences/applications.css   (preferences/applications.css)
   skin/classic/browser/tabbrowser/tabDragIndicator.png      (tabbrowser/tabDragIndicator.png)
 
   skin/classic/browser/sync-desktopIcon.svg  (../shared/sync-desktopIcon.svg)
   skin/classic/browser/sync-mobileIcon.svg  (../shared/sync-mobileIcon.svg)
-#ifdef E10S_TESTING_ONLY
-  skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
-#endif
 
 [extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
 % override chrome://browser/skin/feeds/audioFeedIcon.png              chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/audioFeedIcon16.png            chrome://browser/skin/feeds/feedIcon16.png
 % override chrome://browser/skin/feeds/videoFeedIcon.png              chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/videoFeedIcon16.png            chrome://browser/skin/feeds/feedIcon16.png
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -82,19 +82,16 @@ browser.jar:
   skin/classic/browser/sync-desktopIcon.svg  (../shared/sync-desktopIcon.svg)
   skin/classic/browser/sync-mobileIcon.svg  (../shared/sync-mobileIcon.svg)
   skin/classic/browser/yosemite/menuPanel-customize.png                (menuPanel-customize-yosemite.png)
   skin/classic/browser/yosemite/menuPanel-customize@2x.png             (menuPanel-customize-yosemite@2x.png)
   skin/classic/browser/yosemite/menuPanel-exit.png                     (menuPanel-exit-yosemite.png)
   skin/classic/browser/yosemite/menuPanel-exit@2x.png                  (menuPanel-exit-yosemite@2x.png)
   skin/classic/browser/yosemite/menuPanel-help.png                     (menuPanel-help-yosemite.png)
   skin/classic/browser/yosemite/menuPanel-help@2x.png                  (menuPanel-help-yosemite@2x.png)
-#ifdef E10S_TESTING_ONLY
-  skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
-#endif
 
 [extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
 % override chrome://browser/skin/feeds/audioFeedIcon.png                   chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/audioFeedIcon16.png                 chrome://browser/skin/feeds/feedIcon16.png
 % override chrome://browser/skin/feeds/videoFeedIcon.png                   chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/videoFeedIcon16.png                 chrome://browser/skin/feeds/feedIcon16.png
 % override chrome://browser/skin/notification-icons/geo-detailed.svg       chrome://browser/skin/notification-icons/geo.svg
 
--- a/browser/themes/shared/customizableui/customizeMode.inc.css
+++ b/browser/themes/shared/customizableui/customizeMode.inc.css
@@ -52,24 +52,23 @@
 
 %if defined(XP_MACOSX) || defined(XP_WIN)
 %ifdef XP_WIN
 @media (-moz-windows-default-theme) {
 %endif
 
 .customizationmode-button {
   border: 1px solid #b1b1b1;
-  margin: 6px 10px;
-  padding: 2px 5px;
   background-color: #fcfcfd;
-  color: rgb(71,71,71);
   -moz-appearance: none;
 }
 
-.customizationmode-checkbox {
+.customizationmode-checkbox,
+.customizationmode-button {
+  color: rgb(71, 71, 71);
   margin: 6px 10px;
   padding: 2px 5px;
 }
 
 #customization-reset-button,
 #customization-undo-reset-button,
 #customization-done-button {
   min-width: 10em;
deleted file mode 100644
index 1dc243865cfb412f03aa372d30fa769fd3fd5eac..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -78,20 +78,16 @@ browser.jar:
   skin/classic/browser/window-controls/maximize-themes.svg       (window-controls/maximize-themes.svg)
   skin/classic/browser/window-controls/minimize.svg              (window-controls/minimize.svg)
   skin/classic/browser/window-controls/minimize-highcontrast.svg (window-controls/minimize-highcontrast.svg)
   skin/classic/browser/window-controls/minimize-themes.svg       (window-controls/minimize-themes.svg)
   skin/classic/browser/window-controls/restore.svg               (window-controls/restore.svg)
   skin/classic/browser/window-controls/restore-highcontrast.svg  (window-controls/restore-highcontrast.svg)
   skin/classic/browser/window-controls/restore-themes.svg        (window-controls/restore-themes.svg)
 
-#ifdef E10S_TESTING_ONLY
-  skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
-#endif
-
 [extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
 % override chrome://browser/skin/page-livemarks.png                   chrome://browser/skin/feeds/feedIcon16.png
 % override chrome://browser/skin/feeds/audioFeedIcon.png              chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/audioFeedIcon16.png            chrome://browser/skin/feeds/feedIcon16.png
 % override chrome://browser/skin/feeds/videoFeedIcon.png              chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/videoFeedIcon16.png            chrome://browser/skin/feeds/feedIcon16.png
 
 % override chrome://browser/skin/privatebrowsing-mask-tabstrip.png    chrome://browser/skin/privatebrowsing-mask-tabstrip-win7.png  os=WINNT osversion<=6.1
--- a/devtools/client/debugger/new/debugger.css
+++ b/devtools/client/debugger/new/debugger.css
@@ -415,16 +415,20 @@ body {
   --popup-shadow-color: #d0d0d0;
 }
 
 :root.theme-dark,
 :root .theme-dark {
   --search-overlays-semitransparent: rgba(42, 46, 56, 0.66);
   --popup-shadow-color: #5c667b;
 }
+* {
+  box-sizing: border-box;
+}
+
 .debugger {
   display: flex;
   flex: 1;
   height: 100%;
 }
 
 .editor-pane {
   display: flex;
@@ -872,22 +876,16 @@ html .arrow.expanded svg {
 .managed-tree .tree .node {
   padding: 2px 3px 2px 3px;
   position: relative;
 }
 
 .managed-tree .tree .node.focused {
   color: white;
   background-color: var(--theme-selection-background);
-  padding-bottom: 2px;
-}
-
-.theme-dark .managed-tree .tree .node.focused {
-  background-color: var(--theme-selection-background-hover);
-  padding-bottom: 2px;
 }
 
 html:not([dir="rtl"]) .managed-tree .tree .node > div {
   margin-left: 10px;
 }
 
 html[dir="rtl"] .managed-tree .tree .node > div {
   margin-right: 10px;
@@ -902,17 +900,17 @@ html[dir="rtl"] .managed-tree .tree .nod
 }
 .close-btn path {
   fill: var(--theme-comment-alt);
 }
 
 .close-btn .close {
   width: 14px;
   height: 14px;
-  transition: all 0.25s ease-in-out;
+  transition: all 0.15s ease-in-out;
   border: 1px solid transparent;
   border-radius: 2px;
   padding: 0;
   margin-top: 0;
   display: inline-flex;
   justify-content: center;
 }
 
@@ -1262,37 +1260,39 @@ html[dir="rtl"] .managed-tree .tree .nod
 
 .toggle-search .title {
   font-weight: 500;
   font-size: 120%;
 }
 
 .toggle-search .text {
   margin-left: 1em;
+  cursor: default;
 }
 
 .toggle-search .active {
   color: var(--theme-selection-background);
-  cursor: default;
 }
 .sources-panel {
+  background-color: var(--theme-sidebar-background);
+  display: flex;
   flex: 1;
-  display: flex;
   flex-direction: column;
   overflow: hidden;
   position: relative;
 }
 
 .sources-panel * {
   -moz-user-select: none;
   user-select: none;
 }
 
 .sources-header {
-  height: 30px;
+  height: 29px;
+  background-color: var(--theme-toolbar-background);
   border-bottom: 1px solid var(--theme-splitter-color);
   padding-top: 0px;
   padding-bottom: 0px;
   line-height: 30px;
   font-size: 1.2em;
   display: flex;
   align-items: baseline;
   -moz-user-select: none;
@@ -2231,17 +2231,17 @@ html[dir="rtl"] .arrow svg,
  * BUG https://github.com/devtools-html/debugger.html/issues/63
  */
 .editor-wrapper {
   position: absolute;
   height: calc(100% - 31px);
   width: calc(100% - 1.5px);
   top: 30px;
   left: 0px;
-  --editor-footer-height: 27px;
+  --editor-footer-height: 24px;
 }
 
 html[dir="rtl"] .editor-mount {
   direction: ltr;
 }
 
 .editor-wrapper .breakpoints {
   position: absolute;
@@ -2435,34 +2435,18 @@ html[dir="rtl"] .editor-mount {
   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;
+  border-radius: 2px;
+  margin: 0 -1px -1px -1px;
 }
 .breakpoints-toggle {
   margin: 2px 3px;
 }
 
 .breakpoints-list * {
   -moz-user-select: none;
   user-select: none;
@@ -2561,17 +2545,17 @@ html .breakpoints-list .breakpoint.pause
 
 .breakpoint:hover .close {
   visibility: visible;
 }
 .input-expression {
   width: 100%;
   margin: 0px;
   border: 1px;
-  background-color: var(--theme-body-background);
+  background-color: var(--theme-sidebar-background);
   font-size: 12px;
   padding: 0px 20px;
   color: var(--theme-body-color);
 }
 
 .input-expression::placeholder {
   text-align: center;
   font-style: italic;
@@ -2582,17 +2566,17 @@ html .breakpoints-list .breakpoint.pause
 .input-expression:focus {
   outline: none;
   cursor: text;
 }
 
 .expressions-list {
   /* TODO: add normalize */
   margin: 0;
-  padding: 0.5em 0;
+  padding: 0;
 }
 .expression-input-container {
   padding: 0.5em;
   display: flex;
 }
 
 .expression-container {
   border: 1px;
@@ -2846,41 +2830,48 @@ html .breakpoints-list .breakpoint.pause
 
 .event-listeners .listener .close {
   display: none;
 }
 
 .event-listeners .listener:hover .close {
   display: block;
 }
+
+:root {
+  --accordion-header-background: var(--theme-toolbar-background);
+}
+
+:root.theme-dark {
+  --accordion-header-background: #141416;
+}
+
 .accordion {
-  background-color: var(--theme-body-background);
+  background-color: var(--theme-sidebar-background);
   width: 100%;
 }
 
 .accordion ._header {
-  background-color: var(--theme-toolbar-background);
+  background-color: var(--accordion-header-background);
   border-bottom: 1px solid var(--theme-splitter-color);
+  display: flex;
   font-size: 12px;
-  padding: 5px;
+  padding: 4px;
   transition: all 0.25s ease;
   width: 100%;
+  height: 24px;
   align-items: center;
 
   -webkit-user-select: none;
   -moz-user-select: none;
   -ms-user-select: none;
   -o-user-select: none;
   user-select: none;
 }
 
-.accordion ._header {
-  display: flex;
-}
-
 .accordion ._header:hover {
   background-color: var(--theme-toolbar-background-hover);
 }
 
 .accordion ._header button svg,
 .accordion ._header:hover button svg {
   fill: currentColor;
   height: 16px;
@@ -2916,25 +2907,25 @@ html .breakpoints-list .breakpoint.pause
   width: 16px;
   height: 16px;
 }
 
 .accordion .header-buttons button::-moz-focus-inner {
   border: none;
 }
 .command-bar {
-  flex: 0 0 30px;
+  flex: 0 0 29px;
   border-bottom: 1px solid var(--theme-splitter-color);
   display: flex;
-  height: 30px;
+  height: 29px;
   overflow: hidden;
   position: sticky;
   top: 0;
   z-index: 1;
-  background-color: var(--theme-body-background);
+  background-color: var(--theme-toolbar-background);
 }
 
 .command-bar.vertical {
   width: 100vw;
 }
 
 html[dir="rtl"] .command-bar {
   border-right: 1px solid var(--theme-splitter-color);
@@ -3078,41 +3069,56 @@ html .command-bar > button:disabled {
   height: calc(100% - 30px);
   position: absolute;
   top: 30px;
   left: 0;
   padding: 50px 0 0 0;
   text-align: center;
   font-size: 1.25em;
   color: var(--theme-comment-alt);
-  background-color: var(--theme-tab-toolbar-background);
+  background-color: var(--theme-toolbar-background);
   font-weight: lighter;
   z-index: 100;
 }
 
+.theme-dark .welcomebox {
+  background-color: var(--theme-body-background);
+}
+
 .alignlabel {
   display: inline-block;
-  text-align: left;
 }
 
 .welcomebox .toggle-button-end {
   position: absolute;
   top: auto;
   bottom: 0;
   offset-inline-end: 0;
   offset-inline-start: auto;
 }
 
+.shortcutKeys {
+  text-align: right;
+  float: left;
+  font-family: Courier;
+}
+
+.shortcutFunction {
+  text-align: left;
+  float: left;
+  margin-left: 25px;
+}
+
 html .welcomebox .toggle-button-end.collapsed {
   bottom: 1px;
 }
 .source-header {
   border-bottom: 1px solid var(--theme-splitter-color);
   width: 100%;
-  height: 30px;
+  height: 29px;
   display: flex;
   align-items: flex-end;
 }
 
 .source-header * {
   -moz-user-select: none;
   user-select: none;
 }
@@ -3142,17 +3148,17 @@ html .welcomebox .toggle-button-end.coll
 
 .source-tab {
   border: 1px solid transparent;
   border-top-left-radius: 2px;
   border-top-right-radius: 2px;
   display: inline-flex;
   align-items: flex-end;
   position: relative;
-  transition: all 0.25s ease;
+  transition: all 0.15s ease;
   min-width: 40px;
   overflow: hidden;
   padding: 5px;
   margin-inline-start: 3px;
   margin-top: 4px;
 }
 
 .source-tab:hover {
--- a/devtools/client/debugger/new/debugger.js
+++ b/devtools/client/debugger/new/debugger.js
@@ -1339,17 +1339,16 @@ function warning(message) {
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.InitialState = InitialState;
 exports.getTextSearchResults = getTextSearchResults;
-exports.getTextSearchResult = getTextSearchResult;
 exports.getTextSearchQuery = getTextSearchQuery;
 
 var _immutable = __webpack_require__(146);
 
 var I = _interopRequireWildcard(_immutable);
 
 var _makeRecord = __webpack_require__(230);
 
@@ -1364,44 +1363,46 @@ function _interopRequireWildcard(obj) { 
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Search reducer
  * @module reducers/search
  */
 
 function InitialState() {
-  return (0, _makeRecord2.default)({ query: "", results: I.Map() })();
+  return (0, _makeRecord2.default)({ query: "", results: I.List() })();
 }
 
 function update() {
   var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : InitialState();
   var action = arguments[1];
 
   switch (action.type) {
     case "ADD_QUERY":
       return state.update("query", value => action.query);
 
     case "CLEAR_QUERY":
       return state.remove("query");
 
     case "ADD_SEARCH_RESULT":
-      return state.updateIn(["results", action.result.sourceId], value => action.result);
+      var _results = state.get("results");
+      return state.merge({ results: _results.push(action.result) });
+
+    case "CLEAR_SEARCH_RESULTS":
+      return state.merge({
+        results: state.get("results").clear()
+      });
   }
   return state;
 }
 
 function getTextSearchResults(state) {
   return state.projectTextSearch.get("results");
 }
 
-function getTextSearchResult(state, id) {
-  return state.projectTextSearch.getIn(["results", id]);
-}
-
 function getTextSearchQuery(state) {
   return state.projectTextSearch.get("query");
 }
 
 exports.default = update;
 
 /***/ }),
 /* 32 */
@@ -1822,16 +1823,17 @@ function compose() {
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.addSearchQuery = addSearchQuery;
 exports.clearSearchQuery = clearSearchQuery;
+exports.clearSearchResults = clearSearchResults;
 exports.searchSources = searchSources;
 exports.searchSource = searchSource;
 
 var _search = __webpack_require__(1115);
 
 var _selectors = __webpack_require__(242);
 
 var _sources = __webpack_require__(254);
@@ -1860,59 +1862,69 @@ function clearSearchQuery() {
   return (_ref2) => {
     var dispatch = _ref2.dispatch,
         getState = _ref2.getState;
 
     dispatch({ type: "CLEAR_QUERY" });
   };
 }
 
+function clearSearchResults() {
+  return (_ref3) => {
+    var dispatch = _ref3.dispatch,
+        getState = _ref3.getState;
+
+    dispatch({ type: "CLEAR_SEARCH_RESULTS" });
+  };
+}
+
 function searchSources(query) {
   return (() => {
-    var _ref3 = _asyncToGenerator(function* (_ref4) {
-      var dispatch = _ref4.dispatch,
-          getState = _ref4.getState;
-
+    var _ref4 = _asyncToGenerator(function* (_ref5) {
+      var dispatch = _ref5.dispatch,
+          getState = _ref5.getState;
+
+      yield dispatch(clearSearchResults());
       yield dispatch(addSearchQuery(query));
       yield dispatch((0, _sources.loadAllSources)());
       var sources = (0, _selectors.getSources)(getState());
       var validSources = sources.valueSeq().filter(function (source) {
         return source.has("text");
       }).toJS();
 
       for (var source of validSources) {
         yield dispatch(searchSource(source, query));
       }
     });
 
     return function (_x) {
-      return _ref3.apply(this, arguments);
+      return _ref4.apply(this, arguments);
     };
   })();
 }
 
 function searchSource(source, query) {
   return (() => {
-    var _ref5 = _asyncToGenerator(function* (_ref6) {
-      var dispatch = _ref6.dispatch,
-          getState = _ref6.getState;
+    var _ref6 = _asyncToGenerator(function* (_ref7) {
+      var dispatch = _ref7.dispatch,
+          getState = _ref7.getState;
 
       var matches = yield (0, _search.findSourceMatches)(source, query);
       dispatch({
         type: "ADD_SEARCH_RESULT",
         result: {
           sourceId: source.id,
           filepath: source.url,
           matches
         }
       });
     });
 
     return function (_x2) {
-      return _ref5.apply(this, arguments);
+      return _ref6.apply(this, arguments);
     };
   })();
 }
 
 /***/ }),
 /* 38 */,
 /* 39 */
 /***/ (function(module, exports, __webpack_require__) {
@@ -5956,26 +5968,26 @@ function renderRoot(_React, _ReactDOM, c
   // bail in test environments that do not have a mount
   if (!mount) {
     return;
   }
 
   var root = Root("launchpad-root theme-body");
   mount.appendChild(root);
 
+  if (isDevelopment()) {
+    updateConfig();
+    updateTheme();
+  }
+
   if (component.props || component.propTypes) {
     _ReactDOM.render(createElement(Provider, { store: _store }, createElement(component)), root);
   } else {
     root.appendChild(component);
   }
-
-  if (isDevelopment()) {
-    updateConfig();
-    updateTheme();
-  }
 }
 
 function unmountRoot(_ReactDOM) {
   var mount = document.querySelector("#mount .launchpad-root");
   _ReactDOM.unmountComponentAtNode(mount);
 }
 
 function getTargetFromQuery() {
@@ -15930,17 +15942,17 @@ function thunk(makeArgs) {
 
 "use strict";
 Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
 // @flow
 
 const { isDevelopment } = __webpack_require__(828);
 const { Services, PrefsHelper } = __webpack_require__(830);
 
-const prefsSchemaVersion = "1.0.2";
+const prefsSchemaVersion = "1.0.3";
 
 const pref = Services.pref;
 
 if (isDevelopment()) {
   pref("devtools.debugger.client-source-maps-enabled", true);
   pref("devtools.debugger.pause-on-exceptions", false);
   pref("devtools.debugger.ignore-caught-exceptions", false);
   pref("devtools.debugger.call-stack-visible", false);
@@ -15952,17 +15964,17 @@ if (isDevelopment()) {
   pref("devtools.debugger.pending-selected-location", "{}");
   pref("devtools.debugger.pending-breakpoints", "{}");
   pref("devtools.debugger.expressions", "[]");
   pref("devtools.debugger.file-search-case-sensitive", false);
   pref("devtools.debugger.file-search-whole-word", false);
   pref("devtools.debugger.file-search-regex-match", false);
   pref("devtools.debugger.prefs-schema-version", "1.0.1");
   pref("devtools.debugger.project-text-search-enabled", true);
-  pref("devtools.debugger.features.async-stepping", false);
+  pref("devtools.debugger.features.async-stepping", true);
 }
 
 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"],
@@ -15971,28 +15983,24 @@ const prefs = new PrefsHelper("devtools"
   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", []],
   fileSearchCaseSensitive: ["Bool", "debugger.file-search-case-sensitive"],
   fileSearchWholeWord: ["Bool", "debugger.file-search-whole-word"],
   fileSearchRegexMatch: ["Bool", "debugger.file-search-regex-match"],
-  debuggerPrefsSchemaVersion: ["Char", "debugger.prefs-schema-version"],
-  projectTextSearchEnabled: [
-    "Bool",
-    "debugger.project-text-search-enabled",
-    false
-  ]
+  debuggerPrefsSchemaVersion: ["Char", "debugger.prefs-schema-version"]
 });
 /* harmony export (immutable) */ __webpack_exports__["prefs"] = prefs;
 
 
 const features = new PrefsHelper("devtools.debugger.features", {
-  asyncStepping: ["Bool", "async-stepping", false]
+  asyncStepping: ["Bool", "async-stepping", false],
+  projectTextSearch: ["Bool", "debugger.project-text-search-enabled", true]
 });
 /* harmony export (immutable) */ __webpack_exports__["features"] = features;
 
 
 if (prefs.debuggerPrefsSchemaVersion !== prefsSchemaVersion) {
   // clear pending Breakpoints
   prefs.pendingBreakpoints = {};
   prefs.debuggerPrefsSchemaVersion = prefsSchemaVersion;
@@ -16821,23 +16829,30 @@ function getSourceLineCount(source) {
  * @return String
  * @memberof utils/source
  * @static
  */
 
 function getMode(source) {
   var contentType = source.contentType,
       text = source.text,
-      isWasm = source.isWasm;
+      isWasm = source.isWasm,
+      url = source.url;
 
 
   if (!text || isWasm) {
     return { name: "text" };
   }
 
+  // if the url ends with .marko we set the name to Javascript so
+  // syntax highlighting works for marko too
+  if (url && url.match(/\.marko$/i)) {
+    return { name: "javascript" };
+  }
+
   // Use HTML mode for files in which the first non whitespace
   // character is `<` regardless of extension.
   var isHTMLLike = text.match(/^\s*</);
   if (!contentType) {
     if (isHTMLLike) {
       return { name: "htmlmixed" };
     }
     return { name: "text" };
@@ -17044,17 +17059,17 @@ var _immutable = __webpack_require__(146
 var I = _interopRequireWildcard(_immutable);
 
 var _makeRecord = __webpack_require__(230);
 
 var _makeRecord2 = _interopRequireDefault(_makeRecord);
 
 var _devtoolsSourceMap = __webpack_require__(898);
 
-var _breakpoint2 = __webpack_require__(1057);
+var _breakpoint = __webpack_require__(1057);
 
 var _reselect = __webpack_require__(993);
 
 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 initialState() {
@@ -17071,17 +17086,17 @@ function update() {
   switch (action.type) {
     case "ADD_BREAKPOINT":
       {
         return addBreakpoint(state, action);
       }
 
     case "SYNC_BREAKPOINT":
       {
-        return addBreakpoint(state, action);
+        return syncBreakpoint(state, action);
       }
 
     case "ENABLE_BREAKPOINT":
       {
         return addBreakpoint(state, action);
       }
 
     case "DISABLE_BREAKPOINT":
@@ -17104,80 +17119,83 @@ function update() {
         return remapBreakpoints(state, action);
       }
   }
 
   return state;
 }
 
 function addBreakpoint(state, action) {
-  if (action.status === "start") {
+  if (action.status === "start" && action.breakpoint) {
     var breakpoint = action.breakpoint;
 
-    var locationId = (0, _breakpoint2.makeLocationId)(breakpoint.location);
+    var locationId = (0, _breakpoint.makeLocationId)(breakpoint.location);
     return state.setIn(["breakpoints", locationId], breakpoint);
   }
 
   // when the action completes, we can commit the breakpoint
   if (action.status === "done") {
-    var _action$value = action.value,
-        _breakpoint = _action$value.breakpoint,
-        previousLocation = _action$value.previousLocation;
-
-    var _locationId = (0, _breakpoint2.makeLocationId)(_breakpoint.location);
-
-    if (previousLocation) {
-      return state.deleteIn(["breakpoints", (0, _breakpoint2.makeLocationId)(previousLocation)]).setIn(["breakpoints", _locationId], _breakpoint);
-    }
-
-    return state.setIn(["breakpoints", _locationId], _breakpoint);
+    return syncBreakpoint(state, action.value);
   }
 
   // Remove the optimistic update
-  if (action.status === "error") {
-    var _locationId2 = (0, _breakpoint2.makeLocationId)(action.breakpoint.location);
-    return state.deleteIn(["breakpoints", _locationId2]);
+  if (action.status === "error" && action.breakpoint) {
+    var _locationId = (0, _breakpoint.makeLocationId)(action.breakpoint.location);
+    return state.deleteIn(["breakpoints", _locationId]);
   }
 
   return state;
 }
 
+function syncBreakpoint(state, data) {
+  var breakpoint = data.breakpoint,
+      previousLocation = data.previousLocation;
+
+  var locationId = (0, _breakpoint.makeLocationId)(breakpoint.location);
+
+  if (previousLocation) {
+    return state.deleteIn(["breakpoints", (0, _breakpoint.makeLocationId)(previousLocation)]).setIn(["breakpoints", locationId], breakpoint);
+  }
+
+  return state.setIn(["breakpoints", locationId], breakpoint);
+}
+
 function updateBreakpoint(state, action) {
   var breakpoint = action.breakpoint;
 
-  var locationId = (0, _breakpoint2.makeLocationId)(breakpoint.location);
+  var locationId = (0, _breakpoint.makeLocationId)(breakpoint.location);
   return state.setIn(["breakpoints", locationId], breakpoint);
 }
 
 function remapBreakpoints(state, action) {
   var breakpoints = action.breakpoints.reduce((updatedBreakpoints, breakpoint) => {
-    var locationId = (0, _breakpoint2.makeLocationId)(breakpoint.location);
+    var locationId = (0, _breakpoint.makeLocationId)(breakpoint.location);
     return _extends({}, updatedBreakpoints, { [locationId]: breakpoint });
   }, {});
 
   return state.set("breakpoints", I.Map(breakpoints));
 }
 
 function removeBreakpoint(state, action) {
   var breakpoint = action.breakpoint;
 
-  var id = (0, _breakpoint2.makeLocationId)(breakpoint.location);
+  var id = (0, _breakpoint.makeLocationId)(breakpoint.location);
   return state.deleteIn(["breakpoints", id]);
 }
 
 // Selectors
 // TODO: these functions should be moved out of the reducer
 
 function getBreakpoints(state) {
   return state.breakpoints.breakpoints;
 }
 
 function getBreakpoint(state, location) {
   var breakpoints = getBreakpoints(state);
-  return breakpoints.get((0, _breakpoint2.makeLocationId)(location));
+  return breakpoints.get((0, _breakpoint.makeLocationId)(location));
 }
 
 function getBreakpointsDisabled(state) {
   return state.breakpoints.breakpoints.every(x => x.disabled);
 }
 
 function getBreakpointsLoading(state) {
   var breakpoints = getBreakpoints(state);
@@ -17518,16 +17536,19 @@ function update() {
         shouldIgnoreCaughtExceptions: _shouldIgnoreCaughtExceptions
       });
 
     case "COMMAND":
       return _extends({}, state, { command: action.value.type });
 
     case "CLEAR_COMMAND":
       return _extends({}, state, { command: "" });
+
+    case "NAVIGATE":
+      return _extends({}, state, { debuggeeUrl: action.url });
   }
 
   return state;
 }
 
 // Selectors
 
 // Unfortunately, it's really hard to make these functions accept just
@@ -17606,17 +17627,17 @@ exports.default = update;
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.State = undefined;
-exports.getActiveSearchState = getActiveSearchState;
+exports.getActiveSearch = getActiveSearch;
 exports.getFileSearchQueryState = getFileSearchQueryState;
 exports.getFileSearchModifierState = getFileSearchModifierState;
 exports.getSearchResults = getSearchResults;
 exports.getFrameworkGroupingState = getFrameworkGroupingState;
 exports.getSymbolSearchType = getSymbolSearchType;
 exports.getShownSource = getShownSource;
 exports.getPaneCollapse = getPaneCollapse;
 exports.getHighlightedLineRange = getHighlightedLineRange;
@@ -17743,17 +17764,17 @@ function update() {
       {
         return state;
       }
   }
 }
 
 // NOTE: we'd like to have the app state fully typed
 // https://github.com/devtools-html/debugger.html/blob/master/src/reducers/sources.js#L179-L185
-function getActiveSearchState(state) {
+function getActiveSearch(state) {
   return state.ui.get("activeSearch");
 }
 
 function getFileSearchQueryState(state) {
   return state.ui.get("fileSearchQuery");
 }
 
 function getFileSearchModifierState(state) {
@@ -18022,42 +18043,82 @@ class App extends _react.Component {
     this.state = {
       horizontal: verticalLayoutBreakpoint.matches,
       startPanelSize: 0,
       endPanelSize: 0
     };
 
     this.getChildContext = this.getChildContext.bind(this);
     this.onLayoutChange = this.onLayoutChange.bind(this);
+    this.toggleSymbolModal = this.toggleSymbolModal.bind(this);
     this.renderEditorPane = this.renderEditorPane.bind(this);
     this.renderVerticalLayout = this.renderVerticalLayout.bind(this);
+    this.onEscape = this.onEscape.bind(this);
   }
 
   getChildContext() {
     return { shortcuts };
   }
 
   componentDidMount() {
     verticalLayoutBreakpoint.addListener(this.onLayoutChange);
+    shortcuts.on(L10N.getStr("symbolSearch.search.key2"), this.toggleSymbolModal);
+    shortcuts.on("Escape", this.onEscape);
   }
 
   componentWillUnmount() {
     verticalLayoutBreakpoint.removeListener(this.onLayoutChange);
+    shortcuts.off(L10N.getStr("symbolSearch.search.key2"), this.toggleSymbolModal);
+    shortcuts.off("Escape", this.onEscape);
+  }
+
+  onEscape(_, e) {
+    var _props = this.props,
+        activeSearch = _props.activeSearch,
+        closeActiveSearch = _props.closeActiveSearch;
+
+
+    if (activeSearch) {
+      e.preventDefault();
+      closeActiveSearch();
+    }
+  }
+
+  toggleSymbolModal(_, e) {
+    var _props2 = this.props,
+        selectedSource = _props2.selectedSource,
+        activeSearch = _props2.activeSearch,
+        closeActiveSearch = _props2.closeActiveSearch,
+        setActiveSearch = _props2.setActiveSearch;
+
+
+    e.preventDefault();
+    e.stopPropagation();
+
+    if (!selectedSource) {
+      return;
+    }
+
+    if (activeSearch == "symbol") {
+      return closeActiveSearch();
+    }
+
+    setActiveSearch("symbol");
   }
 
   onLayoutChange() {
     if ((0, _ui.isVisible)()) {
       this.setState({ horizontal: verticalLayoutBreakpoint.matches });
     }
   }
 
   renderEditorPane() {
-    var _props = this.props,
-        startPanelCollapsed = _props.startPanelCollapsed,
-        endPanelCollapsed = _props.endPanelCollapsed;
+    var _props3 = this.props,
+        startPanelCollapsed = _props3.startPanelCollapsed,
+        endPanelCollapsed = _props3.endPanelCollapsed;
     var _state = this.state,
         horizontal = _state.horizontal,
         endPanelSize = _state.endPanelSize,
         startPanelSize = _state.startPanelSize;
 
 
     return _react2.default.createElement(
       "div",
@@ -18079,19 +18140,19 @@ class App extends _react.Component {
         }),
         !this.props.selectedSource ? _react2.default.createElement(_WelcomeBox2.default, { horizontal: horizontal }) : null,
         _react2.default.createElement(_ProjectSearch2.default, null)
       )
     );
   }
 
   renderHorizontalLayout() {
-    var _props2 = this.props,
-        startPanelCollapsed = _props2.startPanelCollapsed,
-        endPanelCollapsed = _props2.endPanelCollapsed;
+    var _props4 = this.props,
+        startPanelCollapsed = _props4.startPanelCollapsed,
+        endPanelCollapsed = _props4.endPanelCollapsed;
     var horizontal = this.state.horizontal;
 
 
     var overflowX = endPanelCollapsed ? "hidden" : "auto";
 
     return _react2.default.createElement(_devtoolsSplitter2.default, {
       style: { width: "100vw" },
       initialSize: "250px",
@@ -18113,19 +18174,19 @@ class App extends _react.Component {
         endPanel: _react2.default.createElement(_SecondaryPanes2.default, { horizontal: horizontal }),
         endPanelCollapsed: endPanelCollapsed,
         vert: horizontal
       })
     });
   }
 
   renderVerticalLayout() {
-    var _props3 = this.props,
-        startPanelCollapsed = _props3.startPanelCollapsed,
-        endPanelCollapsed = _props3.endPanelCollapsed;
+    var _props5 = this.props,
+        startPanelCollapsed = _props5.startPanelCollapsed,
+        endPanelCollapsed = _props5.endPanelCollapsed;
     var horizontal = this.state.horizontal;
 
 
     return _react2.default.createElement(_devtoolsSplitter2.default, {
       style: { width: "100vw" },
       initialSize: "300px",
       minSize: 30,
       maxSize: "99%",
@@ -18141,42 +18202,52 @@ class App extends _react.Component {
         startPanel: _react2.default.createElement(_PrimaryPanes2.default, { horizontal: horizontal }),
         endPanel: this.renderEditorPane()
       }),
       endPanel: _react2.default.createElement(_SecondaryPanes2.default, { horizontal: horizontal }),
       endPanelCollapsed: endPanelCollapsed
     });
   }
 
-  render() {
-    var _props4 = this.props,
-        selectSource = _props4.selectSource,
-        selectedSource = _props4.selectedSource;
-
-
+  renderSymbolModal() {
+    var _props6 = this.props,
+        selectSource = _props6.selectSource,
+        selectedSource = _props6.selectedSource,
+        activeSearch = _props6.activeSearch;
+
+
+    if (activeSearch !== "symbol") {
+      return;
+    }
+
+    return _react2.default.createElement(_SymbolModal2.default, {
+      selectSource: selectSource,
+      selectedSource: selectedSource
+    });
+  }
+
+  render() {
     return _react2.default.createElement(
       "div",
       { className: "debugger" },
       this.state.horizontal ? this.renderHorizontalLayout() : this.renderVerticalLayout(),
-      _react2.default.createElement(_SymbolModal2.default, {
-        selectSource: selectSource,
-        selectedSource: selectedSource
-      })
+      this.renderSymbolModal()
     );
   }
 }
 
 App.displayName = "App";
 
 App.childContextTypes = { shortcuts: _react.PropTypes.object };
 
 exports.default = (0, _reactRedux.connect)(state => ({
   selectedSource: (0, _selectors.getSelectedSource)(state),
   startPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "start"),
-  endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end")
+  endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end"),
+  activeSearch: (0, _selectors.getActiveSearch)(state)
 }), dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(App);
 
 /***/ }),
 /* 244 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
@@ -18220,49 +18291,42 @@ var ast = _interopRequireWildcard(_ast);
 var _coverage = __webpack_require__(322);
 
 var coverage = _interopRequireWildcard(_coverage);
 
 var _projectTextSearch = __webpack_require__(37);
 
 var projectTextSearch = _interopRequireWildcard(_projectTextSearch);
 
-var _sourceSearch = __webpack_require__(1143);
+var _sourceSearch = __webpack_require__(1144);
 
 var sourceSearch = _interopRequireWildcard(_sourceSearch);
 
+var _loadSourceText = __webpack_require__(1143);
+
+var loadSourceText = _interopRequireWildcard(_loadSourceText);
+
 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; } }
 
-exports.default = Object.assign({}, navigation, breakpoints, expressions, eventListeners, sources, pause, ui, ast, coverage, projectTextSearch, sourceSearch);
+exports.default = Object.assign({}, navigation, breakpoints, expressions, eventListeners, sources, pause, ui, ast, coverage, projectTextSearch, sourceSearch, loadSourceText);
 
 /***/ }),
 /* 245 */
 /***/ (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"); } }; }();
 
 var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
-/* 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/. */
-
-/**
- * Redux actions for breakpoints
- * @module actions/breakpoints
- */
-
-// this will need to be changed so that addCLientBreakpoint is removed
-
 
 exports.syncBreakpoint = syncBreakpoint;
 exports.addBreakpoint = addBreakpoint;
 exports.addHiddenBreakpoint = addHiddenBreakpoint;
 exports.removeBreakpoint = removeBreakpoint;
 exports.enableBreakpoint = enableBreakpoint;
 exports.disableBreakpoint = disableBreakpoint;
 exports.toggleAllBreakpoints = toggleAllBreakpoints;
@@ -18289,101 +18353,111 @@ var _remapLocations = __webpack_require_
 
 var _remapLocations2 = _interopRequireDefault(_remapLocations);
 
 var _syncBreakpoint = __webpack_require__(1137);
 
 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"); }); }; }
+/* 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/. */
+
+/**
+ * Redux actions for breakpoints
+ * @module actions/breakpoints
+ */
+
+// this will need to be changed so that addCLientBreakpoint is removed
+
 
 /**
  * Syncing a breakpoint add breakpoint information that is stored, and
  * contact the server for more data.
  *
  * @memberof actions/breakpoints
  * @static
  * @param {String} $1.sourceId String  value
  * @param {PendingBreakpoint} $1.location PendingBreakpoint  value
  */
-function syncBreakpoint(source, pendingBreakpoint) {
-  return (_ref) => {
-    var dispatch = _ref.dispatch,
-        getState = _ref.getState,
-        client = _ref.client,
-        sourceMaps = _ref.sourceMaps;
-
-    var sourceId = source.id;
-    var _pendingBreakpoint$lo = pendingBreakpoint.location,
-        line = _pendingBreakpoint$lo.line,
-        sourceUrl = _pendingBreakpoint$lo.sourceUrl,
-        column = _pendingBreakpoint$lo.column;
-
-    var location = { sourceId, sourceUrl, line, column };
-    var breakpoint = (0, _breakpoint.createBreakpoint)(location, pendingBreakpoint);
-
-    var syncPromise = (0, _syncBreakpoint.syncClientBreakpoint)(getState, client, sourceMaps, source, pendingBreakpoint);
-
-    return dispatch({
-      type: "SYNC_BREAKPOINT",
-      breakpoint,
-      [_promise.PROMISE]: syncPromise
-    });
-  };
+function syncBreakpoint(sourceId, pendingBreakpoint) {
+  return (() => {
+    var _ref = _asyncToGenerator(function* (_ref2) {
+      var dispatch = _ref2.dispatch,
+          getState = _ref2.getState,
+          client = _ref2.client,
+          sourceMaps = _ref2.sourceMaps;
+
+      var _ref3 = yield (0, _syncBreakpoint.syncClientBreakpoint)(getState, client, sourceMaps, sourceId, pendingBreakpoint),
+          breakpoint = _ref3.breakpoint,
+          previousLocation = _ref3.previousLocation;
+
+      return dispatch({
+        type: "SYNC_BREAKPOINT",
+        breakpoint,
+        previousLocation
+      });
+    });
+
+    return function (_x) {
+      return _ref.apply(this, arguments);
+    };
+  })();
 }
 
 /**
  * Add a new breakpoint
  *
  * @memberof actions/breakpoints
  * @static
  * @param {String} $1.condition Conditional breakpoint condition value
  * @param {Boolean} $1.disabled Disable value for breakpoint value
  */
 
 function addBreakpoint(location, condition, hidden) {
   var breakpoint = (0, _breakpoint.createBreakpoint)(location, { condition, hidden });
-  return (_ref2) => {
-    var dispatch = _ref2.dispatch,
-        getState = _ref2.getState,
-        sourceMaps = _ref2.sourceMaps,
-        client = _ref2.client;
+  return (_ref4) => {
+    var dispatch = _ref4.dispatch,
+        getState = _ref4.getState,
+        sourceMaps = _ref4.sourceMaps,
+        client = _ref4.client;
 
     var action = { type: "ADD_BREAKPOINT", breakpoint };
     var promise = (0, _addBreakpoint2.default)(getState, client, sourceMaps, action);
     return dispatch(_extends({}, action, { [_promise.PROMISE]: promise }));
   };
 }
 
 /**
  * Add a new hidden breakpoint
  *
  * @memberOf actions/breakpoints
  * @param location
  * @return {function(ThunkArgs)}
  */
 function addHiddenBreakpoint(location) {
-  return (_ref3) => {
-    var dispatch = _ref3.dispatch;
+  return (_ref5) => {
+    var dispatch = _ref5.dispatch;
 
     return dispatch(addBreakpoint(location, "", true));
   };
 }
 
 /**
  * Remove a single breakpoint
  *
  * @memberof actions/breakpoints
  * @static
  */
 function removeBreakpoint(location) {
-  return (_ref4) => {
-    var dispatch = _ref4.dispatch,
-        getState = _ref4.getState,
-        client = _ref4.client;
+  return (_ref6) => {
+    var dispatch = _ref6.dispatch,
+        getState = _ref6.getState,
+        client = _ref6.client;
 
     var bp = (0, _selectors.getBreakpoint)(getState(), location);
     if (!bp) {
       throw new Error("attempt to remove breakpoint that does not exist");
     }
 
     if (bp.loading) {
       // TODO(jwl): make this wait until the breakpoint is saved if it
@@ -18415,54 +18489,54 @@ function removeBreakpoint(location) {
  * will reuse the existing breakpoint information that is stored.
  *
  * @memberof actions/breakpoints
  * @static
  * @param {Location} $1.location Location  value
  */
 function enableBreakpoint(location) {
   return (() => {
-    var _ref5 = _asyncToGenerator(function* (_ref6) {
-      var dispatch = _ref6.dispatch,
-          getState = _ref6.getState,
-          client = _ref6.client,
-          sourceMaps = _ref6.sourceMaps;
+    var _ref7 = _asyncToGenerator(function* (_ref8) {
+      var dispatch = _ref8.dispatch,
+          getState = _ref8.getState,
+          client = _ref8.client,
+          sourceMaps = _ref8.sourceMaps;
 
       var breakpoint = (0, _selectors.getBreakpoint)(getState(), location);
       if (!breakpoint) {
         throw new Error("attempted to enable a breakpoint that does not exist");
       }
 
       var action = { type: "ENABLE_BREAKPOINT", breakpoint };
       var promise = (0, _addBreakpoint2.default)(getState, client, sourceMaps, action);
       return dispatch({
         type: "ENABLE_BREAKPOINT",
         breakpoint,
         [_promise.PROMISE]: promise
       });
     });
 
-    return function (_x) {
-      return _ref5.apply(this, arguments);
+    return function (_x2) {
+      return _ref7.apply(this, arguments);
     };
   })();
 }
 
 /**
  * Disable a single breakpoint
  *
  * @memberof actions/breakpoints
  * @static
  */
 function disableBreakpoint(location) {
   return (() => {
-    var _ref7 = _asyncToGenerator(function* (_ref8) {
-      var dispatch = _ref8.dispatch,
-          getState = _ref8.getState,
-          client = _ref8.client;
+    var _ref9 = _asyncToGenerator(function* (_ref10) {
+      var dispatch = _ref10.dispatch,
+          getState = _ref10.getState,
+          client = _ref10.client;
 
       var bp = (0, _selectors.getBreakpoint)(getState(), location);
 
       if (!bp) {
         throw new Error("attempt to disable a breakpoint that does not exist");
       }
 
       if (bp.loading) {
@@ -18475,156 +18549,156 @@ function disableBreakpoint(location) {
       var newBreakpoint = _extends({}, bp, { disabled: true });
 
       return dispatch({
         type: "DISABLE_BREAKPOINT",
         breakpoint: newBreakpoint
       });
     });
 
-    return function (_x2) {
-      return _ref7.apply(this, arguments);
+    return function (_x3) {
+      return _ref9.apply(this, arguments);
     };
   })();
 }
 
 /**
  * Toggle All Breakpoints
  *
  * @memberof actions/breakpoints
  * @static
  */
 function toggleAllBreakpoints(shouldDisableBreakpoints) {
   return (() => {
-    var _ref9 = _asyncToGenerator(function* (_ref10) {
-      var dispatch = _ref10.dispatch,
-          getState = _ref10.getState;
+    var _ref11 = _asyncToGenerator(function* (_ref12) {
+      var dispatch = _ref12.dispatch,
+          getState = _ref12.getState;
 
       var breakpoints = (0, _selectors.getBreakpoints)(getState());
-      for (var _ref11 of breakpoints) {
-        var _ref12 = _slicedToArray(_ref11, 2);
-
-        var breakpoint = _ref12[1];
+      for (var _ref13 of breakpoints) {
+        var _ref14 = _slicedToArray(_ref13, 2);
+
+        var breakpoint = _ref14[1];
 
         if (shouldDisableBreakpoints) {
           yield dispatch(disableBreakpoint(breakpoint.location));
         } else {
           yield dispatch(enableBreakpoint(breakpoint.location));
         }
       }
     });
 
-    return function (_x3) {
-      return _ref9.apply(this, arguments);
+    return function (_x4) {
+      return _ref11.apply(this, arguments);
     };
   })();
 }
 
 /**
  * Toggle Breakpoints
  *
  * @memberof actions/breakpoints
  * @static
  */
 function toggleBreakpoints(shouldDisableBreakpoints, breakpoints) {
   return (() => {
-    var _ref13 = _asyncToGenerator(function* (_ref14) {
-      var dispatch = _ref14.dispatch;
-
-      for (var _ref15 of breakpoints) {
-        var _ref16 = _slicedToArray(_ref15, 2);
-
-        var breakpoint = _ref16[1];
+    var _ref15 = _asyncToGenerator(function* (_ref16) {
+      var dispatch = _ref16.dispatch;
+
+      for (var _ref17 of breakpoints) {
+        var _ref18 = _slicedToArray(_ref17, 2);
+
+        var breakpoint = _ref18[1];
 
         if (shouldDisableBreakpoints) {
           yield dispatch(disableBreakpoint(breakpoint.location));
         } else {
           yield dispatch(enableBreakpoint(breakpoint.location));
         }
       }
     });
 
-    return function (_x4) {
-      return _ref13.apply(this, arguments);
+    return function (_x5) {
+      return _ref15.apply(this, arguments);
     };
   })();
 }
 
 /**
  * Removes all breakpoints
  *
  * @memberof actions/breakpoints
  * @static
  */
 function removeAllBreakpoints() {
   return (() => {
-    var _ref17 = _asyncToGenerator(function* (_ref18) {
-      var dispatch = _ref18.dispatch,
-          getState = _ref18.getState;
+    var _ref19 = _asyncToGenerator(function* (_ref20) {
+      var dispatch = _ref20.dispatch,
+          getState = _ref20.getState;
 
       var breakpoints = (0, _selectors.getBreakpoints)(getState());
-      for (var _ref19 of breakpoints) {
-        var _ref20 = _slicedToArray(_ref19, 2);
-
-        var breakpoint = _ref20[1];
+      for (var _ref21 of breakpoints) {
+        var _ref22 = _slicedToArray(_ref21, 2);
+
+        var breakpoint = _ref22[1];
 
         yield dispatch(removeBreakpoint(breakpoint.location));
       }
     });
 
-    return function (_x5) {
-      return _ref17.apply(this, arguments);
+    return function (_x6) {
+      return _ref19.apply(this, arguments);
     };
   })();
 }
 
 /**
  * Removes breakpoints
  *
  * @memberof actions/breakpoints
  * @static
  */
 function removeBreakpoints(breakpoints) {
   return (() => {
-    var _ref21 = _asyncToGenerator(function* (_ref22) {
-      var dispatch = _ref22.dispatch;
-
-      for (var _ref23 of breakpoints) {
-        var _ref24 = _slicedToArray(_ref23, 2);
-
-        var breakpoint = _ref24[1];
+    var _ref23 = _asyncToGenerator(function* (_ref24) {
+      var dispatch = _ref24.dispatch;
+
+      for (var _ref25 of breakpoints) {
+        var _ref26 = _slicedToArray(_ref25, 2);
+
+        var breakpoint = _ref26[1];
 
         yield dispatch(removeBreakpoint(breakpoint.location));
       }
     });
 
-    return function (_x6) {
-      return _ref21.apply(this, arguments);
+    return function (_x7) {
+      return _ref23.apply(this, arguments);
     };
   })();
 }
 
 function remapBreakpoints(sourceId) {
   return (() => {
-    var _ref25 = _asyncToGenerator(function* (_ref26) {
-      var dispatch = _ref26.dispatch,
-          getState = _ref26.getState,
-          sourceMaps = _ref26.sourceMaps;
+    var _ref27 = _asyncToGenerator(function* (_ref28) {
+      var dispatch = _ref28.dispatch,
+          getState = _ref28.getState,
+          sourceMaps = _ref28.sourceMaps;
 
       var breakpoints = (0, _selectors.getBreakpoints)(getState());
       var newBreakpoints = yield (0, _remapLocations2.default)(breakpoints, sourceId, sourceMaps);
 
       return dispatch({
         type: "REMAP_BREAKPOINTS",
         breakpoints: newBreakpoints
       });
     });
 
-    return function (_x7) {
-      return _ref25.apply(this, arguments);
+    return function (_x8) {
+      return _ref27.apply(this, arguments);
     };
   })();
 }
 
 /**
  * Update the condition of a breakpoint.
  *
  * @throws {Error} "not implemented"
@@ -18632,25 +18706,25 @@ function remapBreakpoints(sourceId) {
  * @static
  * @param {Location} location
  *        @see DebuggerController.Breakpoints.addBreakpoint
  * @param {string} condition
  *        The condition to set on the breakpoint
  * @param {Boolean} $1.disabled Disable value for breakpoint value
  */
 function setBreakpointCondition(location) {
-  var _ref27 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
-      condition = _ref27.condition;
+  var _ref29 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+      condition = _ref29.condition;
 
   return (() => {
-    var _ref28 = _asyncToGenerator(function* (_ref29) {
-      var dispatch = _ref29.dispatch,
-          getState = _ref29.getState,
-          client = _ref29.client,
-          sourceMaps = _ref29.sourceMaps;
+    var _ref30 = _asyncToGenerator(function* (_ref31) {
+      var dispatch = _ref31.dispatch,
+          getState = _ref31.getState,
+          client = _ref31.client,
+          sourceMaps = _ref31.sourceMaps;
 
       var bp = (0, _selectors.getBreakpoint)(getState(), location);
       if (!bp) {
         return dispatch(addBreakpoint(location, condition));
       }
 
       if (bp.loading) {
         // TODO(jwl): when this function is called, make sure the action
@@ -18670,28 +18744,28 @@ function setBreakpointCondition(location
       (0, _breakpoint.assertBreakpoint)(newBreakpoint);
 
       return dispatch({
         type: "SET_BREAKPOINT_CONDITION",
         breakpoint: newBreakpoint
       });
     });
 
-    return function (_x9) {
-      return _ref28.apply(this, arguments);
+    return function (_x10) {
+      return _ref30.apply(this, arguments);
     };
   })();
 }
 
 function toggleBreakpoint(line, column) {
-  return (_ref30) => {
-    var dispatch = _ref30.dispatch,
-        getState = _ref30.getState,
-        client = _ref30.client,
-        sourceMaps = _ref30.sourceMaps;
+  return (_ref32) => {
+    var dispatch = _ref32.dispatch,
+        getState = _ref32.getState,
+        client = _ref32.client,
+        sourceMaps = _ref32.sourceMaps;
 
     var selectedSource = (0, _selectors.getSelectedSource)(getState());
     var bp = (0, _selectors.getBreakpointAtLocation)(getState(), { line, column });
 
     if (bp && bp.loading) {
       return;
     }
 
@@ -18710,21 +18784,21 @@ function toggleBreakpoint(line, column) 
       sourceUrl: selectedSource.get("url"),
       line: line,
       column: column
     }));
   };
 }
 
 function addOrToggleDisabledBreakpoint(line, column) {
-  return (_ref31) => {
-    var dispatch = _ref31.dispatch,
-        getState = _ref31.getState,
-        client = _ref31.client,
-        sourceMaps = _ref31.sourceMaps;
+  return (_ref33) => {
+    var dispatch = _ref33.dispatch,
+        getState = _ref33.getState,
+        client = _ref33.client,
+        sourceMaps = _ref33.sourceMaps;
 
     var selectedSource = (0, _selectors.getSelectedSource)(getState());
     var bp = (0, _selectors.getBreakpointAtLocation)(getState(), { line, column });
 
     if (bp && bp.loading) {
       return;
     }
 
@@ -18738,21 +18812,21 @@ function addOrToggleDisabledBreakpoint(l
       sourceUrl: selectedSource.get("url"),
       line: line,
       column: column
     }));
   };
 }
 
 function toggleDisabledBreakpoint(line, column) {
-  return (_ref32) => {
-    var dispatch = _ref32.dispatch,
-        getState = _ref32.getState,
-        client = _ref32.client,
-        sourceMaps = _ref32.sourceMaps;
+  return (_ref34) => {
+    var dispatch = _ref34.dispatch,
+        getState = _ref34.getState,
+        client = _ref34.client,
+        sourceMaps = _ref34.sourceMaps;
 
     var bp = (0, _selectors.getBreakpointAtLocation)(getState(), { line, column });
     if (bp && bp.loading) {
       return;
     }
 
     if (!bp) {
       throw new Error("attempt to disable breakpoint that does not exist");
@@ -19492,32 +19566,34 @@ var checkSelectedSource = (() => {
 
 var checkPendingBreakpoint = (() => {
   var _ref2 = _asyncToGenerator(function* (state, dispatch, pendingBreakpoint, source) {
     var sourceUrl = pendingBreakpoint.location.sourceUrl;
 
     var sameSource = sourceUrl && sourceUrl === source.url;
 
     if (sameSource) {
-      yield dispatch((0, _breakpoints.syncBreakpoint)(source, pendingBreakpoint));
+      yield dispatch((0, _breakpoints.syncBreakpoint)(source.id, pendingBreakpoint));
     }
   });
 
   return function checkPendingBreakpoint(_x4, _x5, _x6, _x7) {
     return _ref2.apply(this, arguments);
   };
 })();
 
 var checkPendingBreakpoints = (() => {
   var _ref3 = _asyncToGenerator(function* (state, dispatch, source) {
-    var pendingBreakpoints = (0, _selectors.getPendingBreakpoints)(state);
-    if (!pendingBreakpoints) {
-      return;
-    }
-
+    var pendingBreakpoints = (0, _selectors.getPendingBreakpointsForSource)(state, source.url);
+    if (!pendingBreakpoints.size) {
+      return;
+    }
+
+    // load the source text if there is a pending breakpoint for it
+    yield dispatch((0, _loadSourceText.loadSourceText)(source));
     var pendingBreakpointsArray = pendingBreakpoints.valueSeq().toJS();
     for (var pendingBreakpoint of pendingBreakpointsArray) {
       yield checkPendingBreakpoint(state, dispatch, pendingBreakpoint, source);
     }
   });
 
   return function checkPendingBreakpoints(_x8, _x9, _x10) {
     return _ref3.apply(this, arguments);
@@ -19537,35 +19613,38 @@ exports.selectSourceURL = selectSourceUR
 exports.selectSource = selectSource;
 exports.jumpToMappedLocation = jumpToMappedLocation;
 exports.addTab = addTab;
 exports.moveTab = moveTab;
 exports.closeTab = closeTab;
 exports.closeTabs = closeTabs;
 exports.togglePrettyPrint = togglePrettyPrint;
 exports.toggleBlackBox = toggleBlackBox;
-exports.loadSourceText = loadSourceText;
 exports.loadAllSources = loadAllSources;
 
 var _promise = __webpack_require__(193);
 
 var _assert = __webpack_require__(223);
 
 var _assert2 = _interopRequireDefault(_assert);
 
 var _breakpoints = __webpack_require__(245);
 
 var _ast = __webpack_require__(1059);
 
 var _projectTextSearch = __webpack_require__(37);
 
+var _ui = __webpack_require__(321);
+
 var _source = __webpack_require__(233);
 
 var _createPrettySource = __webpack_require__(195);
 
+var _loadSourceText = __webpack_require__(1143);
+
 var _prefs = __webpack_require__(226);
 
 var _editor = __webpack_require__(257);
 
 var _selectors = __webpack_require__(242);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
@@ -19718,30 +19797,30 @@ function selectSource(id) {
     }
 
     var source = (0, _selectors.getSource)(getState(), id);
     if (!source) {
       // If there is no source we deselect the current selected source
       return dispatch({ type: "CLEAR_SELECTED_SOURCE" });
     }
 
-    var activeSearch = (0, _selectors.getActiveSearchState)(getState());
+    var activeSearch = (0, _selectors.getActiveSearch)(getState());
     if (activeSearch !== "file") {
-      dispatch({ type: "TOGGLE_ACTIVE_SEARCH", value: null });
+      dispatch((0, _ui.closeActiveSearch)());
     }
 
     dispatch(addTab(source.toJS(), 0));
 
     return dispatch({
       type: "SELECT_SOURCE",
       source: source.toJS(),
       tabIndex: options.tabIndex,
       line: options.line,
       [_promise.PROMISE]: _asyncToGenerator(function* () {
-        yield dispatch(loadSourceText(source.toJS()));
+        yield dispatch((0, _loadSourceText.loadSourceText)(source.toJS()));
         yield dispatch((0, _ast.setOutOfScopeLocations)());
       })()
     });
   };
 }
 
 /**
  * @memberof actions/sources
@@ -19913,90 +19992,45 @@ function toggleBlackBox(source) {
 
     return function (_x19) {
       return _ref21.apply(this, arguments);
     };
   })();
 }
 
 /**
- * @memberof actions/sources
- * @static
- */
-function loadSourceText(source) {
-  return (() => {
-    var _ref23 = _asyncToGenerator(function* (_ref24) {
-      var dispatch = _ref24.dispatch,
-          getState = _ref24.getState,
-          client = _ref24.client,
-          sourceMaps = _ref24.sourceMaps;
-
-      // Fetch the source text only once.
-      if (source.text) {
-        return Promise.resolve(source);
-      }
-
-      yield dispatch({
-        type: "LOAD_SOURCE_TEXT",
-        source: source,
-        [_promise.PROMISE]: _asyncToGenerator(function* () {
-          if (sourceMaps.isOriginalId(source.id)) {
-            return yield sourceMaps.getOriginalSourceText(source);
-          }
-
-          var response = yield client.sourceContents(source.id);
-
-          return {
-            id: source.id,
-            text: response.source,
-            contentType: response.contentType || "text/javascript"
-          };
-        })()
-      });
-
-      yield dispatch((0, _ast.setSymbols)(source.id));
-      yield dispatch((0, _ast.setEmptyLines)(source.id));
-    });
-
-    return function (_x20) {
-      return _ref23.apply(this, arguments);
-    };
-  })();
-}
-
-/**
   Load the text for all the avaliable sources
  * @memberof actions/sources
  * @static
  */
 function loadAllSources() {
   return (() => {
-    var _ref26 = _asyncToGenerator(function* (_ref27) {
-      var dispatch = _ref27.dispatch,
-          getState = _ref27.getState;
+    var _ref23 = _asyncToGenerator(function* (_ref24) {
+      var dispatch = _ref24.dispatch,
+          getState = _ref24.getState;
 
       var sources = (0, _selectors.getSources)(getState());
       var query = (0, _selectors.getTextSearchQuery)(getState());
-      for (var _ref28 of sources) {
-        var _ref29 = _slicedToArray(_ref28, 2);
-
-        var src = _ref29[1];
+      for (var _ref25 of sources) {
+        var _ref26 = _slicedToArray(_ref25, 2);
+
+        var src = _ref26[1];
 
         var source = src.toJS();
-        yield dispatch(loadSourceText(source));
+        yield dispatch((0, _loadSourceText.loadSourceText)(source));
         // If there is a current search query we search
         // each of the source texts as they get loaded
         if (query) {
           yield dispatch((0, _projectTextSearch.searchSource)(source, query));
         }
       }
     });
 
-    return function (_x21) {
-      return _ref26.apply(this, arguments);
+    return function (_x20) {
+      return _ref23.apply(this, arguments);
     };
   })();
 }
 
 /***/ }),
 /* 255 */
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -20459,51 +20493,39 @@ function isWhitespace(query) {
  * Also the token function code is mainly based of work done
  * by the chrome devtools team. Thanks guys! :)
  *
  * @memberof utils/source-search
  * @static
  */
 function searchOverlay(query, modifiers) {
   var regexQuery = (0, _buildQuery2.default)(query, modifiers, {
-    ignoreSpaces: true
-  });
-
-  var matchLength = null;
-
-  return {
-    token: function (stream) {
-      if (stream.column() === 0) {
-        matchLength = null;
-      }
-      if (matchLength !== null) {
-        if (matchLength > 2) {
-          for (var i = 0; i < matchLength - 2; ++i) {
-            stream.next();
-          }
-          matchLength = 1;
-          return "highlight";
-        }
-        stream.next();
-        matchLength = null;
-        return "highlight highlight-end";
-      }
-
-      var match = stream.match(regexQuery, false);
-      if (match) {
-        stream.next();
-        var len = match[0].length;
-        if (len === 1) {
-          return "highlight highlight-full";
-        }
-        matchLength = len;
-        return "highlight highlight-start";
-      }
-      while (!stream.match(regexQuery, false) && stream.peek()) {
-        stream.next();
+    ignoreSpaces: true,
+    // regex must be global for the overlay
+    isGlobal: true
+  });
+
+  return {
+    token: function (stream, state) {
+      // set the last index to be the current stream position
+      // this acts as an offset
+      regexQuery.lastIndex = stream.pos;
+      var match = regexQuery.exec(stream.string);
+      if (match && match.index === stream.pos) {
+        // if we have a match at the current stream position
+        // set the class for a match
+        stream.pos += match[0].length || 1;
+        return "highlight highlight-full";
+      } else if (match) {
+        // if we have a match somewhere in the line, go to that point in the
+        // stream
+        stream.pos = match.index;
+      } else {
+        // if we have no matches in this line, skip to the end of the line
+        stream.skipToEnd();
       }
     }
   };
 }
 
 /**
  * @memberof utils/source-search
  * @static
@@ -20553,16 +20575,17 @@ function doSearch(ctx, rev, query, keepS
 
   if (!cm) {
     return;
   }
   var defaultIndex = { line: -1, ch: -1 };
 
   return cm.operation(function () {
     if (!query || isWhitespace(query)) {
+      clearSearch(cm, query, modifiers);
       return;
     }
 
     var state = getSearchState(cm, query, modifiers);
     var isNewQuery = state.query !== query;
     state.query = query;
 
     updateOverlay(cm, state, query, modifiers);
@@ -21413,46 +21436,49 @@ function pauseOnExceptions(shouldPauseOn
 
 /**
  * Debugger commands like stepOver, stepIn, stepUp
  *
  * @param string $0.type
  * @memberof actions/pause
  * @static
  */
-function command(_ref5) {
-  var type = _ref5.type;
-
-  return (_ref6) => {
-    var dispatch = _ref6.dispatch,
-        client = _ref6.client;
-
-    // execute debugger thread command e.g. stepIn, stepOver
-    client[type]().then(() => dispatch({ type: "CLEAR_COMMAND" }));
-
-    return dispatch({
-      type: "COMMAND",
-      value: { type }
-    });
-  };
+function command(type) {
+  return (() => {
+    var _ref5 = _asyncToGenerator(function* (_ref6) {
+      var dispatch = _ref6.dispatch,
+          client = _ref6.client;
+
+      // execute debugger thread command e.g. stepIn, stepOver
+      dispatch({ type: "COMMAND", value: { type } });
+
+      yield client[type]();
+
+      dispatch({ type: "CLEAR_COMMAND" });
+    });
+
+    return function (_x2) {
+      return _ref5.apply(this, arguments);
+    };
+  })();
 }
 
 /**
  * StepIn
  * @memberof actions/pause
  * @static
  * @returns {Function} {@link command}
  */
 function stepIn() {
   return (_ref7) => {
     var dispatch = _ref7.dispatch,
         getState = _ref7.getState;
 
     if ((0, _selectors.getPause)(getState())) {
-      return dispatch(astCommand("stepIn"));
+      return dispatch(command("stepIn"));
     }
   };
 }
 
 /**
  * stepOver
  * @memberof actions/pause
  * @static
@@ -21476,34 +21502,34 @@ function stepOver() {
  * @returns {Function} {@link command}
  */
 function stepOut() {
   return (_ref9) => {
     var dispatch = _ref9.dispatch,
         getState = _ref9.getState;
 
     if ((0, _selectors.getPause)(getState())) {
-      return dispatch(astCommand("stepOut"));
+      return dispatch(command("stepOut"));
     }
   };
 }
 
 /**
  * resume
  * @memberof actions/pause
  * @static
  * @returns {Function} {@link command}
  */
 function resume() {
   return (_ref10) => {
     var dispatch = _ref10.dispatch,
         getState = _ref10.getState;
 
     if ((0, _selectors.getPause)(getState())) {
-      return dispatch(command({ type: "resume" }));
+      return dispatch(command("resume"));
     }
   };
 }
 
 /**
  * Debugger breakOnNext command.
  * It's different from the comand action because we also want to
  * highlight the pause icon.
@@ -21542,17 +21568,17 @@ function selectFrame(frame) {
 
       dispatch({
         type: "SELECT_FRAME",
         frame,
         scopes
       });
     });
 
-    return function (_x2) {
+    return function (_x3) {
       return _ref12.apply(this, arguments);
     };
   })();
 }
 
 /**
  * @memberof actions/pause
  * @static
@@ -21586,38 +21612,41 @@ function loadObjectProperties(object) {
 function astCommand(stepType) {
   return (() => {
     var _ref15 = _asyncToGenerator(function* (_ref16) {
       var dispatch = _ref16.dispatch,
           getState = _ref16.getState,
           sourceMaps = _ref16.sourceMaps;
 
       if (!_prefs.features.asyncStepping) {
-        return dispatch(command({ type: stepType }));
+        return dispatch(command(stepType));
       }
 
       var pauseInfo = (0, _selectors.getPause)(getState());
       var source = (0, _selectors.getSelectedSource)(getState()).toJS();
       var currentHiddenBreakpointLocation = (0, _breakpoints2.getHiddenBreakpointLocation)(getState());
+
       if (currentHiddenBreakpointLocation) {
         dispatch((0, _breakpoints.removeBreakpoint)(currentHiddenBreakpointLocation));
       }
+
       var pausedPosition = yield (0, _pause.getPausedPosition)(pauseInfo, sourceMaps);
 
-      var _ref17 = yield parser.getNextStep(source, stepType, pausedPosition),
-          nextStepType = _ref17.nextStepType,
-          nextHiddenBreakpointLocation = _ref17.nextHiddenBreakpointLocation;
-
-      if (nextHiddenBreakpointLocation) {
-        yield dispatch((0, _breakpoints.addHiddenBreakpoint)(nextHiddenBreakpointLocation));
-      }
-      return dispatch(command({ type: nextStepType }));
-    });
-
-    return function (_x3) {
+      if (stepType == "stepOver") {
+        var nextLocation = yield parser.getNextStep(source, pausedPosition);
+        if (nextLocation) {
+          yield dispatch((0, _breakpoints.addHiddenBreakpoint)(nextLocation));
+          return dispatch(command("resume"));
+        }
+      }
+
+      return dispatch(command(stepType));
+    });
+
+    return function (_x4) {
       return _ref15.apply(this, arguments);
     };
   })();
 }
 
 /***/ }),
 /* 320 */
 /***/ (function(module, exports, __webpack_require__) {
@@ -21663,16 +21692,17 @@ function willNavigate(_, event) {
           getState = _ref2.getState,
           client = _ref2.client,
           sourceMaps = _ref2.sourceMaps;
 
       yield sourceMaps.clearSourceMaps();
       (0, _wasm.clearWasmStates)();
       (0, _editor.clearDocuments)();
       (0, _parser.clearSymbols)();
+      (0, _parser.clearASTs)();
 
       dispatch(navigate(event.url));
     });
 
     return function (_x) {
       return _ref.apply(this, arguments);
     };
   })();
@@ -21735,55 +21765,69 @@ exports.updateSearchResults = updateSear
 exports.toggleFileSearchModifier = toggleFileSearchModifier;
 exports.showSource = showSource;
 exports.togglePaneCollapse = togglePaneCollapse;
 exports.highlightLineRange = highlightLineRange;
 exports.clearHighlightLineRange = clearHighlightLineRange;
 
 var _selectors = __webpack_require__(242);
 
+var _sourceSearch = __webpack_require__(1144);
+
 function closeActiveSearch() {
-  return {
-    type: "TOGGLE_ACTIVE_SEARCH",
-    value: null
-  };
-}
+  return (_ref) => {
+    var getState = _ref.getState,
+        dispatch = _ref.dispatch;
+
+    var activeSearch = (0, _selectors.getActiveSearch)(getState());
+
+    if (activeSearch == "source") {
+      dispatch((0, _sourceSearch.clearSourceSearchQuery)());
+    }
+
+    dispatch({
+      type: "TOGGLE_ACTIVE_SEARCH",
+      value: null
+    });
+  };
+}
+
 function setActiveSearch(activeSearch) {
-  return (_ref) => {
-    var dispatch = _ref.dispatch,
-        getState = _ref.getState;
-
-    var activeSearchState = (0, _selectors.getActiveSearchState)(getState());
+  return (_ref2) => {
+    var dispatch = _ref2.dispatch,
+        getState = _ref2.getState;
+
+    var activeSearchState = (0, _selectors.getActiveSearch)(getState());
     if (activeSearchState === activeSearch) {
       return;
     }
 
     dispatch({
       type: "TOGGLE_ACTIVE_SEARCH",
       value: activeSearch
     });
   };
 }
 
 function toggleFrameworkGrouping(toggleValue) {
-  return (_ref2) => {
-    var dispatch = _ref2.dispatch,
-        getState = _ref2.getState;
+  return (_ref3) => {
+    var dispatch = _ref3.dispatch,
+        getState = _ref3.getState;
 
     dispatch({
       type: "TOGGLE_FRAMEWORK_GROUPING",
       value: toggleValue
     });
   };
 }
 
 function setSelectedSymbolType(symbolType) {
-  return (_ref3) => {
-    var dispatch = _ref3.dispatch,
-        getState = _ref3.getState;
+  return (_ref4) => {
+    var dispatch = _ref4.dispatch,
+        getState = _ref4.getState;
 
     dispatch({
       type: "SET_SYMBOL_SEARCH_TYPE",
       symbolType
     });
   };
 }
 
@@ -21801,19 +21845,19 @@ function updateSearchResults(results) {
   };
 }
 
 function toggleFileSearchModifier(modifier) {
   return { type: "TOGGLE_FILE_SEARCH_MODIFIER", modifier };
 }
 
 function showSource(sourceId) {
-  return (_ref4) => {
-    var dispatch = _ref4.dispatch,
-        getState = _ref4.getState;
+  return (_ref5) => {
+    var dispatch = _ref5.dispatch,
+        getState = _ref5.getState;
 
     var source = (0, _selectors.getSource)(getState(), sourceId);
 
     dispatch({
       type: "SHOW_SOURCE",
       sourceUrl: ""
     });
 
@@ -24364,19 +24408,19 @@ var isMacOS = appinfo.OS === "Darwin";
  *
  * For Win/Lin this replaces CommandOrControl or CmdOrCtrl with Ctrl
  *
  * @memberof utils/text
  * @static
  */
 function formatKeyShortcut(shortcut) {
   if (isMacOS) {
-    return shortcut.replace(/Shift\+/g, "\u21E7+").replace(/Command\+|Cmd\+/g, "\u2318+").replace(/CommandOrControl\+|CmdOrCtrl\+/g, "\u2318+").replace(/Alt\+/g, "\u2325+");
-  }
-  return shortcut.replace(/CommandOrControl\+|CmdOrCtrl\+/g, `${L10N.getStr("ctrl")}+`);
+    return shortcut.replace(/Shift\+/g, "\u21E7 ").replace(/Command\+|Cmd\+/g, "\u2318 ").replace(/CommandOrControl\+|CmdOrCtrl\+/g, "\u2318 ").replace(/Alt\+/g, "\u2325 ");
+  }
+  return shortcut.replace(/CommandOrControl\+|CmdOrCtrl\+/g, `${L10N.getStr("ctrl")} `).replace(/Shift\+/g, "Shift ");
 }
 
 exports.formatKeyShortcut = formatKeyShortcut;
 
 /***/ }),
 /* 390 */,
 /* 391 */,
 /* 392 */,
@@ -24450,16 +24494,20 @@ class ManagedTree extends _react.Compone
     if (listItems && listItems != this.props.listItems && listItems.length) {
       this.expandListItems(listItems);
     }
 
     var highlightItems = nextProps.highlightItems;
     if (highlightItems && highlightItems != this.props.highlightItems && highlightItems.length) {
       this.highlightItem(highlightItems);
     }
+
+    if (nextProps.focused && nextProps.focused !== this.props.focused) {
+      this.focusItem(nextProps.focused);
+    }
   }
 
   setExpanded(item, isExpanded) {
     var expanded = this.state.expanded;
     var itemPath = this.props.getPath(item);
     if (isExpanded) {
       expanded.add(itemPath);
     } else {
@@ -24473,17 +24521,17 @@ class ManagedTree extends _react.Compone
       this.props.onCollapse(item);
     }
   }
 
   expandListItems(listItems) {
     var expanded = this.state.expanded;
     listItems.forEach(item => expanded.add(this.props.getPath(item)));
     this.focusItem(listItems[0]);
-    this.setState({ expanded: expanded });
+    this.setState({ expanded });
   }
 
   highlightItem(highlightItems) {
     var expanded = this.state.expanded;
 
     // This file is visible, so we highlight it.
     if (expanded.has(this.props.getPath(highlightItems[0]))) {
       this.focusItem(highlightItems[0]);
@@ -24662,17 +24710,17 @@ var _HitMarker2 = _interopRequireDefault
 var _CallSites = __webpack_require__(1159);
 
 var _CallSites2 = _interopRequireDefault(_CallSites);
 
 var _DebugLine = __webpack_require__(313);
 
 var _DebugLine2 = _interopRequireDefault(_DebugLine);
 
-var _EmptyLines = __webpack_require__(1144);
+var _EmptyLines = __webpack_require__(1146);
 
 var _EmptyLines2 = _interopRequireDefault(_EmptyLines);
 
 var _editor = __webpack_require__(257);
 
 __webpack_require__(905);
 
 __webpack_require__(906);
@@ -25341,17 +25389,17 @@ exports.default = (0, _reactRedux.connec
   var selectedLocation = (0, _selectors.getSelectedLocation)(state);
   var sourceId = selectedLocation && selectedLocation.sourceId;
   var selectedSource = (0, _selectors.getSelectedSource)(state);
 
   return {
     selectedLocation,
     selectedSource,
     highlightedLineRange: (0, _selectors.getHighlightedLineRange)(state),
-    searchOn: (0, _selectors.getActiveSearchState)(state) === "file",
+    searchOn: (0, _selectors.getActiveSearch)(state) === "file",
     loadedObjects: (0, _selectors.getLoadedObjects)(state),
     breakpoints: (0, _selectors.getVisibleBreakpoints)(state),
     hitCount: (0, _selectors.getHitCountForSource)(state, sourceId),
     selectedFrame: (0, _selectors.getSelectedFrame)(state),
     pauseData: (0, _selectors.getPause)(state),
     coverageOn: (0, _selectors.getCoverageEnabled)(state),
     query: (0, _selectors.getFileSearchQueryState)(state),
     searchModifiers: (0, _selectors.getFileSearchModifierState)(state),
@@ -25494,19 +25542,19 @@ class SourceFooter extends _react.PureCo
     if (!(0, _devtoolsConfig.isEnabled)("codeCoverage")) {
       return;
     }
 
     return _react2.default.createElement(
       "button",
       {
         className: "coverage action",
-        title: "Code Coverage",
+        title: L10N.getStr("sourceFooter.codeCoverage"),
         onClick: () => recordCoverage(),
-        "aria-label": "Code Coverage"
+        "aria-label": L10N.getStr("sourceFooter.codeCoverage")
       },
       "C"
     );
   }
 
   renderToggleButton() {
     if (this.props.horizontal) {
       return;
@@ -25668,18 +25716,16 @@ var _actions = __webpack_require__(244);
 var _actions2 = _interopRequireDefault(_actions);
 
 var _selectors = __webpack_require__(242);
 
 var _editor = __webpack_require__(257);
 
 var _search = __webpack_require__(1115);
 
-var _source = __webpack_require__(233);
-
 var _resultList = __webpack_require__(343);
 
 var _classnames = __webpack_require__(175);
 
 var _classnames2 = _interopRequireDefault(_classnames);
 
 var _lodash = __webpack_require__(2);
 
@@ -25765,65 +25811,48 @@ class SearchBar extends _react.Component
     shortcuts.on("Escape", (_, e) => this.onEscape(e));
 
     shortcuts.on(shiftSearchAgainShortcut, (_, e) => this.traverseResults(e, true));
 
     shortcuts.on(searchAgainShortcut, (_, e) => this.traverseResults(e, false));
   }
 
   componentDidUpdate(prevProps, prevState) {
-    var _props = this.props,
-        selectedSource = _props.selectedSource,
-        query = _props.query,
-        modifiers = _props.modifiers,
-        searchOn = _props.searchOn;
-
     var searchInput = this.searchInput();
 
     if (searchInput) {
       searchInput.focus();
     }
 
     if (this.refs.resultList && this.refs.resultList.refs) {
       (0, _resultList.scrollList)(this.refs.resultList.refs, this.state.selectedResultIndex);
     }
-
-    var hasLoaded = selectedSource && (0, _source.isLoaded)(selectedSource.toJS());
-    var wasLoading = prevProps.selectedSource && (0, _source.isLoaded)(prevProps.selectedSource.toJS());
-
-    var doneLoading = wasLoading && hasLoaded;
-    var changedFiles = selectedSource != prevProps.selectedSource && hasLoaded;
-    var modifiersUpdated = modifiers && !modifiers.equals(prevProps.modifiers);
-
-    if (searchOn && (doneLoading || changedFiles || modifiersUpdated)) {
-      this.doSearch(query);
-    }
   }
 
   onEscape(e) {
     this.closeSearch(e);
   }
 
   clearSearch() {
-    var _props2 = this.props,
-        ed = _props2.editor,
-        query = _props2.query,
-        modifiers = _props2.modifiers;
+    var _props = this.props,
+        ed = _props.editor,
+        query = _props.query,
+        modifiers = _props.modifiers;
 
     if (ed && modifiers) {
       var ctx = { ed, cm: ed.codeMirror };
       (0, _editor.removeOverlay)(ctx, query, modifiers.toJS());
     }
   }
 
   closeSearch(e) {
-    var _props3 = this.props,
-        editor = _props3.editor,
-        setFileSearchQuery = _props3.setFileSearchQuery,
-        searchOn = _props3.searchOn;
+    var _props2 = this.props,
+        editor = _props2.editor,
+        setFileSearchQuery = _props2.setFileSearchQuery,
+        searchOn = _props2.searchOn;
 
 
     if (editor && searchOn) {
       setFileSearchQuery("");
       this.clearSearch();
       this.props.setActiveSearch();
       this.props.clearHighlightLineRange();
       e.stopPropagation();
@@ -25875,19 +25904,19 @@ class SearchBar extends _react.Component
       if (input instanceof HTMLInputElement) {
         return input;
       }
     }
     return null;
   }
 
   doSearch(query) {
-    var _props4 = this.props,
-        selectedSource = _props4.selectedSource,
-        setFileSearchQuery = _props4.setFileSearchQuery;
+    var _props3 = this.props,
+        selectedSource = _props3.selectedSource,
+        setFileSearchQuery = _props3.setFileSearchQuery;
 
     if (!selectedSource || !selectedSource.get("text")) {
       return;
     }
 
     setFileSearchQuery(query);
 
     this.searchContents(query);
@@ -25902,20 +25931,20 @@ class SearchBar extends _react.Component
       index: characterIndex
     });
   }
 
   searchContents(query) {
     var _this = this;
 
     return _asyncToGenerator(function* () {
-      var _props5 = _this.props,
-          selectedSource = _props5.selectedSource,
-          modifiers = _props5.modifiers,
-          ed = _props5.editor;
+      var _props4 = _this.props,
+          selectedSource = _props4.selectedSource,
+          modifiers = _props4.modifiers,
+          ed = _props4.editor;
 
 
       if (!query || !ed || !selectedSource || !selectedSource.get("text") || !modifiers) {
         return;
       }
 
       var ctx = { ed, cm: ed.codeMirror };
 
@@ -25936,20 +25965,20 @@ class SearchBar extends _react.Component
     var ed = this.props.editor;
 
     if (!ed) {
       return;
     }
 
     var ctx = { ed, cm: ed.codeMirror };
 
-    var _props6 = this.props,
-        query = _props6.query,
-        modifiers = _props6.modifiers,
-        matches = _props6.searchResults.matches;
+    var _props5 = this.props,
+        query = _props5.query,
+        modifiers = _props5.modifiers,
+        matches = _props5.searchResults.matches;
 
 
     if (query === "") {
       this.props.setActiveSearch("file");
     }
 
     if (modifiers) {
       var matchedLocations = matches || [];
@@ -25973,22 +26002,22 @@ class SearchBar extends _react.Component
       return;
     }
 
     this.traverseResults(e, e.shiftKey);
     e.preventDefault();
   }
   // Renderers
   buildSummaryMsg() {
-    var _props7 = this.props,
-        _props7$searchResults = _props7.searchResults,
-        matchIndex = _props7$searchResults.matchIndex,
-        count = _props7$searchResults.count,
-        index = _props7$searchResults.index,
-        query = _props7.query;
+    var _props6 = this.props,
+        _props6$searchResults = _props6.searchResults,
+        matchIndex = _props6$searchResults.matchIndex,
+        count = _props6$searchResults.count,
+        index = _props6$searchResults.index,
+        query = _props6.query;
 
 
     if (query.trim() == "") {
       return "";
     }
 
     if (count == 0) {
       return L10N.getStr("editor.noResults");
@@ -25997,19 +26026,19 @@ class SearchBar extends _react.Component
     if (index == -1) {
       return L10N.getFormatStr("sourceSearch.resultsSummary1", count);
     }
 
     return L10N.getFormatStr("editor.searchResults", matchIndex + 1, count);
   }
 
   renderSearchModifiers() {
-    var _props8 = this.props,
-        modifiers = _props8.modifiers,
-        toggleFileSearchModifier = _props8.toggleFileSearchModifier;
+    var _props7 = this.props,
+        modifiers = _props7.modifiers,
+        toggleFileSearchModifier = _props7.toggleFileSearchModifier;
 
 
     function SearchModBtn(_ref2) {
       var modVal = _ref2.modVal,
           className = _ref2.className,
           svgName = _ref2.svgName,
           tooltip = _ref2.tooltip;
 
@@ -26067,20 +26096,20 @@ class SearchBar extends _react.Component
           onClick: () => this.props.setActiveSearch("symbol")
         },
         L10N.getStr("symbolSearch.search.functionsPlaceholder")
       )
     );
   }
 
   render() {
-    var _props9 = this.props,
-        count = _props9.searchResults.count,
-        query = _props9.query,
-        searchOn = _props9.searchOn;
+    var _props8 = this.props,
+        count = _props8.searchResults.count,
+        query = _props8.query,
+        searchOn = _props8.searchOn;
 
 
     if (!searchOn) {
       return _react2.default.createElement("div", null);
     }
 
     return _react2.default.createElement(
       "div",
@@ -26108,17 +26137,17 @@ class SearchBar extends _react.Component
 
 SearchBar.displayName = "SearchBar";
 SearchBar.contextTypes = {
   shortcuts: _react.PropTypes.object
 };
 
 exports.default = (0, _reactRedux.connect)(state => {
   return {
-    searchOn: (0, _selectors.getActiveSearchState)(state) === "file",
+    searchOn: (0, _selectors.getActiveSearch)(state) === "file",
     query: (0, _selectors.getFileSearchQueryState)(state),
     modifiers: (0, _selectors.getFileSearchModifierState)(state),
     searchResults: (0, _selectors.getSearchResults)(state)
   };
 }, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(SearchBar);
 
 /***/ }),
 /* 434 */,
@@ -26711,22 +26740,23 @@ function getMenuItems(event, _ref) {
   var copySourceUrl = {
     id: "node-menu-copy-source-url",
     label: copySourceUrlLabel,
     accesskey: copySourceUrlKey,
     disabled: false,
     click: () => (0, _clipboard.copyToTheClipboard)(selectedSource.get("url"))
   };
 
+  var selectionText = codeMirror.getSelection().trim();
   var copySource = {
     id: "node-menu-copy-source",
     label: copySourceLabel,
     accesskey: copySourceKey,
-    disabled: false,
-    click: () => (0, _clipboard.copyToTheClipboard)(codeMirror.getSelection())
+    disabled: selectionText.length === 0,
+    click: () => (0, _clipboard.copyToTheClipboard)(selectionText)
   };
 
   var _codeMirror$coordsCha = codeMirror.coordsChar({
     left: event.clientX,
     top: event.clientY
   }),
       line = _codeMirror$coordsCha.line,
       ch = _codeMirror$coordsCha.ch;
@@ -26766,20 +26796,16 @@ function getMenuItems(event, _ref) {
   var showSourceMenuItem = {
     id: "node-menu-show-source",
     label: revealInTreeLabel,
     accesskey: revealInTreeKey,
     disabled: false,
     click: () => showSource(selectedSource.get("id"))
   };
 
-  if (selectedSource && selectedSource.get("isBlackBoxed")) {
-    return [blackBoxMenuItem];
-  }
-
   var menuItems = [copySource, copySourceUrl, jumpLabel, showSourceMenuItem, blackBoxMenuItem];
 
   if (textSelected) {
     menuItems.push(watchExpressionLabel);
   }
 
   return menuItems;
 }
@@ -27404,17 +27430,17 @@ var _devtoolsSplitter2 = _interopRequire
 var _Frames = __webpack_require__(1012);
 
 var _Frames2 = _interopRequireDefault(_Frames);
 
 var _EventListeners = __webpack_require__(736);
 
 var _EventListeners2 = _interopRequireDefault(_EventListeners);
 
-var _Workers = __webpack_require__(1147);
+var _Workers = __webpack_require__(1149);
 
 var _Workers2 = _interopRequireDefault(_Workers);
 
 var _Accordion = __webpack_require__(739);
 
 var _Accordion2 = _interopRequireDefault(_Accordion);
 
 var _CommandBar = __webpack_require__(742);
@@ -28240,16 +28266,18 @@ exports.default = (0, _reactRedux.connec
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 
 var _react = __webpack_require__(0);
 
+var _react2 = _interopRequireDefault(_react);
+
 var _reactImmutableProptypes = __webpack_require__(150);
 
 var _reactImmutableProptypes2 = _interopRequireDefault(_reactImmutableProptypes);
 
 var _redux = __webpack_require__(3);
 
 var _reactRedux = __webpack_require__(151);
 
@@ -28334,48 +28362,48 @@ class Scopes extends _react.Component {
   }
 
   renderItem(item, depth, focused, _, expanded, _ref) {
     var setExpanded = _ref.setExpanded;
 
     var notEnumberable = false;
     var objectValue = "";
 
-    return React.createElement(
+    return _react2.default.createElement(
       "div",
       {
         className: (0, _classnames2.default)("node object-node", {
           focused: false,
           "not-enumerable": notEnumberable
         }),
         style: { marginLeft: depth * 15 },
         key: item.path,
         onClick: e => {
           e.stopPropagation();
           setExpanded(item, !expanded);
         }
       },
-      React.createElement(_Svg2.default, {
+      _react2.default.createElement(_Svg2.default, {
         name: "arrow",
         className: (0, _classnames2.default)({
           expanded,
           hidden: nodeIsPrimitive(item)
         })
       }),
-      React.createElement(
+      _react2.default.createElement(
         "span",
         { className: "object-label" },
         item.name
       ),
-      React.createElement(
+      _react2.default.createElement(
         "span",
         { className: "object-delimiter" },
         objectValue ? ": " : ""
       ),
-      React.createElement(
+      _react2.default.createElement(
         "span",
         { className: "object-value" },
         objectValue || ""
       )
     );
   }
 
   getObjectProperties(item) {
@@ -28435,33 +28463,33 @@ class Scopes extends _react.Component {
     });
   }
 
   render() {
     var pauseInfo = this.props.pauseInfo;
 
 
     if (!pauseInfo) {
-      return React.createElement(
+      return _react2.default.createElement(
         "div",
         { className: (0, _classnames2.default)("pane", "scopes-list") },
-        React.createElement(
+        _react2.default.createElement(
           "div",
           { className: "pane-info" },
           L10N.getStr("scopes.notPaused")
         )
       );
     }
 
     var roots = this.getRoots();
 
-    return React.createElement(
+    return _react2.default.createElement(
       "div",
       { className: (0, _classnames2.default)("pane", "scopes-list") },
-      React.createElement(_ManagedTree2.default, {
+      _react2.default.createElement(_ManagedTree2.default, {
         itemHeight: 20,
         getParent: item => null,
         getChildren: this.getChildren,
         getRoots: () => roots,
         getPath: item => item.path,
         autoExpand: 0,
         autoExpandDepth: 1,
         autoExpandAll: false,
@@ -29265,19 +29293,16 @@ var _text = __webpack_require__(389);
 var _PaneToggle = __webpack_require__(428);
 
 var _PaneToggle2 = _interopRequireDefault(_PaneToggle);
 
 __webpack_require__(922);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
-var _require = __webpack_require__(828),
-    isEnabled = _require.isEnabled;
-
 class WelcomeBox extends _react.Component {
 
   renderToggleButton() {
     var _props = this.props,
         horizontal = _props.horizontal,
         endPanelCollapsed = _props.endPanelCollapsed,
         togglePaneCollapse = _props.togglePaneCollapse;
 
@@ -29289,53 +29314,69 @@ class WelcomeBox extends _react.Componen
       position: "end",
       collapsed: !endPanelCollapsed,
       horizontal: horizontal,
       handleClick: togglePaneCollapse
     });
   }
 
   render() {
-    var keyCombinationOne = (0, _text.formatKeyShortcut)(L10N.getStr("sources.search.key2"));
-
-    var keyCombinationTwo = (0, _text.formatKeyShortcut)(L10N.getStr("projectTextSearch.key"));
+    var searchSourcesShortcut = (0, _text.formatKeyShortcut)(L10N.getStr("sources.search.key2"));
+
+    var searchProjectShortcut = (0, _text.formatKeyShortcut)(L10N.getStr("projectTextSearch.key"));
+    var searchFunctionsShortcut = (0, _text.formatKeyShortcut)(L10N.getStr("functionSearch.key"));
 
     var searchSourcesLabel = L10N.getStr("welcome.search").substring(2);
     var searchProjectLabel = L10N.getStr("welcome.findInFiles").substring(2);
-
-    var searchProjectLabelComp = _react2.default.createElement(
-      "div",
-      null,
-      _react2.default.createElement(
-        "b",
-        null,
-        keyCombinationTwo
-      ),
-      searchProjectLabel
-    );
-
-    var searchSourcesLabelComp = _react2.default.createElement(
-      "div",
-      null,
-      _react2.default.createElement(
-        "b",
-        null,
-        keyCombinationOne
-      ),
-      searchSourcesLabel
-    );
+    var searchFunctionLabel = L10N.getStr("welcome.searchFunction").substring(2);
 
     return _react2.default.createElement(
       "div",
       { className: "welcomebox" },
       _react2.default.createElement(
         "div",
         { className: "alignlabel" },
-        searchSourcesLabelComp,
-        isEnabled("searchNav") ? searchProjectLabelComp : null,
+        _react2.default.createElement(
+          "div",
+          { className: "shortcutKeys" },
+          _react2.default.createElement(
+            "p",
+            null,
+            searchSourcesShortcut
+          ),
+          _react2.default.createElement(
+            "p",
+            null,
+            searchProjectShortcut
+          ),
+          _react2.default.createElement(
+            "p",
+            null,
+            searchFunctionsShortcut
+          )
+        ),
+        _react2.default.createElement(
+          "div",
+          { className: "shortcutFunction" },
+          _react2.default.createElement(
+            "p",
+            null,
+            searchSourcesLabel
+          ),
+          _react2.default.createElement(
+            "p",
+            null,
+            searchProjectLabel
+          ),
+          _react2.default.createElement(
+            "p",
+            null,
+            searchFunctionLabel
+          )
+        ),
         this.renderToggleButton()
       )
     );
   }
 }
 
 WelcomeBox.displayName = "WelcomeBox";
 
@@ -29637,24 +29678,21 @@ class SourceTabs extends _react.PureComp
 
   toggleSourcesDropdown(e) {
     this.setState({
       dropdownShown: !this.state.dropdownShown
     });
   }
 
   renderDropdownSource(source) {
-    var moveTab = this.props.moveTab;
+    var selectSource = this.props.selectSource;
 
     var filename = (0, _source.getFilename)(source.toJS());
 
-    var onClick = () => {
-      var tabIndex = 0;
-      moveTab(source.get("url"), tabIndex);
-    };
+    var onClick = () => selectSource(source.get("id"));
     return _react2.default.createElement(
       "li",
       { key: source.get("id"), onClick: onClick },
       filename
     );
   }
 
   renderTabs() {
@@ -29847,18 +29885,18 @@ class SourceTabs extends _react.PureComp
 
 SourceTabs.displayName = "SourceTabs";
 
 exports.default = (0, _reactRedux.connect)(state => {
   return {
     selectedSource: (0, _selectors.getSelectedSource)(state),
     searchTabs: (0, _selectors.getSearchTabs)(state),
     sourceTabs: (0, _selectors.getSourcesForTabs)(state),
-    activeSearch: (0, _selectors.getActiveSearchState)(state),
-    searchOn: (0, _selectors.getActiveSearchState)(state) === "source"
+    activeSearch: (0, _selectors.getActiveSearch)(state),
+    searchOn: (0, _selectors.getActiveSearch)(state) === "source"
   };
 }, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(SourceTabs);
 
 /***/ }),
 /* 751 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -30230,23 +30268,27 @@ PreviewFunction.displayName = "PreviewFu
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.findScopeByName = exports.getASTLocation = undefined;
 
 var getASTLocation = exports.getASTLocation = (() => {
   var _ref = _asyncToGenerator(function* (source, location) {
     var symbols = yield (0, _parser.getSymbols)(source);
-    var functions = [].concat(_toConsumableArray(symbols.functions), _toConsumableArray(symbols.memberExpressions));
+    var functions = [].concat(_toConsumableArray(symbols.functions));
 
     var scope = findClosestScope(functions, location);
     if (scope) {
+      // we only record the line, but at some point we may
+      // also do column offsets
       var line = location.line - scope.location.start.line;
-      var column = location.column;
-      return { name: scope.name, offset: { line, column } };
+      return {
+        name: scope.name,
+        offset: { line }
+      };
     }
     return { name: undefined, offset: location };
   });
 
   return function getASTLocation(_x, _x2) {
     return _ref.apply(this, arguments);
   };
 })();
@@ -30279,17 +30321,20 @@ function findClosestScope(functions, loc
     if (currNode.name === "anonymous" || !(0, _contains.containsPosition)(currNode.location, location)) {
       return found;
     }
 
     if (!found) {
       return currNode;
     }
 
-    if (found.location.start.line > currNode.location.start.line || found.location.start.column > currNode.location.start.column) {
+    if (found.location.start.line > currNode.location.start.line) {
+      return found;
+    }
+    if (found.location.start.line === currNode.location.start.line && found.location.start.column > currNode.location.start.column) {
       return found;
     }
 
     return currNode;
   }, null);
 }
 
 /***/ }),
@@ -30715,32 +30760,33 @@ exports.default = (0, _reactRedux.connec
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.getEmptyLines = exports.getNextStep = exports.clearSymbols = exports.getOutOfScopeLocations = exports.getVariablesInScope = exports.getSymbols = exports.getClosestExpression = exports.stopParserWorker = exports.startParserWorker = undefined;
+exports.getEmptyLines = exports.getNextStep = exports.clearASTs = exports.clearSymbols = exports.getOutOfScopeLocations = exports.getVariablesInScope = exports.getSymbols = exports.getClosestExpression = exports.stopParserWorker = exports.startParserWorker = undefined;
 
 var _devtoolsUtils = __webpack_require__(900);
 
 var WorkerDispatcher = _devtoolsUtils.workerUtils.WorkerDispatcher;
 
 
 var dispatcher = new WorkerDispatcher();
 var startParserWorker = exports.startParserWorker = dispatcher.start.bind(dispatcher);
 var stopParserWorker = exports.stopParserWorker = dispatcher.stop.bind(dispatcher);
 
 var getClosestExpression = exports.getClosestExpression = dispatcher.task("getClosestExpression");
 var getSymbols = exports.getSymbols = dispatcher.task("getSymbols");
 var getVariablesInScope = exports.getVariablesInScope = dispatcher.task("getVariablesInScope");
 var getOutOfScopeLocations = exports.getOutOfScopeLocations = dispatcher.task("getOutOfScopeLocations");
 var clearSymbols = exports.clearSymbols = dispatcher.task("clearSymbols");
+var clearASTs = exports.clearASTs = dispatcher.task("clearASTs");
 var getNextStep = exports.getNextStep = dispatcher.task("getNextStep");
 var getEmptyLines = exports.getEmptyLines = dispatcher.task("getEmptyLines");
 
 /***/ }),
 /* 828 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -31978,28 +32024,32 @@ var onConnect = (() => {
     var commands = client.clientCommands;
 
     var _bootstrapStore = (0, _bootstrap.bootstrapStore)(commands, services),
         store = _bootstrapStore.store,
         actions = _bootstrapStore.actions,
         selectors = _bootstrapStore.selectors;
 
     (0, _bootstrap.bootstrapWorkers)();
-    yield client.onConnect(connection, actions);
+
+    var _ref2 = yield client.onConnect(connection, actions),
+        bpClients = _ref2.bpClients;
+
     yield loadFromPrefs(actions);
 
     window.getGlobalsForTesting = function () {
       return {
         store,
         actions,
         selectors,
         client: client.clientCommands,
         prefs: _prefs.prefs,
         features: _prefs.features,
-        connection
+        connection,
+        bpClients
       };
     };
 
     if (!(0, _devtoolsConfig.isFirefoxPanel)()) {
       console.group("Development Notes");
       var baseUrl = "https://devtools-html.github.io/debugger.html";
       var localDevelopmentUrl = `${baseUrl}/docs/local-development.html`;
       console.log("Debugging Tips", localDevelopmentUrl);
@@ -32068,27 +32118,28 @@ var onConnect = exports.onConnect = (() 
   var _ref = _asyncToGenerator(function* (connection, actions) {
     var _connection$tabConnec = connection.tabConnection,
         tabTarget = _connection$tabConnec.tabTarget,
         threadClient = _connection$tabConnec.threadClient,
         debuggerClient = _connection$tabConnec.debuggerClient;
 
 
     if (!tabTarget || !threadClient || !debuggerClient) {
-      return;
+      return { bpClients: {} };
     }
 
     var supportsWasm = (0, _devtoolsConfig.isEnabled)("wasm") && !!debuggerClient.mainRoot.traits.wasmBinarySource;
 
-    (0, _commands.setupCommands)({
+    var _setupCommands = (0, _commands.setupCommands)({
       threadClient,
       tabTarget,
       debuggerClient,
       supportsWasm
-    });
+    }),
+        bpClients = _setupCommands.bpClients;
 
     if (actions) {
       (0, _events.setupEvents)({ threadClient, actions, supportsWasm });
     }
 
     tabTarget.on("will-navigate", actions.willNavigate);
     tabTarget.on("navigate", actions.navigated);
 
@@ -32108,16 +32159,18 @@ var onConnect = exports.onConnect = (() 
     yield actions.newSources(sources);
 
     // If the threadClient is already paused, make sure to show a
     // paused state.
     var pausedPacket = threadClient.getLastPausePacket();
     if (pausedPacket) {
       _events.clientEvents.paused("paused", pausedPacket);
     }
+
+    return { bpClients };
   });
 
   return function onConnect(_x, _x2) {
     return _ref.apply(this, arguments);
   };
 })();
 
 var _commands = __webpack_require__(890);
@@ -32204,16 +32257,18 @@ var debuggerClient = void 0;
 var supportsWasm = void 0;
 
 function setupCommands(dependencies) {
   threadClient = dependencies.threadClient;
   tabTarget = dependencies.tabTarget;
   debuggerClient = dependencies.debuggerClient;
   supportsWasm = dependencies.supportsWasm;
   bpClients = {};
+
+  return { bpClients };
 }
 
 function resume() {
   return new Promise(resolve => {
     threadClient.resume(resolve);
   });
 }
 
@@ -38171,17 +38226,17 @@ module.exports = {
   supportsObject,
   maxLengthMap
 };
 
 /***/ }),
 /* 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 (copySource): This is the text that appears in the\n# context menu to copy the selected source of file open.\ncopySource=Copy\ncopySource.accesskey=y\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\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\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 (workersHeader): The text to display in the events\n# header.\nworkersHeader=Workers\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 (projectTextSearch.key): A key shortcut to open the\n# full project text search for searching all the files the debugger has seen.\nprojectTextSearch.key=CmdOrCtrl+Shift+F\n\n# LOCALIZATION NOTE (projectTextSearch.placeholder): A placeholder shown\n# when searching across all of the files in a project.\nprojectTextSearch.placeholder=Find in files…\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.enableSelf.accesskey=E\nbreakpointMenuItem.disableSelf=Disable breakpoint\nbreakpointMenuItem.disableSelf.accesskey=D\nbreakpointMenuItem.deleteSelf=Remove breakpoint\nbreakpointMenuItem.deleteSelf.accesskey=R\nbreakpointMenuItem.enableOthers=Enable others\nbreakpointMenuItem.enableOthers.accesskey=o\nbreakpointMenuItem.disableOthers=Disable others\nbreakpointMenuItem.disableOthers.accesskey=s\nbreakpointMenuItem.deleteOthers=Remove others\nbreakpointMenuItem.deleteOthers.accesskey=h\nbreakpointMenuItem.enableAll=Enable all breakpoints\nbreakpointMenuItem.enableAll.accesskey=b\nbreakpointMenuItem.disableAll=Disable all breakpoints\nbreakpointMenuItem.disableAll.accesskey=k\nbreakpointMenuItem.deleteAll=Remove all breakpoints\nbreakpointMenuItem.deleteAll.accesskey=a\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\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\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\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\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\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\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\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\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\nsourceTabs.prettyPrint.accesskey=p\n\n# LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.blackbox=Blackbox Source\nsourceFooter.blackbox.accesskey=B\n\n# LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.unblackbox=Unblackbox Source\nsourceFooter.unblackbox.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 (welcome.findInFiles): The center pane welcome panel's\n# search prompt. e.g. cmd+f to search for files. On windows, it's ctrl+shift+f, on\n# a mac we use the unicode character.\nwelcome.findInFiles=%S to find in files\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.noResults2=No results 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.modifiersLabel): A label\n# preceding the group of modifiers\nsymbolSearch.searchModifier.modifiersLabel=Modifiers:\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 (copySource): This is the text that appears in the\n# context menu to copy the selected source of file open.\ncopySource=Copy\ncopySource.accesskey=y\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\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\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 (workersHeader): The text to display in the events\n# header.\nworkersHeader=Workers\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 (projectTextSearch.key): A key shortcut to open the\n# full project text search for searching all the files the debugger has seen.\nprojectTextSearch.key=CmdOrCtrl+Shift+F\n\n# LOCALIZATION NOTE (functionSearch.key): A key shortcut to open the\n# modal for searching functions in a file.\nfunctionSearch.key=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE (projectTextSearch.placeholder): A placeholder shown\n# when searching across all of the files in a project.\nprojectTextSearch.placeholder=Find in files…\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.enableSelf.accesskey=E\nbreakpointMenuItem.disableSelf=Disable breakpoint\nbreakpointMenuItem.disableSelf.accesskey=D\nbreakpointMenuItem.deleteSelf=Remove breakpoint\nbreakpointMenuItem.deleteSelf.accesskey=R\nbreakpointMenuItem.enableOthers=Enable others\nbreakpointMenuItem.enableOthers.accesskey=o\nbreakpointMenuItem.disableOthers=Disable others\nbreakpointMenuItem.disableOthers.accesskey=s\nbreakpointMenuItem.deleteOthers=Remove others\nbreakpointMenuItem.deleteOthers.accesskey=h\nbreakpointMenuItem.enableAll=Enable all breakpoints\nbreakpointMenuItem.enableAll.accesskey=b\nbreakpointMenuItem.disableAll=Disable all breakpoints\nbreakpointMenuItem.disableAll.accesskey=k\nbreakpointMenuItem.deleteAll=Remove all breakpoints\nbreakpointMenuItem.deleteAll.accesskey=a\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\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\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\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\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\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\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\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\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\nsourceTabs.prettyPrint.accesskey=p\n\n# LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.blackbox=Blackbox Source\nsourceFooter.blackbox.accesskey=B\n\n# LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.unblackbox=Unblackbox Source\nsourceFooter.unblackbox.accesskey=b\n\n# LOCALIZATION NOTE (sourceFooter.blackboxed): Text associated\n# with a blackboxed source\nsourceFooter.blackboxed=Blackboxed Source\n\n# LOCALIZATION NOTE (sourceFooter.codeCoverage): Text associated\n# with a code coverage button\nsourceFooter.codeCoverage=Code Coverage\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 (outline.header): Outline left sidebar header\noutline.header=Outline\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 (welcome.findInFiles): The center pane welcome panel's\n# search prompt. e.g. cmd+f to search for files. On windows, it's ctrl+shift+f, on\n# a mac we use the unicode character.\nwelcome.findInFiles=%S to find in files\n\n# LOCALIZATION NOTE (welcome.searchFunction): Label displayed in the welcome\n# panel. %S is replaced by the keyboard shortcut to search for functions.\nwelcome.searchFunction=%S to search for functions in file\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.noResults2=No results 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.modifiersLabel): A label\n# preceding the group of modifiers\nsymbolSearch.searchModifier.modifiersLabel=Modifiers:\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 */
 /***/ (function(module, exports) {
 
 // removed by extract-text-webpack-plugin
 
@@ -41790,22 +41845,25 @@ function breakpointExists(state, locatio
   return currentBp && !currentBp.disabled;
 }
 
 function createBreakpoint(location) {
   var overrides = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
   var condition = overrides.condition,
       disabled = overrides.disabled,
       hidden = overrides.hidden,
-      generatedLocation = overrides.generatedLocation;
+      generatedLocation = overrides.generatedLocation,
+      astLocation = overrides.astLocation;
+
 
   var properties = {
     condition: condition || null,
     disabled: disabled || false,
     hidden: hidden || false,
+    astLocation: astLocation || { offset: location },
     generatedLocation: generatedLocation || location,
     location
   };
 
   return properties;
 }
 
 function createPendingLocation(location) {
@@ -41821,16 +41879,17 @@ function createPendingBreakpoint(bp) {
   var pendingGeneratedLocation = createPendingLocation(bp.generatedLocation);
 
   assertPendingLocation(pendingLocation);
 
   return {
     condition: bp.condition,
     disabled: bp.disabled,
     location: pendingLocation,
+    astLocation: bp.astLocation,
     generatedLocation: pendingGeneratedLocation
   };
 }
 
 /***/ }),
 /* 1058 */
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -42242,90 +42301,99 @@ var _SearchInput = __webpack_require__(3
 var _SearchInput2 = _interopRequireDefault(_SearchInput);
 
 __webpack_require__(866);
 
 var _sourcesTree = __webpack_require__(39);
 
 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 TextSearch extends _react.Component {
   constructor(props) {
     super(props);
     this.state = {
       inputValue: this.props.query || ""
     };
 
-    this.focused = null;
+    this.focusedItem = null;
+    this.inputFocused = false;
 
     this.inputOnChange = this.inputOnChange.bind(this);
     this.onKeyDown = this.onKeyDown.bind(this);
     this.onEnterPress = this.onEnterPress.bind(this);
-    this.close = this.close.bind(this);
     this.selectMatchItem = this.selectMatchItem.bind(this);
   }
 
-  close() {
-    this.props.closeActiveSearch();
+  componentDidMount() {
+    var shortcuts = this.context.shortcuts;
+    shortcuts.on("Enter", this.onEnterPress);
+  }
+
+  componentWillUnmount() {
+    var shortcuts = this.context.shortcuts;
+    shortcuts.off("Enter", this.onEnterPress);
+  }
+
+  selectMatchItem(matchItem) {
+    this.props.selectSource(matchItem.sourceId, { line: matchItem.line });
+  }
+
+  getResults() {
+    var results = this.props.results;
+
+    return results.filter(result => result.filepath && result.matches.length > 0);
+  }
+
+  getResultCount() {
+    var results = this.getResults();
+    return results.reduce((count, file) => count + (file.matches ? file.matches.length : 0), 0);
   }
 
   onKeyDown(e) {
-    var _this = this;
-
-    return _asyncToGenerator(function* () {
-      if (e.key !== "Enter") {
-        return;
-      }
-      _this.props.searchSources(_this.state.inputValue);
-    })();
+    if (e.key === "Escape") {
+      return;
+    }
+
+    e.stopPropagation();
+
+    if (e.key !== "Enter") {
+      return;
+    }
+    this.focusedItem = null;
+    this.props.searchSources(this.state.inputValue);
   }
 
   onEnterPress() {
-    if (this.focused) {
-      var _focused = this.focused,
-          setExpanded = _focused.setExpanded,
-          file = _focused.file,
-          expanded = _focused.expanded,
-          match = _focused.match;
+    if (this.focusedItem && !this.inputFocused) {
+      var _focusedItem = this.focusedItem,
+          setExpanded = _focusedItem.setExpanded,
+          file = _focusedItem.file,
+          expanded = _focusedItem.expanded,
+          match = _focusedItem.match;
 
       if (setExpanded) {
         setExpanded(file, !expanded);
       } else {
         this.selectMatchItem(match);
       }
     }
   }
 
-  componentWillUnmount() {
-    var shortcuts = this.context.shortcuts;
-    shortcuts.off("Enter", this.onEnterPress);
-  }
-
-  componentDidMount() {
-    var shortcuts = this.context.shortcuts;
-    shortcuts.on("Enter", this.onEnterPress);
-  }
-
   inputOnChange(e) {
     var inputValue = e.target.value;
     this.setState({ inputValue });
   }
 
-  selectMatchItem(matchItem) {
-    this.props.selectSource(matchItem.sourceId, { line: matchItem.line });
-  }
-
   renderFile(file, focused, expanded, setExpanded) {
     if (focused) {
-      this.focused = { setExpanded, file, expanded };
-    }
-
-    var matches = ` (${file.matches.length} match${file.matches.length > 1 ? "es" : ""})`;
+      this.focusedItem = { setExpanded, file, expanded };
+    }
+
+    var matchesLength = file.matches.length;
+    var matches = ` (${matchesLength} match${matchesLength > 1 ? "es" : ""})`;
 
     return _react2.default.createElement(
       "div",
       {
         className: (0, _classnames2.default)("file-result", { focused }),
         key: file.sourceId,
         onClick: e => setExpanded(file, !expanded)
       },
@@ -42341,133 +42409,109 @@ class TextSearch extends _react.Componen
         { className: "matches-summary" },
         matches
       )
     );
   }
 
   renderMatch(match, focused) {
     if (focused) {
-      this.focused = { match };
+      this.focusedItem = { match };
     }
     return _react2.default.createElement(
       "div",
       {
         className: (0, _classnames2.default)("result", { focused }),
         onClick: () => setTimeout(() => this.selectMatchItem(match), 50)
       },
       _react2.default.createElement(
         "span",
         { className: "line-number", key: match.line },
         match.line
       ),
-      this.renderMatchValue(match.value)
-    );
-  }
-
-  renderMatchValue(value) {
-    var inputValue = this.state.inputValue;
-
-    var match = void 0;
-    var len = inputValue.length;
-    var matchIndexes = [];
-    var matches = [];
-    var re = new RegExp((0, _lodash.escapeRegExp)(inputValue), "g");
-    while ((match = re.exec(value)) !== null) {
-      matchIndexes.push(match.index);
-    }
-
-    matchIndexes.forEach((matchIndex, index) => {
-      if (matchIndex > 0 && index === 0) {
-        matches.push(_react2.default.createElement(
-          "span",
-          { className: "line-match", key: `case1-${index}` },
-          value.slice(0, matchIndex)
-        ));
-      }
-      if (matchIndex > matchIndexes[index - 1] + len) {
-        matches.push(_react2.default.createElement(
-          "span",
-          { className: "line-match", key: `case2-${index}` },
-          value.slice(matchIndexes[index - 1] + len, matchIndex)
-        ));
-      }
-      matches.push(_react2.default.createElement(
-        "span",
-        { className: "query-match", key: index },
-        value.substr(matchIndex, len)
-      ));
-      if (index === matchIndexes.length - 1) {
-        matches.push(_react2.default.createElement(
-          "span",
-          { className: "line-match", key: `case3-${index}` },
-          value.slice(matchIndex + len, value.length)
-        ));
-      }
-    });
+      this.renderMatchValue(match)
+    );
+  }
+
+  renderMatchValue(lineMatch) {
+    var value = lineMatch.value,
+        column = lineMatch.column,
+        match = lineMatch.match;
+
+    var len = match.length;
 
     return _react2.default.createElement(
       "span",
       { className: "line-value" },
-      matches
-    );
-  }
-
-  getResults() {
-    var results = this.props.results;
-
-    return results.filter(result => result.filepath && result.matches.length > 0);
+      _react2.default.createElement(
+        "span",
+        { className: "line-match", key: 0 },
+        value.slice(0, column)
+      ),
+      _react2.default.createElement(
+        "span",
+        { className: "query-match", key: 1 },
+        value.substr(column, len)
+      ),
+      _react2.default.createElement(
+        "span",
+        { className: "line-match", key: 2 },
+        value.slice(column + len, value.length)
+      )
+    );
   }
 
   renderResults() {
     var results = this.getResults();
     results = results.filter(result => result.matches.length > 0);
-    function getFilePath(item) {
-      return item.filepath ? `${item.sourceId}` : `${item.sourceId}-${item.line}-${item.column}`;
+    function getFilePath(item, index) {
+      return item.filepath ? `${item.sourceId}-${index}` : `${item.sourceId}-${item.line}-${item.column}-${index}`;
     }
 
     var renderItem = (item, depth, focused, _, expanded, _ref) => {
       var setExpanded = _ref.setExpanded;
 
       return item.filepath ? this.renderFile(item, focused, expanded, setExpanded) : this.renderMatch(item, focused);
     };
 
+    var getFocusedItem = () => {
+      if (this.focusedItem === null) {
+        return results[0] ? results[0].matches[0] : null;
+      }
+      return this.focusedItem.file || this.focusedItem.match;
+    };
+
     return _react2.default.createElement(_ManagedTree2.default, {
       getRoots: () => results,
       getChildren: file => file.matches || [],
       itemHeight: 24,
       autoExpand: 1,
       autoExpandDepth: 1,
-      focused: results[0],
+      focused: getFocusedItem(),
       getParent: item => null,
       getPath: getFilePath,
       renderItem: renderItem
     });
   }
 
-  resultCount() {
-    var results = this.getResults();
-    return results.reduce((count, file) => count + (file.matches ? file.matches.length : 0), 0);
-  }
-
   renderInput() {
-    var resultCount = this.resultCount();
+    var resultCount = this.getResultCount();
     var summaryMsg = L10N.getFormatStr("sourceSearch.resultsSummary1", resultCount);
 
     return _react2.default.createElement(_SearchInput2.default, {
       query: this.state.inputValue,
       count: resultCount,
       placeholder: L10N.getStr("projectTextSearch.placeholder"),
       size: "big",
       summaryMsg: summaryMsg,
       onChange: e => this.inputOnChange(e),
-      onFocus: () => this.setState({ focused: true }),
-      onBlur: () => this.setState({ focused: false }),
+      onFocus: () => this.inputFocused = true,
+      onBlur: () => this.inputFocused = false,
       onKeyDown: e => this.onKeyDown(e),
-      handleClose: this.close,
+      handleClose: this.props.closeActiveSearch,
       ref: "searchInput"
     });
   }
 
   render() {
     var searchBottomBar = this.props.searchBottomBar;
 
     return _react2.default.createElement(
@@ -42754,16 +42798,17 @@ exports.containsPosition = containsPosit
 exports.containsLocation = containsLocation;
 exports.nodeContainsPosition = nodeContainsPosition;
 function containsPosition(a, b) {
   var startsBefore = a.start.line < b.line || a.start.line === b.line && a.start.column <= b.column;
   var endsAfter = a.end.line > b.line || a.end.line === b.line && a.end.column >= b.column;
 
   return startsBefore && endsAfter;
 }
+
 function containsLocation(a, b) {
   return containsPosition(a, b.start) && containsPosition(a, b.end);
 }
 
 function nodeContainsPosition(node, position) {
   return containsPosition(node.loc, position);
 }
 
@@ -42994,16 +43039,17 @@ function getSourceSearchQuery(state) {
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.initialState = initialState;
 exports.getPendingBreakpoints = getPendingBreakpoints;
+exports.getPendingBreakpointsForSource = getPendingBreakpointsForSource;
 
 var _immutable = __webpack_require__(146);
 
 var I = _interopRequireWildcard(_immutable);
 
 var _makeRecord = __webpack_require__(230);
 
 var _makeRecord2 = _interopRequireDefault(_makeRecord);
@@ -43038,17 +43084,17 @@ function update() {
   switch (action.type) {
     case "ADD_BREAKPOINT":
       {
         return addBreakpoint(state, action);
       }
 
     case "SYNC_BREAKPOINT":
       {
-        return addBreakpoint(state, action);
+        return syncBreakpoint(state, action);
       }
 
     case "ENABLE_BREAKPOINT":
       {
         return addBreakpoint(state, action);
       }
 
     case "DISABLE_BREAKPOINT":
@@ -43079,16 +43125,30 @@ function addBreakpoint(state, action) {
   var breakpoint = action.value.breakpoint;
 
   var locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location);
   var pendingBreakpoint = (0, _breakpoint.createPendingBreakpoint)(breakpoint);
 
   return state.setIn(["pendingBreakpoints", locationId], pendingBreakpoint);
 }
 
+function syncBreakpoint(state, action) {
+  var breakpoint = action.breakpoint,
+      previousLocation = action.previousLocation;
+
+  var locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location);
+  var pendingBreakpoint = (0, _breakpoint.createPendingBreakpoint)(breakpoint);
+
+  if (previousLocation) {
+    return state.deleteIn(["pendingBreakpoints", (0, _breakpoint.makePendingLocationId)(previousLocation)]).setIn(["pendingBreakpoints", locationId], pendingBreakpoint);
+  }
+
+  return state.setIn(["pendingBreakpoints", locationId], pendingBreakpoint);
+}
+
 function updateBreakpoint(state, action) {
   var breakpoint = action.breakpoint;
 
   var locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location);
   var pendingBreakpoint = (0, _breakpoint.createPendingBreakpoint)(breakpoint);
 
   return state.setIn(["pendingBreakpoints", locationId], pendingBreakpoint);
 }
@@ -43103,16 +43163,21 @@ function removeBreakpoint(state, action)
 
 // Selectors
 // TODO: these functions should be moved out of the reducer
 
 function getPendingBreakpoints(state) {
   return state.pendingBreakpoints.pendingBreakpoints;
 }
 
+function getPendingBreakpointsForSource(state, sourceUrl) {
+  var pendingBreakpoints = state.pendingBreakpoints.pendingBreakpoints || [];
+  return pendingBreakpoints.filter(pendingBreakpoint => pendingBreakpoint.location.sourceUrl === sourceUrl);
+}
+
 function restorePendingBreakpoints() {
   return I.Map(_prefs.prefs.pendingBreakpoints);
 }
 
 exports.default = update;
 
 /***/ }),
 /* 1134 */
@@ -43275,18 +43340,19 @@ function _asyncToGenerator(fn) { return 
 
 exports.default = (() => {
   var _ref = _asyncToGenerator(function* (getState, client, sourceMaps, _ref2) {
     var breakpoint = _ref2.breakpoint;
 
     var state = getState();
 
     var source = (0, _selectors.getSource)(state, breakpoint.location.sourceId);
+    var sourceRecord = source.toJS();
     var location = _extends({}, breakpoint.location, { sourceUrl: source.get("url") });
-    var generatedLocation = yield (0, _sourceMaps.getGeneratedLocation)(state, source.toJS(), location, sourceMaps);
+    var generatedLocation = yield (0, _sourceMaps.getGeneratedLocation)(state, sourceRecord, location, sourceMaps);
 
     (0, _breakpoint.assertLocation)(location);
     (0, _breakpoint.assertLocation)(generatedLocation);
 
     if ((0, _breakpoint.breakpointExists)(state, location)) {
       var _newBreakpoint = _extends({}, breakpoint, { location, generatedLocation });
       (0, _breakpoint.assertBreakpoint)(_newBreakpoint);
       return { breakpoint: _newBreakpoint };
@@ -43295,23 +43361,26 @@ exports.default = (() => {
     var _ref3 = yield client.setBreakpoint(generatedLocation, breakpoint.condition, sourceMaps.isOriginalId(location.sourceId)),
         id = _ref3.id,
         hitCount = _ref3.hitCount,
         actualLocation = _ref3.actualLocation;
 
     var newGeneratedLocation = actualLocation || generatedLocation;
     var newLocation = yield sourceMaps.getOriginalLocation(newGeneratedLocation);
 
+    var astLocation = yield (0, _breakpoint.getASTLocation)(sourceRecord, location);
+
     var newBreakpoint = {
       id,
       disabled: false,
       hidden: breakpoint.hidden,
       loading: false,
       condition: breakpoint.condition,
       location: newLocation,
+      astLocation,
       hitCount,
       generatedLocation: newGeneratedLocation
     };
 
     (0, _breakpoint.assertBreakpoint)(newBreakpoint);
 
     var previousLocation = (0, _breakpoint.locationMoved)(location, newLocation) ? location : null;
 
@@ -43337,107 +43406,117 @@ exports.default = (() => {
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.syncClientBreakpoint = undefined;
 
 var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
 
+var makeScopedLocation = (() => {
+  var _ref = _asyncToGenerator(function* (_ref2, location, source) {
+    var name = _ref2.name,
+        offset = _ref2.offset;
+
+    var scope = yield (0, _breakpoint.findScopeByName)(source, name);
+    // fallback onto the location line, if the scope is not found
+    // note: we may at some point want to delete the breakpoint if the scope
+    // disappears
+    var line = scope ? scope.location.start.line + offset.line : location.line;
+    return {
+      line,
+      column: location.column,
+      sourceUrl: source.url,
+      sourceId: source.id
+    };
+  });
+
+  return function makeScopedLocation(_x, _x2, _x3) {
+    return _ref.apply(this, arguments);
+  };
+})();
+
 // we have three forms of syncing: disabled syncing, existing server syncing
 // and adding a new breakpoint
 var syncClientBreakpoint = exports.syncClientBreakpoint = (() => {
-  var _ref = _asyncToGenerator(function* (getState, client, sourceMaps, source, pendingBreakpoint) {
-    var sourceId = source.id;
+  var _ref3 = _asyncToGenerator(function* (getState, client, sourceMaps, sourceId, pendingBreakpoint) {
+    (0, _breakpoint.assertPendingBreakpoint)(pendingBreakpoint);
+
+    var source = (0, _selectors.getSource)(getState(), sourceId).toJS();
     var generatedSourceId = sourceMaps.isOriginalId(sourceId) ? (0, _devtoolsSourceMap.originalToGeneratedId)(sourceId) : sourceId;
 
+    var location = pendingBreakpoint.location,
+        astLocation = pendingBreakpoint.astLocation;
+
+    var previousLocation = _extends({}, location, { sourceId });
+
+    var scopedLocation = yield makeScopedLocation(astLocation, previousLocation, source);
+
+    var scopedGeneratedLocation = yield (0, _sourceMaps.getGeneratedLocation)(getState(), source, scopedLocation, sourceMaps);
+
     // this is the generatedLocation of the pending breakpoint, with
     // the source id updated to reflect the new connection
     var generatedLocation = _extends({}, pendingBreakpoint.generatedLocation, {
       sourceId: generatedSourceId
     });
 
-    var location = _extends({}, pendingBreakpoint.location, {
-      sourceId
-    });
-
-    (0, _breakpoint3.assertPendingBreakpoint)(pendingBreakpoint);
-
-    /** ******* CASE 1: Disabled ***********/
-    // early return if breakpoint is disabled, send overrides to update
-    // the id as expected
-    if (pendingBreakpoint.disabled) {
-      var _newLocation = yield sourceMaps.getOriginalLocation(generatedLocation);
-
-      var _breakpoint = _extends({}, pendingBreakpoint, {
-        id: (0, _breakpoint3.makeLocationId)(_newLocation),
-        generatedLocation,
-        location: _newLocation
-      });
-
-      var previousLocation = (0, _breakpoint3.locationMoved)(location, _newLocation) ? location : null;
-
-      (0, _breakpoint3.assertBreakpoint)(_breakpoint);
-      return { breakpoint: _breakpoint, previousLocation };
-    }
-
-    /** ******* CASE 2: Merge Server Breakpoint ***********/
-    // early return if breakpoint exists on the server, send overrides
-    // to update the id as expected
+    var isSameLocation = !(0, _breakpoint.locationMoved)(generatedLocation, scopedGeneratedLocation);
+
     var existingClient = client.getBreakpointByLocation(generatedLocation);
 
+    /** ******* CASE 1: No server change ***********/
+    // early return if breakpoint is disabled or we are in the sameLocation
+    // send update only to redux
+    if (pendingBreakpoint.disabled || existingClient && isSameLocation) {
+      return createSyncData(pendingBreakpoint, scopedLocation, scopedGeneratedLocation);
+    }
+
+    // clear server breakpoints if they exist and we have moved
     if (existingClient) {
-      var _newGeneratedLocation = yield (0, _sourceMaps.getGeneratedLocation)(getState(), source, location, sourceMaps);
-
-      if ((0, _breakpoint3.locationMoved)(generatedLocation, _newGeneratedLocation)) {
-        yield client.removeBreakpoint(generatedLocation);
-        yield client.setBreakpoint(_newGeneratedLocation, pendingBreakpoint.condition, sourceMaps.isOriginalId(sourceId));
-      }
-
-      var _breakpoint2 = _extends({}, pendingBreakpoint, {
-        id: (0, _breakpoint3.makeLocationId)(location),
-        generatedLocation: _newGeneratedLocation,
-        location: location
-      });
-
-      (0, _breakpoint3.assertBreakpoint)(_breakpoint2);
-      return { breakpoint: _breakpoint2, previousLocation: location };
-    }
-
-    /** ******* CASE 3: Add New Breakpoint ***********/
+      yield client.removeBreakpoint(generatedLocation);
+    }
+
+    /** ******* Case 2: Add New Breakpoint ***********/
     // If we are not disabled, set the breakpoint on the server and get
     // that info so we can set it on our breakpoints.
-    var clientBreakpoint = yield client.setBreakpoint(generatedLocation, pendingBreakpoint.condition, sourceMaps.isOriginalId(sourceId));
-
+    var clientBreakpoint = yield client.setBreakpoint(scopedGeneratedLocation, pendingBreakpoint.condition, sourceMaps.isOriginalId(sourceId));
+
+    // the breakpoint might have slid server side, so we want to get the location
+    // based on the server's return value
     var newGeneratedLocation = clientBreakpoint.actualLocation;
     var newLocation = yield sourceMaps.getOriginalLocation(newGeneratedLocation);
 
-    var breakpoint = _extends({}, pendingBreakpoint, {
-      id: (0, _breakpoint3.makeLocationId)(newGeneratedLocation),
-      generatedLocation: newGeneratedLocation,
-      location: newLocation
-    });
-
-    (0, _breakpoint3.assertBreakpoint)(breakpoint);
-    return { breakpoint, previousLocation: location };
-  });
-
-  return function syncClientBreakpoint(_x, _x2, _x3, _x4, _x5) {
-    return _ref.apply(this, arguments);
+    return createSyncData(pendingBreakpoint, newLocation, newGeneratedLocation, previousLocation);
+  });
+
+  return function syncClientBreakpoint(_x5, _x6, _x7, _x8, _x9) {
+    return _ref3.apply(this, arguments);
   };
 })();
 
-var _breakpoint3 = __webpack_require__(1057);
+var _breakpoint = __webpack_require__(1057);
 
 var _sourceMaps = __webpack_require__(797);
 
 var _devtoolsSourceMap = __webpack_require__(898);
 
+var _selectors = __webpack_require__(242);
+
 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"); }); }; }
 
+function createSyncData(pendingBreakpoint, location, generatedLocation) {
+  var previousLocation = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
+
+  var overrides = _extends({}, pendingBreakpoint, { generatedLocation });
+  var breakpoint = (0, _breakpoint.createBreakpoint)(location, overrides);
+
+  (0, _breakpoint.assertBreakpoint)(breakpoint);
+  return { breakpoint, previousLocation };
+}
+
 /***/ }),
 /* 1138 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
@@ -43459,17 +43538,17 @@ function _interopRequireDefault(obj) { r
  */
 function ignoreWhiteSpace(str) {
   return (/^\s{0,2}$/.test(str) ? "(?!\\s*.*)" : str
   );
 }
 
 
 function wholeMatch(query, wholeWord) {
-  if (query == "" || !wholeWord) {
+  if (query === "" || !wholeWord) {
     return query;
   }
 
   return `\\b${query}\\b`;
 }
 
 function buildFlags(caseSensitive, isGlobal) {
   if (caseSensitive && isGlobal) {
@@ -43492,17 +43571,17 @@ function buildQuery(originalQuery, modif
       isGlobal = _ref$isGlobal === undefined ? false : _ref$isGlobal,
       _ref$ignoreSpaces = _ref.ignoreSpaces,
       ignoreSpaces = _ref$ignoreSpaces === undefined ? false : _ref$ignoreSpaces;
   var caseSensitive = modifiers.caseSensitive,
       regexMatch = modifiers.regexMatch,
       wholeWord = modifiers.wholeWord;
 
 
-  if (originalQuery == "") {
+  if (originalQuery === "") {
     return new RegExp(originalQuery);
   }
 
   var query = originalQuery;
   if (ignoreSpaces) {
     query = ignoreWhiteSpace(query);
   }
 
@@ -43582,29 +43661,28 @@ class ProjectSearch extends _react.Compo
   }
 
   componentWillUnmount() {
     var shortcuts = this.context.shortcuts;
     shortcuts.off(L10N.getStr("projectTextSearch.key"), this.toggleProjectTextSearch);
 
     var searchKeys = [L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key")];
     searchKeys.forEach(key => shortcuts.off(key, this.toggleSourceSearch));
-    shortcuts.off("Escape", this.onEscape);
   }
 
   toggleProjectTextSearch(key, e) {
     var _props = this.props,
         closeActiveSearch = _props.closeActiveSearch,
         setActiveSearch = _props.setActiveSearch;
 
     if (e) {
       e.preventDefault();
     }
 
-    if (!_prefs.prefs.projectTextSearchEnabled) {
+    if (!_prefs.features.projectTextSearch) {
       return;
     }
 
     if (this.isProjectSearchEnabled()) {
       return closeActiveSearch();
     }
     return setActiveSearch("project");
   }
@@ -43659,17 +43737,17 @@ class ProjectSearch extends _react.Compo
         searchSources = _props4.searchSources,
         closeActiveSearch = _props4.closeActiveSearch,
         selectSource = _props4.selectSource,
         textSearchQuery = _props4.textSearchQuery;
 
 
     return _react2.default.createElement(_TextSearch2.default, {
       sources: sources,
-      results: results.valueSeq().toJS(),
+      results: results.toJS(),
       searchSources: searchSources,
       closeActiveSearch: closeActiveSearch,
       selectSource: selectSource,
       query: textSearchQuery,
       searchBottomBar: _react2.default.createElement(_ToggleSearch2.default, { kind: "project", toggle: this.toggleSourceSearch })
     });
   }
 
@@ -43703,17 +43781,17 @@ ProjectSearch.propTypes = {
 ProjectSearch.contextTypes = {
   shortcuts: _react.PropTypes.object
 };
 
 ProjectSearch.displayName = "ProjectSearch";
 
 exports.default = (0, _reactRedux.connect)(state => ({
   sources: (0, _selectors.getSources)(state),
-  activeSearch: (0, _selectors.getActiveSearchState)(state),
+  activeSearch: (0, _selectors.getActiveSearch)(state),
   results: (0, _selectors.getTextSearchResults)(state),
   textSearchQuery: (0, _selectors.getTextSearchQuery)(state),
   sourceSearchQuery: (0, _selectors.getSourceSearchQuery)(state)
 }), dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(ProjectSearch);
 
 /***/ }),
 /* 1140 */,
 /* 1141 */
@@ -43737,69 +43815,38 @@ var _utils = __webpack_require__(234);
 var _Autocomplete = __webpack_require__(342);
 
 var _Autocomplete2 = _interopRequireDefault(_Autocomplete);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 class SourceSearch extends _react.Component {
 
-  constructor(props) {
-    super(props);
-
-    this.close = this.close.bind(this);
-  }
-
-  componentWillUnmount() {
-    var shortcuts = this.context.shortcuts;
-    shortcuts.off("Escape", this.onEscape);
-  }
-
-  componentDidMount() {
-    var shortcuts = this.context.shortcuts;
-    shortcuts.on("Escape", this.onEscape);
-  }
-
-  onEscape(shortcut, e) {
-    if (this.isProjectSearchEnabled()) {
-      e.preventDefault();
-      this.close();
-    }
-  }
-
   searchResults(sourceMap) {
     return sourceMap.valueSeq().toJS().filter(source => !(0, _source.isPretty)(source)).map(source => ({
       value: (0, _source.getSourcePath)(source),
       title: (0, _source.getSourcePath)(source).split("/").pop(),
       subtitle: (0, _utils.endTruncateStr)((0, _source.getSourcePath)(source), 100),
       id: source.id
     }));
   }
 
-  close() {
-    this.props.clearQuery();
-    this.props.closeActiveSearch();
-  }
-
   render() {
     var _props = this.props,
         sources = _props.sources,
         searchBottomBar = _props.searchBottomBar,
         selectSource = _props.selectSource,
         query = _props.query,
         setQuery = _props.setQuery;
 
     return _react2.default.createElement(
       _Autocomplete2.default,
       {
-        selectItem: (e, result) => {
-          selectSource(result.id);
-          this.close();
-        },
-        close: this.close,
+        selectItem: (e, result) => selectSource(result.id),
+        close: this.props.closeActiveSearch,
         items: this.searchResults(sources),
         inputValue: query,
         placeholder: L10N.getStr("sourceSearch.search"),
         onChangeHandler: setQuery,
         size: "big"
       },
       searchBottomBar
     );
@@ -43873,36 +43920,40 @@ class PrimaryPanes extends _react.Compon
     this.setState({ selectedPane });
   }
 
   renderOutlineTabs() {
     if (!(0, _devtoolsConfig.isEnabled)("outline")) {
       return;
     }
 
+    var sources = (0, _text.formatKeyShortcut)(L10N.getStr("sources.header"));
+
+    var outline = (0, _text.formatKeyShortcut)(L10N.getStr("outline.header"));
+
     return [_react2.default.createElement(
       "div",
       {
         className: (0, _classnames2.default)("tab", {
           active: this.state.selectedPane === "sources"
         }),
         onClick: () => this.showPane("sources"),
         key: "sources-tab"
       },
-      "Sources View"
+      sources
     ), _react2.default.createElement(
       "div",
       {
         className: (0, _classnames2.default)("tab", {
           active: this.state.selectedPane === "outline"
         }),
         onClick: () => this.showPane("outline"),
         key: "outline-tab"
       },
-      "Outline View"
+      outline
     )];
   }
 
   renderFooter() {
     return _react2.default.createElement(
       "div",
       { className: "source-footer" },
       this.renderOutlineTabs()
@@ -43957,29 +44008,92 @@ class PrimaryPanes extends _react.Compon
     );
   }
 }
 
 PrimaryPanes.displayName = "PrimaryPanes";
 
 exports.default = (0, _reactRedux.connect)(state => ({
   sources: (0, _selectors.getSources)(state),
-  sourceSearchOn: (0, _selectors.getActiveSearchState)(state) === "source"
+  sourceSearchOn: (0, _selectors.getActiveSearch)(state) === "source"
 }), dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(PrimaryPanes);
 
 /***/ }),
 /* 1143 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
+exports.loadSourceText = loadSourceText;
+
+var _promise = __webpack_require__(193);
+
+var _ast = __webpack_require__(1059);
+
+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"); }); }; }
+
+/**
+ * @memberof actions/sources
+ * @static
+ */
+function loadSourceText(source) {
+  return (() => {
+    var _ref = _asyncToGenerator(function* (_ref2) {
+      var dispatch = _ref2.dispatch,
+          getState = _ref2.getState,
+          client = _ref2.client,
+          sourceMaps = _ref2.sourceMaps;
+
+      // Fetch the source text only once.
+      if (source.text) {
+        return Promise.resolve(source);
+      }
+
+      yield dispatch({
+        type: "LOAD_SOURCE_TEXT",
+        source: source,
+        [_promise.PROMISE]: _asyncToGenerator(function* () {
+          if (sourceMaps.isOriginalId(source.id)) {
+            return yield sourceMaps.getOriginalSourceText(source);
+          }
+
+          var response = yield client.sourceContents(source.id);
+
+          return {
+            id: source.id,
+            text: response.source,
+            contentType: response.contentType || "text/javascript"
+          };
+        })()
+      });
+
+      yield dispatch((0, _ast.setSymbols)(source.id));
+      yield dispatch((0, _ast.setEmptyLines)(source.id));
+    });
+
+    return function (_x) {
+      return _ref.apply(this, arguments);
+    };
+  })();
+}
+
+/***/ }),
+/* 1144 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
 exports.setSourceSearchQuery = setSourceSearchQuery;
 exports.clearSourceSearchQuery = clearSourceSearchQuery;
 function setSourceSearchQuery(queryString) {
   return (_ref) => {
     var dispatch = _ref.dispatch,
         getState = _ref.getState;
 
     dispatch({
@@ -43996,96 +44110,16 @@ function clearSourceSearchQuery() {
 
     dispatch({
       type: "CLEAR_QUERY_STRING"
     });
   };
 }
 
 /***/ }),
-/* 1144 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-
-var _reactRedux = __webpack_require__(151);
-
-var _redux = __webpack_require__(3);
-
-var _react = __webpack_require__(0);
-
-var _actions = __webpack_require__(244);
-
-var _actions2 = _interopRequireDefault(_actions);
-
-var _selectors = __webpack_require__(242);
-
-__webpack_require__(1146);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-class EmptyLines extends _react.Component {
-
-  componentDidMount() {
-    this.disableEmptyLines();
-  }
-
-  componentDidUpdate() {
-    this.disableEmptyLines();
-  }
-
-  componentWillUnmount() {
-    var _props = this.props,
-        emptyLines = _props.emptyLines,
-        editor = _props.editor;
-
-
-    if (!emptyLines) {
-      return;
-    }
-    editor.codeMirror.operation(() => {
-      emptyLines.forEach(line => editor.codeMirror.removeLineClass(line, "line", "empty-line"));
-    });
-  }
-
-  disableEmptyLines() {
-    var _props2 = this.props,
-        emptyLines = _props2.emptyLines,
-        editor = _props2.editor;
-
-
-    if (!emptyLines) {
-      return;
-    }
-    editor.codeMirror.operation(() => {
-      emptyLines.forEach(line => editor.codeMirror.addLineClass(line, "line", "empty-line"));
-    });
-  }
-
-  render() {
-    return null;
-  }
-}
-
-EmptyLines.displayName = "EmptyLines";
-
-exports.default = (0, _reactRedux.connect)(state => {
-  var selectedSource = (0, _selectors.getSelectedSource)(state);
-  return {
-    selectedSource,
-    emptyLines: selectedSource ? (0, _selectors.getEmptyLines)(state, selectedSource.toJS()) : []
-  };
-}, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(EmptyLines);
-
-/***/ }),
 /* 1145 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
@@ -44132,27 +44166,28 @@ class Outline extends _react.Component {
     }
     var selectedSourceId = selectedSource.get("id");
     var startLine = location.start.line;
     selectSource(selectedSourceId, { line: startLine });
   }
 
   renderFunction(func) {
     var name = func.name,
-        location = func.location;
+        location = func.location,
+        parameterNames = func.parameterNames;
 
 
     return _react2.default.createElement(
       "li",
       {
         key: `${name}:${location.start.line}:${location.start.column}`,
         className: "outline-list__element",
         onClick: () => this.selectItem(location)
       },
-      _react2.default.createElement(_PreviewFunction2.default, { func: { name } })
+      _react2.default.createElement(_PreviewFunction2.default, { func: { name, parameterNames } })
     );
   }
 
   renderFunctions() {
     var symbols = this.props.symbols;
 
 
     return symbols.functions.filter(func => func.name != "anonymous").map(func => this.renderFunction(func));
@@ -44185,82 +44220,96 @@ exports.default = (0, _reactRedux.connec
   return {
     symbols: (0, _selectors.getSymbols)(state, selectedSource && selectedSource.toJS()),
     selectedSource
   };
 }, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(Outline);
 
 /***/ }),
 /* 1146 */
-/***/ (function(module, exports) {
-
-// removed by extract-text-webpack-plugin
-
-/***/ }),
-/* 1147 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-exports.Workers = undefined;
-
-var _react = __webpack_require__(0);
-
-var _react2 = _interopRequireDefault(_react);
-
-__webpack_require__(1149);
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
 
 var _reactRedux = __webpack_require__(151);
 
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-class Workers extends _react.PureComponent {
-  renderWorkers(workers) {
-    return workers.map(w => _react2.default.createElement(
-      "div",
-      null,
-      w
-    ));
-  }
-
-  renderNoWorkersPlaceholder() {
-    return L10N.getStr("noWorkersText");
-  }
-
-  render() {
-    var workers = this.props.workers;
-
-    return _react2.default.createElement(
-      "div",
-      { className: "pane" },
-      _react2.default.createElement(
-        "div",
-        { className: "pane-info" },
-        workers && workers.length > 0 ? this.renderWorkers(workers) : this.renderNoWorkersPlaceholder()
-      )
-    );
-  }
-}
-
-exports.Workers = Workers;
-Workers.displayName = "Workers";
-Workers.propTypes = {
-  workers: _react.PropTypes.array.isRequired
-};
-
-function mapStateToProps(state) {
-  return { workers: [] };
-}
-exports.default = (0, _reactRedux.connect)(mapStateToProps)(Workers);
-
-/***/ }),
+var _redux = __webpack_require__(3);
+
+var _react = __webpack_require__(0);
+
+var _actions = __webpack_require__(244);
+
+var _actions2 = _interopRequireDefault(_actions);
+
+var _selectors = __webpack_require__(242);
+
+__webpack_require__(1161);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+class EmptyLines extends _react.Component {
+
+  componentDidMount() {
+    this.disableEmptyLines();
+  }
+
+  componentDidUpdate() {
+    this.disableEmptyLines();
+  }
+
+  componentWillUnmount() {
+    var _props = this.props,
+        emptyLines = _props.emptyLines,
+        editor = _props.editor;
+
+
+    if (!emptyLines) {
+      return;
+    }
+    editor.codeMirror.operation(() => {
+      emptyLines.forEach(line => editor.codeMirror.removeLineClass(line, "line", "empty-line"));
+    });
+  }
+
+  disableEmptyLines() {
+    var _props2 = this.props,
+        emptyLines = _props2.emptyLines,
+        editor = _props2.editor;
+
+
+    if (!emptyLines) {
+      return;
+    }
+    editor.codeMirror.operation(() => {
+      emptyLines.forEach(line => editor.codeMirror.addLineClass(line, "line", "empty-line"));
+    });
+  }
+
+  render() {
+    return null;
+  }
+}
+
+EmptyLines.displayName = "EmptyLines";
+
+exports.default = (0, _reactRedux.connect)(state => {
+  var selectedSource = (0, _selectors.getSelectedSource)(state);
+  return {
+    selectedSource,
+    emptyLines: selectedSource ? (0, _selectors.getEmptyLines)(state, selectedSource.toJS()) : []
+  };
+}, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(EmptyLines);
+
+/***/ }),
+/* 1147 */,
 /* 1148 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
@@ -44564,19 +44613,74 @@ exports.default = (0, _reactRedux.connec
     shownSource: (0, _selectors.getShownSource)(state),
     selectedSource: (0, _selectors.getSelectedSource)(state),
     debuggeeUrl: (0, _selectors.getDebuggeeUrl)(state)
   };
 }, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(SourcesTree);
 
 /***/ }),
 /* 1149 */
-/***/ (function(module, exports) {
-
-// removed by extract-text-webpack-plugin
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.Workers = undefined;
+
+var _react = __webpack_require__(0);
+
+var _react2 = _interopRequireDefault(_react);
+
+__webpack_require__(1162);
+
+var _reactRedux = __webpack_require__(151);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+class Workers extends _react.PureComponent {
+  renderWorkers(workers) {
+    return workers.map(w => _react2.default.createElement(
+      "div",
+      null,
+      w
+    ));
+  }
+
+  renderNoWorkersPlaceholder() {
+    return L10N.getStr("noWorkersText");
+  }
+
+  render() {
+    var workers = this.props.workers;
+
+    return _react2.default.createElement(
+      "div",
+      { className: "pane" },
+      _react2.default.createElement(
+        "div",
+        { className: "pane-info" },
+        workers && workers.length > 0 ? this.renderWorkers(workers) : this.renderNoWorkersPlaceholder()
+      )
+    );
+  }
+}
+
+exports.Workers = Workers;
+Workers.displayName = "Workers";
+Workers.propTypes = {
+  workers: _react.PropTypes.array.isRequired
+};
+
+function mapStateToProps(state) {
+  return { workers: [] };
+}
+exports.default = (0, _reactRedux.connect)(mapStateToProps)(Workers);
 
 /***/ }),
 /* 1150 */,
 /* 1151 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
@@ -45830,18 +45934,28 @@ exports.default = (0, _reactRedux.connec
     selectedSource,
     callSites: getCallSites(symbols, breakpoints),
     breakpoints: breakpoints
   };
 }, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(CallSites);
 
 /***/ }),
 /* 1160 */,
-/* 1161 */,
-/* 1162 */,
+/* 1161 */
+/***/ (function(module, exports) {
+
+// removed by extract-text-webpack-plugin
+
+/***/ }),
+/* 1162 */
+/***/ (function(module, exports) {
+
+// removed by extract-text-webpack-plugin
+
+/***/ }),
 /* 1163 */,
 /* 1164 */,
 /* 1165 */,
 /* 1166 */,
 /* 1167 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -46015,48 +46129,32 @@ class SymbolModal extends _react.Compone
     self.onChange = this.onChange.bind(this);
     self.onKeyUp = this.onKeyUp.bind(this);
     self.updateResults = this.updateResults.bind(this);
     self.traverseResults = this.traverseResults.bind(this);
     self.renderResults = this.renderResults.bind(this);
     self.buildSummaryMsg = this.buildSummaryMsg.bind(this);
     self.buildPlaceHolder = this.buildPlaceHolder.bind(this);
     self.selectResultItem = this.selectResultItem.bind(this);
-    self.openSymbolModal = this.openSymbolModal.bind(this);
-  }
-
-  componentWillUnmount() {
-    var shortcuts = this.context.shortcuts;
-    shortcuts.off(L10N.getStr("symbolSearch.search.key2"));
-    shortcuts.off("Escape");
   }
 
   componentDidMount() {
-    var shortcuts = this.context.shortcuts;
-    shortcuts.on(L10N.getStr("symbolSearch.search.key2"), this.openSymbolModal);
-    shortcuts.on("Escape", this.closeModal);
     this.updateResults(this.state.query);
   }
 
   componentDidUpdate(prevProps, prevState) {
     if (this.refs.resultList && this.refs.resultList.refs) {
       (0, _resultList.scrollList)(this.refs.resultList.refs, this.state.resultsIndex);
     }
 
     if (!prevProps.enabled && this.props.enabled) {
       this.updateResults(this.state.query);
     }
   }
 
-  openSymbolModal(_, e) {
-    e.preventDefault();
-    e.stopPropagation();
-    this.props.setActiveSearch("symbol");
-  }
-
   onClick(e) {
     e.stopPropagation();
   }
 
   onChange(e) {
     var selectedSource = this.props.selectedSource;
 
     if (!selectedSource || !selectedSource.get("text")) {
@@ -46065,17 +46163,16 @@ class SymbolModal extends _react.Compone
 
     this.setState({ query: e.target.value });
     return this.updateResults(e.target.value);
   }
 
   closeModal() {
     this.props.closeActiveSearch();
     this.props.clearHighlightLineRange();
-    this.setState({ query: "" });
   }
 
   selectResultItem(e, item) {
     var _props = this.props,
         selectSource = _props.selectSource,
         selectedSource = _props.selectedSource;
 
 
@@ -46269,26 +46366,26 @@ function _getFormattedSymbols(state, sou
     variables: variables.map(formatSymbol),
     functions: functions.map(formatSymbol)
   };
 }
 
 exports.default = (0, _reactRedux.connect)(state => {
   var source = (0, _selectors.getSelectedSource)(state);
   return {
-    enabled: Boolean((0, _selectors.getActiveSearchState)(state) === "symbol" && source),
+    enabled: Boolean((0, _selectors.getActiveSearch)(state) === "symbol" && source),
     symbolType: (0, _selectors.getSymbolSearchType)(state),
     symbols: _getFormattedSymbols(state, source)
   };
 }, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(SymbolModal);
 
 /***/ }),
 /* 1171 */,
 /* 1172 */,
 /* 1173 */,
 /* 1174 */
 /***/ (function(module, exports) {
 
 module.exports = "<svg xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 400 400\" xml:space=\"preserve\" id=\"svg2\" version=\"1.1\"><metadata id=\"metadata8\"><rdf:RDF><cc:Work rdf:about><dc:format>image/svg+xml</dc:format><dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"></dc></cc:Work></rdf:RDF></metadata><defs id=\"defs6\"></defs><g transform=\"matrix(1.3333333,0,0,-1.3333333,0,400)\" id=\"g10\"><g transform=\"translate(178.0626,235.0086)\" id=\"g12\"><path id=\"path14\" style=\"fill:#41b883;fill-opacity:1;fill-rule:nonzero;stroke:none\" d=\"M 0,0 -22.669,-39.264 -45.338,0 h -75.491 L -22.669,-170.017 75.491,0 Z\"></path></g><g transform=\"translate(178.0626,235.0086)\" id=\"g16\"><path id=\"path18\" style=\"fill:#34495e;fill-opacity:1;fill-rule:nonzero;stroke:none\" d=\"M 0,0 -22.669,-39.264 -45.338,0 H -81.565 L -22.669,-102.01 36.227,0 Z\"></path></g></g></svg>"
 
 /***/ })
 /******/ ]);
-});
+});
\ No newline at end of file
--- a/devtools/client/debugger/new/parser-worker.js
+++ b/devtools/client/debugger/new/parser-worker.js
@@ -4121,55 +4121,17 @@ var baseCreate = (function() {
     return result;
   };
 }());
 
 module.exports = baseCreate;
 
 
 /***/ }),
-/* 404 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var isArrayLike = __webpack_require__(220),
-    isObjectLike = __webpack_require__(14);
-
-/**
- * This method is like `_.isArrayLike` except that it also checks if `value`
- * is an object.
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is an array-like object,
- *  else `false`.
- * @example
- *
- * _.isArrayLikeObject([1, 2, 3]);
- * // => true
- *
- * _.isArrayLikeObject(document.body.children);
- * // => true
- *
- * _.isArrayLikeObject('abc');
- * // => false
- *
- * _.isArrayLikeObject(_.noop);
- * // => false
- */
-function isArrayLikeObject(value) {
-  return isObjectLike(value) && isArrayLike(value);
-}
-
-module.exports = isArrayLikeObject;
-
-
-/***/ }),
+/* 404 */,
 /* 405 */,
 /* 406 */
 /***/ (function(module, exports, __webpack_require__) {
 
 var assignValue = __webpack_require__(114),
     baseAssignValue = __webpack_require__(115);
 
 /**
@@ -28512,63 +28474,61 @@ module.exports = basePropertyDeep;
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
 exports.getNextStep = getNextStep;
 
 var _debuggerHtml = __webpack_require__(843);
 
 var _types = __webpack_require__(844);
 
 var _closest = __webpack_require__(1055);
 
-var _contains = __webpack_require__(1127);
-
 var _helpers = __webpack_require__(1052);
 
-function getNextStep(source, stepType, pausedPosition) {
+function getNextStep(source, pausedPosition) {
+  var awaitExpression = getAwaitExpression(source, pausedPosition);
+  if (!awaitExpression) {
+    return null;
+  }
+  var awaitStatement = awaitExpression.getStatementParent();
+  return getLocationAfterAwaitExpression(awaitStatement, pausedPosition);
+}
+
+function getAwaitExpression(source, pausedPosition) {
   var closestPath = (0, _closest.getClosestPath)(source, pausedPosition);
+
   if (!closestPath) {
-    return { nextStepType: stepType };
-  }
-  if ((0, _helpers.isAwaitExpression)(closestPath, pausedPosition)) {
-    var nextHiddenBreakpointLocation = getLocationAfterAwaitExpression(closestPath, pausedPosition);
-    return { nextStepType: "resume", nextHiddenBreakpointLocation };
-  }
-  return { nextStepType: stepType };
-}
-
-function getLocationAfterAwaitExpression(path, position) {
-  var children = getFunctionBodyChildren(path);
-  if (!children) {
-    return;
-  }
-  for (var i = 0; i !== children.length; i++) {
-    var child = children[i];
-    if ((0, _contains.containsPosition)(child.loc, position)) {
-      var nextChild = children[++i];
-      var nextLocation = nextChild.loc.start;
-      nextLocation.sourceId = position.sourceId;
-      return nextLocation;
-    }
-  }
-}
-
-function getFunctionBodyChildren(path) {
-  var blockScope = path.scope.block;
-  if (!blockScope) {
-    return;
-  }
-  var children = blockScope.body.body;
-  return children;
+    return null;
+  }
+
+  if ((0, _helpers.isAwaitExpression)(closestPath)) {
+    return closestPath;
+  }
+
+  return closestPath.find(p => p.isAwaitExpression());
+}
+
+function getLocationAfterAwaitExpression(statement, position) {
+  var nextStatement = statement.getSibling(statement.key + 1);
+  if (nextStatement.node) {
+    return _extends({}, nextStatement.node.loc.start, {
+      sourceId: position.sourceId
+    });
+  }
+
+  return null;
 }
 
 /***/ }),
 /* 843 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
@@ -28932,16 +28892,18 @@ module.exports = {
 var _closest = __webpack_require__(1055);
 
 var _scopes = __webpack_require__(1049);
 
 var _getSymbols = __webpack_require__(1050);
 
 var _getSymbols2 = _interopRequireDefault(_getSymbols);
 
+var _ast = __webpack_require__(1051);
+
 var _getOutOfScopeLocations = __webpack_require__(1072);
 
 var _getOutOfScopeLocations2 = _interopRequireDefault(_getOutOfScopeLocations);
 
 var _steps = __webpack_require__(842);
 
 var _getEmptyLines = __webpack_require__(845);
 
@@ -28954,16 +28916,17 @@ function _interopRequireDefault(obj) { r
 var workerHandler = _devtoolsUtils.workerUtils.workerHandler;
 
 
 self.onmessage = workerHandler({
   getClosestExpression: _closest.getClosestExpression,
   getOutOfScopeLocations: _getOutOfScopeLocations2.default,
   getSymbols: _getSymbols2.default,
   clearSymbols: _getSymbols.clearSymbols,
+  clearASTs: _ast.clearASTs,
   getVariablesInScope: _scopes.getVariablesInScope,
   getNextStep: _steps.getNextStep,
   getEmptyLines: _getEmptyLines2.default
 });
 
 /***/ }),
 /* 962 */,
 /* 963 */
@@ -29740,16 +29703,17 @@ function clearSymbols() {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.getAst = getAst;
+exports.clearASTs = clearASTs;
 exports.traverseAst = traverseAst;
 
 var _parseScriptTags = __webpack_require__(1023);
 
 var _parseScriptTags2 = _interopRequireDefault(_parseScriptTags);
 
 var _babylon = __webpack_require__(435);
 
@@ -29817,16 +29781,20 @@ function getAst(source) {
   } else if (source.contentType == "text/javascript") {
     ast = parse(source.text);
   }
 
   ASTs.set(source.id, ast);
   return ast;
 }
 
+function clearASTs() {
+  ASTs = new Map();
+}
+
 function traverseAst(source, visitor) {
   var ast = getAst(source);
   if ((0, _isEmpty2.default)(ast)) {
     return null;
   }
 
   (0, _babelTraverse2.default)(ast, visitor);
   return ast;
@@ -32837,33 +32805,34 @@ exports.containsPosition = containsPosit
 exports.containsLocation = containsLocation;
 exports.nodeContainsPosition = nodeContainsPosition;
 function containsPosition(a, b) {
   var startsBefore = a.start.line < b.line || a.start.line === b.line && a.start.column <= b.column;
   var endsAfter = a.end.line > b.line || a.end.line === b.line && a.end.column >= b.column;
 
   return startsBefore && endsAfter;
 }
+
 function containsLocation(a, b) {
   return containsPosition(a, b.start) && containsPosition(a, b.end);
 }
 
 function nodeContainsPosition(node, position) {
   return containsPosition(node.loc, position);
 }
 
 /***/ }),
 /* 1128 */,
 /* 1129 */
 /***/ (function(module, exports, __webpack_require__) {
 
 var baseDifference = __webpack_require__(1131),
     baseFlatten = __webpack_require__(707),
     baseRest = __webpack_require__(411),
-    isArrayLikeObject = __webpack_require__(404);
+    isArrayLikeObject = __webpack_require__(1155);
 
 /**
  * Creates an array of `array` values not included in the other given arrays
  * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
  * for equality comparisons. The order and references of result values are
  * determined by the first array.
  *
  * **Note:** Unlike `_.pullAll`, this method returns a new array.
@@ -32959,11 +32928,73 @@ function baseDifference(array, values, i
     }
   }
   return result;
 }
 
 module.exports = baseDifference;
 
 
+/***/ }),
+/* 1132 */,
+/* 1133 */,
+/* 1134 */,
+/* 1135 */,
+/* 1136 */,
+/* 1137 */,
+/* 1138 */,
+/* 1139 */,
+/* 1140 */,
+/* 1141 */,
+/* 1142 */,
+/* 1143 */,
+/* 1144 */,
+/* 1145 */,
+/* 1146 */,
+/* 1147 */,
+/* 1148 */,
+/* 1149 */,
+/* 1150 */,
+/* 1151 */,
+/* 1152 */,
+/* 1153 */,
+/* 1154 */,
+/* 1155 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var isArrayLike = __webpack_require__(220),
+    isObjectLike = __webpack_require__(14);
+
+/**
+ * This method is like `_.isArrayLike` except that it also checks if `value`
+ * is an object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array-like object,
+ *  else `false`.
+ * @example
+ *
+ * _.isArrayLikeObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isArrayLikeObject(document.body.children);
+ * // => true
+ *
+ * _.isArrayLikeObject('abc');
+ * // => false
+ *
+ * _.isArrayLikeObject(_.noop);
+ * // => false
+ */
+function isArrayLikeObject(value) {
+  return isObjectLike(value) && isArrayLike(value);
+}
+
+module.exports = isArrayLikeObject;
+
+
 /***/ })
 /******/ ]);
 });
\ No newline at end of file
--- a/devtools/client/debugger/new/search-worker.js
+++ b/devtools/client/debugger/new/search-worker.js
@@ -312,17 +312,17 @@ function _interopRequireDefault(obj) { r
  */
 function ignoreWhiteSpace(str) {
   return (/^\s{0,2}$/.test(str) ? "(?!\\s*.*)" : str
   );
 }
 
 
 function wholeMatch(query, wholeWord) {
-  if (query == "" || !wholeWord) {
+  if (query === "" || !wholeWord) {
     return query;
   }
 
   return `\\b${query}\\b`;
 }
 
 function buildFlags(caseSensitive, isGlobal) {
   if (caseSensitive && isGlobal) {
@@ -345,17 +345,17 @@ function buildQuery(originalQuery, modif
       isGlobal = _ref$isGlobal === undefined ? false : _ref$isGlobal,
       _ref$ignoreSpaces = _ref.ignoreSpaces,
       ignoreSpaces = _ref$ignoreSpaces === undefined ? false : _ref$ignoreSpaces;
   var caseSensitive = modifiers.caseSensitive,
       regexMatch = modifiers.regexMatch,
       wholeWord = modifiers.wholeWord;
 
 
-  if (originalQuery == "") {
+  if (originalQuery === "") {
     return new RegExp(originalQuery);
   }
 
   var query = originalQuery;
   if (ignoreSpaces) {
     query = ignoreWhiteSpace(query);
   }
 
@@ -438,36 +438,30 @@ Object.defineProperty(exports, "__esModu
 exports.default = getMatches;
 
 var _buildQuery = __webpack_require__(1138);
 
 var _buildQuery2 = _interopRequireDefault(_buildQuery);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
-var MAX_LENGTH = 100000;
-
 function getMatches(query, text, modifiers) {
   if (!query || !text || !modifiers) {
     return [];
   }
   var regexQuery = (0, _buildQuery2.default)(query, modifiers, {
     isGlobal: true
   });
   var matchedLocations = [];
   var lines = text.split("\n");
   for (var i = 0; i < lines.length; i++) {
     var singleMatch = void 0;
     var line = lines[i];
-    if (line.length <= MAX_LENGTH) {
-      while ((singleMatch = regexQuery.exec(line)) !== null) {
-        matchedLocations.push({ line: i, ch: singleMatch.index });
-      }
-    } else {
-      return [];
+    while ((singleMatch = regexQuery.exec(line)) !== null) {
+      matchedLocations.push({ line: i, ch: singleMatch.index });
     }
   }
   return matchedLocations;
 }
 
 /***/ }),
 
 /***/ 121:
@@ -868,23 +862,30 @@ function getSourceLineCount(source) {
  * @return String
  * @memberof utils/source
  * @static
  */
 
 function getMode(source) {
   var contentType = source.contentType,
       text = source.text,
-      isWasm = source.isWasm;
+      isWasm = source.isWasm,
+      url = source.url;
 
 
   if (!text || isWasm) {
     return { name: "text" };
   }
 
+  // if the url ends with .marko we set the name to Javascript so
+  // syntax highlighting works for marko too
+  if (url && url.match(/\.marko$/i)) {
+    return { name: "javascript" };
+  }
+
   // Use HTML mode for files in which the first non whitespace
   // character is `<` regardless of extension.
   var isHTMLLike = text.match(/^\s*</);
   if (!contentType) {
     if (isHTMLLike) {
       return { name: "htmlmixed" };
     }
     return { name: "text" };
--- a/devtools/client/debugger/new/test/mochitest/browser.ini
+++ b/devtools/client/debugger/new/test/mochitest/browser.ini
@@ -43,16 +43,17 @@ support-files =
   examples/script-switching-02.js
   examples/script-switching-01.js
   examples/times2.js
 
 [browser_dbg-async-stepping.js]
 [browser_dbg-breaking.js]
 [browser_dbg-breaking-from-console.js]
 [browser_dbg-breakpoints.js]
+[browser_dbg-breakpoints-toggle.js]
 [browser_dbg-breakpoints-reloading.js]
 skip-if = true # Bug 1383576
 [browser_dbg-breakpoints-cond.js]
 [browser_dbg-call-stack.js]
 [browser_dbg-expressions.js]
 [browser_dbg-scopes.js]
 [browser_dbg-chrome-create.js]
 [browser_dbg-chrome-debugging.js]
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-async-stepping.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-async-stepping.js
@@ -1,15 +1,12 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// Tests async stepping will:
-// 1. step over await statements
-// 2. step into async functions
-// 3. step out of async functions
+// Tests async stepping will step over await statements
 add_task(async function test() {
   Services.prefs.setBoolPref("devtools.debugger.features.async-stepping", true);
   const dbg = await initDebugger("doc-async.html", "async");
 
   await selectSource(dbg, "async");
   await addBreakpoint(dbg, "async", 8);
   invokeInTab("main");
 
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-breaking-from-console.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-breaking-from-console.js
@@ -4,30 +4,30 @@
 // Tests that `debugger` statements are hit before the debugger even
 // initializes and it properly highlights the right location in the
 // debugger.
 
 async function waitOnToolbox(toolbox, event) {
   return new Promise(resolve => toolbox.on(event, resolve));
 }
 
-add_task(function*() {
+add_task(async function() {
   const url = EXAMPLE_URL + "doc-script-switching.html";
-  const toolbox = yield openNewTabAndToolbox(url, "webconsole");
+  const toolbox = await openNewTabAndToolbox(url, "webconsole");
 
   // Type "debugger" into console
   let jsterm = toolbox.getPanel("webconsole").hud.jsterm;
   jsterm.execute("debugger");
 
   // Wait for the debugger to be selected and make sure it's paused
-  yield waitOnToolbox(toolbox, "jsdebugger-selected");
+  await waitOnToolbox(toolbox, "jsdebugger-selected");
   is(toolbox.threadClient.state, "paused");
 
   // Create a dbg context
   const dbg = createDebuggerContext(toolbox);
   const { selectors: { getSelectedSource }, getState } = dbg;
 
   // Make sure the thread is paused in the right source and location
-  yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
+  await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
   is(dbg.win.cm.getValue(), "debugger");
   const source = getSelectedSource(getState()).toJS();
   assertPausedLocation(dbg);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-breaking.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-breaking.js
@@ -1,32 +1,32 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests the breakpoints are hit in various situations.
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-scripts.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-scripts.html");
   const { selectors: { getSelectedSource }, getState } = dbg;
 
   // Make sure we can set a top-level breakpoint and it will be hit on
   // reload.
-  yield addBreakpoint(dbg, "scripts.html", 18);
+  await addBreakpoint(dbg, "scripts.html", 18);
   reload(dbg);
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
-  yield resume(dbg);
+  await resume(dbg);
 
   const paused = waitForPaused(dbg);
 
   // Create an eval script that pauses itself.
   invokeInTab("doEval");
 
-  yield paused;
-  yield resume(dbg);
+  await paused;
+  await resume(dbg);
   const source = getSelectedSource(getState()).toJS();
   ok(!source.url, "It is an eval source");
 
-  yield addBreakpoint(dbg, source, 5);
+  await addBreakpoint(dbg, source, 5);
   invokeInTab("evaledFunc");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints-cond.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints-cond.js
@@ -19,56 +19,54 @@ function assertEditorBreakpoint(dbg, lin
     exists === shouldExist,
     "Breakpoint " +
       (shouldExist ? "exists" : "does not exist") +
       " on line " +
       line
   );
 }
 
-function setConditionalBreakpoint(dbg, index, condition) {
-  return Task.spawn(function*() {
-    rightClickElement(dbg, "gutter", index);
-    selectMenuItem(dbg, 2);
-    yield waitForElement(dbg, ".conditional-breakpoint-panel input");
-    findElementWithSelector(dbg, ".conditional-breakpoint-panel input").focus();
-    // Position cursor reliably at the end of the text.
-    pressKey(dbg, "End");
-    type(dbg, condition);
-    pressKey(dbg, "Enter");
-  });
+async function setConditionalBreakpoint(dbg, index, condition) {
+  rightClickElement(dbg, "gutter", index);
+  selectMenuItem(dbg, 2);
+  await waitForElement(dbg, ".conditional-breakpoint-panel input");
+  findElementWithSelector(dbg, ".conditional-breakpoint-panel input").focus();
+  // Position cursor reliably at the end of the text.
+  pressKey(dbg, "End");
+  type(dbg, condition);
+  pressKey(dbg, "Enter");
 }
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-scripts.html");
-  yield selectSource(dbg, "simple2");
+add_task(async function() {
+  const dbg = await initDebugger("doc-scripts.html");
+  await selectSource(dbg, "simple2");
 
   // Adding a conditional Breakpoint
-  yield setConditionalBreakpoint(dbg, 5, "1");
-  yield waitForDispatch(dbg, "ADD_BREAKPOINT");
+  await setConditionalBreakpoint(dbg, 5, "1");
+  await waitForDispatch(dbg, "ADD_BREAKPOINT");
   let bp = findBreakpoint(dbg, "simple2", 5);
   is(bp.condition, "1", "breakpoint is created with the condition");
   assertEditorBreakpoint(dbg, 5, true);
 
   // Editing a conditional Breakpoint
-  yield setConditionalBreakpoint(dbg, 5, "2");
-  yield waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
+  await setConditionalBreakpoint(dbg, 5, "2");
+  await waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
   bp = findBreakpoint(dbg, "simple2", 5);
   is(bp.condition, "12", "breakpoint is created with the condition");
   assertEditorBreakpoint(dbg, 5, true);
 
   // Removing a conditional breakpoint
   clickElement(dbg, "gutter", 5);
-  yield waitForDispatch(dbg, "REMOVE_BREAKPOINT");
+  await waitForDispatch(dbg, "REMOVE_BREAKPOINT");
   bp = findBreakpoint(dbg, "simple2", 5);
   is(bp, null, "breakpoint was removed");
   assertEditorBreakpoint(dbg, 5, false);
 
   // Adding a condition to a breakpoint
   clickElement(dbg, "gutter", 5);
-  yield waitForDispatch(dbg, "ADD_BREAKPOINT");
-  yield setConditionalBreakpoint(dbg, 5, "1");
-  yield waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
+  await waitForDispatch(dbg, "ADD_BREAKPOINT");
+  await setConditionalBreakpoint(dbg, 5, "1");
+  await waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
 
   bp = findBreakpoint(dbg, "simple2", 5);
   is(bp.condition, "1", "breakpoint is created with the condition");
   assertEditorBreakpoint(dbg, 5, true);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints-reloading.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints-reloading.js
@@ -18,27 +18,27 @@ function addBreakpoint(dbg, line) {
   return waitForDispatch(dbg, "ADD_BREAKPOINT");
 }
 
 function assertEditorBreakpoint(dbg, line) {
   const exists = !!getLineEl(dbg, line).querySelector(".new-breakpoint");
   ok(exists, `Breakpoint exists on line ${line}`);
 }
 
-add_task(function*() {
+add_task(async function() {
   requestLongerTimeout(3);
 
-  const dbg = yield initDebugger("doc-scripts.html");
+  const dbg = await initDebugger("doc-scripts.html");
   const { selectors: { getBreakpoints, getBreakpoint }, getState } = dbg;
   const source = findSource(dbg, "simple1.js");
 
-  yield selectSource(dbg, source.url);
-  yield addBreakpoint(dbg, 5);
-  yield addBreakpoint(dbg, 4);
+  await selectSource(dbg, source.url);
+  await addBreakpoint(dbg, 5);
+  await addBreakpoint(dbg, 4);
 
   const syncedBps = waitForDispatch(dbg, "SYNC_BREAKPOINT", 2);
-  yield reload(dbg, "simple1");
-  yield waitForSelectedSource(dbg);
-  yield syncedBps;
+  await reload(dbg, "simple1");
+  await waitForSelectedSource(dbg);
+  await syncedBps;
 
   assertEditorBreakpoint(dbg, 4);
   assertEditorBreakpoint(dbg, 5);
 });
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints-toggle.js
@@ -0,0 +1,87 @@
+function toggleBreakpoint(dbg, index) {
+  const bp = findElement(dbg, "breakpointItem", index);
+  const input = bp.querySelector("input");
+  input.click();
+}
+
+async function removeBreakpoint(dbg, index) {
+  const removed = waitForDispatch(dbg, "REMOVE_BREAKPOINT");
+  const bp = findElement(dbg, "breakpointItem", index);
+  bp.querySelector(".close-btn").click();
+  await removed;
+}
+
+async function disableBreakpoint(dbg, index) {
+  const disabled = waitForDispatch(dbg, "DISABLE_BREAKPOINT");
+  toggleBreakpoint(dbg, index);
+  await disabled;
+}
+
+async function enableBreakpoint(dbg, index) {
+  const enabled = waitForDispatch(dbg, "ENABLE_BREAKPOINT");
+  toggleBreakpoint(dbg, index);
+  await enabled;
+}
+
+function toggleBreakpoints(dbg, count) {
+  clickElement(dbg, "toggleBreakpoints");
+}
+
+function disableBreakpoints(dbg, count) {
+  const toggled = waitForDispatch(dbg, "DISABLE_BREAKPOINT", count);
+  toggleBreakpoints(dbg);
+  return toggled;
+}
+
+function enableBreakpoints(dbg, count) {
+  const enabled = waitForDispatch(dbg, "ENABLE_BREAKPOINT", count);
+  toggleBreakpoints(dbg);
+  return enabled;
+}
+
+function findBreakpoint(dbg, url, line) {
+  const { selectors: { getBreakpoint }, getState } = dbg;
+  const source = findSource(dbg, url);
+  return getBreakpoint(getState(), { sourceId: source.id, line });
+}
+
+function findBreakpoints(dbg) {
+  const { selectors: { getBreakpoints }, getState } = dbg;
+  return getBreakpoints(getState());
+}
+
+// toggle all breakpoints
+add_task(async function() {
+  const dbg = await initDebugger("doc-scripts.html", "simple2");
+
+  // Create two breakpoints
+  await selectSource(dbg, "simple2");
+  await addBreakpoint(dbg, "simple2", 3);
+  await addBreakpoint(dbg, "simple2", 5);
+
+  // Disable all of the breakpoints
+  await disableBreakpoints(dbg, 2);
+  let bp1 = findBreakpoint(dbg, "simple2", 3);
+  let bp2 = findBreakpoint(dbg, "simple2", 5);
+
+  if (!bp2) {
+    debugger;
+  }
+
+  is(bp1.disabled, true, "first breakpoint is disabled");
+  is(bp2.disabled, true, "second breakpoint is disabled");
+
+  // Enable all of the breakpoints
+  await enableBreakpoints(dbg, 2);
+  bp1 = findBreakpoint(dbg, "simple2", 3);
+  bp2 = findBreakpoint(dbg, "simple2", 5);
+
+  is(bp1.disabled, false, "first breakpoint is enabled");
+  is(bp2.disabled, false, "second breakpoint is enabled");
+
+  // Remove the breakpoints
+  await removeBreakpoint(dbg, 1);
+  await removeBreakpoint(dbg, 1);
+  const bps = findBreakpoints(dbg);
+  is(bps.size, 0, "breakpoints are removed");
+});
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints.js
@@ -2,106 +2,75 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function toggleBreakpoint(dbg, index) {
   const bp = findElement(dbg, "breakpointItem", index);
   const input = bp.querySelector("input");
   input.click();
 }
 
-function removeBreakpoint(dbg, index) {
-  return Task.spawn(function*() {
-    const bp = findElement(dbg, "breakpointItem", index);
-    bp.querySelector(".close-btn").click();
-    yield waitForDispatch(dbg, "REMOVE_BREAKPOINT");
-  });
+async function removeBreakpoint(dbg, index) {
+  const removed = waitForDispatch(dbg, "REMOVE_BREAKPOINT");
+  const bp = findElement(dbg, "breakpointItem", index);
+  bp.querySelector(".close-btn").click();
+  await removed;
 }
 
-function disableBreakpoint(dbg, index) {
-  return Task.spawn(function*() {
-    toggleBreakpoint(dbg, index);
-    yield waitForDispatch(dbg, "DISABLE_BREAKPOINT");
-  });
+async function disableBreakpoint(dbg, index) {
+  const disabled = waitForDispatch(dbg, "DISABLE_BREAKPOINT");
+  toggleBreakpoint(dbg, index);
+  await disabled;
 }
 
-function enableBreakpoint(dbg, index) {
-  return Task.spawn(function*() {
-    toggleBreakpoint(dbg, index);
-    yield waitForDispatch(dbg, "ENABLE_BREAKPOINT");
-  });
+async function enableBreakpoint(dbg, index) {
+  const enabled = waitForDispatch(dbg, "ENABLE_BREAKPOINT");
+  toggleBreakpoint(dbg, index);
+  await enabled;
 }
 
 function toggleBreakpoints(dbg, count) {
   clickElement(dbg, "toggleBreakpoints");
 }
 
 function disableBreakpoints(dbg, count) {
+  const toggled = waitForDispatch(dbg, "DISABLE_BREAKPOINT", count);
   toggleBreakpoints(dbg);
-  return waitForDispatch(dbg, "DISABLE_BREAKPOINT", count);
+  return toggled;
 }
 
 function enableBreakpoints(dbg, count) {
+  const enabled = waitForDispatch(dbg, "ENABLE_BREAKPOINT", count);
   toggleBreakpoints(dbg);
-  return waitForDispatch(dbg, "ENABLE_BREAKPOINT", count);
+  return enabled;
 }
 
 function findBreakpoint(dbg, url, line) {
   const { selectors: { getBreakpoint }, getState } = dbg;
   const source = findSource(dbg, url);
   return getBreakpoint(getState(), { sourceId: source.id, line });
 }
 
 function findBreakpoints(dbg) {
   const { selectors: { getBreakpoints }, getState } = dbg;
   return getBreakpoints(getState());
 }
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-scripts.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-scripts.html");
 
   // Create two breakpoints
-  yield selectSource(dbg, "simple2");
-  yield addBreakpoint(dbg, "simple2", 3);
-  yield addBreakpoint(dbg, "simple2", 5);
+  await selectSource(dbg, "simple2");
+  await addBreakpoint(dbg, "simple2", 3);
+  await addBreakpoint(dbg, "simple2", 5);
 
   // Disable the first one
-  yield disableBreakpoint(dbg, 1);
+  await disableBreakpoint(dbg, 1);
   let bp1 = findBreakpoint(dbg, "simple2", 3);
   let bp2 = findBreakpoint(dbg, "simple2", 5);
   is(bp1.disabled, true, "first breakpoint is disabled");
   is(bp2.disabled, false, "second breakpoint is enabled");
 
   // Disable and Re-Enable the second one
-  yield disableBreakpoint(dbg, 2);
-  yield enableBreakpoint(dbg, 2);
+  await disableBreakpoint(dbg, 2);
+  await enableBreakpoint(dbg, 2);
   bp2 = findBreakpoint(dbg, "simple2", 5);
   is(bp2.disabled, false, "second breakpoint is enabled");
 });
-
-// toggle all
-add_task(function*() {
-  const dbg = yield initDebugger("doc-scripts.html");
-
-  // Create two breakpoints
-  yield selectSource(dbg, "simple2");
-  yield addBreakpoint(dbg, "simple2", 3);
-  yield addBreakpoint(dbg, "simple2", 5);
-
-  // Disable all of the breakpoints
-  yield disableBreakpoints(dbg, 2);
-  let bp1 = findBreakpoint(dbg, "simple2", 3);
-  let bp2 = findBreakpoint(dbg, "simple2", 5);
-  is(bp1.disabled, true, "first breakpoint is disabled");
-  is(bp2.disabled, true, "second breakpoint is disabled");
-
-  // Enable all of the breakpoints
-  yield enableBreakpoints(dbg, 2);
-  bp1 = findBreakpoint(dbg, "simple2", 3);
-  bp2 = findBreakpoint(dbg, "simple2", 5);
-  is(bp1.disabled, false, "first breakpoint is enabled");
-  is(bp2.disabled, false, "second breakpoint is enabled");
-
-  // Remove the breakpoints
-  yield removeBreakpoint(dbg, 1);
-  yield removeBreakpoint(dbg, 1);
-  const bps = findBreakpoints(dbg);
-  is(bps.size, 0, "breakpoints are removed");
-});
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-call-stack.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-call-stack.js
@@ -12,40 +12,40 @@ function isFrameSelected(dbg, index, tit
   return elSelected && titleSelected;
 }
 
 function toggleButton(dbg) {
   const callStackBody = findElement(dbg, "callStackBody");
   return callStackBody.querySelector(".show-more");
 }
 
-add_task(function* () {
-  const dbg = yield initDebugger("doc-script-switching.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-script-switching.html");
 
   toggleCallStack(dbg);
 
   const notPaused = findElement(dbg, "callStackBody").innerText;
   is(notPaused, "Not Paused", "Not paused message is shown");
 
   invokeInTab("firstCall");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
 
   ok(isFrameSelected(dbg, 1, "secondCall"), "the first frame is selected");
 
   let button = toggleButton(dbg);
   ok(!button, "toggle button shouldn't be there");
 });
 
-add_task(function* () {
-  const dbg = yield initDebugger("doc-frames.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-frames.html");
 
   toggleCallStack(dbg);
 
   invokeInTab("startRecursion");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
 
   ok(isFrameSelected(dbg, 1, "recurseA"), "the first frame is selected");
 
   // check to make sure that the toggle button isn't there
   let button = toggleButton(dbg);
   let frames = findAllElements(dbg, "frames");
   is(button.innerText, "Expand Rows", "toggle button should be expand");
   is(frames.length, 7, "There should be at most seven frames");
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-chrome-create.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-chrome-create.js
@@ -37,22 +37,22 @@ function onClose() {
   finish();
 }
 
 registerCleanupFunction(function() {
   Services.prefs.clearUserPref("devtools.debugger.remote-enabled");
   gProcess = null;
 });
 
-add_task(function*() {
+add_task(async function() {
   // Windows XP and 8.1 test slaves are terribly slow at this test.
   requestLongerTimeout(5);
   Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
 
-  gProcess = yield initChromeDebugger();
+  gProcess = await initChromeDebugger();
 
   ok(
     gProcess._dbgProcess,
     "The remote debugger process wasn't created properly!"
   );
   ok(
     gProcess._dbgProcess.exitCode == null,
     "The remote debugger process isn't running!"
@@ -76,10 +76,10 @@ add_task(function*() {
   is(
     gProcess._dbgProfilePath,
     OS.Path.join(OS.Constants.Path.profileDir, "chrome_debugger_profile"),
     "The remote debugger profile isn't where we expect it!"
   );
 
   info("profile path: " + gProcess._dbgProfilePath);
 
-  yield gProcess.close();
+  await gProcess.close();
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-chrome-debugging.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-chrome-debugging.js
@@ -63,26 +63,26 @@ registerCleanupFunction(function() {
   gThreadClient = null;
   gNewGlobal = null;
   gNewChromeSource = null;
 
   customLoader = null;
   DebuggerServer = null;
 });
 
-add_task(function*() {
+add_task(async function() {
   gClient = initDebuggerClient();
 
-  const [type] = yield gClient.connect();
+  const [type] = await gClient.connect();
   is(type, "browser", "Root actor should identify itself as a browser.");
 
-  const response = yield gClient.getProcess();
+  const response = await gClient.getProcess();
   let actor = response.form.actor;
-  gThreadClient = yield attachThread(gClient, actor);
+  gThreadClient = await attachThread(gClient, actor);
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:mozilla");
 
   // listen for a new source and global
   gThreadClient.addListener("newSource", onNewSource);
   gClient.addListener("newGlobal", onNewGlobal);
-  yield promise.all([gNewGlobal.promise, gNewChromeSource.promise]);
+  await promise.all([gNewGlobal.promise, gNewChromeSource.promise]);
 
-  yield resumeAndCloseConnection();
+  await resumeAndCloseConnection();
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-console.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-console.js
@@ -20,26 +20,27 @@ function getSplitConsole(dbg) {
     toolbox.getPanelWhenReady("webconsole").then(() => {
       ok(toolbox.splitConsole, "Split console is shown.");
       let jsterm = toolbox.getPanel("webconsole").hud.jsterm;
       resolve(jsterm);
     });
   });
 }
 
-add_task(function* () {
+add_task(async function() {
   Services.prefs.setBoolPref("devtools.toolbox.splitconsoleEnabled", true);
-  const dbg = yield initDebugger("doc-script-switching.html");
+  const dbg = await initDebugger("doc-script-switching.html");
 
-  yield selectSource(dbg, "switching-01");
+  await selectSource(dbg, "switching-01");
 
   // open the console
-  yield getSplitConsole(dbg);
+  await getSplitConsole(dbg);
   ok(dbg.toolbox.splitConsole, "Split console is shown.");
 
   // close the console
-  clickElement(dbg, "codeMirror");
+  await clickElement(dbg, "codeMirror");
   // First time to focus out of text area
   pressKey(dbg, "Escape");
+
   // Second time to hide console
   pressKey(dbg, "Escape");
   ok(!dbg.toolbox.splitConsole, "Split console is hidden.");
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-debugger-buttons.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-debugger-buttons.js
@@ -19,36 +19,36 @@ function clickStepOut(dbg) {
 /**
  * Test debugger buttons
  *  1. resume
  *  2. stepOver
  *  3. stepIn
  *  4. stepOver to the end of a function
  *  5. stepUp at the end of a function
  */
-add_task(function*() {
-  const dbg = yield initDebugger("doc-debugger-statements.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-debugger-statements.html");
 
-  yield reload(dbg);
-  yield waitForPaused(dbg);
+  await reload(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
 
   // resume
   clickElement(dbg, "resume");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
 
   // step over
-  yield clickStepOver(dbg);
+  await clickStepOver(dbg);
   assertPausedLocation(dbg);
 
   // step into
-  yield clickStepIn(dbg);
+  await clickStepIn(dbg);
   assertPausedLocation(dbg);
 
   // step over
-  yield clickStepOver(dbg);
+  await clickStepOver(dbg);
   assertPausedLocation(dbg);
 
   // step out
-  yield clickStepOut(dbg);
+  await clickStepOut(dbg);
   assertPausedLocation(dbg);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-gutter.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-gutter.js
@@ -20,27 +20,27 @@ function assertEditorBreakpoint(dbg, lin
     exists === shouldExist,
     "Breakpoint " +
       (shouldExist ? "exists" : "does not exist") +
       " on line " +
       line
   );
 }
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-scripts.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-scripts.html");
   const { selectors: { getBreakpoints, getBreakpoint }, getState } = dbg;
   const source = findSource(dbg, "simple1.js");
 
-  yield selectSource(dbg, source.url);
+  await selectSource(dbg, source.url);
 
   // Make sure that clicking the gutter creates a breakpoint icon.
   clickGutter(dbg, 4);
-  yield waitForDispatch(dbg, "ADD_BREAKPOINT");
+  await waitForDispatch(dbg, "ADD_BREAKPOINT");
   is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
   assertEditorBreakpoint(dbg, 4, true);
 
   // Make sure clicking at the same place removes the icon.
   clickGutter(dbg, 4);
-  yield waitForDispatch(dbg, "REMOVE_BREAKPOINT");
+  await waitForDispatch(dbg, "REMOVE_BREAKPOINT");
   is(getBreakpoints(getState()).size, 0, "No breakpoints exist");
   assertEditorBreakpoint(dbg, 4, false);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-highlight.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-highlight.js
@@ -1,51 +1,51 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that the editor will always highight the right line, no
 // matter if the source text doesn't exist yet or even if the source
 // doesn't exist.
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-scripts.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-scripts.html");
   const { selectors: { getSource }, getState } = dbg;
   const sourceUrl = EXAMPLE_URL + "long.js";
 
   // The source itself doesn't even exist yet, and using
   // `selectSourceURL` will set a pending request to load this source
   // and highlight a specific line.
   dbg.actions.selectSourceURL(sourceUrl, { line: 66 });
 
   // Wait for the source text to load and make sure we're in the right
   // place.
-  yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
+  await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
 
   // TODO: revisit highlighting lines when the debugger opens
   //assertHighlightLocation(dbg, "long.js", 66);
 
   // Jump to line 16 and make sure the editor scrolled.
-  yield selectSource(dbg, "long.js", 16);
+  await selectSource(dbg, "long.js", 16);
   assertHighlightLocation(dbg, "long.js", 16);
 
   // Make sure only one line is ever highlighted and the flash
   // animation is cancelled on old lines.
-  yield selectSource(dbg, "long.js", 17);
-  yield selectSource(dbg, "long.js", 18);
+  await selectSource(dbg, "long.js", 17);
+  await selectSource(dbg, "long.js", 18);
   assertHighlightLocation(dbg, "long.js", 18);
   is(
     findAllElements(dbg, "highlightLine").length,
     1,
     "Only 1 line is highlighted"
   );
 
   // Test jumping to a line in a source that exists but hasn't been
   // loaded yet.
   selectSource(dbg, "simple1.js", 6);
 
   // Make sure the source is in the loading state, wait for it to be
   // fully loaded, and check the highlighted line.
   const simple1 = findSource(dbg, "simple1.js");
   ok(getSource(getState(), simple1.id).get("loadedState"));
-  yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
+  await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
   ok(getSource(getState(), simple1.id).get("text"));
   assertHighlightLocation(dbg, "simple1.js", 6);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-mode.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-mode.js
@@ -1,14 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that the editor sets the correct mode for different file
 // types
-add_task(function* () {
-  const dbg = yield initDebugger("doc-scripts.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-scripts.html");
 
-  yield selectSource(dbg, "simple1.js");
+  await selectSource(dbg, "simple1.js");
   is(dbg.win.cm.getOption("mode").name, "javascript", "Mode is correct");
 
-  yield selectSource(dbg, "doc-scripts.html");
+  await selectSource(dbg, "doc-scripts.html");
   is(dbg.win.cm.getOption("mode").name, "htmlmixed", "Mode is correct");
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-select.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-select.js
@@ -6,49 +6,49 @@
 
 // checks to see if the first breakpoint is visible
 function isElementVisible(dbg, elementName) {
   const bpLine = findElement(dbg, elementName);
   const cm = findElement(dbg, "codeMirror");
   return bpLine && isVisibleWithin(cm, bpLine);
 }
 
-add_task(function*() {
+add_task(async function() {
   // This test runs too slowly on linux debug. I'd like to figure out
   // which is the slowest part of this and make it run faster, but to
   // fix a frequent failure allow a longer timeout.
   requestLongerTimeout(2);
 
-  const dbg = yield initDebugger("doc-scripts.html");
+  const dbg = await initDebugger("doc-scripts.html");
   const { selectors: { getSelectedSource }, getState } = dbg;
   const simple1 = findSource(dbg, "simple1.js");
   const simple2 = findSource(dbg, "simple2.js");
 
   // Set the initial breakpoint.
-  yield addBreakpoint(dbg, simple1, 4);
+  await addBreakpoint(dbg, simple1, 4);
   ok(!getSelectedSource(getState()), "No selected source");
 
   // Call the function that we set a breakpoint in.
   invokeInTab("main");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
 
   // Step through to another file and make sure it's paused in the
   // right place.
-  yield stepIn(dbg);
+  await stepIn(dbg);
   assertPausedLocation(dbg);
 
   // Step back out to the initial file.
-  yield stepOut(dbg);
-  yield stepOut(dbg);
+  await stepOut(dbg);
+  await stepOut(dbg);
   assertPausedLocation(dbg);
-  yield resume(dbg);
+  await resume(dbg);
 
   // Make sure that we can set a breakpoint on a line out of the
   // viewport, and that pausing there scrolls the editor to it.
   let longSrc = findSource(dbg, "long.js");
-  yield addBreakpoint(dbg, longSrc, 66);
+  await addBreakpoint(dbg, longSrc, 66);
 
   invokeInTab("testModel");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
   ok(isElementVisible(dbg, "breakpoint"), "Breakpoint is visible");
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-expressions.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-expressions.js
@@ -48,37 +48,37 @@ async function editExpression(dbg, input
   dblClickElement(dbg, "expressionNode", 1);
   // Position cursor reliably at the end of the text.
   pressKey(dbg, "End");
   type(dbg, input);
   pressKey(dbg, "Enter");
   await waitForDispatch(dbg, "EVALUATE_EXPRESSION");
 }
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-script-switching.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-script-switching.html");
 
   invokeInTab("firstCall");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
 
-  yield addExpression(dbg, "f");
+  await addExpression(dbg, "f");
   is(getLabel(dbg, 1), "f");
   is(getValue(dbg, 1), "(unavailable)");
 
-  yield editExpression(dbg, "oo");
+  await editExpression(dbg, "oo");
   is(getLabel(dbg, 1), "foo()");
 
   // There is no "value" element for functions.
   assertEmptyValue(dbg, 1);
 
-  yield addExpression(dbg, "location");
+  await addExpression(dbg, "location");
   is(getLabel(dbg, 2), "location");
   ok(getValue(dbg, 2).includes("Location"), "has a value");
 
   // can expand an expression
   toggleExpression(dbg, 2);
-  yield waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES");
+  await waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES");
 
-  yield deleteExpression(dbg, "foo");
-  yield deleteExpression(dbg, "location");
+  await deleteExpression(dbg, "foo");
+  await deleteExpression(dbg, "location");
 
   is(findAllElements(dbg, "expressionNodes").length, 0);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-iframes.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-iframes.js
@@ -1,26 +1,26 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Test debugging a page with iframes
  *  1. pause in the main thread
  *  2. pause in the iframe
  */
-add_task(function*() {
-  const dbg = yield initDebugger("doc-iframes.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-iframes.html");
 
   // test pausing in the main thread
-  yield reload(dbg);
-  yield waitForPaused(dbg);
+  await reload(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
 
   // test pausing in the iframe
-  yield resume(dbg);
-  yield waitForPaused(dbg);
+  await resume(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
 
   // test pausing in the iframe
-  yield resume(dbg);
-  yield waitForPaused(dbg);
+  await resume(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-navigation.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-navigation.js
@@ -5,46 +5,48 @@ function countSources(dbg) {
   const sources = dbg.selectors.getSources(dbg.getState());
   return sources.size;
 }
 
 /**
  * Test navigating
  * navigating while paused will reset the pause state and sources
  */
-add_task(function*() {
-  const dbg = yield initDebugger("doc-script-switching.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-script-switching.html");
   const { selectors: { getSelectedSource, getPause }, getState } = dbg;
 
   invokeInTab("firstCall");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
 
-  yield navigate(dbg, "doc-scripts.html", "simple1.js");
-  yield addBreakpoint(dbg, "simple1.js", 4);
+  await navigate(dbg, "doc-scripts.html", "simple1.js");
+  await addBreakpoint(dbg, "simple1.js", 4);
   invokeInTab("main");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
   is(countSources(dbg), 4, "4 sources are loaded.");
 
-  yield navigate(dbg, "about:blank");
-  yield waitForDispatch(dbg, "NAVIGATE");
+  await navigate(dbg, "about:blank");
+  await waitForDispatch(dbg, "NAVIGATE");
   is(countSources(dbg), 0, "0 sources are loaded.");
   ok(!getPause(getState()), "No pause state exists");
 
-  yield navigate(
+  await navigate(
     dbg,
     "doc-scripts.html",
     "simple1.js",
     "simple2.js",
     "long.js",
     "scripts.html"
   );
 
   is(countSources(dbg), 4, "4 sources are loaded.");
 
   // Test that the current select source persists across reloads
-  yield selectSource(dbg, "long.js");
-  yield reload(dbg, "long.js");
+  await selectSource(dbg, "long.js");
+  await reload(dbg, "long.js");
   ok(
-    getSelectedSource(getState()).get("url").includes("long.js"),
+    getSelectedSource(getState())
+      .get("url")
+      .includes("long.js"),
     "Selected source is long.js"
   );
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-pause-exceptions.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-pause-exceptions.js
@@ -11,35 +11,35 @@ function caughtException() {
 
 /*
   Tests Pausing on exception
   1. skip an uncaught exception
   2. pause on an uncaught exception
   3. pause on a caught error
   4. skip a caught error
 */
-add_task(function*() {
-  const dbg = yield initDebugger("doc-exceptions.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-exceptions.html");
 
   // test skipping an uncaught exception
-  yield uncaughtException();
+  await uncaughtException();
   ok(!isPaused(dbg));
 
   // Test pausing on an uncaught exception
-  yield togglePauseOnExceptions(dbg, true, false);
+  await togglePauseOnExceptions(dbg, true, false);
   uncaughtException();
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
-  yield resume(dbg);
+  await resume(dbg);
 
   // Test pausing on a caught Error
   caughtException();
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
-  yield resume(dbg);
+  await resume(dbg);
 
   // Test skipping a caught error
-  yield togglePauseOnExceptions(dbg, true, true);
+  await togglePauseOnExceptions(dbg, true, true);
   caughtException();
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
-  yield resume(dbg);
+  await resume(dbg);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print-paused.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print-paused.js
@@ -1,23 +1,23 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests pretty-printing a source that is currently paused.
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-minified.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-minified.html");
 
-  yield selectSource(dbg, "math.min.js");
-  yield addBreakpoint(dbg, "math.min.js", 2);
+  await selectSource(dbg, "math.min.js");
+  await addBreakpoint(dbg, "math.min.js", 2);
 
   invokeInTab("arithmetic");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
 
   clickElement(dbg, "prettyPrintButton");
-  yield waitForDispatch(dbg, "SELECT_SOURCE");
+  await waitForDispatch(dbg, "SELECT_SOURCE");
 
   // this doesnt work yet
   // assertPausedLocation(dbg);
 
-  yield resume(dbg);
+  await resume(dbg);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print.js
@@ -1,35 +1,35 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests basic pretty-printing functionality.
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-minified.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-minified.html");
 
-  yield selectSource(dbg, "math.min.js", 2);
+  await selectSource(dbg, "math.min.js", 2);
   clickElement(dbg, "prettyPrintButton");
 
-  yield waitForSource(dbg, "math.min.js:formatted");
+  await waitForSource(dbg, "math.min.js:formatted");
   const ppSrc = findSource(dbg, "math.min.js:formatted");
 
   ok(ppSrc, "Pretty-printed source exists");
 
   // this is not implemented yet
   // assertHighlightLocation(dbg, "math.min.js:formatted", 18);
 
-  yield addBreakpoint(dbg, ppSrc, 18);
+  await addBreakpoint(dbg, ppSrc, 18);
 
   invokeInTab("arithmetic");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
-  yield stepOver(dbg);
+  await stepOver(dbg);
   assertPausedLocation(dbg);
-  yield resume(dbg);
+  await resume(dbg);
 
   // The pretty-print button should go away in the pretty-printed
   // source.
   ok(!findElement(dbg, "editorFooter"), "Footer is hidden");
 
-  yield selectSource(dbg, "math.min.js");
+  await selectSource(dbg, "math.min.js");
   ok(findElement(dbg, "editorFooter"), "Footer is hidden");
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-scopes-mutations.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-scopes-mutations.js
@@ -18,74 +18,74 @@ function expandNode(dbg, index) {
 function toggleScopes(dbg) {
   return findElement(dbg, "scopesHeader").click();
 }
 
 function onLoadObjectProperties(dbg) {
   return waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES");
 }
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-script-mutate.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-script-mutate.html");
 
   toggleScopes(dbg);
 
   let onPaused = waitForPaused(dbg);
   invokeInTab("mutate");
-  yield onPaused;
+  await onPaused;
 
   is(
     getScopeNodeLabel(dbg, 2),
     "<this>",
     'The second element in the scope panel is "<this>"'
   );
   is(
     getScopeNodeLabel(dbg, 3),
     "phonebook",
     'The third element in the scope panel is "phonebook"'
   );
 
   info("Expand `phonebook`");
-  yield expandNode(dbg, 3);
+  await expandNode(dbg, 3);
   is(
     getScopeNodeLabel(dbg, 4),
     "S",
     'The fourth element in the scope panel is "S"'
   );
 
   info("Expand `S`");
-  yield expandNode(dbg, 4);
+  await expandNode(dbg, 4);
   is(
     getScopeNodeLabel(dbg, 5),
     "sarah",
     'The fifth element in the scope panel is "sarah"'
   );
   is(
     getScopeNodeLabel(dbg, 6),
     "serena",
     'The sixth element in the scope panel is "serena"'
   );
 
   info("Expand `sarah`");
-  yield expandNode(dbg, 5);
+  await expandNode(dbg, 5);
   is(
     getScopeNodeLabel(dbg, 6),
     "lastName",
     'The sixth element in the scope panel is now "lastName"'
   );
   is(
     getScopeNodeValue(dbg, 6),
     '"Doe"',
     'The "lastName" element has the expected "Doe" value'
   );
 
   info("Resuming");
   onPaused = waitForPaused(dbg);
-  yield resume(dbg);
-  yield onPaused;
+  await resume(dbg);
+  await onPaused;
 
   is(
     getScopeNodeLabel(dbg, 2),
     "<this>",
     'The second element in the scope panel is "<this>"'
   );
   is(
     getScopeNodeLabel(dbg, 3),
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-scopes.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-scopes.js
@@ -4,28 +4,28 @@
 function toggleNode(dbg, index) {
   clickElement(dbg, "scopeNode", index);
 }
 
 function getLabel(dbg, index) {
   return findElement(dbg, "scopeNode", index).innerText;
 }
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-script-switching.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-script-switching.html");
 
   toggleScopes(dbg);
 
   invokeInTab("firstCall");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
 
   is(getLabel(dbg, 1), "secondCall");
   is(getLabel(dbg, 2), "<this>");
   is(getLabel(dbg, 4), "foo()");
 
   toggleNode(dbg, 4);
-  yield waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES");
+  await waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES");
   is(getLabel(dbg, 5), "arguments");
 
-  yield stepOver(dbg);
+  await stepOver(dbg);
   is(getLabel(dbg, 4), "foo()");
   is(getLabel(dbg, 5), "Window");
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-search-file.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-search-file.js
@@ -7,40 +7,40 @@ function waitForSearchState(dbg) {
   return waitForState(dbg, () => getCM(dbg).state.search);
 }
 
 function getFocusedEl(dbg) {
   let doc = dbg.win.document;
   return doc.activeElement;
 }
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-scripts.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-scripts.html");
   const {
     selectors: { getBreakpoints, getBreakpoint, getActiveSearch },
     getState
   } = dbg;
   const source = findSource(dbg, "simple1.js");
 
-  yield selectSource(dbg, source.url);
+  await selectSource(dbg, source.url);
 
   const cm = getCM(dbg);
   pressKey(dbg, "fileSearch");
-  is(dbg.selectors.getActiveSearchState(dbg.getState()), "file");
+  is(dbg.selectors.getActiveSearch(dbg.getState()), "file");
 
   // test closing and re-opening
   pressKey(dbg, "Escape");
-  is(dbg.selectors.getActiveSearchState(dbg.getState()), null);
+  is(dbg.selectors.getActiveSearch(dbg.getState()), null);
 
   pressKey(dbg, "fileSearch");
 
   const el = getFocusedEl(dbg);
 
   type(dbg, "con");
-  yield waitForSearchState(dbg);
+  await waitForSearchState(dbg);
 
   const state = cm.state.search;
 
   pressKey(dbg, "Enter");
   is(state.posFrom.line, 3);
 
   pressKey(dbg, "Enter");
   is(state.posFrom.line, 4);
@@ -50,12 +50,12 @@ add_task(function*() {
 
   pressKey(dbg, "fileSearch");
   type(dbg, "fun");
 
   pressKey(dbg, "Enter");
   is(state.posFrom.line, 4);
 
   // selecting another source keeps search open
-  yield selectSource(dbg, "simple2");
+  await selectSource(dbg, "simple2");
   pressKey(dbg, "Enter");
   is(state.posFrom.line, 0);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-search-project.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-search-project.js
@@ -1,68 +1,67 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function openProjectSearch(dbg) {
   synthesizeKeyShortcut("CmdOrCtrl+Shift+F");
   return waitForState(
     dbg,
-    state => dbg.selectors.getActiveSearchState(state) === "project"
+    state => dbg.selectors.getActiveSearch(state) === "project"
   );
 }
 
 function closeProjectSearch(dbg) {
   pressKey(dbg, "Escape");
-  return waitForState(dbg, state => !dbg.selectors.getActiveSearchState(state));
-}
-
-function getResult(dbg) {
-  return findElementWithSelector(dbg, ".managed-tree .result");
+  return waitForState(dbg, state => !dbg.selectors.getActiveSearch(state));
 }
 
 async function selectResult(dbg) {
-  const item = getResult(dbg);
-  const select = waitForDispatch(dbg, "SELECT_SOURCE");
-  item.click();
+  const select = waitForState(
+    dbg,
+    () => !dbg.selectors.getActiveSearch(dbg.getState())
+  );
+  await clickElement(dbg, "fileMatch");
   return select;
 }
 
 function getResultsCount(dbg) {
   const matches = dbg.selectors
     .getTextSearchResults(dbg.getState())
     .valueSeq()
     .map(file => file.matches)
     .toJS();
 
   return [...matches].length;
 }
 
 // Testing project search
-add_task(function*() {
+add_task(async function() {
   Services.prefs.setBoolPref(
     "devtools.debugger.project-text-search-enabled",
     true
   );
 
-  const dbg = yield initDebugger("doc-script-switching.html", "switching-01");
+  const dbg = await initDebugger("doc-script-switching.html", "switching-01");
 
-  yield selectSource(dbg, "switching-01");
+  await selectSource(dbg, "switching-01");
 
   // test opening and closing
-  yield openProjectSearch(dbg);
-  yield closeProjectSearch(dbg);
+  await openProjectSearch(dbg);
+  await closeProjectSearch(dbg);
 
-  yield openProjectSearch(dbg);
+  await openProjectSearch(dbg);
   type(dbg, "first");
   pressKey(dbg, "Enter");
 
-  yield waitForState(dbg, () => getResultsCount(dbg) === 1);
+  await waitForState(dbg, () => getResultsCount(dbg) === 1);
 
-  yield selectResult(dbg);
-  is(dbg.selectors.getActiveSearchState(dbg.getState()), null);
+  await selectResult(dbg);
+
+  is(dbg.selectors.getActiveSearch(dbg.getState()), null);
 
   const selectedSource = dbg.selectors.getSelectedSource(dbg.getState());
   ok(selectedSource.get("url").includes("switching-01"));
 });
 
 registerCleanupFunction(() => {
   Services.prefs.clearUserPref(
     "devtools.debugger.project-text-search-enabled",
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-search-sources.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-search-sources.js
@@ -1,34 +1,34 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Testing source search
-add_task(function*() {
-  const dbg = yield initDebugger("doc-script-switching.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-script-switching.html");
 
   // test opening and closing
   pressKey(dbg, "sourceSearch");
-  is(dbg.selectors.getActiveSearchState(dbg.getState()), "source");
+  is(dbg.selectors.getActiveSearch(dbg.getState()), "source");
   pressKey(dbg, "Escape");
-  is(dbg.selectors.getActiveSearchState(dbg.getState()), null);
+  is(dbg.selectors.getActiveSearch(dbg.getState()), null);
 
   pressKey(dbg, "sourceSearch");
-  yield waitForElement(dbg, "input");
+  await waitForElement(dbg, "input");
   findElementWithSelector(dbg, "input").focus();
   type(dbg, "sw");
   pressKey(dbg, "Enter");
 
-  yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
+  await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
   let source = dbg.selectors.getSelectedSource(dbg.getState());
   ok(source.get("url").match(/switching-01/), "first source is selected");
 
   // 2. arrow keys and check to see if source is selected
   pressKey(dbg, "sourceSearch");
   findElementWithSelector(dbg, "input").focus();
   type(dbg, "sw");
   pressKey(dbg, "Down");
   pressKey(dbg, "Enter");
 
-  yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
+  await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
   source = dbg.selectors.getSelectedSource(dbg.getState());
   ok(source.get("url").match(/switching-02/), "second source is selected");
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-search-symbols.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-search-symbols.js
@@ -6,25 +6,25 @@ async function openFunctionSearch(dbg) {
   return new Promise(r => setTimeout(r, 200));
 }
 
 function resultCount(dbg) {
   return findAllElements(dbg, "resultItems").length;
 }
 
 // Testing function search
-add_task(function*() {
-  const dbg = yield initDebugger("doc-script-switching.html", "switching-01");
+add_task(async function() {
+  const dbg = await initDebugger("doc-script-switching.html", "switching-01");
 
-  yield selectSource(dbg, "switching-01");
+  await selectSource(dbg, "switching-01");
 
   // test opening and closing
-  yield openFunctionSearch(dbg);
-  is(dbg.selectors.getActiveSearchState(dbg.getState()), "symbol");
+  await openFunctionSearch(dbg);
+  is(dbg.selectors.getActiveSearch(dbg.getState()), "symbol");
   pressKey(dbg, "Escape");
-  is(dbg.selectors.getActiveSearchState(dbg.getState()), null);
+  is(dbg.selectors.getActiveSearch(dbg.getState()), null);
 
-  yield openFunctionSearch(dbg);
+  await openFunctionSearch(dbg);
   is(resultCount(dbg), 1);
 
   type(dbg, "x");
   is(resultCount(dbg), 0);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps-bogus.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps-bogus.js
@@ -1,26 +1,26 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that an error while loading a sourcemap does not break
 // debugging.
 
-add_task(function*() {
+add_task(async function() {
   // NOTE: the CORS call makes the test run times inconsistent
   requestLongerTimeout(2);
 
-  const dbg = yield initDebugger("doc-sourcemap-bogus.html");
+  const dbg = await initDebugger("doc-sourcemap-bogus.html");
   const { selectors: { getSources }, getState } = dbg;
 
-  yield selectSource(dbg, "bogus-map.js");
+  await selectSource(dbg, "bogus-map.js");
 
   // We should still be able to set breakpoints and pause in the
   // generated source.
-  yield addBreakpoint(dbg, "bogus-map.js", 4);
+  await addBreakpoint(dbg, "bogus-map.js", 4);
   invokeInTab("runCode");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
 
   // Make sure that only the single generated source exists. The
   // sourcemap failed to download.
   is(getSources(getState()).size, 1, "Only 1 source exists");
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps-reloading.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps-reloading.js
@@ -1,43 +1,43 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-add_task(function*() {
+add_task(async function() {
   // NOTE: the CORS call makes the test run times inconsistent
   requestLongerTimeout(2);
 
-  const dbg = yield initDebugger("doc-sourcemaps.html");
+  const dbg = await initDebugger("doc-sourcemaps.html");
   const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
 
-  yield waitForSources(dbg, "entry.js", "output.js", "times2.js", "opts.js");
+  await waitForSources(dbg, "entry.js", "output.js", "times2.js", "opts.js");
   ok(true, "Original sources exist");
   const entrySrc = findSource(dbg, "entry.js");
 
-  yield selectSource(dbg, entrySrc);
+  await selectSource(dbg, entrySrc);
   ok(
     dbg.win.cm.getValue().includes("window.keepMeAlive"),
     "Original source text loaded correctly"
   );
 
   // Test that breakpoint sliding is not attempted. The breakpoint
   // should not move anywhere.
-  yield addBreakpoint(dbg, entrySrc, 13);
+  await addBreakpoint(dbg, entrySrc, 13);
   is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
   ok(
     getBreakpoint(getState(), { sourceId: entrySrc.id, line: 13 }),
     "Breakpoint has correct line"
   );
 
-  yield addBreakpoint(dbg, entrySrc, 15);
-  yield disableBreakpoint(dbg, entrySrc, 15);
+  await addBreakpoint(dbg, entrySrc, 15);
+  await disableBreakpoint(dbg, entrySrc, 15);
 
   // Test reloading the debugger
-  yield reload(dbg, "opts.js");
-  yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
+  await reload(dbg, "opts.js");
+  await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
 
   is(getBreakpoints(getState()).size, 2, "One breakpoint exists");
 
   ok(
     getBreakpoint(getState(), { sourceId: entrySrc.id, line: 13 }),
     "Breakpoint has correct line"
   );
 
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps.js
@@ -28,61 +28,61 @@ function getLineEl(dbg, line) {
   const lines = dbg.win.document.querySelectorAll(".CodeMirror-code > div");
   return lines[line - 1];
 }
 
 function clickGutter(dbg, line) {
   clickElement(dbg, "gutter", line);
 }
 
-add_task(function*() {
+add_task(async function() {
   // NOTE: the CORS call makes the test run times inconsistent
   requestLongerTimeout(2);
 
-  const dbg = yield initDebugger("doc-sourcemaps.html");
+  const dbg = await initDebugger("doc-sourcemaps.html");
   const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
 
-  yield waitForSources(dbg, "entry.js", "output.js", "times2.js", "opts.js");
+  await waitForSources(dbg, "entry.js", "output.js", "times2.js", "opts.js");
   ok(true, "Original sources exist");
   const bundleSrc = findSource(dbg, "bundle.js");
 
-  yield selectSource(dbg, bundleSrc);
+  await selectSource(dbg, bundleSrc);
 
-  yield clickGutter(dbg, 13);
-  yield waitForDispatch(dbg, "ADD_BREAKPOINT");
+  await clickGutter(dbg, 13);
+  await waitForDispatch(dbg, "ADD_BREAKPOINT");
   assertEditorBreakpoint(dbg, 13, true);
 
-  yield clickGutter(dbg, 13);
-  yield waitForDispatch(dbg, "REMOVE_BREAKPOINT");
+  await clickGutter(dbg, 13);
+  await waitForDispatch(dbg, "REMOVE_BREAKPOINT");
   is(getBreakpoints(getState()).size, 0, "No breakpoints exists");
 
   const entrySrc = findSource(dbg, "entry.js");
 
-  yield selectSource(dbg, entrySrc);
+  await selectSource(dbg, entrySrc);
   ok(
     dbg.win.cm.getValue().includes("window.keepMeAlive"),
     "Original source text loaded correctly"
   );
 
   // Test that breakpoint sliding is not attempted. The breakpoint
   // should not move anywhere.
-  yield addBreakpoint(dbg, entrySrc, 13);
+  await addBreakpoint(dbg, entrySrc, 13);
   is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
   assertBreakpointExists(dbg, entrySrc, 13);
 
   // Test breaking on a breakpoint
-  yield addBreakpoint(dbg, "entry.js", 15);
+  await addBreakpoint(dbg, "entry.js", 15);
   is(getBreakpoints(getState()).size, 2, "Two breakpoints exist");
   assertBreakpointExists(dbg, entrySrc, 15);
 
   invokeInTab("keepMeAlive");
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
 
-  yield stepIn(dbg);
+  await stepIn(dbg);
   assertPausedLocation(dbg);
-  yield stepOver(dbg);
+  await stepOver(dbg);
   assertPausedLocation(dbg);
 
-  yield stepOut(dbg);
-  yield stepOut(dbg);
+  await stepOut(dbg);
+  await stepOut(dbg);
   assertPausedLocation(dbg);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps2.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps2.js
@@ -1,35 +1,35 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests loading sourcemapped sources, setting breakpoints, and
 // stepping in them.
 
 // This source map does not have source contents, so it's fetched separately
 
-add_task(function*() {
+add_task(async function() {
   // NOTE: the CORS call makes the test run times inconsistent
   requestLongerTimeout(2);
 
-  const dbg = yield initDebugger("doc-sourcemaps2.html");
+  const dbg = await initDebugger("doc-sourcemaps2.html");
   const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
 
-  yield waitForSources(dbg, "main.js", "main.min.js");
+  await waitForSources(dbg, "main.js", "main.min.js");
 
   ok(true, "Original sources exist");
   const mainSrc = findSource(dbg, "main.js");
 
-  yield selectSource(dbg, mainSrc);
+  await selectSource(dbg, mainSrc);
 
   // Test that breakpoint is not off by a line.
-  yield addBreakpoint(dbg, mainSrc, 4);
+  await addBreakpoint(dbg, mainSrc, 4);
   is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
   ok(
     getBreakpoint(getState(), { sourceId: mainSrc.id, line: 4, column: 2 }),
     "Breakpoint has correct line"
   );
 
   invokeInTab("logMessage");
 
-  yield waitForPaused(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-sources.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sources.js
@@ -1,89 +1,91 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that the source tree works.
 
-function* waitForSourceCount(dbg, i) {
+async function waitForSourceCount(dbg, i) {
   // We are forced to wait until the DOM nodes appear because the
   // source tree batches its rendering.
-  yield waitUntil(() => {
+  await waitUntil(() => {
     return findAllElements(dbg, "sourceNodes").length === i;
   });
 }
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-sources.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-sources.html");
   const { selectors: { getSelectedSource }, getState } = dbg;
 
-  yield waitForSources(dbg, "simple1", "simple2", "nested-source", "long.js");
+  await waitForSources(dbg, "simple1", "simple2", "nested-source", "long.js");
 
   // Expand nodes and make sure more sources appear.
   is(findAllElements(dbg, "sourceNodes").length, 2);
 
-  clickElement(dbg, "sourceArrow", 2);
+  await clickElement(dbg, "sourceArrow", 2);
   is(findAllElements(dbg, "sourceNodes").length, 7);
 
-  clickElement(dbg, "sourceArrow", 3);
+  await clickElement(dbg, "sourceArrow", 3);
   is(findAllElements(dbg, "sourceNodes").length, 8);
 
   // Select a source.
   ok(
     !findElementWithSelector(dbg, ".sources-list .focused"),
     "Source is not focused"
   );
   const selected = waitForDispatch(dbg, "SELECT_SOURCE");
-  clickElement(dbg, "sourceNode", 4);
-  yield selected;
+  await clickElement(dbg, "sourceNode", 4);
+  await selected;
   ok(
     findElementWithSelector(dbg, ".sources-list .focused"),
     "Source is focused"
   );
   ok(
-    getSelectedSource(getState()).get("url").includes("nested-source.js"),
+    getSelectedSource(getState())
+      .get("url")
+      .includes("nested-source.js"),
     "The right source is selected"
   );
 
   // Make sure new sources appear in the list.
   ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
     const script = content.document.createElement("script");
     script.src = "math.min.js";
     content.document.body.appendChild(script);
   });
 
-  yield waitForSourceCount(dbg, 9);
+  await waitForSourceCount(dbg, 9);
   is(
     findElement(dbg, "sourceNode", 7).textContent,
     "math.min.js",
     "The dynamic script exists"
   );
 
   // Make sure named eval sources appear in the list.
 });
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-sources.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-sources.html");
   const { selectors: { getSelectedSource }, getState } = dbg;
 
-  yield waitForSources(dbg, "simple1", "simple2", "nested-source", "long.js");
+  await waitForSources(dbg, "simple1", "simple2", "nested-source", "long.js");
 
   ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
     content.eval("window.evaledFunc = function() {} //# sourceURL=evaled.js");
   });
-  yield waitForSourceCount(dbg, 3);
+  await waitForSourceCount(dbg, 3);
   is(
     findElement(dbg, "sourceNode", 3).textContent,
     "(no domain)",
     "the folder exists"
   );
 
   // work around: the folder is rendered at the bottom, so we close the
   // root folder and open the (no domain) folder
-  clickElement(dbg, "sourceArrow", 3);
-  yield waitForSourceCount(dbg, 4);
+  await clickElement(dbg, "sourceArrow", 3);
+  await waitForSourceCount(dbg, 4);
 
   is(
     findElement(dbg, "sourceNode", 4).textContent,
     "evaled.js",
     "the eval script exists"
   );
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-tabs.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-tabs.js
@@ -2,38 +2,38 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests adding and removing tabs
 
 function countTabs(dbg) {
   return findElement(dbg, "sourceTabs").children.length;
 }
 
-add_task(function*() {
-  let dbg = yield initDebugger("doc-scripts.html");
+add_task(async function() {
+  let dbg = await initDebugger("doc-scripts.html");
 
-  yield selectSource(dbg, "simple1");
-  yield selectSource(dbg, "simple2");
+  await selectSource(dbg, "simple1");
+  await selectSource(dbg, "simple2");
   is(countTabs(dbg), 2);
 
   // Test reloading the debugger
-  yield reload(dbg, "simple1", "simple2");
+  await reload(dbg, "simple1", "simple2");
   is(countTabs(dbg), 2);
-  yield waitForSelectedSource(dbg);
+  await waitForSelectedSource(dbg);
 
   // Test reloading the debuggee a second time
-  yield reload(dbg, "simple1", "simple2");
+  await reload(dbg, "simple1", "simple2");
   is(countTabs(dbg), 2);
-  yield waitForSelectedSource(dbg);
+  await waitForSelectedSource(dbg);
 });
 
-add_task(function*() {
-  let dbg = yield initDebugger("doc-scripts.html", "simple1", "simple2");
+add_task(async function() {
+  let dbg = await initDebugger("doc-scripts.html", "simple1", "simple2");
 
-  yield selectSource(dbg, "simple1");
-  yield selectSource(dbg, "simple2");
+  await selectSource(dbg, "simple1");
+  await selectSource(dbg, "simple2");
   closeTab(dbg, "simple1");
   closeTab(dbg, "simple2");
 
   // Test reloading the debugger
-  yield reload(dbg, "simple1", "simple2");
+  await reload(dbg, "simple1", "simple2");
   is(countTabs(dbg), 0);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-toggling-tools.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-toggling-tools.js
@@ -20,19 +20,19 @@ function getSplitConsole(dbg) {
     toolbox.getPanelWhenReady("webconsole").then(() => {
       ok(toolbox.splitConsole, "Split console is shown.");
       let jsterm = toolbox.getPanel("webconsole").hud.jsterm;
       resolve(jsterm);
     });
   });
 }
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-scripts.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-scripts.html");
 
-  yield selectSource(dbg, "long");
+  await selectSource(dbg, "long");
   dbg.win.cm.scrollTo(0, 284);
 
   pressKey(dbg, "inspector");
   pressKey(dbg, "debugger");
 
   is(dbg.win.cm.getScrollInfo().top, 284);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg_keyboard-shortcuts.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg_keyboard-shortcuts.js
@@ -20,27 +20,27 @@ function pressStepIn(dbg) {
   return waitForPaused(dbg);
 }
 
 function pressStepOut(dbg) {
   pressKey(dbg, "stepOutKey");
   return waitForPaused(dbg);
 }
 
-add_task(function*() {
-  const dbg = yield initDebugger("doc-debugger-statements.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-debugger-statements.html");
 
-  yield reload(dbg);
-  yield waitForPaused(dbg);
+  await reload(dbg);
+  await waitForPaused(dbg);
   assertPausedLocation(dbg);
 
-  yield pressResume(dbg);
+  await pressResume(dbg);
   assertPausedLocation(dbg);
 
-  yield pressStepIn(dbg);
+  await pressStepIn(dbg);
   assertPausedLocation(dbg);
 
-  yield pressStepOut(dbg);
+  await pressStepOut(dbg);
   assertPausedLocation(dbg);
 
-  yield pressStepOver(dbg);
+  await pressStepOver(dbg);
   assertPausedLocation(dbg);
 });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg_keyboard_navigation.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg_keyboard_navigation.js
@@ -1,29 +1,38 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that keyboard navigation into and out of debugger code editor
 
-add_task(function* () {
-  const dbg = yield initDebugger("doc-scripts.html");
+add_task(async function() {
+  const dbg = await initDebugger("doc-scripts.html");
   let doc = dbg.win.document;
 
-  yield selectSource(dbg, "simple2");
+  await selectSource(dbg, "simple2");
 
-  yield waitForElement(dbg, ".CodeMirror");
+  await waitForElement(dbg, ".CodeMirror");
   findElementWithSelector(dbg, ".CodeMirror").focus();
 
   // Enter code editor
   pressKey(dbg, "Enter");
-  is(findElementWithSelector(dbg, "textarea"), doc.activeElement,
-    "Editor is enabled");
+  is(
+    findElementWithSelector(dbg, "textarea"),
+    doc.activeElement,
+    "Editor is enabled"
+  );
 
   // Exit code editor and focus on container
   pressKey(dbg, "Escape");
-  is(findElementWithSelector(dbg, ".CodeMirror"), doc.activeElement,
-    "Focused on container");
+  is(
+    findElementWithSelector(dbg, ".CodeMirror"),
+    doc.activeElement,
+    "Focused on container"
+  );
 
   // Enter code editor
   pressKey(dbg, "Tab");
-  is(findElementWithSelector(dbg, "textarea"), doc.activeElement,
-    "Editor is enabled");
+  is(
+    findElementWithSelector(dbg, "textarea"),
+    doc.activeElement,
+    "Editor is enabled"
+  );
 });
--- a/devtools/client/debugger/new/test/mochitest/examples/doc-async.html
+++ b/devtools/client/debugger/new/test/mochitest/examples/doc-async.html
@@ -4,10 +4,12 @@
 <html>
   <head>
     <meta charset="utf-8"/>
     <title>Async</title>
     <script src="async.js"></script>
   </head>
 
   <body>
+
+    <button onclick="main()">Main</button>
   </body>
 </html>
--- a/devtools/client/debugger/new/test/mochitest/head.js
+++ b/devtools/client/debugger/new/test/mochitest/head.js
@@ -206,18 +206,19 @@ function waitForSources(dbg, ...sources)
  */
 function waitForSource(dbg, url) {
   return waitForState(dbg, state => {
     const sources = dbg.selectors.getSources(state);
     return sources.find(s => (s.get("url") || "").includes(url));
   });
 }
 
-function waitForElement(dbg, selector) {
-  return waitUntil(() => findElementWithSelector(dbg, selector));
+async function waitForElement(dbg, selector) {
+  await waitUntil(() => findElementWithSelector(dbg, selector));
+  return findElementWithSelector(dbg, selector);
 }
 
 function waitForSelectedSource(dbg, sourceId) {
   return waitForState(dbg, state => {
     const source = dbg.selectors.getSelectedSource(state);
     const isLoaded =
       source && source.has("loadedState") && sourceUtils.isLoaded(source);
     if (sourceId) {
@@ -285,17 +286,19 @@ function assertHighlightLocation(dbg, so
   // Check the highlight line
   const lineEl = findElement(dbg, "highlightLine");
   ok(lineEl, "Line is highlighted");
   ok(
     isVisibleWithin(findElement(dbg, "codeMirror"), lineEl),
     "Highlighted line is visible"
   );
   ok(
-    getCM(dbg).lineInfo(line - 1).wrapClass.includes("highlight-line"),
+    getCM(dbg)
+      .lineInfo(line - 1)
+      .wrapClass.includes("highlight-line"),
     "Line is highlighted"
   );
 }
 
 /**
  * Returns boolean for whether the debugger is paused.
  *
  * @memberof mochitest/asserts
@@ -725,17 +728,18 @@ const selectors = {
   stepIn: ".stepIn.active",
   toggleBreakpoints: ".breakpoints-toggle",
   prettyPrintButton: ".prettyPrint",
   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`,
-  resultItems: `.result-list .result-item`
+  resultItems: `.result-list .result-item`,
+  fileMatch: `.managed-tree .result`
 };
 
 function getSelector(elementName, ...args) {
   let selector = selectors[elementName];
   if (!selector) {
     throw new Error(`The selector ${elementName} is not defined`);
   }
 
@@ -765,22 +769,27 @@ function findAllElements(dbg, elementNam
  *
  * @memberof mochitest/helpers
  * @param {Object} dbg
  * @param {String} elementName
  * @param {Array} args
  * @return {Promise}
  * @static
  */
-function clickElement(dbg, elementName, ...args) {
+async function clickElement(dbg, elementName, ...args) {
   const selector = getSelector(elementName, ...args);
-  const el = findElement(dbg, elementName, ...args);
+  const el = await waitForElement(dbg, selector);
+
   el.scrollIntoView();
 
-  return EventUtils.synthesizeMouseAtCenter(
+  return clickElementWithSelector(dbg, selector);
+}
+
+function clickElementWithSelector(dbg, selector) {
+  EventUtils.synthesizeMouseAtCenter(
     findElementWithSelector(dbg, selector),
     {},
     dbg.win
   );
 }
 
 function dblClickElement(dbg, elementName, ...args) {
   const selector = getSelector(elementName, ...args);
--- a/devtools/client/inspector/layout/components/Accordion.css
+++ b/devtools/client/inspector/layout/components/Accordion.css
@@ -21,16 +21,17 @@
 .accordion {
   background-color: var(--theme-sidebar-background);
   width: 100%;
 }
 
 .accordion ._header {
   background-color: var(--accordion-header-background);
   border-bottom: 1px solid var(--theme-splitter-color);
+  color: var(--theme-toolbar-color);
   cursor: pointer;
   font-size: 12px;
   padding: 4px;
   transition: all 0.25s ease;
   width: 100%;
   align-items: center;
   display: flex;
 
--- a/devtools/client/locales/en-US/debugger.properties
+++ b/devtools/client/locales/en-US/debugger.properties
@@ -138,16 +138,20 @@ 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 (projectTextSearch.key): A key shortcut to open the
 # full project text search for searching all the files the debugger has seen.
 projectTextSearch.key=CmdOrCtrl+Shift+F
 
+# LOCALIZATION NOTE (functionSearch.key): A key shortcut to open the
+# modal for searching functions in a file.
+functionSearch.key=CmdOrCtrl+Shift+O
+
 # LOCALIZATION NOTE (projectTextSearch.placeholder): A placeholder shown
 # when searching across all of the files in a project.
 projectTextSearch.placeholder=Find in files…
 
 # LOCALIZATION NOTE (sources.noSourcesAvailable): Text shown when the debugger
 # does not have any sources.
 sources.noSourcesAvailable=This page has no sources
 
@@ -390,16 +394,20 @@ sourceFooter.blackbox.accesskey=B
 # with the blackbox button
 sourceFooter.unblackbox=Unblackbox Source
 sourceFooter.unblackbox.accesskey=b
 
 # LOCALIZATION NOTE (sourceFooter.blackboxed): Text associated
 # with a blackboxed source
 sourceFooter.blackboxed=Blackboxed Source
 
+# LOCALIZATION NOTE (sourceFooter.codeCoverage): Text associated
+# with a code coverage button
+sourceFooter.codeCoverage=Code Coverage
+
 # LOCALIZATION NOTE (sourceTabs.closeTabButtonTooltip): The tooltip that is displayed
 # for close tab button in source tabs.
 sourceTabs.closeTabButtonTooltip=Close tab
 
 # LOCALIZATION NOTE (sourceTabs.newTabButtonTooltip): The tooltip that is displayed for
 # new tab button in source tabs.
 sourceTabs.newTabButtonTooltip=Search for sources (%S)
 
@@ -416,16 +424,19 @@ scopes.notPaused=Not Paused
 
 # LOCALIZATION NOTE (scopes.block): Refers to a block of code in
 # the scopes pane when the debugger is paused.
 scopes.block=Block
 
 # LOCALIZATION NOTE (sources.header): Sources left sidebar header
 sources.header=Sources
 
+# LOCALIZATION NOTE (outline.header): Outline left sidebar header
+outline.header=Outline
+
 # LOCALIZATION NOTE (sources.search): Sources left sidebar prompt
 # e.g. Cmd+P to search. On a mac, we use the command unicode character.
 # On windows, it's ctrl.
 sources.search=%S to search
 
 # LOCALIZATION NOTE (watchExpressions.header): Watch Expressions right sidebar
 # pane header.
 watchExpressions.header=Watch Expressions
@@ -439,19 +450,23 @@ watchExpressions.refreshButton=Refresh
 # a mac we use the unicode character.
 welcome.search=%S to search for sources
 
 # LOCALIZATION NOTE (welcome.findInFiles): The center pane welcome panel's
 # search prompt. e.g. cmd+f to search for files. On windows, it's ctrl+shift+f, on
 # a mac we use the unicode character.
 welcome.findInFiles=%S to find in files
 
+# LOCALIZATION NOTE (welcome.searchFunction): Label displayed in the welcome
+# panel. %S is replaced by the keyboard shortcut to search for functions.
+welcome.searchFunction=%S to search for functions in file
+
 # LOCALIZATION NOTE (sourceSearch.search): The center pane Source Search
 # prompt for searching for files.
-sourceSearch.search=Search Sources…
+sourceSearch.search=Search sources…
 
 # LOCALIZATION NOTE (sourceSearch.noResults): The center pane Source Search
 # message when the query did not match any of the sources.
 sourceSearch.noResults2=No results found
 
 # LOCALIZATION NOTE (ignoreExceptions): The pause on exceptions button tooltip
 # when the debugger will not pause on exceptions.
 ignoreExceptions=Ignore exceptions. Click to pause on uncaught exceptions
--- a/devtools/client/preferences/debugger.js
+++ b/devtools/client/preferences/debugger.js
@@ -33,10 +33,10 @@ pref("devtools.debugger.start-panel-coll
 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", false);
 pref("devtools.debugger.file-search-whole-word", false);
 pref("devtools.debugger.file-search-regex-match", false);
-pref("devtools.debugger.features.async-stepping", false);
+pref("devtools.debugger.features.async-stepping", true);
 pref("devtools.debugger.project-text-search-enabled", true);
--- a/devtools/client/shared/components/tabs/tabs.css
+++ b/devtools/client/shared/components/tabs/tabs.css
@@ -76,17 +76,17 @@
   border-bottom: 1px solid var(--theme-splitter-color);
   background: var(--theme-tab-toolbar-background);
 }
 
 .theme-dark .tabs .tabs-menu-item,
 .theme-light .tabs .tabs-menu-item {
   margin: 0;
   padding: 0;
-  color: var(--theme-content-color1);
+  color: var(--theme-toolbar-color);
 }
 
 .theme-dark .tabs .tabs-menu-item:last-child,
 .theme-light:not(.theme-firebug) .tabs .tabs-menu-item:last-child {
   border-inline-end-width: 1px;
 }
 
 .theme-dark .tabs .tabs-menu-item a,
--- a/devtools/client/themes/animationinspector.css
+++ b/devtools/client/themes/animationinspector.css
@@ -104,17 +104,16 @@ html {
 
 body {
   margin: 0;
   padding: 0;
   display : flex;
   flex-direction: column;
   height: 100%;
   overflow: hidden;
-  color: var(--theme-content-color3);
 }
 
 /* The top toolbar, containing the toggle-all button. And the timeline toolbar,
    containing playback control buttons, shown only when there are animations
    displayed in the timeline */
 
 #global-toolbar,
 #timeline-toolbar {
--- a/devtools/client/themes/rules.css
+++ b/devtools/client/themes/rules.css
@@ -217,18 +217,19 @@
   color: #0000FF;
 }
 
 .ruleview-rule-source:not([unselectable]):hover {
   text-decoration: underline;
 }
 
 .ruleview-header {
-  background-color: var(--rule-header-background-color);
+  background: var(--rule-header-background-color);
   border-bottom: 1px solid var(--theme-splitter-color);
+  color: var(--theme-toolbar-color);
   font-size: 12px;
   padding: 4px;
   width: 100%;
   align-items: center;
   display: flex;
 
   -moz-user-select: none;
 }
--- a/devtools/client/themes/toolbox.css
+++ b/devtools/client/themes/toolbox.css
@@ -135,22 +135,18 @@
   min-width: 24px;
 }
 
 /* Save space on the tab-strip in Firebug theme */
 .theme-firebug .devtools-tab {
   -moz-box-flex: initial;
 }
 
-.theme-dark .devtools-tab {
-  color: var(--theme-body-color-alt);
-}
-
-.theme-light .devtools-tab {
-  color: var(--theme-body-color);
+.devtools-tab {
+  color: var(--theme-toolbar-color);
 }
 
 .theme-dark .devtools-tab:hover {
   color: #ced3d9;
 }
 
 .devtools-tab:hover {
   background-color: var(--theme-toolbar-hover);
--- a/devtools/client/themes/variables.css
+++ b/devtools/client/themes/variables.css
@@ -19,16 +19,17 @@
 :root.theme-light {
   --theme-body-background: white;
   --theme-sidebar-background: white;
   --theme-contrast-background: #e6b064;
 
   /* Toolbar */
   --theme-tab-toolbar-background: var(--grey-10);
   --theme-toolbar-background: var(--grey-10);
+  --theme-toolbar-color: var(--grey-90);
   --theme-toolbar-background-hover: rgba(221, 225, 228, 0.66);
   --theme-toolbar-background-alt: #f5f5f5;
   --theme-toolbar-hover: rgba(170, 170, 170, .2);
   --theme-toolbar-hover-active: rgba(170, 170, 170, .4);
 
   /* Selection */
   --theme-selection-background: var(--blue-55);
   --theme-selection-background-hover: #F0F9FE;
@@ -36,17 +37,17 @@
 
   /* Border color that splits the toolbars/panels/headers.
    * This needs to be sync with commandline.css and commandline-browser.css. */
   --theme-splitter-color: #e0e0e1;
 
   --theme-comment: #696969;
   --theme-comment-alt: #ccd1d5;
 
-  --theme-body-color: #393f4c;
+  --theme-body-color: var(--grey-60);
   --theme-body-color-alt: #585959;
   --theme-body-color-inactive: #999797;
   --theme-content-color1: #292e33;
   --theme-content-color2: #8fa1b2;
   --theme-content-color3: #667380;
 
   --theme-highlight-green: #2cbb0f;
   --theme-highlight-blue: #0088cc;
@@ -94,16 +95,17 @@
 :root.theme-dark {
   --theme-body-background: var(--grey-80);
   --theme-sidebar-background: var(--grey-90);
   --theme-contrast-background: #ffb35b;
 
   /* Toolbar */
   --theme-tab-toolbar-background: var(--grey-90);
   --theme-toolbar-background: var(--grey-90);
+  --theme-toolbar-color: var(--grey-40);
   --theme-toolbar-background-hover: #20232B;
   --theme-toolbar-background-alt: #2F343E;
   --theme-toolbar-hover: rgba(110, 120, 130, 0.1);
   --theme-toolbar-hover-active: rgba(110, 120, 130, 0.2);
 
   /* Selection */
   --theme-selection-background: #204E8A;
   --theme-selection-background-hover: #353B48;
@@ -111,21 +113,21 @@
 
   /* Border color that splits the toolbars/panels/headers.
    * This needs to be sync with commandline.css and commandline-browser.css. */
   --theme-splitter-color: #3c3c3d;
 
   --theme-comment: #757873;
   --theme-comment-alt: #5a6375;
 
-  --theme-body-color: #8fa1b2;
+  --theme-body-color: var(--grey-40);
   --theme-body-color-alt: #b6babf;
-  --theme-body-color-inactive: #8fa1b2;
+  --theme-body-color-inactive: var(--grey-40);
   --theme-content-color1: #a9bacb;
-  --theme-content-color2: #8fa1b2;
+  --theme-content-color2: var(--grey-40);
   --theme-content-color3: #5f7387;
 
   --theme-highlight-green: #00ff7f;
   --theme-highlight-blue: #46afe3;
   --theme-highlight-bluegrey: #5e88b0;
   --theme-highlight-purple: #bcb8db;
   --theme-highlight-lightorange: #d99b28;
   --theme-highlight-orange: #d96629;
--- a/dom/base/nsCopySupport.cpp
+++ b/dom/base/nsCopySupport.cpp
@@ -835,27 +835,30 @@ nsCopySupport::FireClipboardEvent(EventM
     InternalClipboardEvent evt(true, originalEventMessage);
     evt.mClipboardData = clipboardData;
     EventDispatcher::Dispatch(content, presShell->GetPresContext(), &evt,
                               nullptr, &status);
     // If the event was cancelled, don't do the clipboard operation
     doDefault = (status != nsEventStatus_eConsumeNoDefault);
   }
 
+  // When this function exits, the event dispatch is over. We want to disconnect
+  // our DataTransfer, which means setting its mode to `Protected` and clearing
+  // all stored data, before we return.
+  auto clearAfter = MakeScopeExit([&] {
+    if (clipboardData) {
+      clipboardData->SetMode(DataTransfer::Mode::Protected);
+      clipboardData->ClearAll();
+    }
+  });
+
   // No need to do anything special during a paste. Either an event listener
   // took care of it and cancelled the event, or the caller will handle it.
   // Return true to indicate that the event wasn't cancelled.
   if (originalEventMessage == ePaste) {
-    // Clear and mark the clipboardData as readonly. This prevents someone
-    // from reading the clipboard contents after the paste event has fired.
-    if (clipboardData) {
-      clipboardData->ClearAll();
-      clipboardData->SetReadOnly();
-    }
-
     if (aActionTaken) {
       *aActionTaken = true;
     }
     return doDefault;
   }
 
   // Update the presentation in case the event handler modified the selection,
   // see bug 602231.
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -4529,17 +4529,17 @@ void
 nsPIDOMWindowInner::UpdateWebSocketCount(int32_t aDelta)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (aDelta == 0) {
     return;
   }
 
-  if (!IsTopInnerWindow()) {
+  if (mTopInnerWindow && !IsTopInnerWindow()) {
     mTopInnerWindow->UpdateWebSocketCount(aDelta);
   }
 
   MOZ_DIAGNOSTIC_ASSERT(
     aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets));
 
   mNumOfOpenWebSockets += aDelta;
 }
@@ -4557,17 +4557,17 @@ void
 nsPIDOMWindowInner::UpdateUserMediaCount(int32_t aDelta)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (aDelta == 0) {
     return;
   }
 
-  if (!IsTopInnerWindow()) {
+  if (mTopInnerWindow && !IsTopInnerWindow()) {
     mTopInnerWindow->UpdateUserMediaCount(aDelta);
   }
 
   MOZ_DIAGNOSTIC_ASSERT(
     aDelta > 0 || ((aDelta + mNumOfActiveUserMedia) < mNumOfActiveUserMedia));
 
   mNumOfActiveUserMedia += aDelta;
 }
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -16,16 +16,17 @@
 class nsIAtom;
 class nsIURI;
 class nsRuleWalker;
 class nsAttrValue;
 class nsAttrName;
 class nsTextFragment;
 class nsIFrame;
 class nsXBLBinding;
+class nsITextControlElement;
 
 namespace mozilla {
 class EventChainPreVisitor;
 struct URLExtraData;
 namespace dom {
 class ShadowRoot;
 } // namespace dom
 namespace widget {
@@ -975,16 +976,21 @@ public:
   virtual nsresult GetEventTargetParent(
                      mozilla::EventChainPreVisitor& aVisitor) override;
 
   virtual bool IsPurple() = 0;
   virtual void RemovePurple() = 0;
 
   virtual bool OwnedOnlyByTheDOMTree() { return false; }
 
+  virtual already_AddRefed<nsITextControlElement> GetAsTextControlElement()
+  {
+    return nullptr;
+  }
+
 protected:
   /**
    * Hook for implementing GetID.  This is guaranteed to only be
    * called if HasID() is true.
    */
   nsIAtom* DoGetID() const;
 
   // Returns base URI without considering xml:base.
--- a/dom/base/nsRange.h
+++ b/dom/base/nsRange.h
@@ -594,18 +594,24 @@ protected:
     AsRaw() const
     {
       return RangeBoundaryBase<nsINode*, nsIContent*>(*this);
     }
 
     template<typename A, typename B>
     RangeBoundaryBase& operator=(const RangeBoundaryBase<A,B>& aOther)
     {
-      mParent = aOther.mParent;
-      mRef = aOther.mRef;
+      // Since the member variables may be nsCOMPtrs, better to try to avoid
+      // extra Release/AddRef calls.
+      if (mParent != aOther.mParent) {
+        mParent = aOther.mParent;
+      }
+      if (mRef != aOther.mRef) {
+        mRef = aOther.mRef;
+      }
       mOffset = aOther.mOffset;
       return *this;
     }
 
   private:
     ParentType mParent;
     RefType mRef;
 
--- a/dom/cache/TypeUtils.cpp
+++ b/dom/cache/TypeUtils.cpp
@@ -338,17 +338,17 @@ TypeUtils::ToInternalRequest(const Cache
   internalRequest->Headers()->Fill(*internalHeaders, result);
   MOZ_DIAGNOSTIC_ASSERT(!result.Failed());
 
   internalRequest->Headers()->SetGuard(aIn.headersGuard(), result);
   MOZ_DIAGNOSTIC_ASSERT(!result.Failed());
 
   nsCOMPtr<nsIInputStream> stream = ReadStream::Create(aIn.body());
 
-  internalRequest->SetBody(stream);
+  internalRequest->SetBody(stream, -1);
 
   return internalRequest.forget();
 }
 
 already_AddRefed<Request>
 TypeUtils::ToRequest(const CacheRequest& aIn)
 {
   RefPtr<InternalRequest> internalRequest = ToInternalRequest(aIn);
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -76,40 +76,56 @@ const char DataTransfer::sEffects[8][9] 
 };
 
 // Used for custom clipboard types.
 enum CustomClipboardTypeId {
   eCustomClipboardTypeId_None,
   eCustomClipboardTypeId_String
 };
 
+static DataTransfer::Mode
+ModeForEvent(EventMessage aEventMessage)
+{
+  switch (aEventMessage) {
+  case eCut:
+  case eCopy:
+  case eDragStart:
+    // For these events, we want to be able to add data to the data transfer,
+    // Otherwise, the data is already present.
+    return DataTransfer::Mode::ReadWrite;
+  case eDrop:
+  case ePaste:
+  case ePasteNoFormatting:
+    // For these events we want to be able to read the data which is stored in
+    // the DataTransfer, rather than just the type information.
+    return DataTransfer::Mode::ReadOnly;
+  default:
+    return DataTransfer::Mode::Protected;
+  }
+}
+
 DataTransfer::DataTransfer(nsISupports* aParent, EventMessage aEventMessage,
                            bool aIsExternal, int32_t aClipboardType)
   : mParent(aParent)
   , mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE)
   , mEffectAllowed(nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
   , mEventMessage(aEventMessage)
   , mCursorState(false)
-  , mReadOnly(true)
+  , mMode(ModeForEvent(aEventMessage))
   , mIsExternal(aIsExternal)
   , mUserCancelled(false)
   , mIsCrossDomainSubFrameDrop(false)
   , mClipboardType(aClipboardType)
   , mDragImageX(0)
   , mDragImageY(0)
 {
   mItems = new DataTransferItemList(this, aIsExternal);
-  // For these events, we want to be able to add data to the data transfer, so
-  // clear the readonly state. Otherwise, the data is already present. For
-  // external usage, cache the data from the native clipboard or drag.
-  if (aEventMessage == eCut ||
-      aEventMessage == eCopy ||
-      aEventMessage == eDragStart) {
-    mReadOnly = false;
-  } else if (mIsExternal) {
+
+  // For external usage, cache the data from the native clipboard or drag.
+  if (mIsExternal && mMode != Mode::ReadWrite) {
     if (aEventMessage == ePasteNoFormatting) {
       mEventMessage = ePaste;
       CacheExternalClipboardFormats(true);
     } else if (aEventMessage == ePaste) {
       CacheExternalClipboardFormats(false);
     } else if (aEventMessage >= eDragDropEventFirst &&
                aEventMessage <= eDragDropEventLast) {
       CacheExternalDragFormats();
@@ -129,17 +145,17 @@ DataTransfer::DataTransfer(nsISupports* 
                            Element* aDragImage,
                            uint32_t aDragImageX,
                            uint32_t aDragImageY)
   : mParent(aParent)
   , mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE)
   , mEffectAllowed(aEffectAllowed)
   , mEventMessage(aEventMessage)
   , mCursorState(aCursorState)
-  , mReadOnly(true)
+  , mMode(ModeForEvent(aEventMessage))
   , mIsExternal(aIsExternal)
   , mUserCancelled(aUserCancelled)
   , mIsCrossDomainSubFrameDrop(aIsCrossDomainSubFrameDrop)
   , mClipboardType(aClipboardType)
   , mDragImage(aDragImage)
   , mDragImageX(aDragImageX)
   , mDragImageY(aDragImageY)
 {
@@ -424,17 +440,17 @@ DataTransfer::SetData(const nsAString& a
   aRv = SetDataAtInternal(aFormat, variant, 0, &aSubjectPrincipal);
 }
 
 void
 DataTransfer::ClearData(const Optional<nsAString>& aFormat,
                         nsIPrincipal& aSubjectPrincipal,
                         ErrorResult& aRv)
 {
-  if (mReadOnly) {
+  if (IsReadOnly()) {
     aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     return;
   }
 
   if (MozItemCount() == 0) {
     return;
   }
 
@@ -654,26 +670,45 @@ DataTransfer::PrincipalMaySetData(const 
 }
 
 void
 DataTransfer::TypesListMayHaveChanged()
 {
   DataTransferBinding::ClearCachedTypesValue(this);
 }
 
+already_AddRefed<DataTransfer>
+DataTransfer::MozCloneForEvent(const nsAString& aEvent, ErrorResult& aRv)
+{
+  nsCOMPtr<nsIAtom> atomEvt = NS_Atomize(aEvent);
+  if (!atomEvt) {
+    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+    return nullptr;
+  }
+  EventMessage eventMessage = nsContentUtils::GetEventMessage(atomEvt);
+
+  RefPtr<DataTransfer> dt;
+  nsresult rv = Clone(mParent, eventMessage, false, false, getter_AddRefs(dt));
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return nullptr;
+  }
+  return dt.forget();
+}
+
 nsresult
 DataTransfer::SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData,
                                 uint32_t aIndex,
                                 nsIPrincipal* aSubjectPrincipal)
 {
   if (aFormat.IsEmpty()) {
     return NS_OK;
   }
 
-  if (mReadOnly) {
+  if (IsReadOnly()) {
     return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
   }
 
   // Specifying an index less than the current length will replace an existing
   // item. Specifying an index equal to the current length will add a new item.
   if (aIndex > MozItemCount()) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
@@ -711,17 +746,17 @@ DataTransfer::MozSetDataAt(JSContext* aC
   }
 }
 
 void
 DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
                              nsIPrincipal& aSubjectPrincipal,
                              ErrorResult& aRv)
 {
-  if (mReadOnly) {
+  if (IsReadOnly()) {
     aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     return;
   }
 
   if (aIndex >= MozItemCount()) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
@@ -748,32 +783,32 @@ DataTransfer::MozClearDataAt(const nsASt
   }
 }
 
 void
 DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
                                    nsIPrincipal& aSubjectPrincipal,
                                    ErrorResult& aRv)
 {
-  MOZ_ASSERT(!mReadOnly);
+  MOZ_ASSERT(!IsReadOnly());
   MOZ_ASSERT(aIndex < MozItemCount());
   MOZ_ASSERT(aIndex == 0 ||
              (mEventMessage != eCut && mEventMessage != eCopy &&
               mEventMessage != ePaste));
 
   nsAutoString format;
   GetRealFormat(aFormat, format);
 
   mItems->MozRemoveByTypeAt(format, aIndex, aSubjectPrincipal, aRv);
 }
 
 void
 DataTransfer::SetDragImage(Element& aImage, int32_t aX, int32_t aY)
 {
-  if (!mReadOnly) {
+  if (!IsReadOnly()) {
     mDragImage = &aImage;
     mDragImageX = aX;
     mDragImageY = aY;
   }
 }
 
 NS_IMETHODIMP
 DataTransfer::SetDragImage(nsIDOMElement* aImage, int32_t aX, int32_t aY)
@@ -843,17 +878,17 @@ DataTransfer::GetFiles(bool aRecursiveFl
 {
   // Currently we don't support directories.
   return GetFilesAndDirectories(aSubjectPrincipal, aRv);
 }
 
 void
 DataTransfer::AddElement(Element& aElement, ErrorResult& aRv)
 {
-  if (mReadOnly) {
+  if (IsReadOnly()) {
     aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     return;
   }
 
   mDragTarget = &aElement;
 }
 
 NS_IMETHODIMP
--- a/dom/events/DataTransfer.h
+++ b/dom/events/DataTransfer.h
@@ -56,23 +56,32 @@ public:
 
   friend class mozilla::EventStateManager;
 
   static DataTransfer* Cast(nsIDOMDataTransfer* aArg)
   {
     return static_cast<DataTransfer*>(aArg);
   }
 
+  /// An enum which represents which "Drag Data Store Mode" the DataTransfer is
+  /// in according to the spec.
+  enum class Mode : uint8_t {
+    ReadWrite,
+    ReadOnly,
+    Protected,
+  };
+
 protected:
 
   // hide the default constructor
   DataTransfer();
 
   // this constructor is used only by the Clone method to copy the fields as
   // needed to a new data transfer.
+  // NOTE: Do not call this method directly.
   DataTransfer(nsISupports* aParent,
                EventMessage aEventMessage,
                const uint32_t aEffectAllowed,
                bool aCursorState,
                bool aIsExternal,
                bool aUserCancelled,
                bool aIsCrossDomainSubFrameDrop,
                int32_t aClipboardType,
@@ -209,23 +218,35 @@ public:
 
   nsresult GetDataAtNoSecurityCheck(const nsAString& aFormat, uint32_t aIndex,
                                     nsIVariant** aData);
 
   DataTransferItemList* Items() const {
     return mItems;
   }
 
-  // a readonly dataTransfer cannot have new data added or existing data
-  // removed. Only the dropEffect and effectAllowed may be modified.
+  // Returns the current "Drag Data Store Mode" of the DataTransfer. This
+  // determines what modifications may be performed on the DataTransfer, and
+  // what data may be read from it.
+  Mode GetMode() const {
+    return mMode;
+  }
+  void SetMode(Mode aMode) {
+    mMode = aMode;
+  }
+
+  // Helper method. Is true if the DataTransfer's mode is ReadOnly or Protected,
+  // which means that the DataTransfer cannot be modified.
   bool IsReadOnly() const {
-    return mReadOnly;
+    return mMode != Mode::ReadWrite;
   }
-  void SetReadOnly() {
-    mReadOnly = true;
+  // Helper method. Is true if the DataTransfer's mode is Protected, which means
+  // that DataTransfer type information may be read, but data may not be.
+  bool IsProtected() const {
+    return mMode == Mode::Protected;
   }
 
   int32_t ClipboardType() const {
     return mClipboardType;
   }
   EventMessage GetEventMessage() const {
     return mEventMessage;
   }
@@ -273,16 +294,22 @@ public:
   // returns a weak reference to the drag image
   Element* GetDragImage(int32_t* aX, int32_t* aY) const
   {
     *aX = mDragImageX;
     *aY = mDragImageY;
     return mDragImage;
   }
 
+  // This method makes a copy of the DataTransfer object, with a few properties
+  // changed, and the mode updated to reflect the correct mode for the given
+  // event. This method is used during the drag operation to generate the
+  // DataTransfer objects for each event after `dragstart`. Event objects will
+  // lazily clone the DataTransfer stored in the DragSession (which is a clone
+  // of the DataTransfer used in the `dragstart` event) when requested.
   nsresult Clone(nsISupports* aParent, EventMessage aEventMessage,
                  bool aUserCancelled, bool aIsCrossDomainSubFrameDrop,
                  DataTransfer** aResult);
 
   // converts some formats used for compatibility in aInFormat into aOutFormat.
   // Text and text/unicode become text/plain, and URL becomes text/uri-list
   void GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat) const;
 
@@ -290,16 +317,21 @@ public:
                                   nsIVariant* aData,
                                   nsIPrincipal* aPrincipal);
 
   // Notify the DataTransfer that the list returned from GetTypes may have
   // changed.  This can happen due to items we care about for purposes of
   // GetTypes being added or removed or changing item kinds.
   void TypesListMayHaveChanged();
 
+  // Testing method used to emulate internal DataTransfer management.
+  // NOTE: Please don't use this. See the comments in the webidl for more.
+  already_AddRefed<DataTransfer> MozCloneForEvent(const nsAString& aEvent,
+                                                  ErrorResult& aRv);
+
 protected:
 
   // caches text and uri-list data formats that exist in the drag service or
   // clipboard for retrieval later.
   nsresult CacheExternalData(const char* aFormat, uint32_t aIndex,
                              nsIPrincipal* aPrincipal, bool aHidden);
 
   // caches the formats that exist in the drag service that were added by an
@@ -338,19 +370,18 @@ protected:
 
   // the event message this data transfer is for. This will correspond to an
   // event->mMessage value.
   EventMessage mEventMessage;
 
   // Indicates the behavior of the cursor during drag operations
   bool mCursorState;
 
-  // readonly data transfers may not be modified except the drop effect and
-  // effect allowed.
-  bool mReadOnly;
+  // The current "Drag Data Store Mode" which the DataTransfer is in.
+  Mode mMode;
 
   // true for drags started without a data transfer, for example, those from
   // another application.
   bool mIsExternal;
 
   // true if the user cancelled the drag. Used only for the dragend event.
   bool mUserCancelled;
 
--- a/dom/events/DataTransferItem.cpp
+++ b/dom/events/DataTransferItem.cpp
@@ -498,24 +498,30 @@ DataTransferItem::DataNoSecurityCheck()
   return data.forget();
 }
 
 already_AddRefed<nsIVariant>
 DataTransferItem::Data(nsIPrincipal* aPrincipal, ErrorResult& aRv)
 {
   MOZ_ASSERT(aPrincipal);
 
-  nsCOMPtr<nsIVariant> variant = DataNoSecurityCheck();
-
   // If the inbound principal is system, we can skip the below checks, as
   // they will trivially succeed.
   if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
-    return variant.forget();
+    return DataNoSecurityCheck();
   }
 
+  // We should not allow raw data to be accessed from a Protected DataTransfer.
+  // We don't prevent this access if the accessing document is Chrome.
+  if (mDataTransfer->IsProtected()) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIVariant> variant = DataNoSecurityCheck();
+
   MOZ_ASSERT(!ChromeOnly(), "Non-chrome code shouldn't see a ChromeOnly DataTransferItem");
   if (ChromeOnly()) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return nullptr;
   }
 
   bool checkItemPrincipal = mDataTransfer->IsCrossDomainSubFrameDrop() ||
     (mDataTransfer->GetEventMessage() != eDrop &&
--- a/dom/events/DataTransferItemList.cpp
+++ b/dom/events/DataTransferItemList.cpp
@@ -557,16 +557,24 @@ DataTransferItemList::RegenerateFiles()
 }
 
 void
 DataTransferItemList::GenerateFiles(FileList* aFiles,
                                     nsIPrincipal* aFilesPrincipal)
 {
   MOZ_ASSERT(aFiles);
   MOZ_ASSERT(aFilesPrincipal);
+
+  // For non-system principals, the Files list should be empty if the
+  // DataTransfer is protected.
+  if (!nsContentUtils::IsSystemPrincipal(aFilesPrincipal) &&
+      mDataTransfer->IsProtected()) {
+    return;
+  }
+
   uint32_t count = Length();
   for (uint32_t i = 0; i < count; i++) {
     bool found;
     RefPtr<DataTransferItem> item = IndexedGetter(i, found);
     MOZ_ASSERT(found);
 
     if (item->Kind() == DataTransferItem::KIND_FILE) {
       IgnoredErrorResult rv;
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -1767,16 +1767,22 @@ EventStateManager::GenerateDragGesture(n
       }
 
       nsCOMPtr<nsPIDOMWindowOuter> window = docshell->GetWindow();
       if (!window)
         return;
 
       RefPtr<DataTransfer> dataTransfer =
         new DataTransfer(window, eDragStart, false, -1);
+      auto protectDataTransfer = MakeScopeExit([&] {
+        if (dataTransfer) {
+          dataTransfer->SetMode(DataTransfer::Mode::Protected);
+          dataTransfer->ClearAll();
+        }
+      });
 
       nsCOMPtr<nsISelection> selection;
       nsCOMPtr<nsIContent> eventContent, targetContent;
       mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(eventContent));
       if (eventContent)
         DetermineDragTargetAndDefaultData(window, eventContent, dataTransfer,
                                           getter_AddRefs(selection),
                                           getter_AddRefs(targetContent));
@@ -1834,21 +1840,16 @@ EventStateManager::GenerateDragGesture(n
         mozilla::services::GetObserverService();
       // Emit observer event to allow addons to modify the DataTransfer object.
       if (observerService) {
         observerService->NotifyObservers(dataTransfer,
                                          "on-datatransfer-available",
                                          nullptr);
       }
 
-      // now that the dataTransfer has been updated in the dragstart and
-      // draggesture events, make it read only so that the data doesn't
-      // change during the drag.
-      dataTransfer->SetReadOnly();
-
       if (status != nsEventStatus_eConsumeNoDefault) {
         bool dragStarted = DoDefaultDragStart(aPresContext, event, dataTransfer,
                                               targetContent, selection);
         if (dragStarted) {
           sActiveESM = nullptr;
           aEvent->StopPropagation();
         }
       }
@@ -2001,29 +2002,41 @@ EventStateManager::DoDefaultDragStart(ns
   int32_t imageX, imageY;
   Element* dragImage = aDataTransfer->GetDragImage(&imageX, &imageY);
 
   nsCOMPtr<nsIArray> transArray =
     aDataTransfer->GetTransferables(dragTarget->AsDOMNode());
   if (!transArray)
     return false;
 
+  // After this function returns, the DataTransfer will be cleared so it appears
+  // empty to content. We need to pass a DataTransfer into the Drag Session, so
+  // we need to make a copy.
+  RefPtr<DataTransfer> dataTransfer;
+  aDataTransfer->Clone(aDragTarget, eDrop, aDataTransfer->MozUserCancelled(),
+                       false, getter_AddRefs(dataTransfer));
+
+  // Copy over the drop effect, as Clone doesn't copy it for us.
+  uint32_t dropEffect;
+  aDataTransfer->GetDropEffectInt(&dropEffect);
+  dataTransfer->SetDropEffectInt(dropEffect);
+
   // XXXndeakin don't really want to create a new drag DOM event
   // here, but we need something to pass to the InvokeDragSession
   // methods.
   RefPtr<DragEvent> event =
     NS_NewDOMDragEvent(dragTarget, aPresContext, aDragEvent);
 
   // Use InvokeDragSessionWithSelection if a selection is being dragged,
   // such that the image can be generated from the selected text. However,
   // use InvokeDragSessionWithImage if a custom image was set or something
   // other than a selection is being dragged.
   if (!dragImage && aSelection) {
     dragService->InvokeDragSessionWithSelection(aSelection, transArray,
-                                                action, event, aDataTransfer);
+                                                action, event, dataTransfer);
   }
   else {
     // if dragging within a XUL tree and no custom drag image was
     // set, the region argument to InvokeDragSessionWithImage needs
     // to be set to the area encompassing the selected rows of the
     // tree to ensure that the drag feedback gets clipped to those
     // rows. For other content, region should be null.
     nsCOMPtr<nsIScriptableRegion> region;
@@ -2040,17 +2053,17 @@ EventStateManager::DoDefaultDragStart(ns
     }
 #endif
 
     dragService->InvokeDragSessionWithImage(dragTarget->AsDOMNode(), transArray,
                                             region, action,
                                             dragImage ? dragImage->AsDOMNode() :
                                                         nullptr,
                                             imageX, imageY, event,
-                                            aDataTransfer);
+                                            dataTransfer);
   }
 
   return true;
 }
 
 nsresult
 EventStateManager::GetContentViewer(nsIContentViewer** aCv)
 {
--- a/dom/events/test/test_DataTransferItemList.html
+++ b/dom/events/test/test_DataTransferItemList.html
@@ -125,16 +125,19 @@
     var dragenterFired = 0;
     over.addEventListener('dragenter', onDragEnter);
     function onDragEnter(e) {
       over.removeEventListener('dragenter', onDragEnter);
 
       var dt = e.dataTransfer;
       dragenterFired++;
 
+      // NOTE: This test is run with chrome privileges.
+      // For back-compat reasons, protected mode acts like readonly mode for
+      // chrome documents.
       readOnly(e);
     }
 
     var dropFired = 0;
     over.addEventListener('drop', onDrop);
     function onDrop(e) {
       over.removeEventListener('drop', onDrop);
 
--- a/dom/events/test/test_bug1327798.html
+++ b/dom/events/test/test_bug1327798.html
@@ -29,18 +29,18 @@ SimpleTest.waitForFocus(() => {
   // does the clipboard contain text/unicode data ?
   ok(clipboard.hasDataMatchingFlavors(["text/unicode"], 1, clipboard.kGlobalClipboard),
      "clipboard contains unicode text");
   // does the clipboard contain text/html data ?
   ok(clipboard.hasDataMatchingFlavors(["text/html"], 1, clipboard.kGlobalClipboard),
      "clipboard contains html text");
 
   window.addEventListener("paste", (e) => {
-    ok(e.clipboardData.types.indexOf('text/html'), -1, "clipboardData shouldn't have text/html");
-    ok(e.clipboardData.getData('text/plain'), "Formatted Text",  "getData(text/plain) should return plain text");
+    is(e.clipboardData.types.indexOf('text/html'), -1, "clipboardData shouldn't have text/html");
+    is(e.clipboardData.getData('text/plain'), "Formatted Text",  "getData(text/plain) should return plain text");
     SimpleTest.finish();
   });
 
   SpecialPowers.doCommand(window, "cmd_pasteNoFormatting");
 });
 </script>
 </pre>
 </body>
--- a/dom/events/test/test_bug508479.html
+++ b/dom/events/test/test_bug508479.html
@@ -69,17 +69,17 @@ function runTests()
   is(gGotNotHandlingDrop, false, "Didn't get drop on unaccepting element (1)");
 
   // reset
   gGotHandlingDrop = false;
   gGotNotHandlingDrop = false;
 
   SpecialPowers.addChromeEventListener("drop", chromeListener, true, false);
   var targetNotHandling = document.getElementById("nothandling_target");
-  fireDrop(targetNotHandling, true, true);
+  fireDrop(targetNotHandling, false, true);
   SpecialPowers.removeChromeEventListener("drop", chromeListener, true);
   ok(chromeGotEvent, "Chrome should have got drop event!");
   is(gGotHandlingDrop, false, "Didn't get drop on accepting element (2)");
   is(gGotNotHandlingDrop, false, "Didn't get drop on unaccepting element (2)");
 
   SimpleTest.finish();
 }
 
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -364,22 +364,25 @@ FetchDriver::HttpFetch()
     // void string if no header was set.
 #ifdef DEBUG
     bool hasContentTypeHeader =
       mRequest->Headers()->Has(NS_LITERAL_CSTRING("content-type"), result);
     MOZ_ASSERT(!result.Failed());
     MOZ_ASSERT_IF(!hasContentTypeHeader, contentType.IsVoid());
 #endif // DEBUG
 
+    int64_t bodyLength;
     nsCOMPtr<nsIInputStream> bodyStream;
-    mRequest->GetBody(getter_AddRefs(bodyStream));
+    mRequest->GetBody(getter_AddRefs(bodyStream), &bodyLength);
     if (bodyStream) {
       nsAutoCString method;
       mRequest->GetMethod(method);
-      rv = uploadChan->ExplicitSetUploadStream(bodyStream, contentType, -1, method, false /* aStreamHasHeaders */);
+      rv = uploadChan->ExplicitSetUploadStream(bodyStream, contentType,
+                                               bodyLength, method,
+                                               false /* aStreamHasHeaders */);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   // If preflight is required, start a "CORS preflight fetch"
   // https://fetch.spec.whatwg.org/#cors-preflight-fetch-0. All the
   // implementation is handled by the http channel calling into
   // nsCORSListenerProxy. We just inform it which unsafe headers are included
--- a/dom/fetch/InternalRequest.cpp
+++ b/dom/fetch/InternalRequest.cpp
@@ -25,16 +25,17 @@ InternalRequest::GetRequestConstructorCo
 {
   MOZ_RELEASE_ASSERT(!mURLList.IsEmpty(), "Internal Request's urlList should not be empty when copied from constructor.");
   RefPtr<InternalRequest> copy = new InternalRequest(mURLList.LastElement(),
                                                      mFragment);
   copy->SetMethod(mMethod);
   copy->mHeaders = new InternalHeaders(*mHeaders);
   copy->SetUnsafeRequest();
   copy->mBodyStream = mBodyStream;
+  copy->mBodyLength = mBodyLength;
   copy->mForceOriginHeader = true;
   // The "client" is not stored in our implementation. Fetch API users should
   // use the appropriate window/document/principal and other Gecko security
   // mechanisms as appropriate.
   copy->mSameOriginDataURL = true;
   copy->mPreserveContentCodings = true;
   copy->mReferrer = mReferrer;
   copy->mReferrerPolicy = mReferrerPolicy;
@@ -74,16 +75,17 @@ InternalRequest::Clone()
     mBodyStream.swap(replacementBody);
   }
   return clone.forget();
 }
 InternalRequest::InternalRequest(const nsACString& aURL,
                                  const nsACString& aFragment)
   : mMethod("GET")
   , mHeaders(new InternalHeaders(HeadersGuardEnum::None))
+  , mBodyLength(InternalResponse::UNKNOWN_BODY_SIZE)
   , mContentPolicyType(nsIContentPolicy::TYPE_FETCH)
   , mReferrer(NS_LITERAL_STRING(kFETCH_CLIENT_REFERRER_STR))
   , mReferrerPolicy(ReferrerPolicy::_empty)
   , mEnvironmentReferrerPolicy(net::RP_Unset)
   , mMode(RequestMode::No_cors)
   , mCredentialsMode(RequestCredentials::Omit)
   , mResponseTainting(LoadTainting::Basic)
   , mCacheMode(RequestCache::Default)
--- a/dom/fetch/InternalRequest.h
+++ b/dom/fetch/InternalRequest.h
@@ -457,30 +457,35 @@ public:
 
   void
   UnsetSameOriginDataURL()
   {
     mSameOriginDataURL = false;
   }
 
   void
-  SetBody(nsIInputStream* aStream)
+  SetBody(nsIInputStream* aStream, int64_t aBodyLength)
   {
     // A request's body may not be reset once set.
     MOZ_ASSERT_IF(aStream, !mBodyStream);
     mBodyStream = aStream;
+    mBodyLength = aBodyLength;
   }
 
   // Will return the original stream!
   // Use a tee or copy if you don't want to erase the original.
   void
-  GetBody(nsIInputStream** aStream)
+  GetBody(nsIInputStream** aStream, int64_t* aBodyLength = nullptr)
   {
     nsCOMPtr<nsIInputStream> s = mBodyStream;
     s.forget(aStream);
+
+    if (aBodyLength) {
+      *aBodyLength = mBodyLength;
+    }
   }
 
   // The global is used as the client for the new object.
   already_AddRefed<InternalRequest>
   GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult& aRv) const;
 
   bool
   WasCreatedByFetchEvent() const
@@ -549,16 +554,17 @@ private:
   static bool
   IsWorkerContentPolicy(nsContentPolicyType aContentPolicyType);
 
   nsCString mMethod;
   // mURLList: a list of one or more fetch URLs
   nsTArray<nsCString> mURLList;
   RefPtr<InternalHeaders> mHeaders;
   nsCOMPtr<nsIInputStream> mBodyStream;
+  int64_t mBodyLength;
 
   nsContentPolicyType mContentPolicyType;
 
   // Empty string: no-referrer
   // "about:client": client (default)
   // URL: an URL
   nsString mReferrer;
   ReferrerPolicy mReferrerPolicy;
--- a/dom/fetch/InternalResponse.h
+++ b/dom/fetch/InternalResponse.h
@@ -207,17 +207,17 @@ public:
         Type() == ResponseType::Opaqueredirect) {
       *aStream = nullptr;
       if (aBodySize) {
         *aBodySize = UNKNOWN_BODY_SIZE;
       }
       return;
     }
 
-    return GetUnfilteredBody(aStream, aBodySize);
+    GetUnfilteredBody(aStream, aBodySize);
   }
 
   void
   SetBody(nsIInputStream* aBody, int64_t aBodySize)
   {
     if (mWrappedResponse) {
       return mWrappedResponse->SetBody(aBody, aBodySize);
     }
--- a/dom/fetch/Request.cpp
+++ b/dom/fetch/Request.cpp
@@ -575,21 +575,21 @@ Request::Constructor(const GlobalObject&
   }
 
   if (aInit.mBody.WasPassed()) {
     const Nullable<fetch::OwningBodyInit>& bodyInitNullable = aInit.mBody.Value();
     if (!bodyInitNullable.IsNull()) {
       const fetch::OwningBodyInit& bodyInit = bodyInitNullable.Value();
       nsCOMPtr<nsIInputStream> stream;
       nsAutoCString contentTypeWithCharset;
-      uint64_t contentLengthUnused;
+      uint64_t contentLength = 0;
       aRv = ExtractByteStreamFromBody(bodyInit,
                                       getter_AddRefs(stream),
                                       contentTypeWithCharset,
-                                      contentLengthUnused);
+                                      contentLength);
       if (NS_WARN_IF(aRv.Failed())) {
         return nullptr;
       }
 
       nsCOMPtr<nsIInputStream> temporaryBody = stream;
 
       if (!contentTypeWithCharset.IsVoid() &&
           !requestHeaders->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) {
@@ -599,32 +599,32 @@ Request::Constructor(const GlobalObject&
 
       if (NS_WARN_IF(aRv.Failed())) {
         return nullptr;
       }
 
       request->ClearCreatedByFetchEvent();
 
       if (hasCopiedBody) {
-        request->SetBody(nullptr);
+        request->SetBody(nullptr, 0);
       }
 
-      request->SetBody(temporaryBody);
+      request->SetBody(temporaryBody, contentLength);
     }
   }
 
   RefPtr<Request> domRequest = new Request(global, request, signal);
   domRequest->SetMimeType();
 
   if (aInput.IsRequest()) {
     RefPtr<Request> inputReq = &aInput.GetAsRequest();
     nsCOMPtr<nsIInputStream> body;
     inputReq->GetBody(getter_AddRefs(body));
     if (body) {
-      inputReq->SetBody(nullptr);
+      inputReq->SetBody(nullptr, 0);
       inputReq->SetBodyUsed(aGlobal.Context(), aRv);
       if (NS_WARN_IF(aRv.Failed())) {
         return nullptr;
       }
     }
   }
   return domRequest.forget();
 }
--- a/dom/fetch/Request.h
+++ b/dom/fetch/Request.h
@@ -121,23 +121,29 @@ public:
   InternalHeaders*
   GetInternalHeaders() const
   {
     return mRequest->Headers();
   }
 
   Headers* Headers_();
 
-  void
-  GetBody(nsIInputStream** aStream) { return mRequest->GetBody(aStream); }
-
   using FetchBody::GetBody;
 
   void
-  SetBody(nsIInputStream* aStream) { return mRequest->SetBody(aStream); }
+  GetBody(nsIInputStream** aStream, int64_t* aBodyLength = nullptr)
+  {
+    mRequest->GetBody(aStream, aBodyLength);
+  }
+
+  void
+  SetBody(nsIInputStream* aStream, int64_t aBodyLength)
+  {
+    mRequest->SetBody(aStream, aBodyLength);
+  }
 
   static already_AddRefed<Request>
   Constructor(const GlobalObject& aGlobal, const RequestOrUSVString& aInput,
               const RequestInit& aInit, ErrorResult& rv);
 
   nsIGlobalObject* GetParentObject() const
   {
     return mOwner;
--- a/dom/fetch/Response.h
+++ b/dom/fetch/Response.h
@@ -100,17 +100,20 @@ public:
   GetPrincipalInfo() const
   {
     return mInternalResponse->GetPrincipalInfo();
   }
 
   Headers* Headers_();
 
   void
-  GetBody(nsIInputStream** aStream) { return mInternalResponse->GetBody(aStream); }
+  GetBody(nsIInputStream** aStream, int64_t* aBodyLength = nullptr)
+  {
+    mInternalResponse->GetBody(aStream, aBodyLength);
+  }
 
   using FetchBody::GetBody;
 
   static already_AddRefed<Response>
   Error(const GlobalObject& aGlobal);
 
   static already_AddRefed<Response>
   Redirect(const GlobalObject& aGlobal, const nsAString& aUrl, uint16_t aStatus, ErrorResult& aRv);
--- a/dom/file/ipc/IPCBlobInputStream.cpp
+++ b/dom/file/ipc/IPCBlobInputStream.cpp
@@ -4,32 +4,37 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "IPCBlobInputStream.h"
 #include "IPCBlobInputStreamChild.h"
 #include "IPCBlobInputStreamStorage.h"
 #include "mozilla/ipc/InputStreamParams.h"
 #include "nsIAsyncInputStream.h"
+#include "nsIStreamTransportService.h"
+#include "nsITransport.h"
+#include "nsNetCID.h"
 
 namespace mozilla {
 namespace dom {
 
 namespace {
 
-class CallbackRunnable final : public CancelableRunnable
+static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
+
+class InputStreamCallbackRunnable final : public CancelableRunnable
 {
 public:
   static void
   Execute(nsIInputStreamCallback* aCallback,
           nsIEventTarget* aEventTarget,
           IPCBlobInputStream* aStream)
   {
-    RefPtr<CallbackRunnable> runnable =
-      new CallbackRunnable(aCallback, aStream);
+    RefPtr<InputStreamCallbackRunnable> runnable =
+      new InputStreamCallbackRunnable(aCallback, aStream);
 
     nsCOMPtr<nsIEventTarget> target = aEventTarget;
     if (!target) {
       target = NS_GetCurrentThread();
     }
 
     target->Dispatch(runnable, NS_DISPATCH_NORMAL);
   }
@@ -39,43 +44,86 @@ public:
   {
     mCallback->OnInputStreamReady(mStream);
     mCallback = nullptr;
     mStream = nullptr;
     return NS_OK;
   }
 
 private:
-  CallbackRunnable(nsIInputStreamCallback* aCallback,
-                   IPCBlobInputStream* aStream)
-    : CancelableRunnable("dom::CallbackRunnable")
+  InputStreamCallbackRunnable(nsIInputStreamCallback* aCallback,
+                              IPCBlobInputStream* aStream)
+    : CancelableRunnable("dom::InputStreamCallbackRunnable")
     , mCallback(aCallback)
     , mStream(aStream)
   {
     MOZ_ASSERT(mCallback);
     MOZ_ASSERT(mStream);
   }
 
   nsCOMPtr<nsIInputStreamCallback> mCallback;
   RefPtr<IPCBlobInputStream> mStream;
 };
 
+class FileMetadataCallbackRunnable final : public CancelableRunnable
+{
+public:
+  static void
+  Execute(nsIFileMetadataCallback* aCallback,
+          nsIEventTarget* aEventTarget,
+          IPCBlobInputStream* aStream)
+  {
+    RefPtr<FileMetadataCallbackRunnable> runnable =
+      new FileMetadataCallbackRunnable(aCallback, aStream);
+
+    nsCOMPtr<nsIEventTarget> target = aEventTarget;
+    if (!target) {
+      target = NS_GetCurrentThread();
+    }
+
+    target->Dispatch(runnable, NS_DISPATCH_NORMAL);
+  }
+
+  NS_IMETHOD
+  Run() override
+  {
+    mCallback->OnFileMetadataReady(mStream);
+    mCallback = nullptr;
+    mStream = nullptr;
+    return NS_OK;
+  }
+
+private:
+  FileMetadataCallbackRunnable(nsIFileMetadataCallback* aCallback,
+                               IPCBlobInputStream* aStream)
+    : CancelableRunnable("dom::FileMetadataCallbackRunnable")
+    , mCallback(aCallback)
+    , mStream(aStream)
+  {
+    MOZ_ASSERT(mCallback);
+    MOZ_ASSERT(mStream);
+  }
+
+  nsCOMPtr<nsIFileMetadataCallback> mCallback;
+  RefPtr<IPCBlobInputStream> mStream;
+};
+
 } // anonymous
 
 NS_IMPL_ADDREF(IPCBlobInputStream);
 NS_IMPL_RELEASE(IPCBlobInputStream);
 
 NS_INTERFACE_MAP_BEGIN(IPCBlobInputStream)
   NS_INTERFACE_MAP_ENTRY(nsIInputStream)
   NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStream)
   NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
   NS_INTERFACE_MAP_ENTRY(nsICloneableInputStream)
   NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableInputStream)
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekableStream())
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIFileMetadata, IsFileMetadata())
+  NS_INTERFACE_MAP_ENTRY(nsIFileMetadata)
+  NS_INTERFACE_MAP_ENTRY(nsIAsyncFileMetadata)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
 NS_INTERFACE_MAP_END
 
 IPCBlobInputStream::IPCBlobInputStream(IPCBlobInputStreamChild* aActor)
   : mActor(aActor)
   , mState(eInit)
 {
   MOZ_ASSERT(aActor);
@@ -104,50 +152,81 @@ IPCBlobInputStream::Available(uint64_t* 
   // We don't have a remoteStream yet. Let's return the full known size.
   if (mState == eInit || mState == ePending) {
     *aLength = mActor->Size();
     return NS_OK;
   }
 
   if (mState == eRunning) {
     MOZ_ASSERT(mRemoteStream);
-    return mRemoteStream->Available(aLength);
+
+    // This will go away eventually: an async input stream can return 0 in
+    // Available(), but this is not currently fully supported in the rest of
+    // gecko.
+    if (!mAsyncRemoteStream) {
+      *aLength = mActor->Size();
+      return NS_OK;
+    }
+
+    nsresult rv = EnsureAsyncRemoteStream();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    MOZ_ASSERT(mAsyncRemoteStream);
+    return mAsyncRemoteStream->Available(aLength);
   }
 
   MOZ_ASSERT(mState == eClosed);
   return NS_BASE_STREAM_CLOSED;
 }
 
 NS_IMETHODIMP
 IPCBlobInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount)
 {
   // Read is not available is we don't have a remoteStream.
   if (mState == eInit || mState == ePending) {
     return NS_BASE_STREAM_WOULD_BLOCK;
   }
 
   if (mState == eRunning) {
-    return mRemoteStream->Read(aBuffer, aCount, aReadCount);
+    MOZ_ASSERT(mRemoteStream);
+
+    nsresult rv = EnsureAsyncRemoteStream();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    MOZ_ASSERT(mAsyncRemoteStream);
+    return mAsyncRemoteStream->Read(aBuffer, aCount, aReadCount);
   }
 
   MOZ_ASSERT(mState == eClosed);
   return NS_BASE_STREAM_CLOSED;
 }
 
 NS_IMETHODIMP
 IPCBlobInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
                                  uint32_t aCount, uint32_t *aResult)
 {
   // ReadSegments is not available is we don't have a remoteStream.
   if (mState == eInit || mState == ePending) {
     return NS_BASE_STREAM_WOULD_BLOCK;
   }
 
   if (mState == eRunning) {
-    return mRemoteStream->ReadSegments(aWriter, aClosure, aCount, aResult);
+    MOZ_ASSERT(mRemoteStream);
+
+    nsresult rv = EnsureAsyncRemoteStream();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    MOZ_ASSERT(mAsyncRemoteStream);
+    return mAsyncRemoteStream->ReadSegments(aWriter, aClosure, aCount, aResult);
   }
 
   MOZ_ASSERT(mState == eClosed);
   return NS_BASE_STREAM_CLOSED;
 }
 
 NS_IMETHODIMP
 IPCBlobInputStream::IsNonBlocking(bool* aNonBlocking)
@@ -159,22 +238,31 @@ IPCBlobInputStream::IsNonBlocking(bool* 
 NS_IMETHODIMP
 IPCBlobInputStream::Close()
 {
   if (mActor) {
     mActor->ForgetStream(this);
     mActor = nullptr;
   }
 
+  if (mAsyncRemoteStream) {
+    mAsyncRemoteStream->Close();
+    mAsyncRemoteStream = nullptr;
+  }
+
   if (mRemoteStream) {
     mRemoteStream->Close();
     mRemoteStream = nullptr;
   }
 
-  mCallback = nullptr;
+  mInputStreamCallback = nullptr;
+  mInputStreamCallbackEventTarget = nullptr;
+
+  mFileMetadataCallback = nullptr;
+  mFileMetadataCallbackEventTarget = nullptr;
 
   mState = eClosed;
   return NS_OK;
 }
 
 // nsICloneableInputStream interface
 
 NS_IMETHODIMP
@@ -217,36 +305,36 @@ IPCBlobInputStream::AsyncWait(nsIInputSt
 {
   // See IPCBlobInputStream.h for more information about this state machine.
 
   switch (mState) {
   // First call, we need to retrieve the stream from the parent actor.
   case eInit:
     MOZ_ASSERT(mActor);
 
-    mCallback = aCallback;
-    mCallbackEventTarget = aEventTarget;
+    mInputStreamCallback = aCallback;
+    mInputStreamCallbackEventTarget = aEventTarget;
     mState = ePending;
 
     mActor->StreamNeeded(this, aEventTarget);
     return NS_OK;
 
   // We are still waiting for the remote inputStream
   case ePending:
-    if (mCallback && aCallback) {
+    if (mInputStreamCallback && aCallback) {
       return NS_ERROR_FAILURE;
     }
 
-    mCallback = aCallback;
-    mCallbackEventTarget = aEventTarget;
+    mInputStreamCallback = aCallback;
+    mInputStreamCallbackEventTarget = aEventTarget;
     return NS_OK;
 
   // We have the remote inputStream, let's check if we can execute the callback.
   case eRunning:
-    return MaybeExecuteCallback(aCallback, aEventTarget);
+    return MaybeExecuteInputStreamCallback(aCallback, aEventTarget);
 
   // Stream is closed.
   default:
     MOZ_ASSERT(mState == eClosed);
     return NS_BASE_STREAM_CLOSED;
   }
 }
 
@@ -260,93 +348,103 @@ IPCBlobInputStream::StreamReady(nsIInput
     }
     return;
   }
 
   // If aInputStream is null, it means that the serialization went wrong or the
   // stream is not available anymore. We keep the state as pending just to block
   // any additional operation.
 
-  nsCOMPtr<nsIInputStreamCallback> callback;
-  callback.swap(mCallback);
+  if (!aInputStream) {
+    return;
+  }
+
+  mRemoteStream = aInputStream;
 
-  nsCOMPtr<nsIEventTarget> callbackEventTarget;
-  callbackEventTarget.swap(mCallbackEventTarget);
+  MOZ_ASSERT(mState == ePending);
+  mState = eRunning;
+
+  nsCOMPtr<nsIFileMetadataCallback> fileMetadataCallback;
+  fileMetadataCallback.swap(mFileMetadataCallback);
+
+  nsCOMPtr<nsIEventTarget> fileMetadataCallbackEventTarget;
+  fileMetadataCallbackEventTarget.swap(mFileMetadataCallbackEventTarget);
 
-  if (aInputStream && callback) {
-    MOZ_ASSERT(mState == ePending);
+  if (fileMetadataCallback) {
+    FileMetadataCallbackRunnable::Execute(fileMetadataCallback,
+                                          fileMetadataCallbackEventTarget,
+                                          this);
+  }
 
-    mRemoteStream = aInputStream;
-    mState = eRunning;
+  nsCOMPtr<nsIInputStreamCallback> inputStreamCallback;
+  inputStreamCallback.swap(mInputStreamCallback);
 
-    MaybeExecuteCallback(callback, callbackEventTarget);
+  nsCOMPtr<nsIEventTarget> inputStreamCallbackEventTarget;
+  inputStreamCallbackEventTarget.swap(mInputStreamCallbackEventTarget);
+
+  if (inputStreamCallback) {
+    MaybeExecuteInputStreamCallback(inputStreamCallback,
+                                    inputStreamCallbackEventTarget);
   }
 }
 
 nsresult
-IPCBlobInputStream::MaybeExecuteCallback(nsIInputStreamCallback* aCallback,
-                                         nsIEventTarget* aCallbackEventTarget)
+IPCBlobInputStream::MaybeExecuteInputStreamCallback(nsIInputStreamCallback* aCallback,
+                                                    nsIEventTarget* aCallbackEventTarget)
 {
   MOZ_ASSERT(mState == eRunning);
   MOZ_ASSERT(mRemoteStream);
 
-  // If the stream supports nsIAsyncInputStream, we need to call its AsyncWait
-  // and wait for OnInputStreamReady.
-  nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(mRemoteStream);
-  if (asyncStream) {
-    // If the callback has been already set, we return an error.
-    if (mCallback && aCallback) {
-      return NS_ERROR_FAILURE;
-    }
-
-    mCallback = aCallback;
-    mCallbackEventTarget = aCallbackEventTarget;
-
-    if (!mCallback) {
-      return NS_OK;
-    }
-
-    RefPtr<nsIEventTarget> target = GetCurrentThreadEventTarget();
-    return asyncStream->AsyncWait(this, 0, 0, target);
+  // If the callback has been already set, we return an error.
+  if (mInputStreamCallback && aCallback) {
+    return NS_ERROR_FAILURE;
   }
 
-  MOZ_ASSERT(!mCallback);
-  MOZ_ASSERT(!mCallbackEventTarget);
+  mInputStreamCallback = aCallback;
+  mInputStreamCallbackEventTarget = aCallbackEventTarget;
 
-  if (!aCallback) {
+  if (!mInputStreamCallback) {
     return NS_OK;
   }
 
-  CallbackRunnable::Execute(aCallback, aCallbackEventTarget, this);
-  return NS_OK;
+  nsresult rv = EnsureAsyncRemoteStream();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  MOZ_ASSERT(mAsyncRemoteStream);
+
+  return mAsyncRemoteStream->AsyncWait(this, 0, 0, aCallbackEventTarget);
 }
 
 // nsIInputStreamCallback
 
 NS_IMETHODIMP
 IPCBlobInputStream::OnInputStreamReady(nsIAsyncInputStream* aStream)
 {
   // We have been closed in the meantime.
   if (mState == eClosed) {
     return NS_OK;
   }
 
   MOZ_ASSERT(mState == eRunning);
-  MOZ_ASSERT(mRemoteStream == aStream);
+  MOZ_ASSERT(mAsyncRemoteStream == aStream);
 
   // The callback has been canceled in the meantime.
-  if (!mCallback) {
+  if (!mInputStreamCallback) {
     return NS_OK;
   }
 
-  CallbackRunnable::Execute(mCallback, mCallbackEventTarget, this);
+  nsCOMPtr<nsIInputStreamCallback> callback;
+  callback.swap(mInputStreamCallback);
 
-  mCallback = nullptr;
-  mCallbackEventTarget = nullptr;
-
+  nsCOMPtr<nsIEventTarget> callbackEventTarget;
+  callbackEventTarget.swap(mInputStreamCallbackEventTarget);
+ 
+  InputStreamCallbackRunnable::Execute(callback, callbackEventTarget, this);
   return NS_OK;
 }
 
 // nsIIPCSerializableInputStream
 
 void
 IPCBlobInputStream::Serialize(mozilla::ipc::InputStreamParams& aParams,
                               FileDescriptorArray& aFileDescriptors)
@@ -366,27 +464,60 @@ IPCBlobInputStream::Deserialize(const mo
 }
 
 mozilla::Maybe<uint64_t>
 IPCBlobInputStream::ExpectedSerializedLength()
 {
   return mozilla::Nothing();
 }
 
-// nsIFileMetadata
+// nsIAsyncFileMetadata
 
-bool
-IPCBlobInputStream::IsFileMetadata() const
+NS_IMETHODIMP
+IPCBlobInputStream::AsyncWait(nsIFileMetadataCallback* aCallback,
+                              nsIEventTarget* aEventTarget)
 {
-  // We are nsIFileMetadata only if we have the remote stream and that is a
-  // nsIFileMetadata.
-  nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(mRemoteStream);
-  return !!fileMetadata;
+  // See IPCBlobInputStream.h for more information about this state machine.
+
+  switch (mState) {
+  // First call, we need to retrieve the stream from the parent actor.
+  case eInit:
+    MOZ_ASSERT(mActor);
+
+    mFileMetadataCallback = aCallback;
+    mFileMetadataCallbackEventTarget = aEventTarget;
+    mState = ePending;
+
+    mActor->StreamNeeded(this, aEventTarget);
+    return NS_OK;
+
+  // We are still waiting for the remote inputStream
+  case ePending:
+    if (mFileMetadataCallback && aCallback) {
+      return NS_ERROR_FAILURE;
+    }
+
+    mFileMetadataCallback = aCallback;
+    mFileMetadataCallbackEventTarget = aEventTarget;
+    return NS_OK;
+
+  // We have the remote inputStream, let's check if we can execute the callback.
+  case eRunning:
+    FileMetadataCallbackRunnable::Execute(aCallback, aEventTarget, this);
+    return NS_OK;
+
+  // Stream is closed.
+  default:
+    MOZ_ASSERT(mState == eClosed);
+    return NS_BASE_STREAM_CLOSED;
+  }
 }
 
+// nsIFileMetadata
+
 NS_IMETHODIMP
 IPCBlobInputStream::GetSize(int64_t* aRetval)
 {
   nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(mRemoteStream);
   if (!fileMetadata) {
     return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_ERROR_FAILURE;
   }
 
@@ -410,50 +541,66 @@ IPCBlobInputStream::GetFileDescriptor(PR
   nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(mRemoteStream);
   if (!fileMetadata) {
     return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_ERROR_FAILURE;
   }
 
   return fileMetadata->GetFileDescriptor(aRetval);
 }
 
-// nsISeekableStream
-
-bool
-IPCBlobInputStream::IsSeekableStream() const
+nsresult
+IPCBlobInputStream::EnsureAsyncRemoteStream()
 {
-  // We are nsISeekableStream only if we have the remote stream and that is a
-  // nsISeekableStream.
-  nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(mRemoteStream);
-  return !!seekableStream;
-}
+  if (!mRemoteStream) {
+    return NS_ERROR_FAILURE;
+  }
 
-NS_IMETHODIMP
-IPCBlobInputStream::Seek(int32_t aWhence, int64_t aOffset)
-{
-  nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(mRemoteStream);
-  if (!seekableStream) {
-    return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_ERROR_FAILURE;
+  // We already have an async remote stream.
+  if (mAsyncRemoteStream) {
+    return NS_OK;
+  }
+
+  // If the stream is blocking, we want to make it unblocking using a pipe.
+  bool nonBlocking = false;
+  nsresult rv = mRemoteStream->IsNonBlocking(&nonBlocking);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
   }
 
-  return seekableStream->Seek(aWhence, aOffset);
-}
+  nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(mRemoteStream);
+  if (!asyncStream || !nonBlocking) {
+    nsCOMPtr<nsIStreamTransportService> sts =
+      do_GetService(kStreamTransportServiceCID, &rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
 
-NS_IMETHODIMP
-IPCBlobInputStream::Tell(int64_t *aResult)
-{
-  nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(mRemoteStream);
-  if (!seekableStream) {
-    return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_ERROR_FAILURE;
+    nsCOMPtr<nsITransport> transport;
+    rv = sts->CreateInputTransport(mRemoteStream,
+                                   /* aStartOffset */ 0,
+                                   /* aReadLimit */ -1,
+                                   /* aCloseWhenDone */ true,
+                                   getter_AddRefs(transport));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    nsCOMPtr<nsIInputStream> wrapper;
+    rv = transport->OpenInputStream(/* aFlags */ 0,
+                                    /* aSegmentSize */ 0,
+                                    /* aSegmentCount */ 0,
+                                    getter_AddRefs(wrapper));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    asyncStream = do_QueryInterface(wrapper);
   }
 
-  return seekableStream->Tell(aResult);
-}
+  MOZ_ASSERT(asyncStream);
+  mAsyncRemoteStream = asyncStream;
 
-NS_IMETHODIMP
-IPCBlobInputStream::SetEOF()
-{
-  // This is a read-only stream.
-  return NS_ERROR_FAILURE;
+  return NS_OK;
+
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/file/ipc/IPCBlobInputStream.h
+++ b/dom/file/ipc/IPCBlobInputStream.h
@@ -6,58 +6,53 @@
 
 #ifndef mozilla_dom_ipc_IPCBlobInputStream_h
 #define mozilla_dom_ipc_IPCBlobInputStream_h
 
 #include "nsIAsyncInputStream.h"
 #include "nsICloneableInputStream.h"
 #include "nsIFileStreams.h"
 #include "nsIIPCSerializableInputStream.h"
-#include "nsISeekableStream.h"
 #include "nsCOMPtr.h"
 
 namespace mozilla {
 namespace dom {
 
 class IPCBlobInputStreamChild;
 
 class IPCBlobInputStream final : public nsIAsyncInputStream
                                , public nsIInputStreamCallback
                                , public nsICloneableInputStream
                                , public nsIIPCSerializableInputStream
-                               , public nsISeekableStream
-                               , public nsIFileMetadata
+                               , public nsIAsyncFileMetadata
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIINPUTSTREAM
   NS_DECL_NSIASYNCINPUTSTREAM
   NS_DECL_NSIINPUTSTREAMCALLBACK
   NS_DECL_NSICLONEABLEINPUTSTREAM
   NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
-  NS_DECL_NSISEEKABLESTREAM
   NS_DECL_NSIFILEMETADATA
+  NS_DECL_NSIASYNCFILEMETADATA
 
   explicit IPCBlobInputStream(IPCBlobInputStreamChild* aActor);
 
   void
   StreamReady(nsIInputStream* aInputStream);
 
 private:
   ~IPCBlobInputStream();
 
   nsresult
-  MaybeExecuteCallback(nsIInputStreamCallback* aCallback,
-                       nsIEventTarget* aEventTarget);
+  MaybeExecuteInputStreamCallback(nsIInputStreamCallback* aCallback,
+                                  nsIEventTarget* aEventTarget);
 
-  bool
-  IsSeekableStream() const;
-
-  bool
-  IsFileMetadata() const;
+  nsresult
+  EnsureAsyncRemoteStream();
 
   RefPtr<IPCBlobInputStreamChild> mActor;
 
   // This is the list of possible states.
   enum {
     // The initial state. Only ::Available() can be used without receiving an
     // error. The available size is known by the actor.
     eInit,
@@ -73,18 +68,23 @@ private:
 
     // If Close() or CloseWithStatus() is called, we move to this state.
     // mRemoveStream is released and any method will return
     // NS_BASE_STREAM_CLOSED.
     eClosed,
   } mState;
 
   nsCOMPtr<nsIInputStream> mRemoteStream;
+  nsCOMPtr<nsIAsyncInputStream> mAsyncRemoteStream;
 
   // These 2 values are set only if mState is ePending.
-  nsCOMPtr<nsIInputStreamCallback> mCallback;
-  nsCOMPtr<nsIEventTarget> mCallbackEventTarget;
+  nsCOMPtr<nsIInputStreamCallback> mInputStreamCallback;
+  nsCOMPtr<nsIEventTarget> mInputStreamCallbackEventTarget;
+
+  // These 2 values are set only if mState is ePending.
+  nsCOMPtr<nsIFileMetadataCallback> mFileMetadataCallback;
+  nsCOMPtr<nsIEventTarget> mFileMetadataCallbackEventTarget;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_ipc_IPCBlobInputStream_h
--- a/dom/flyweb/HttpServer.cpp
+++ b/dom/flyweb/HttpServer.cpp
@@ -682,17 +682,17 @@ HttpServer::Connection::ConsumeLine(cons
                                getter_AddRefs(output),
                                0,          // Segment size
                                UINT32_MAX, // Unlimited buffer size
                                false,      // not nonBlockingInput
                                true);      // nonBlockingOutput
       NS_ENSURE_SUCCESS(rv, rv);
 
       mCurrentRequestBody = do_QueryInterface(output);
-      mPendingReq->SetBody(input);
+      mPendingReq->SetBody(input, -1);
     } else {
       LOG_V("HttpServer::Connection::ConsumeLine(%p) - No body", this);
       mState = eRequestLine;
     }
 
     mPendingRequests.AppendElement(PendingRequest(mPendingReq, nullptr));
 
     LOG_V("HttpServer::Connection::ConsumeLine(%p) - Fire OnRequest", this);
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -338,16 +338,22 @@ public:
     return mSelectionProperties;
   }
 
   bool HasPatternAttribute() const
   {
     return mHasPatternAttribute;
   }
 
+  virtual already_AddRefed<nsITextControlElement> GetAsTextControlElement() override
+  {
+    nsCOMPtr<nsITextControlElement> txt = this;
+    return txt.forget();
+  }
+
   // nsIConstraintValidation
   bool     IsTooLong();
   bool     IsTooShort();
   bool     IsValueMissing() const;
   bool     HasTypeMismatch() const;
   bool     HasPatternMismatch() const;
   bool     IsRangeOverflow() const;
   bool     IsRangeUnderflow() const;
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -163,16 +163,22 @@ public:
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTextAreaElement,
                                            nsGenericHTMLFormElementWithState)
 
+  virtual already_AddRefed<nsITextControlElement> GetAsTextControlElement() override
+  {
+    nsCOMPtr<nsITextControlElement> txt = this;
+    return txt.forget();
+  }
+
   // nsIConstraintValidation
   bool     IsTooLong();
   bool     IsTooShort();
   bool     IsValueMissing() const;
   void     UpdateTooLongValidityState();
   void     UpdateTooShortValidityState();
   void     UpdateValueMissingValidityState();
   void     UpdateBarredFromConstraintValidation();
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -1472,16 +1472,17 @@ DispatchFileHandleSuccessEvent(FileHandl
 /*******************************************************************************
  * Actor class declarations
  ******************************************************************************/
 
 // CancelableRunnable is used to make workers happy.
 class BackgroundRequestChild::PreprocessHelper final
   : public CancelableRunnable
   , public nsIInputStreamCallback
+  , public nsIFileMetadataCallback
 {
   typedef std::pair<nsCOMPtr<nsIInputStream>,
                     nsCOMPtr<nsIInputStream>> StreamPair;
 
   nsCOMPtr<nsIEventTarget> mOwningEventTarget;
   nsTArray<StreamPair> mStreamPairs;
   nsTArray<RefPtr<JS::WasmModule>> mModuleSet;
   BackgroundRequestChild* mActor;
@@ -1555,19 +1556,23 @@ private:
   ProcessCurrentStreamPair();
 
   nsresult
   WaitForStreamReady(nsIInputStream* aInputStream);
 
   void
   ContinueWithStatus(nsresult aStatus);
 
+  nsresult
+  DataIsReady(nsIInputStream* aInputStream);
+
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSIINPUTSTREAMCALLBACK
+  NS_DECL_NSIFILEMETADATACALLBACK
 
   virtual nsresult
   Cancel() override;
 };
 
 /*******************************************************************************
  * Local class implementations
  ******************************************************************************/
@@ -3513,16 +3518,27 @@ PreprocessHelper::ProcessCurrentStreamPa
 
 nsresult
 BackgroundRequestChild::
 PreprocessHelper::WaitForStreamReady(nsIInputStream* aInputStream)
 {
   MOZ_ASSERT(!IsOnOwningThread());
   MOZ_ASSERT(aInputStream);
 
+  nsCOMPtr<nsIAsyncFileMetadata> asyncFileMetadata =
+    do_QueryInterface(aInputStream);
+  if (asyncFileMetadata) {
+    nsresult rv = asyncFileMetadata->AsyncWait(this, mTaskQueueEventTarget);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    return NS_OK;
+  }
+
   nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aInputStream);
   if (!asyncStream) {
     return NS_ERROR_NO_INTERFACE;
   }
 
   nsresult rv = asyncStream->AsyncWait(this, 0, 0, mTaskQueueEventTarget);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
@@ -3559,17 +3575,18 @@ PreprocessHelper::ContinueWithStatus(nsr
     eventTarget = mTaskQueueEventTarget;
   }
 
   nsresult rv = eventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
   Unused <<  NS_WARN_IF(NS_FAILED(rv));
 }
 
 NS_IMPL_ISUPPORTS_INHERITED(BackgroundRequestChild::PreprocessHelper,
-                            CancelableRunnable, nsIInputStreamCallback)
+                            CancelableRunnable, nsIInputStreamCallback,
+                            nsIFileMetadataCallback)
 
 NS_IMETHODIMP
 BackgroundRequestChild::
 PreprocessHelper::Run()
 {
   if (IsOnOwningThread()) {
     RunOnOwningThread();
   } else {
@@ -3578,16 +3595,33 @@ PreprocessHelper::Run()
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 BackgroundRequestChild::
 PreprocessHelper::OnInputStreamReady(nsIAsyncInputStream* aStream)
 {
+  return DataIsReady(aStream);
+}
+
+NS_IMETHODIMP
+BackgroundRequestChild::
+PreprocessHelper::OnFileMetadataReady(nsIAsyncFileMetadata* aObject)
+{
+  nsCOMPtr<nsIInputStream> stream = do_QueryInterface(aObject);
+  MOZ_ASSERT(stream, "It was a stream before!");
+
+  return DataIsReady(stream);
+}
+
+nsresult
+BackgroundRequestChild::
+PreprocessHelper::DataIsReady(nsIInputStream* aStream)
+{
   MOZ_ASSERT(!IsOnOwningThread());
   MOZ_ASSERT(aStream);
   MOZ_ASSERT(!mStreamPairs.IsEmpty());
 
   // We still don't have the current bytecode FileDesc.
   if (!mCurrentBytecodeFileDesc) {
     mCurrentBytecodeFileDesc = GetFileDescriptorFromStream(aStream);
     if (!mCurrentBytecodeFileDesc) {
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -263,21 +263,16 @@
 #include "mozilla/CodeCoverageHandler.h"
 #endif
 
 // For VP9Benchmark::sBenchmarkFpsPref
 #include "Benchmark.h"
 
 static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
 
-#if defined(XP_WIN)
-// e10s forced enable pref, defined in nsAppRunner.cpp
-extern const char* kForceEnableE10sPref;
-#endif
-
 using base::ChildPrivileges;
 using base::KillProcess;
 
 #ifdef MOZ_CRASHREPORTER
 using namespace CrashReporter;
 #endif
 using namespace mozilla::dom::power;
 using namespace mozilla::media;
@@ -1306,23 +1301,18 @@ ContentParent::Init()
     obs->NotifyObservers(static_cast<nsIObserver*>(this), "ipc:content-created", cpId.get());
   }
 
 #ifdef ACCESSIBILITY
   // If accessibility is running in chrome process then start it in content
   // process.
   if (nsIPresShell::IsAccessibilityActive()) {
 #if defined(XP_WIN)
-#if defined(RELEASE_OR_BETA)
-    // On Windows we currently only enable a11y in the content process
-    // for testing purposes.
-    if (Preferences::GetBool(kForceEnableE10sPref, false))
-#endif
-      Unused << SendActivateA11y(::GetCurrentThreadId(),
-                                 a11y::AccessibleWrap::GetContentProcessIdFor(ChildID()));
+    Unused << SendActivateA11y(::GetCurrentThreadId(),
+                                a11y::AccessibleWrap::GetContentProcessIdFor(ChildID()));
 #else
     Unused << SendActivateA11y(0, 0);
 #endif
   }
 #endif
 
 #ifdef MOZ_GECKO_PROFILER
   Unused << SendInitProfiler(ProfilerParent::CreateForProcess(OtherPid()));
@@ -2846,23 +2836,18 @@ ContentParent::Observe(nsISupports* aSub
     Unused << SendLastPrivateDocShellDestroyed();
   }
 #ifdef ACCESSIBILITY
   else if (aData && !strcmp(aTopic, "a11y-init-or-shutdown")) {
     if (*aData == '1') {
       // Make sure accessibility is running in content process when
       // accessibility gets initiated in chrome process.
 #if defined(XP_WIN)
-#if defined(RELEASE_OR_BETA)
-      // On Windows we currently only enable a11y in the content process
-      // for testing purposes.
-      if (Preferences::GetBool(kForceEnableE10sPref, false))
-#endif
-        Unused << SendActivateA11y(::GetCurrentThreadId(),
-                                   a11y::AccessibleWrap::GetContentProcessIdFor(ChildID()));
+      Unused << SendActivateA11y(::GetCurrentThreadId(),
+                                  a11y::AccessibleWrap::GetContentProcessIdFor(ChildID()));
 #else
       Unused << SendActivateA11y(0, 0);
 #endif
     } else {
       // If possible, shut down accessibility in content process when
       // accessibility gets shutdown in chrome process.
       Unused << SendShutdownA11y();
     }
--- a/dom/tests/mochitest/general/test_clipboard_events.html
+++ b/dom/tests/mochitest/general/test_clipboard_events.html
@@ -654,32 +654,29 @@ function compareSynthetic(event, eventty
 
 function checkCachedDataTransfer(cd, eventtype)
 {
   var testprefix = "cached " + eventtype + " dataTransfer";
 
   setClipboardText("Some Clipboard Text");
 
   var oldtext = cd.getData("text/plain");
-  ok(oldtext != "Some Clipboard Text", "clipboard get using " + testprefix);
+  ok(!oldtext, "clipboard get using " + testprefix);
 
-  var exh = false;
-  try { cd.mozSetDataAt("text/plain", "Test Cache Data", 0); } catch (ex) { exh = true; }
-  ok(eventtype == "paste" ? exh : !exh, "exception occured setting " + testprefix);
-
-  var newtext = (eventtype == "paste") ? cd.getData("text/plain") :
-                                         cd.mozGetDataAt("text/plain", 0);
-  is(newtext, (eventtype == "paste") ? oldtext : "Test Cache Data",
-     " clipboardData not changed using " + testprefix);
+  try {
+    cd.mozSetDataAt("text/plain", "Test Cache Data", 0);
+  } catch (ex) {}
+  ok(!cd.getData("text/plain"), "clipboard set using " + testprefix);
 
   is(getClipboardText(), "Some Clipboard Text", "clipboard not changed using " + testprefix);
 
-  var exh = false;
-  try { cd.mozClearDataAt("text/plain", 0); } catch (ex) { exh = true; }
-  ok(eventtype == "paste" ? exh : !exh, "exception occured clearing " + testprefix);
+  try {
+    cd.mozClearDataAt("text/plain", 0);
+  } catch (ex) {}
+  ok(!cd.getData("text/plain"), "clipboard clear using " + testprefix);
 
   is(getClipboardText(), "Some Clipboard Text", "clipboard not changed using " + testprefix);
 }
 
 function test_input_cut_disallowed_types_dataTransfer() {
   selectContentInput();
   let oncutExecuted = false;
   contentInput.oncut = function(event) {
--- a/dom/webidl/DataTransfer.webidl
+++ b/dom/webidl/DataTransfer.webidl
@@ -150,9 +150,21 @@ partial interface DataTransfer {
   readonly attribute boolean mozUserCancelled;
 
   /**
    * The node that the mouse was pressed over to begin the drag. For external
    * drags, or if the caller cannot access this node, this will be null.
    */
   [UseCounter]
   readonly attribute Node? mozSourceNode;
+
+  /**
+   * Copy the given DataTransfer for the given event. Used by testing code for
+   * creating emulated Drag and Drop events in the UI.
+   *
+   * NOTE: Don't expose a DataTransfer produced with this method to the web or
+   * use this for non-testing purposes. It can easily be used to get the
+   * DataTransfer into an invalid state, and is an unstable implementation
+   * detail of EventUtils.synthesizeDrag.
+   */
+  [Throws, ChromeOnly]
+  DataTransfer mozCloneForEvent(DOMString event);
 };
--- a/dom/workers/FileReaderSync.cpp
+++ b/dom/workers/FileReaderSync.cpp
@@ -204,18 +204,24 @@ FileReaderSync::ReadAsText(Blob& aBlob,
     return;
   }
 
   aRv = multiplexStream->AppendStream(sniffStringStream);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
+  uint64_t blobSize = aBlob.GetSize(aRv);
+  if (NS_WARN_IF(aRv.Failed())){
+    return;
+  }
+
   nsCOMPtr<nsIInputStream> syncStream;
-  aRv = ConvertAsyncToSyncStream(stream, getter_AddRefs(syncStream));
+  aRv = ConvertAsyncToSyncStream(blobSize - sniffBuf.Length(), stream,
+                                 getter_AddRefs(syncStream));
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   // ConvertAsyncToSyncStream returns a null syncStream if the stream has been
   // already closed or there is nothing to read.
   if (syncStream) {
     aRv = multiplexStream->AppendStream(syncStream);
@@ -250,35 +256,35 @@ FileReaderSync::ReadAsDataURL(Blob& aBlo
   scratchResult.AppendLiteral(";base64,");
 
   nsCOMPtr<nsIInputStream> stream;
   aBlob.GetInternalStream(getter_AddRefs(stream), aRv);
   if (NS_WARN_IF(aRv.Failed())){
     return;
   }
 
+  uint64_t blobSize = aBlob.GetSize(aRv);
+  if (NS_WARN_IF(aRv.Failed())){
+    return;
+  }
+
   nsCOMPtr<nsIInputStream> syncStream;
-  aRv = ConvertAsyncToSyncStream(stream, getter_AddRefs(syncStream));
+  aRv = ConvertAsyncToSyncStream(blobSize, stream, getter_AddRefs(syncStream));
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   MOZ_ASSERT(syncStream);
 
   uint64_t size;
   aRv = syncStream->Available(&size);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
-  uint64_t blobSize = aBlob.GetSize(aRv);
-  if (NS_WARN_IF(aRv.Failed())){
-    return;
-  }
-
   // The file is changed in the meantime?
   if (blobSize != size) {
     return;
   }
 
   nsAutoString encodedData;
   aRv = Base64EncodeInputStream(syncStream, encodedData, size);
   if (NS_WARN_IF(aRv.Failed())){
@@ -461,49 +467,39 @@ FileReaderSync::SyncRead(nsIInputStream*
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   // Now, we can try to read again.
   return SyncRead(aStream, aBuffer, aBufferSize, aRead);
 }
 
 nsresult
-FileReaderSync::ConvertAsyncToSyncStream(nsIInputStream* aAsyncStream,
+FileReaderSync::ConvertAsyncToSyncStream(uint64_t aStreamSize,
+                                         nsIInputStream* aAsyncStream,
                                          nsIInputStream** aSyncStream)
 {
   // If the stream is not async, we just need it to be bufferable.
   nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aAsyncStream);
   if (!asyncStream) {
     return NS_NewBufferedInputStream(aSyncStream, aAsyncStream, 4096);
   }
 
-  uint64_t length;
-  nsresult rv = aAsyncStream->Available(&length);
-  if (rv == NS_BASE_STREAM_CLOSED) {
-    // The stream has already been closed. Nothing to do.
-    *aSyncStream = nullptr;
-    return NS_OK;
+  nsAutoCString buffer;
+  if (!buffer.SetLength(aStreamSize, fallible)) {
+    return NS_ERROR_OUT_OF_MEMORY;
   }
 
+  uint32_t read;
+  nsresult rv =
+    SyncRead(aAsyncStream, buffer.BeginWriting(), aStreamSize, &read);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  nsAutoCString buffer;
-  if (!buffer.SetLength(length, fallible)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  uint32_t read;
-  rv = SyncRead(aAsyncStream, buffer.BeginWriting(), length, &read);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  if (read != length) {
+  if (read != aStreamSize) {
     return NS_ERROR_FAILURE;
   }
 
   rv = NS_NewCStringInputStream(aSyncStream, buffer);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
--- a/dom/workers/FileReaderSync.h
+++ b/dom/workers/FileReaderSync.h
@@ -27,17 +27,18 @@ private:
   // Private destructor, to discourage deletion outside of Release():
   ~FileReaderSync()
   {
   }
 
   nsresult ConvertStream(nsIInputStream *aStream, const char *aCharset,
                          nsAString &aResult);
 
-  nsresult ConvertAsyncToSyncStream(nsIInputStream* aAsyncStream,
+  nsresult ConvertAsyncToSyncStream(uint64_t aStreamSize,
+                                    nsIInputStream* aAsyncStream,
                                     nsIInputStream** aSyncStream);
 
   nsresult SyncRead(nsIInputStream* aStream, char* aBuffer,
                     uint32_t aBufferSize, uint32_t* aRead);
 
 public:
   static already_AddRefed<FileReaderSync>
   Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
--- a/dom/workers/ServiceWorkerPrivate.cpp
+++ b/dom/workers/ServiceWorkerPrivate.cpp
@@ -1598,17 +1598,17 @@ private:
                                                               mCacheMode,
                                                               mRequestMode,
                                                               mRequestRedirect,
                                                               mRequestCredentials,
                                                               NS_ConvertUTF8toUTF16(mReferrer),
                                                               mReferrerPolicy,
                                                               mContentPolicyType,
                                                               mIntegrity);
-    internalReq->SetBody(mUploadStream);
+    internalReq->SetBody(mUploadStream, -1);
     // For Telemetry, note that this Request object was created by a Fetch event.
     internalReq->SetCreatedByFetchEvent();
 
     nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(globalObj.GetAsSupports());
     if (NS_WARN_IF(!global)) {
       return false;
     }
 
--- a/gfx/thebes/gfxFontEntry.h
+++ b/gfx/thebes/gfxFontEntry.h
@@ -641,16 +641,18 @@ public:
         }
         if (aFontEntry->mFamilyName.IsEmpty()) {
             aFontEntry->mFamilyName = Name();
         } else {
             MOZ_ASSERT(aFontEntry->mFamilyName.Equals(Name()));
         }
         aFontEntry->mSkipDefaultFeatureSpaceCheck = mSkipDefaultFeatureSpaceCheck;
         mAvailableFonts.AppendElement(aFontEntry);
+        mIsSimpleFamily = false; // CheckForSimpleFamily may set this later,
+                                 // but at this point we're not sure
     }
 
     // note that the styles for this family have been added
     bool HasStyles() { return mHasStyles; }
     void SetHasStyles(bool aHasStyles) { mHasStyles = aHasStyles; }
 
     // choose a specific face to match a style using CSS font matching
     // rules (weight matching occurs here).  may return a face that doesn't
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -178,24 +178,27 @@ MacOSFontEntry::ReadCMAP(FontInfoData *a
     }
 
     if (NS_SUCCEEDED(rv) && !HasGraphiteTables()) {
         // We assume a Graphite font knows what it's doing,
         // and provides whatever shaping is needed for the
         // characters it supports, so only check/clear the
         // complex-script ranges for non-Graphite fonts
 
-        // for layout support, check for the presence of mort/morx and/or
+        // for layout support, check for the presence of mort/morx/kerx and/or
         // opentype layout tables
         bool hasAATLayout = HasFontTable(TRUETYPE_TAG('m','o','r','x')) ||
                             HasFontTable(TRUETYPE_TAG('m','o','r','t'));
+        bool hasAppleKerning = HasFontTable(TRUETYPE_TAG('k','e','r','x'));
         bool hasGSUB = HasFontTable(TRUETYPE_TAG('G','S','U','B'));
         bool hasGPOS = HasFontTable(TRUETYPE_TAG('G','P','O','S'));
-        if (hasAATLayout && !(hasGSUB || hasGPOS)) {
-            mRequiresAAT = true; // prefer CoreText if font has no OTL tables
+        if ((hasAATLayout && !(hasGSUB || hasGPOS)) || hasAppleKerning) {
+            mRequiresAAT = true; // prefer CoreText if font has no OTL tables,
+                                 // or if it uses the Apple-specific 'kerx'
+                                 // variant of kerning table
         }
 
         for (const ScriptRange* sr = gfxPlatformFontList::sComplexScriptRanges;
              sr->rangeStart; sr++) {
             // check to see if the cmap includes complex script codepoints
             if (charmap->TestRange(sr->rangeStart, sr->rangeEnd)) {
                 if (hasAATLayout) {
                     // prefer CoreText for Apple's complex-script fonts,
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -969,37 +969,38 @@ js::Nursery::maybeResizeNursery(JS::gcre
     }
 
 #ifdef JS_GC_ZEAL
     // This zeal mode disabled nursery resizing.
     if (runtime()->hasZealMode(ZealMode::GenerationalGC))
         return;
 #endif
 
-    bool canUsePromotionRate;
-    const float promotionRate = calcPromotionRate(&canUsePromotionRate);
+    /*
+     * This incorrect promotion rate results in better nursery sizing
+     * decisions, however we should to better tuning based on the real
+     * promotion rate in the future.
+     */
+    const float promotionRate =
+        float(previousGC.tenuredBytes) / float(previousGC.nurseryCapacity);
 
     newMaxNurseryChunks = runtime()->gc.tunables.gcMaxNurseryBytes() >> ChunkShift;
     if (newMaxNurseryChunks != maxNurseryChunks_) {
         maxNurseryChunks_ = newMaxNurseryChunks;
         /* The configured maximum nursery size is changing */
         const int extraChunks = numChunks() - newMaxNurseryChunks;
         if (extraChunks > 0) {
             /* We need to shrink the nursery */
             shrinkAllocableSpace(extraChunks);
 
-            if (canUsePromotionRate)
-                previousPromotionRate_ = promotionRate;
+            previousPromotionRate_ = promotionRate;
             return;
         }
     }
 
-    if (!canUsePromotionRate)
-        return;
-
     if (promotionRate > GrowThreshold)
         growAllocableSpace();
     else if (promotionRate < ShrinkThreshold && previousPromotionRate_ < ShrinkThreshold)
         shrinkAllocableSpace(1);
 
     previousPromotionRate_ = promotionRate;
 }
 
--- a/js/src/jit/IonCacheIRCompiler.cpp
+++ b/js/src/jit/IonCacheIRCompiler.cpp
@@ -5,23 +5,24 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/DebugOnly.h"
 
 #include "jit/BaselineIC.h"
 #include "jit/CacheIRCompiler.h"
 #include "jit/IonCaches.h"
 #include "jit/IonIC.h"
-
+#include "jit/JSJitFrameIter.h"
 #include "jit/Linker.h"
 #include "jit/SharedICHelpers.h"
 #include "proxy/Proxy.h"
 
 #include "jscompartmentinlines.h"
 
+#include "jit/JSJitFrameIter-inl.h"
 #include "jit/MacroAssembler-inl.h"
 #include "vm/TypeInference-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::DebugOnly;
 
@@ -319,16 +320,31 @@ void
 CacheRegisterAllocator::restoreIonLiveRegisters(MacroAssembler& masm, LiveRegisterSet liveRegs)
 {
     masm.PopRegsInMask(liveRegs);
 
     availableRegs_.set() = GeneralRegisterSet();
     availableRegsAfterSpill_.set() = GeneralRegisterSet::All();
 }
 
+static void*
+GetReturnAddressToIonCode(JSContext* cx)
+{
+    JSJitFrameIter frame(cx);
+    MOZ_ASSERT(frame.type() == JitFrame_Exit,
+               "An exit frame is expected as update functions are called with a VMFunction.");
+
+    void* returnAddr = frame.returnAddress();
+#ifdef DEBUG
+    ++frame;
+    MOZ_ASSERT(frame.isIonJS());
+#endif
+    return returnAddr;
+}
+
 void
 IonCacheIRCompiler::prepareVMCall(MacroAssembler& masm)
 {
     uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS,
                                               IonICCallFrameLayout::Size());
     pushStubCodePointer();
     masm.Push(Imm32(descriptor));
     masm.Push(ImmPtr(GetReturnAddressToIonCode(cx_)));
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -21,17 +21,16 @@
 # include "jit/PerfSpewer.h"
 #endif
 #include "jit/VMFunctions.h"
 #include "js/Proxy.h"
 #include "proxy/Proxy.h"
 #include "vm/Shape.h"
 #include "vm/Stack.h"
 
-#include "jit/JitFrames-inl.h"
 #include "jit/MacroAssembler-inl.h"
 #include "jit/shared/Lowering-shared-inl.h"
 #include "vm/Interpreter-inl.h"
 #include "vm/Shape-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
@@ -80,23 +79,8 @@ CodeLocationLabel::repoint(JitCode* code
 
 void
 CodeOffsetJump::fixup(MacroAssembler* masm)
 {
 #ifdef JS_SMALL_BRANCH
      jumpTableIndex_ = masm->actualIndex(jumpTableIndex_);
 #endif
 }
-
-void*
-jit::GetReturnAddressToIonCode(JSContext* cx)
-{
-    JSJitFrameIter frame(cx);
-    MOZ_ASSERT(frame.type() == JitFrame_Exit,
-               "An exit frame is expected as update functions are called with a VMFunction.");
-
-    void* returnAddr = frame.returnAddress();
-#ifdef DEBUG
-    ++frame;
-    MOZ_ASSERT(frame.isIonJS());
-#endif
-    return returnAddr;
-}
--- a/js/src/jit/IonCaches.h
+++ b/js/src/jit/IonCaches.h
@@ -18,17 +18,9 @@
 #endif
 #include "jit/JitCompartment.h"
 #include "jit/Registers.h"
 #include "jit/shared/Assembler-shared.h"
 #include "js/TrackedOptimizationInfo.h"
 
 #include "vm/TypedArrayObject.h"
 
-namespace js {
-namespace jit {
-
-void* GetReturnAddressToIonCode(JSContext* cx);
-
-} // namespace jit
-} // namespace js
-
 #endif /* jit_IonCaches_h */
--- a/js/src/jit/arm/AtomicOperations-arm.h
+++ b/js/src/jit/arm/AtomicOperations-arm.h
@@ -4,16 +4,18 @@
  * 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/. */
 
 #ifndef jit_arm_AtomicOperations_arm_h
 #define jit_arm_AtomicOperations_arm_h
 
 #include "jit/arm/Architecture-arm.h"
 
+#include "vm/ArrayBufferObject.h"
+
 // For documentation, see jit/AtomicOperations.h
 
 // NOTE, this file is *not* used with the ARM simulator, only when compiling for
 // actual ARM hardware.  The simulators get the files that are appropriate for
 // the hardware the simulator is running on.  See the comments before the
 // #include nest at the bottom of jit/AtomicOperations.h for more information.
 
 // Firefox requires gcc > 4.8, so we will always have the __atomic intrinsics
@@ -147,24 +149,48 @@ inline T
 js::jit::AtomicOperations::loadSafeWhenRacy(T* addr)
 {
     MOZ_ASSERT(tier1Constraints(addr));
     T v;
     __atomic_load(addr, &v, __ATOMIC_RELAXED);
     return v;
 }
 
+namespace js { namespace jit {
+
+template<>
+inline uint8_clamped
+js::jit::AtomicOperations::loadSafeWhenRacy(uint8_clamped* addr)
+{
+    uint8_t v;
+    __atomic_load(&addr->val, &v, __ATOMIC_RELAXED);
+    return uint8_clamped(v);
+}
+
+} }
+
 template<typename T>
 inline void
 js::jit::AtomicOperations::storeSafeWhenRacy(T* addr, T val)
 {
     MOZ_ASSERT(tier1Constraints(addr));
     __atomic_store(addr, &val, __ATOMIC_RELAXED);
 }
 
+namespace js { namespace jit {
+
+template<>
+inline void
+js::jit::AtomicOperations::storeSafeWhenRacy(uint8_clamped* addr, uint8_clamped val)
+{
+    __atomic_store(&addr->val, &val.val, __ATOMIC_RELAXED);
+}
+
+} }
+
 inline void
 js::jit::AtomicOperations::memcpySafeWhenRacy(void* dest, const void* src, size_t nbytes)
 {
     MOZ_ASSERT(!((char*)dest <= (char*)src && (char*)src < (char*)dest+nbytes));
     MOZ_ASSERT(!((char*)src <= (char*)dest && (char*)dest < (char*)src+nbytes));
     memcpy(dest, src, nbytes);
 }
 
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -1810,17 +1810,18 @@ PresShell::Initialize(nscoord aWidth, ns
 
   if (root) {
     {
       nsAutoCauseReflowNotifier reflowNotifier(this);
       mFrameConstructor->BeginUpdate();
 
       // Have the style sheet processor construct frame for the root
       // content object down
-      mFrameConstructor->ContentInserted(nullptr, root, nullptr, false);
+      mFrameConstructor->ContentInserted(
+          nullptr, root, nullptr, nsCSSFrameConstructor::InsertionKind::Sync);
       VERIFY_STYLE_TREE;
 
       // Something in mFrameConstructor->ContentInserted may have caused
       // Destroy() to get called, bug 337586.
       NS_ENSURE_STATE(!mHaveShutDown);
 
       mFrameConstructor->EndUpdate();
     }
@@ -4432,17 +4433,20 @@ PresShell::ContentAppended(nsIDocument *
 
   nsAutoCauseReflowNotifier crNotifier(this);
 
   // Call this here so it only happens for real content mutations and
   // not cases when the frame constructor calls its own methods to force
   // frame reconstruction.
   mPresContext->RestyleManager()->ContentAppended(aContainer, aFirstNewContent);
 
-  mFrameConstructor->ContentAppended(aContainer, aFirstNewContent, true);
+  mFrameConstructor->ContentAppended(
+      aContainer,
+      aFirstNewContent,
+      nsCSSFrameConstructor::InsertionKind::Async);
 
   VERIFY_STYLE_TREE;
 }
 
 void
 PresShell::ContentInserted(nsIDocument* aDocument,
                            nsIContent*  aMaybeContainer,
                            nsIContent*  aChild,
@@ -4458,17 +4462,21 @@ PresShell::ContentInserted(nsIDocument* 
 
   nsAutoCauseReflowNotifier crNotifier(this);
 
   // Call this here so it only happens for real content mutations and
   // not cases when the frame constructor calls its own methods to force
   // frame reconstruction.
   mPresContext->RestyleManager()->ContentInserted(container, aChild);
 
-  mFrameConstructor->ContentInserted(aMaybeContainer, aChild, nullptr, true);
+  mFrameConstructor->ContentInserted(
+      aMaybeContainer,
+      aChild,
+      nullptr,
+      nsCSSFrameConstructor::InsertionKind::Async);
 
   if (aChild->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE) {
     MOZ_ASSERT(container == aDocument);
     NotifyFontSizeInflationEnabledIsDirty();
   }
 
   VERIFY_STYLE_TREE;
 }
@@ -4561,17 +4569,17 @@ PresShell::ReconstructFrames()
   mDocument->FlushPendingNotifications(FlushType::Style);
 
   if (mIsDestroying) {
     return;
   }
 
   nsAutoCauseReflowNotifier crNotifier(this);
   mFrameConstructor->BeginUpdate();
-  mFrameConstructor->ReconstructDocElementHierarchy();
+  mFrameConstructor->ReconstructDocElementHierarchy(nsCSSFrameConstructor::InsertionKind::Sync);
   VERIFY_STYLE_TREE;
   mFrameConstructor->EndUpdate();
 }
 
 void
 nsIPresShell::RestyleForCSSRuleChanges()
 {
   if (mIsDestroying) {
@@ -8256,16 +8264,33 @@ PresShell::HandleEventInternal(WidgetEve
     }
     case eMouseUp:
       // reset the capturing content now that the mouse button is up
       SetCapturingContent(nullptr, 0);
       break;
     case eMouseMove:
       nsIPresShell::AllowMouseCapture(false);
       break;
+    case eDrag:
+    case eDragEnd:
+    case eDragEnter:
+    case eDragExit:
+    case eDragLeave:
+    case eDragOver:
+    case eDrop: {
+      // After any drag event other than dragstart (which is handled separately,
+      // as we need to collect the data first), the DataTransfer needs to be
+      // made protected, and then disconnected.
+      DataTransfer* dataTransfer = aEvent->AsDragEvent()->mDataTransfer;
+      if (dataTransfer) {
+        dataTransfer->SetMode(DataTransfer::Mode::Protected);
+        dataTransfer->ClearAll();
+      }
+      break;
+    }
     default:
       break;
     }
 
     if (aEvent->IsTrusted() && aEvent->mTimeStamp > mLastOSWake) {
       switch (aEvent->mMessage) {
         case eKeyPress:
         case eKeyDown:
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -1396,19 +1396,27 @@ RestyleManager::ProcessRestyledFrames(ns
       ++i;
     }
     if (i != lazyRangeStart) {
       nsIContent* start = aChangeList[lazyRangeStart].mContent;
       nsIContent* end = NextSiblingWhichMayHaveFrame(aChangeList[i-1].mContent);
       nsIContent* container = start->GetParent();
       MOZ_ASSERT(container);
       if (!end) {
-        frameConstructor->ContentAppended(container, start, false);
+        frameConstructor->ContentAppended(
+            container,
+            start,
+            nsCSSFrameConstructor::InsertionKind::Sync);
       } else {
-        frameConstructor->ContentRangeInserted(container, start, end, nullptr, false);
+        frameConstructor->ContentRangeInserted(
+            container,
+            start,
+            end,
+            nullptr,
+            nsCSSFrameConstructor::InsertionKind::Sync);
       }
     }
     for (size_t j = lazyRangeStart; j < i; ++j) {
       MOZ_ASSERT(!aChangeList[j].mContent->GetPrimaryFrame() ||
                  !aChangeList[j].mContent->HasFlag(NODE_NEEDS_FRAME));
     }
     if (i == aChangeList.Length()) {
       break;
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -6408,24 +6408,24 @@ nsCSSFrameConstructor::ConstructFramesFr
 
 inline bool
 IsRootBoxFrame(nsIFrame *aFrame)
 {
   return (aFrame->IsRootFrame());
 }
 
 void
-nsCSSFrameConstructor::ReconstructDocElementHierarchy()
+nsCSSFrameConstructor::ReconstructDocElementHierarchy(InsertionKind aInsertionKind)