Merge inbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Fri, 08 Sep 2017 13:36:31 -0700
changeset 429279 ea7b55d65d76214f97aaae502d65cb26fc6f5659
parent 429232 dd3736e98e4e7558af2f202803bce36278a26c66 (current diff)
parent 429278 ec521bf6357cf3564d5785a66da787be53be45cd (diff)
child 429312 6017b2756cd5516be9f196583f13612aa490cd15
child 429361 e78342f09ee6e90b78dc098742f3b0bae3b9bc84
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone57.0a1
first release with
nightly linux32
ea7b55d65d76 / 57.0a1 / 20170908220146 / files
nightly linux64
ea7b55d65d76 / 57.0a1 / 20170908220146 / files
nightly mac
ea7b55d65d76 / 57.0a1 / 20170908220146 / files
nightly win32
ea7b55d65d76 / 57.0a1 / 20170908220146 / files
nightly win64
ea7b55d65d76 / 57.0a1 / 20170908220146 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge 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;
     }