Merge mozilla-central to mozilla-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 20 Sep 2016 12:02:20 +0200
changeset 314615 150109898e5fe28f6f1e3b2587fc357329f5195f
parent 314614 3c1e96d92dcf6c4f87762cd6a695cc8ab4a13715 (current diff)
parent 314470 62f79d676e0e11b3ad59a5425b3ebb3ec5bbefb5 (diff)
child 314616 9729df5c77a395d99dd95f73182c32a9514eabb2
push id30732
push usercbook@mozilla.com
push dateWed, 21 Sep 2016 10:04:03 +0000
treeherdermozilla-central@560b2c805bf7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to mozilla-inbound
mobile/android/base/java/org/mozilla/gecko/SysInfo.java
mobile/android/base/java/org/mozilla/gecko/annotation/JNITarget.java
mobile/android/base/java/org/mozilla/gecko/annotation/ReflectionTarget.java
mobile/android/base/java/org/mozilla/gecko/annotation/RobocopTarget.java
mobile/android/base/java/org/mozilla/gecko/annotation/WebRTCJNITarget.java
mobile/android/base/java/org/mozilla/gecko/annotation/WrapForJNI.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/UnusedResourcesUtil.java
mobile/android/thirdparty/com/googlecode/eyesfree/braille/selfbraille/ISelfBrailleService.java
mobile/android/thirdparty/com/googlecode/eyesfree/braille/selfbraille/SelfBrailleClient.java
mobile/android/thirdparty/com/googlecode/eyesfree/braille/selfbraille/WriteData.java
--- a/addon-sdk/moz.build
+++ b/addon-sdk/moz.build
@@ -27,16 +27,17 @@ addons = [
     'contributors',
     'curly-id',
     'developers',
     'e10s-content',
     'e10s-l10n',
     'e10s-remote',
     'e10s-tabs',
     'e10s',
+    'embedded-webextension',
     'l10n-properties',
     'l10n',
     'layout-change',
     'main',
     'name-in-numbers-plus',
     'name-in-numbers',
     'packaging',
     'packed',
@@ -178,16 +179,20 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk
         'source/lib/sdk/windows/tabs-fennec.js',
     ]
 
 EXTRA_JS_MODULES.commonjs += [
     'source/lib/index.js',
     'source/lib/test.js',
 ]
 
+EXTRA_JS_MODULES.commonjs.sdk += [
+    'source/lib/sdk/webextension.js',
+]
+
 EXTRA_JS_MODULES.commonjs.dev += [
     'source/lib/dev/debuggee.js',
     'source/lib/dev/frame-script.js',
     'source/lib/dev/panel.js',
     'source/lib/dev/ports.js',
     'source/lib/dev/theme.js',
     'source/lib/dev/toolbox.js',
     'source/lib/dev/utils.js',
--- a/addon-sdk/source/app-extension/bootstrap.js
+++ b/addon-sdk/source/app-extension/bootstrap.js
@@ -252,16 +252,19 @@ function startup(data, reasonCode) {
           checkMemory: options.check_memory,
         }
       }
     });
 
     let module = cuddlefish.Module('sdk/loader/cuddlefish', cuddlefishURI);
     let require = cuddlefish.Require(loader, module);
 
+    // Init the 'sdk/webextension' module from the bootstrap addon parameter.
+    require("sdk/webextension").initFromBootstrapAddonParam(data);
+
     require('sdk/addon/runner').startup(reason, {
       loader: loader,
       main: main,
       prefsURI: rootURI + 'defaults/preferences/prefs.js'
     });
   } catch (error) {
     dump('Bootstrap error: ' +
          (error.message ? error.message : String(error)) + '\n' +
--- a/addon-sdk/source/lib/sdk/addon/bootstrap.js
+++ b/addon-sdk/source/lib/sdk/addon/bootstrap.js
@@ -118,27 +118,30 @@ Bootstrap.prototype = {
         paths: Object.assign({
           "": "resource://gre/modules/commonjs/",
           "devtools/": "resource://devtools/",
           "./": baseURI
         }, readPaths(id)),
         manifest: metadata,
         metadata: metadata,
         modules: {
-          "@test/options": {}
+          "@test/options": {},
         },
         noQuit: prefs.get(`extensions.${id}.sdk.test.no-quit`, false)
       });
       self.loader = loader;
 
       const module = Module("package.json", `${baseURI}package.json`);
       const require = Require(loader, module);
       const main = command === "test" ? "sdk/test/runner" : null;
       const prefsURI = `${baseURI}defaults/preferences/prefs.js`;
 
+      // Init the 'sdk/webextension' module from the bootstrap addon parameter.
+      require("sdk/webextension").initFromBootstrapAddonParam(addon);
+
       const { startup } = require("sdk/addon/runner");
       startup(reason, {loader, main, prefsURI});
     }.bind(this)).catch(error => {
       console.error(`Failed to start ${id} addon`, error);
       throw error;
     });
   },
   shutdown(addon, code) {
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/sdk/webextension.js
@@ -0,0 +1,43 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+module.metadata = {
+  "stability": "experimental"
+};
+
+let webExtension;
+let waitForWebExtensionAPI;
+
+module.exports = {
+  initFromBootstrapAddonParam(data) {
+    if (webExtension) {
+      throw new Error("'sdk/webextension' module has been already initialized");
+    }
+
+    webExtension = data.webExtension;
+  },
+
+  startup() {
+    if (!webExtension) {
+      return Promise.reject(new Error(
+        "'sdk/webextension' module is currently disabled. " +
+        "('hasEmbeddedWebExtension' option is missing or set to false)"
+      ));
+    }
+
+    // NOTE: calling `startup` more than once raises an "Embedded Extension already started"
+    // error, but given that SDK addons are going to have access to the startup method through
+    // an SDK module that can be required in any part of the addon, it will be nicer if any
+    // additional startup calls return the startup promise instead of raising an exception,
+    // so that the SDK addon can access the API object in the other addon modules without the
+    // need to manually pass this promise around.
+    if (!waitForWebExtensionAPI) {
+      waitForWebExtensionAPI = webExtension.startup();
+    }
+
+    return waitForWebExtensionAPI;
+  }
+};
--- a/addon-sdk/source/python-lib/cuddlefish/rdf.py
+++ b/addon-sdk/source/python-lib/cuddlefish/rdf.py
@@ -128,16 +128,21 @@ def gen_manifest(template_root_dir, targ
     manifest.set("em:creator",
                  target_cfg.get("author", ""))
     manifest.set("em:bootstrap", str(bootstrap).lower())
     # XPIs remain packed by default, but package.json can override that. The
     # RDF format accepts "true" as True, anything else as False. We expect
     # booleans in the .json file, not strings.
     manifest.set("em:unpack", "true" if target_cfg.get("unpack") else "false")
 
+    if target_cfg.get('hasEmbeddedWebExtension', False):
+        elem = dom.createElement("em:hasEmbeddedWebExtension");
+        elem.appendChild(dom.createTextNode("true"))
+        dom.documentElement.getElementsByTagName("Description")[0].appendChild(elem)
+
     for translator in target_cfg.get("translators", [ ]):
         elem = dom.createElement("em:translator");
         elem.appendChild(dom.createTextNode(translator))
         dom.documentElement.getElementsByTagName("Description")[0].appendChild(elem)
 
     for developer in target_cfg.get("developers", [ ]):
         elem = dom.createElement("em:developer");
         elem.appendChild(dom.createTextNode(developer))
--- a/addon-sdk/source/python-lib/cuddlefish/xpi.py
+++ b/addon-sdk/source/python-lib/cuddlefish/xpi.py
@@ -43,37 +43,42 @@ def build_xpi(template_root_dir, manifes
     if 'icon64' in harness_options:
         zf.write(os.path.join(str(harness_options['icon64'])), 'icon64.png')
         del harness_options['icon64']
 
     # chrome.manifest
     if os.path.isfile(os.path.join(pkgdir, 'chrome.manifest')):
       files_to_copy['chrome.manifest'] = os.path.join(pkgdir, 'chrome.manifest')
 
-    # chrome folder (would contain content, skin, and locale folders typically)
-    folder = 'chrome'
-    if os.path.exists(os.path.join(pkgdir, folder)):
-      dirs_to_create.add('chrome')
-      # cp -r folder
-      abs_dirname = os.path.join(pkgdir, folder)
-      for dirpath, dirnames, filenames in os.walk(abs_dirname):
+    def add_special_dir(folder):
+      if os.path.exists(os.path.join(pkgdir, folder)):
+        dirs_to_create.add(folder)
+        # cp -r folder
+        abs_dirname = os.path.join(pkgdir, folder)
+        for dirpath, dirnames, filenames in os.walk(abs_dirname):
           goodfiles = list(filter_filenames(filenames, IGNORED_FILES))
           dirnames[:] = filter_dirnames(dirnames)
           for dirname in dirnames:
             arcpath = make_zipfile_path(template_root_dir,
                                         os.path.join(dirpath, dirname))
             dirs_to_create.add(arcpath)
           for filename in goodfiles:
               abspath = os.path.join(dirpath, filename)
               arcpath = ZIPSEP.join(
                   [folder,
                    make_zipfile_path(abs_dirname, os.path.join(dirpath, filename)),
                    ])
               files_to_copy[str(arcpath)] = str(abspath)
 
+
+    # chrome folder (would contain content, skin, and locale folders typically)
+    add_special_dir('chrome')
+    # optionally include a `webextension/` dir from the add-on dir.
+    add_special_dir('webextension')
+
     for dirpath, dirnames, filenames in os.walk(template_root_dir):
         if template_root_dir == dirpath:
             filenames = list(filter_filenames(filenames, IGNORED_TOP_LVL_FILES))
         filenames = list(filter_filenames(filenames, IGNORED_FILES))
         dirnames[:] = filter_dirnames(dirnames)
         for dirname in dirnames:
             arcpath = make_zipfile_path(template_root_dir,
                                         os.path.join(dirpath, dirname))
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/embedded-webextension/main.js
@@ -0,0 +1,159 @@
+const tabs = require("sdk/tabs");
+const webExtension = require('sdk/webextension');
+
+exports.testEmbeddedWebExtensionModuleInitializedException = function (assert) {
+  let actualErr;
+
+  assert.throws(
+    () => webExtension.initFromBootstrapAddonParam({webExtension: null}),
+    /'sdk\/webextension' module has been already initialized/,
+    "Got the expected exception if the module is initialized twice"
+  );
+};
+
+exports.testEmbeddedWebExtensionBackgroungPage = function* (assert) {
+  try {
+    const api = yield webExtension.startup();
+    assert.ok(api, `webextension waitForStartup promise successfully resolved`);
+
+    const apiSecondStartup = yield webExtension.startup();
+    assert.equal(api, apiSecondStartup, "Got the same API object from the second startup call");
+
+    const {browser} = api;
+
+    let messageListener;
+    let waitForBackgroundPageMessage = new Promise((resolve, reject) => {
+      let numExpectedMessage = 2;
+      messageListener = (msg, sender, sendReply) => {
+        numExpectedMessage -= 1;
+        if (numExpectedMessage == 1) {
+          assert.equal(msg, "bg->sdk message",
+                       "Got the expected message from the background page");
+          sendReply("sdk reply");
+        } else if (numExpectedMessage == 0) {
+          assert.equal(msg, "sdk reply",
+                       "The background page received the expected reply message");
+          resolve();
+        } else {
+          console.error("Unexpected message received", {msg,sender, numExpectedMessage});
+          assert.ok(false, `unexpected message received`);
+          reject();
+        }
+      };
+      browser.runtime.onMessage.addListener(messageListener);
+    });
+
+    let portListener;
+    let waitForBackgroundPagePort = new Promise((resolve, reject) => {
+      portListener = (port) => {
+        let numExpectedMessages = 2;
+        port.onMessage.addListener((msg) => {
+          numExpectedMessages -= 1;
+
+          if (numExpectedMessages == 1) {
+            // Check that the legacy context has been able to receive the first port message
+            // and reply with a port message to the background page.
+            assert.equal(msg, "bg->sdk port message",
+                         "Got the expected port message from the background page");
+            port.postMessage("sdk->bg port message");
+          } else if (numExpectedMessages == 0) {
+            // Check that the background page has received the above port message.
+            assert.equal(msg, "bg received sdk->bg port message",
+                         "The background page received the expected port message");
+          }
+        });
+
+        port.onDisconnect.addListener(() => {
+          assert.equal(numExpectedMessages, 0, "Got the expected number of port messages");
+          resolve();
+        });
+      };
+      browser.runtime.onConnect.addListener(portListener);
+    });
+
+    yield Promise.all([
+      waitForBackgroundPageMessage,
+      waitForBackgroundPagePort,
+    ]).then(() => {
+      browser.runtime.onMessage.removeListener(messageListener);
+      browser.runtime.onConnect.removeListener(portListener);
+    });
+
+  } catch (err) {
+    assert.fail(`Unexpected webextension startup exception: ${err} - ${err.stack}`);
+  }
+};
+
+exports.testEmbeddedWebExtensionContentScript = function* (assert, done) {
+  try {
+    const {browser} = yield webExtension.startup();
+    assert.ok(browser, `webextension startup promise resolved successfully to the API object`);
+
+    let messageListener;
+    let waitForContentScriptMessage = new Promise((resolve, reject) => {
+      let numExpectedMessage = 2;
+      messageListener = (msg, sender, sendReply) => {
+        numExpectedMessage -= 1;
+        if (numExpectedMessage == 1) {
+          assert.equal(msg, "content script->sdk message",
+                       "Got the expected message from the content script");
+          sendReply("sdk reply");
+        } else if (numExpectedMessage == 0) {
+          assert.equal(msg, "sdk reply",
+                       "The content script received the expected reply message");
+          resolve();
+        } else {
+          console.error("Unexpected message received", {msg,sender, numExpectedMessage});
+          assert.ok(false, `unexpected message received`);
+          reject();
+        }
+      };
+      browser.runtime.onMessage.addListener(messageListener);
+    });
+
+    let portListener;
+    let waitForContentScriptPort = new Promise((resolve, reject) => {
+      portListener = (port) => {
+        let numExpectedMessages = 2;
+        port.onMessage.addListener((msg) => {
+          numExpectedMessages -= 1;
+
+          if (numExpectedMessages == 1) {
+            assert.equal(msg, "content script->sdk port message",
+                         "Got the expected message from the content script port");
+            port.postMessage("sdk->content script port message");
+          } else if (numExpectedMessages == 0) {
+            assert.equal(msg, "content script received sdk->content script port message",
+                         "The content script received the expected port message");
+          }
+        });
+        port.onDisconnect.addListener(() => {
+          assert.equal(numExpectedMessages, 0, "Got the epected number of port messages");
+          resolve();
+        });
+      };
+      browser.runtime.onConnect.addListener(portListener);
+    });
+
+    let url = "data:text/html;charset=utf-8,<h1>Test Page</h1>";
+
+    var openedTab;
+    tabs.once('open', function onOpen(tab) {
+      openedTab = tab;
+    });
+    tabs.open(url);
+
+    yield Promise.all([
+      waitForContentScriptMessage,
+      waitForContentScriptPort,
+    ]).then(() => {
+      browser.runtime.onMessage.removeListener(messageListener);
+      browser.runtime.onConnect.removeListener(portListener);
+      openedTab.close();
+    });
+  } catch (err) {
+    assert.fail(`Unexpected webextension startup exception: ${err} - ${err.stack}`);
+  }
+};
+
+require("sdk/test/runner").runTestsFromModule(module);
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/embedded-webextension/package.json
@@ -0,0 +1,6 @@
+{
+  "id": "embedded-webextension@jetpack",
+  "version": "0.1.0",
+  "main": "./main.js",
+  "hasEmbeddedWebExtension": true
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/embedded-webextension/webextension/background-page.js
@@ -0,0 +1,10 @@
+browser.runtime.sendMessage("bg->sdk message", (reply) => {
+  browser.runtime.sendMessage(reply);
+});
+
+let port = browser.runtime.connect();
+port.onMessage.addListener((msg) => {
+  port.postMessage(`bg received ${msg}`);
+  port.disconnect();
+});
+port.postMessage("bg->sdk port message");
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/embedded-webextension/webextension/content-script.js
@@ -0,0 +1,10 @@
+browser.runtime.sendMessage("content script->sdk message", (reply) => {
+  browser.runtime.sendMessage(reply);
+});
+
+let port = browser.runtime.connect();
+port.onMessage.addListener((msg) => {
+  port.postMessage(`content script received ${msg}`);
+  port.disconnect();
+});
+port.postMessage("content script->sdk port message");
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/embedded-webextension/webextension/manifest.json
@@ -0,0 +1,18 @@
+{
+  "name": "Test SDK Embedded WebExtension",
+  "description": "",
+  "version": "0.1.0",
+  "applications": {
+    "gecko": {
+      "id": "embedded-webextension@jetpack"
+    }
+  },
+  "manifest_version": 2,
+  "permissions": ["tabs"],
+  "background": {
+    "scripts": ["background-page.js"]
+  },
+  "content_scripts": [
+    {"matches": ["<all_urls>"], "js": ["content-script.js"]}
+  ]
+}
--- a/addon-sdk/source/test/addons/jetpack-addon.ini
+++ b/addon-sdk/source/test/addons/jetpack-addon.ini
@@ -12,16 +12,17 @@ skip-if = true
 [e10s-content.xpi]
 skip-if = true
 [e10s-l10n.xpi]
 skip-if = true
 [e10s-remote.xpi]
 skip-if = true
 [e10s-tabs.xpi]
 skip-if = true
+[embedded-webextension.xpi]
 [l10n.xpi]
 [l10n-properties.xpi]
 [layout-change.xpi]
 [main.xpi]
 [name-in-numbers.xpi]
 [name-in-numbers-plus.xpi]
 [packaging.xpi]
 [packed.xpi]
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -926,17 +926,19 @@ BrowserGlue.prototype = {
         SCALING_PROBE_NAME = "DISPLAY_SCALING_OSX";
         break;
       case "linux":
         SCALING_PROBE_NAME = "DISPLAY_SCALING_LINUX";
         break;
     }
     if (SCALING_PROBE_NAME) {
       let scaling = aWindow.devicePixelRatio * 100;
-      Services.telemetry.getHistogramById(SCALING_PROBE_NAME).add(scaling);
+      try {
+        Services.telemetry.getHistogramById(SCALING_PROBE_NAME).add(scaling);
+      } catch (ex) {}
     }
   },
 
   // the first browser window has finished initializing
   _onFirstWindowLoaded: function BG__onFirstWindowLoaded(aWindow) {
     // Initialize PdfJs when running in-process and remote. This only
     // happens once since PdfJs registers global hooks. If the PdfJs
     // extension is installed the init method below will be overridden
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -1285,18 +1285,18 @@
               this.query = event.target.oneOffSearchQuery || event.target.value;
               break;
             case "popupshowing":
               this._rebuild();
               break;
             case "popuphidden":
               Services.tm.mainThread.dispatch(() => {
                 this.selectedButton = null;
+                this._contextEngine = null;
               }, Ci.nsIThread.DISPATCH_NORMAL);
-              this._contextEngine = null;
               break;
           }
         ]]></body>
       </method>
 
       <method name="showSettings">
         <body><![CDATA[
           BrowserUITelemetry.countSearchSettingsEvent(this.telemetryOrigin);
--- a/browser/components/search/test/browser.ini
+++ b/browser/components/search/test/browser.ini
@@ -24,16 +24,17 @@ support-files =
 [browser_contextSearchTabPosition.js]
 skip-if = os == "mac" # bug 967013
 [browser_google.js]
 [browser_google_codes.js]
 [browser_google_behavior.js]
 [browser_healthreport.js]
 [browser_hiddenOneOffs_cleanup.js]
 [browser_hiddenOneOffs_diacritics.js]
+[browser_oneOffContextMenu.js]
 [browser_oneOffHeader.js]
 [browser_private_search_perwindowpb.js]
 [browser_yahoo.js]
 [browser_yahoo_behavior.js]
 [browser_abouthome_behavior.js]
 skip-if = true # Bug ??????, Bug 1100301 - leaks windows until shutdown when --run-by-dir
 [browser_aboutSearchReset.js]
 [browser_searchbar_openpopup.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/search/test/browser_oneOffContextMenu.js
@@ -0,0 +1,99 @@
+"use strict";
+
+const TEST_ENGINE_NAME = "Foo";
+const TEST_ENGINE_BASENAME = "testEngine.xml";
+
+const searchbar = document.getElementById("searchbar");
+const searchPopup = document.getElementById("PopupSearchAutoComplete");
+const searchIcon = document.getAnonymousElementByAttribute(
+  searchbar, "anonid", "searchbar-search-button"
+);
+const oneOffBinding = document.getAnonymousElementByAttribute(
+  searchPopup, "anonid", "search-one-off-buttons"
+);
+const contextMenu = document.getAnonymousElementByAttribute(
+  oneOffBinding, "anonid", "search-one-offs-context-menu"
+);
+const oneOffButtons = document.getAnonymousElementByAttribute(
+  oneOffBinding, "anonid", "search-panel-one-offs"
+);
+const searchInNewTabMenuItem = document.getAnonymousElementByAttribute(
+  oneOffBinding, "anonid", "search-one-offs-context-open-in-new-tab"
+);
+
+add_task(function* init() {
+  yield promiseNewEngine(TEST_ENGINE_BASENAME, {
+    setAsCurrent: false,
+  });
+});
+
+add_task(function* extendedTelemetryDisabled() {
+  yield SpecialPowers.pushPrefEnv({set: [["toolkit.telemetry.enabled", false]]});
+  yield doTest();
+  checkTelemetry("other");
+});
+
+add_task(function* extendedTelemetryEnabled() {
+  yield SpecialPowers.pushPrefEnv({set: [["toolkit.telemetry.enabled", true]]});
+  yield doTest();
+  checkTelemetry("other-" + TEST_ENGINE_NAME);
+});
+
+function* doTest() {
+  // Open the popup.
+  let promise = promiseEvent(searchPopup, "popupshown");
+  info("Opening search panel");
+  EventUtils.synthesizeMouseAtCenter(searchIcon, {});
+  yield promise;
+
+  // Get the one-off button for the test engine.
+  let oneOffButton;
+  for (let node of oneOffButtons.childNodes) {
+    if (node.engine && node.engine.name == TEST_ENGINE_NAME) {
+      oneOffButton = node;
+      break;
+    }
+  }
+  Assert.notEqual(oneOffButton, undefined,
+                  "One-off for test engine should exist");
+
+  // Open the context menu on the one-off.
+  promise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
+  EventUtils.synthesizeMouseAtCenter(oneOffButton, {
+    type: "contextmenu",
+    button: 2,
+  });
+  yield promise;
+
+  // Click the Search in New Tab menu item.
+  promise = BrowserTestUtils.waitForNewTab(gBrowser);
+  EventUtils.synthesizeMouseAtCenter(searchInNewTabMenuItem, {});
+  let tab = yield promise;
+
+  // Check the loaded tab.
+  Assert.equal(tab.linkedBrowser.currentURI.spec,
+               "http://mochi.test:8888/browser/browser/components/search/test/",
+               "Expected search tab should have loaded");
+
+  yield BrowserTestUtils.removeTab(tab);
+
+  // Move the cursor out of the panel area to avoid messing with other tests.
+  yield EventUtils.synthesizeNativeMouseMove(searchbar);
+}
+
+function checkTelemetry(expectedEngineName) {
+  let propertyPath = [
+    "countableEvents",
+    "__DEFAULT__",
+    "search-oneoff",
+    expectedEngineName + ".oneoff-context-searchbar",
+    "unknown",
+    "tab-background",
+  ];
+  let telem = BrowserUITelemetry.getToolbarMeasures();
+  for (let prop of propertyPath) {
+    Assert.ok(prop in telem, "Property " + prop + " should be in the telemetry");
+    telem = telem[prop];
+  }
+  Assert.equal(telem, 1, "Click count");
+}
--- a/devtools/client/debugger/new/bundle.js
+++ b/devtools/client/debugger/new/bundle.js
@@ -1,9 +1,9 @@
-// Generated from: 30002d3cfc4341840af847af9eb2c31cab18abb5 Move some of editor-select.js test into editor-highlight.js to make tests more focused (and avoid timeouts on linux debug) (#746)
+// Generated from: 7c393c99dd82e9b181dab64ff474ee6ca9dc1c3f Revert "Add search input"
 
 var Debugger =
 /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
 /******/
 /******/ 	// The require function
 /******/ 	function __webpack_require__(moduleId) {
@@ -93,32 +93,32 @@ var Debugger =
 	
 	var _require5 = __webpack_require__(96);
 	
 	var getClient = _require5.getClient;
 	var connectClients = _require5.connectClients;
 	var startDebugging = _require5.startDebugging;
 	
 	var firefox = __webpack_require__(98);
-	var configureStore = __webpack_require__(179);
-	var reducers = __webpack_require__(187);
-	var selectors = __webpack_require__(198);
-	
-	var Tabs = __webpack_require__(205);
-	var App = __webpack_require__(211);
+	var configureStore = __webpack_require__(180);
+	var reducers = __webpack_require__(188);
+	var selectors = __webpack_require__(199);
+	
+	var Tabs = __webpack_require__(206);
+	var App = __webpack_require__(212);
 	
 	var createStore = configureStore({
 	  log: getValue("logging.actions"),
 	  makeThunkArgs: (args, state) => {
 	    return Object.assign({}, args, { client: getClient(state) });
 	  }
 	});
 	
 	var store = createStore(combineReducers(reducers));
-	var actions = bindActionCreators(__webpack_require__(213), store.dispatch);
+	var actions = bindActionCreators(__webpack_require__(214), store.dispatch);
 	
 	if (isDevelopment()) {
 	  AppConstants.DEBUG_JS_MODULES = true;
 	  injectGlobals({ store });
 	}
 	
 	// Expose the bound actions so external things can do things like
 	// selecting a source.
@@ -164,27 +164,27 @@ var Debugger =
 	if (connTarget) {
 	  startDebugging(connTarget, actions).then(tabs => {
 	    actions.newTabs(tabs);
 	    actions.selectTab({ id: connTarget.param });
 	    renderRoot(App);
 	  });
 	} else if (isFirefoxPanel()) {
 	  (function () {
-	    var sourceMap = __webpack_require__(215);
+	    var sourceMap = __webpack_require__(216);
 	
 	    module.exports = {
 	      bootstrap: _ref => {
 	        var threadClient = _ref.threadClient;
 	        var tabTarget = _ref.tabTarget;
 	
 	        firefox.setThreadClient(threadClient);
 	        firefox.setTabTarget(tabTarget);
-	        firefox.initPage(actions);
 	        renderRoot(App);
+	        return firefox.initPage(actions);
 	      },
 	      destroy: () => {
 	        unmountRoot();
 	        sourceMap.destroy();
 	      },
 	      store: store,
 	      actions: actions,
 	      selectors: selectors,
@@ -10169,17 +10169,17 @@ var Debugger =
 
 	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 _require = __webpack_require__(97);
 	
 	var Task = _require.Task;
 	
 	var firefox = __webpack_require__(98);
-	var chrome = __webpack_require__(172);
+	var chrome = __webpack_require__(173);
 	
 	var _require2 = __webpack_require__(45);
 	
 	var debugGlobal = _require2.debugGlobal;
 	
 	
 	var clientType = void 0;
 	function getClient() {
@@ -10321,16 +10321,20 @@ var Debugger =
 	var setupCommands = _require6.setupCommands;
 	var clientCommands = _require6.clientCommands;
 	
 	var _require7 = __webpack_require__(171);
 	
 	var setupEvents = _require7.setupEvents;
 	var clientEvents = _require7.clientEvents;
 	
+	var _require8 = __webpack_require__(172);
+	
+	var createSource = _require8.createSource;
+	
 	
 	var debuggerClient = null;
 	var threadClient = null;
 	var tabTarget = null;
 	
 	function getThreadClient() {
 	  return threadClient;
 	}
@@ -10413,26 +10417,34 @@ var Debugger =
 	  tabTarget.on("navigate", actions.navigated);
 	
 	  // Listen to all the requested events.
 	  setupEvents({ threadClient, actions });
 	  Object.keys(clientEvents).forEach(eventName => {
 	    threadClient.addListener(eventName, clientEvents[eventName]);
 	  });
 	
-	  threadClient.reconfigure({
-	    "useSourceMaps": false,
-	    "autoBlackBox": false
-	  });
-	
-	  // In Firefox, we need to initially request all of the sources which
-	  // makes the server iterate over them and fire individual
-	  // `newSource` notifications. We don't need to do anything with the
-	  // response since `newSource` notifications are fired.
-	  threadClient.getSources();
+	  // In Firefox, we need to initially request all of the sources. This
+	  // usually fires off individual `newSource` notifications as the
+	  // debugger finds them, but there may be existing sources already in
+	  // the debugger (if it's paused already, or if loading the page from
+	  // bfcache) so explicity fire `newSource` events for all returned
+	  // sources.
+	  return threadClient.getSources().then(_ref => {
+	    var sources = _ref.sources;
+	
+	    actions.newSources(sources.map(createSource));
+	
+	    // If the threadClient is already paused, make sure to show a
+	    // paused state.
+	    var pausedPacket = threadClient.getLastPausePacket();
+	    if (pausedPacket) {
+	      clientEvents.paused(null, pausedPacket);
+	    }
+	  });
 	}
 	
 	module.exports = {
 	  connectClient,
 	  connectTab,
 	  clientCommands,
 	  getThreadClient,
 	  setThreadClient,
@@ -19868,33 +19880,64 @@ var Debugger =
 	
 	  return function paused(_x, _x2) {
 	    return _ref.apply(this, arguments);
 	  };
 	})();
 	
 	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) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
 	
+	var _require = __webpack_require__(172);
+	
+	var createFrame = _require.createFrame;
+	var createSource = _require.createSource;
+	
+	
+	var CALL_STACK_PAGE_SIZE = 1000;
+	
+	var threadClient = void 0;
+	var actions = void 0;
+	
+	function setupEvents(dependencies) {
+	  threadClient = dependencies.threadClient;
+	  actions = dependencies.actions;
+	}
+	
+	function resumed(_, packet) {
+	  actions.resumed(packet);
+	}
+	
+	function newSource(_, _ref2) {
+	  var source = _ref2.source;
+	
+	  actions.newSource(createSource(source));
+	}
+	
+	var clientEvents = {
+	  paused,
+	  resumed,
+	  newSource
+	};
+	
+	module.exports = {
+	  setupEvents,
+	  clientEvents
+	};
+
+/***/ },
+/* 172 */
+/***/ function(module, exports, __webpack_require__) {
+
 	var _require = __webpack_require__(114);
 	
 	var Source = _require.Source;
 	var Frame = _require.Frame;
 	var Location = _require.Location;
 	
 	
-	var CALL_STACK_PAGE_SIZE = 1000;
-	var threadClient = void 0;
-	var actions = void 0;
-	var evalIndex = 1;
-	
-	function setupEvents(dependencies) {
-	  threadClient = dependencies.threadClient;
-	  actions = dependencies.actions;
-	}
-	
 	function createFrame(frame) {
 	  var title = void 0;
 	  if (frame.type == "call") {
 	    var c = frame.callee;
 	    title = c.name || c.userDisplayName || c.displayName || "(anonymous)";
 	  } else {
 	    title = "(" + frame.type + ")";
 	  }
@@ -19907,77 +19950,63 @@ var Debugger =
 	      line: frame.where.line,
 	      column: frame.where.column
 	    }),
 	    this: frame.this,
 	    scope: frame.environment
 	  });
 	}
 	
-	function resumed(_, packet) {
-	  actions.resumed(packet);
-	}
-	
-	function newSource(_, packet) {
-	  var source = packet.source;
-	
+	var evalIndex = 1;
+	function createSource(source) {
 	  if (!source.url) {
 	    source.url = `SOURCE${ evalIndex++ }`;
 	  }
 	
-	  actions.newSource(Source({
+	  return Source({
 	    id: source.actor,
 	    url: source.url,
 	    isPrettyPrinted: false,
 	    sourceMapURL: source.sourceMapURL
-	  }));
-	}
-	
-	var clientEvents = {
-	  paused,
-	  resumed,
-	  newSource
-	};
-	
-	module.exports = {
-	  setupEvents,
-	  clientEvents
-	};
-
-/***/ },
-/* 172 */
+	  });
+	}
+	
+	module.exports = { createFrame, createSource };
+
+/***/ },
+/* 173 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* eslint-disable */
 	
-	var _require = __webpack_require__(173);
+	var _require = __webpack_require__(174);
 	
 	var connect = _require.connect;
 	
 	var defer = __webpack_require__(112);
 	
 	var _require2 = __webpack_require__(114);
 	
 	var Tab = _require2.Tab;
 	
 	var _require3 = __webpack_require__(46);
 	
 	var isEnabled = _require3.isEnabled;
 	var getValue = _require3.getValue;
 	
-	var _require4 = __webpack_require__(174);
+	var _require4 = __webpack_require__(175);
 	
 	var networkRequest = _require4.networkRequest;
 	
-	var _require5 = __webpack_require__(177);
+	var _require5 = __webpack_require__(178);
 	
 	var setupCommands = _require5.setupCommands;
 	var clientCommands = _require5.clientCommands;
 	
-	var _require6 = __webpack_require__(178);
+	var _require6 = __webpack_require__(179);
 	
 	var setupEvents = _require6.setupEvents;
 	var clientEvents = _require6.clientEvents;
 	var pageEvents = _require6.pageEvents;
 	
 	// TODO: figure out a way to avoid patching native prototypes.
 	// Unfortunately the Chrome client requires it to work.
 	
@@ -20057,26 +20086,26 @@ var Debugger =
 	  connectClient,
 	  clientCommands,
 	  connectNode,
 	  connectTab,
 	  initPage
 	};
 
 /***/ },
-/* 173 */
+/* 174 */
 /***/ function(module, exports) {
 
 	module.exports = {};
 
 /***/ },
-/* 174 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var _require = __webpack_require__(175);
+/* 175 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var _require = __webpack_require__(176);
 	
 	var log = _require.log;
 	
 	
 	function networkRequest(url) {
 	  return Promise.race([fetch(`/get?url=${ url }`).then(res => {
 	    if (res.status >= 200 && res.status < 300) {
 	      return res.json();
@@ -20088,17 +20117,17 @@ var Debugger =
 	  })]);
 	}
 	
 	module.exports = {
 	  networkRequest
 	};
 
 /***/ },
-/* 175 */
+/* 176 */
 /***/ function(module, exports, __webpack_require__) {
 
 	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 asyncMap = (() => {
 	  var _ref = _asyncToGenerator(function* (items, callback) {
 	    var newItems = [];
 	    for (var item of items) {
@@ -20131,17 +20160,17 @@ var Debugger =
 	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) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
 	
 	/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
-	var co = __webpack_require__(176);
+	var co = __webpack_require__(177);
 	
 	var _require = __webpack_require__(46);
 	
 	var isDevelopment = _require.isDevelopment;
 	
 	var defer = __webpack_require__(112);
 	
 	function asPaused(client, func) {
@@ -20333,17 +20362,17 @@ var Debugger =
 	  mapObject,
 	  compose,
 	  log,
 	  updateObj,
 	  throttle
 	};
 
 /***/ },
-/* 176 */
+/* 177 */
 /***/ function(module, exports) {
 
 	
 	/**
 	 * slice() reference.
 	 */
 	
 	var slice = Array.prototype.slice;
@@ -20576,17 +20605,17 @@ var Debugger =
 	 */
 	
 	function isObject(val) {
 	  return Object == val.constructor;
 	}
 
 
 /***/ },
-/* 177 */
+/* 178 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var _require = __webpack_require__(114);
 	
 	var BreakpointResult = _require.BreakpointResult;
 	var Location = _require.Location;
 	
 	
@@ -20700,17 +20729,17 @@ var Debugger =
 	};
 	
 	module.exports = {
 	  setupCommands,
 	  clientCommands
 	};
 
 /***/ },
-/* 178 */
+/* 179 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var paused = (() => {
 	  var _ref = _asyncToGenerator(function* (callFrames, reason, data, hitBreakpoints, asyncStackTrace) {
 	    var frames = callFrames.map(function (frame) {
 	      return Frame({
 	        id: frame.callFrameId,
 	        displayName: frame.functionName,
@@ -20810,46 +20839,46 @@ var Debugger =
 	
 	module.exports = {
 	  setupEvents,
 	  pageEvents,
 	  clientEvents
 	};
 
 /***/ },
-/* 179 */
+/* 180 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* 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/. */
 	/* global window */
 	
 	var _require = __webpack_require__(2);
 	
 	var createStore = _require.createStore;
 	var applyMiddleware = _require.applyMiddleware;
 	
-	var _require2 = __webpack_require__(180);
+	var _require2 = __webpack_require__(181);
 	
 	var waitUntilService = _require2.waitUntilService;
 	
-	var _require3 = __webpack_require__(181);
+	var _require3 = __webpack_require__(182);
 	
 	var log = _require3.log;
 	
-	var _require4 = __webpack_require__(182);
+	var _require4 = __webpack_require__(183);
 	
 	var history = _require4.history;
 	
-	var _require5 = __webpack_require__(183);
+	var _require5 = __webpack_require__(184);
 	
 	var promise = _require5.promise;
 	
-	var _require6 = __webpack_require__(186);
+	var _require6 = __webpack_require__(187);
 	
 	var thunk = _require6.thunk;
 	
 	/**
 	 * This creates a dispatcher with all the standard middleware in place
 	 * that all code requires. It can also be optionally configured in
 	 * various ways, such as logging and recording.
 	 *
@@ -20887,17 +20916,17 @@ var Debugger =
 	  var devtoolsExt = typeof window === "object" && window.devToolsExtension ? window.devToolsExtension() : f => f;
 	
 	  return applyMiddleware.apply(undefined, middleware)(devtoolsExt(createStore));
 	};
 	
 	module.exports = configureStore;
 
 /***/ },
-/* 180 */
+/* 181 */
 /***/ function(module, exports) {
 
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	/**
@@ -20957,17 +20986,17 @@ var Debugger =
 	    checkPending(action);
 	    return result;
 	  };
 	}
 	exports.waitUntilService = waitUntilService;
 
 
 /***/ },
-/* 181 */
+/* 182 */
 /***/ function(module, exports) {
 
 	/**
 	 * A middleware that logs all actions coming through the system
 	 * to the console.
 	 */
 	function log(_ref) {
 	  var dispatch = _ref.dispatch;
@@ -20979,17 +21008,17 @@ var Debugger =
 	    console.log(`[DISPATCH ${ action.type }]`, action, truncatedActionText);
 	    next(action);
 	  };
 	}
 	
 	exports.log = log;
 
 /***/ },
-/* 182 */
+/* 183 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* 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/. */
 	
 	var _require = __webpack_require__(46);
 	
@@ -21013,32 +21042,32 @@ var Debugger =
 	    return next => action => {
 	      log.push(action);
 	      next(action);
 	    };
 	  };
 	};
 
 /***/ },
-/* 183 */
-/***/ function(module, exports, __webpack_require__) {
-
-	/* 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/. */
-	
-	var uuidgen = __webpack_require__(184).uuid;
+/* 184 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* 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/. */
+	
+	var uuidgen = __webpack_require__(185).uuid;
 	var defer = __webpack_require__(112);
 	
-	var _require = __webpack_require__(175);
+	var _require = __webpack_require__(176);
 	
 	var entries = _require.entries;
 	var toObject = _require.toObject;
 	
-	var _require2 = __webpack_require__(185);
+	var _require2 = __webpack_require__(186);
 	
 	var executeSoon = _require2.executeSoon;
 	
 	
 	var PROMISE = exports.PROMISE = "@@dispatch/promise";
 	
 	function promiseMiddleware(_ref) {
 	  var dispatch = _ref.dispatch;
@@ -21080,30 +21109,30 @@ var Debugger =
 	    });
 	    return deferred.promise;
 	  };
 	}
 	
 	exports.promise = promiseMiddleware;
 
 /***/ },
-/* 184 */
+/* 185 */
 /***/ function(module, exports) {
 
 	
 	let i = 1;
 	function uuid() {
 	  return 'not-really-uuid' + (i++);
 	}
 	
 	module.exports = { uuid };
 
 
 /***/ },
-/* 185 */
+/* 186 */
 /***/ function(module, exports) {
 
 	function reportException(who, exception) {
 	  var msg = who + " threw an exception: ";
 	  console.error(msg, exception);
 	}
 	
 	function assert(condition, message) {
@@ -21120,17 +21149,17 @@ var Debugger =
 	
 	module.exports = {
 	  reportException,
 	  executeSoon,
 	  assert
 	};
 
 /***/ },
-/* 186 */
+/* 187 */
 /***/ function(module, exports) {
 
 	
 	/**
 	 * A middleware that allows thunks (functions) to be dispatched. If
 	 * it's a thunk, it is called with an argument that contains
 	 * `dispatch`, `getState`, and any additional args passed in via the
 	 * middleware constructure. This allows the action to create multiple
@@ -21146,48 +21175,48 @@ var Debugger =
 	    return next => action => {
 	      return typeof action === "function" ? action(makeArgs ? makeArgs(args, getState()) : args) : next(action);
 	    };
 	  };
 	}
 	exports.thunk = thunk;
 
 /***/ },
-/* 187 */
-/***/ function(module, exports, __webpack_require__) {
-
-	/* 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/. */
-	
-	var eventListeners = __webpack_require__(188);
-	var sources = __webpack_require__(190);
-	var breakpoints = __webpack_require__(194);
-	var asyncRequests = __webpack_require__(195);
-	var tabs = __webpack_require__(196);
-	var pause = __webpack_require__(197);
+/* 188 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* 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/. */
+	
+	var eventListeners = __webpack_require__(189);
+	var sources = __webpack_require__(191);
+	var breakpoints = __webpack_require__(195);
+	var asyncRequests = __webpack_require__(196);
+	var tabs = __webpack_require__(197);
+	var pause = __webpack_require__(198);
 	
 	module.exports = {
 	  eventListeners,
 	  sources: sources.update,
 	  breakpoints: breakpoints.update,
 	  pause: pause.update,
 	  asyncRequests,
 	  tabs
 	};
 
 /***/ },
-/* 188 */
-/***/ function(module, exports, __webpack_require__) {
-
-	/* 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/. */
-	
-	var constants = __webpack_require__(189);
+/* 189 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* 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/. */
+	
+	var constants = __webpack_require__(190);
 	
 	var initialState = {
 	  activeEventNames: [],
 	  listeners: [],
 	  fetchingListeners: false
 	};
 	
 	function update() {
@@ -21214,17 +21243,17 @@ var Debugger =
 	  }
 	
 	  return state;
 	}
 	
 	module.exports = update;
 
 /***/ },
-/* 189 */
+/* 190 */
 /***/ function(module, exports) {
 
 	/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
@@ -21262,28 +21291,28 @@ var Debugger =
 	exports.SELECT_FRAME = "SELECT_FRAME";
 	exports.LOAD_OBJECT_PROPERTIES = "LOAD_OBJECT_PROPERTIES";
 	exports.ADD_EXPRESSION = "ADD_EXPRESSION";
 	exports.EVALUATE_EXPRESSION = "EVALUATE_EXPRESSION";
 	exports.UPDATE_EXPRESSION = "UPDATE_EXPRESSION";
 	exports.DELETE_EXPRESSION = "DELETE_EXPRESSION";
 
 /***/ },
-/* 190 */
+/* 191 */
 /***/ function(module, exports, __webpack_require__) {
 
 	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
 	
 	/* 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/. */
 	
-	var fromJS = __webpack_require__(191);
-	var I = __webpack_require__(192);
-	var makeRecord = __webpack_require__(193);
+	var fromJS = __webpack_require__(192);
+	var I = __webpack_require__(193);
+	var makeRecord = __webpack_require__(194);
 	
 	var State = makeRecord({
 	  sources: I.Map(),
 	  selectedLocation: undefined,
 	  pendingSelectedLocation: undefined,
 	  sourcesText: I.Map(),
 	  sourceMaps: I.Map(),
 	  tabs: I.List([])
@@ -21295,21 +21324,16 @@ var Debugger =
 	
 	  switch (action.type) {
 	    case "ADD_SOURCE":
 	      {
 	        var _source = action.source;
 	        return state.mergeIn(["sources", action.source.id], _source);
 	      }
 	
-	    case "ADD_SOURCES":
-	      return state.mergeIn(["sources"], I.Map(action.sources.map(source => {
-	        return [source.id, fromJS(source)];
-	      })));
-	
 	    case "LOAD_SOURCE_MAP":
 	      if (action.status == "done") {
 	        return state.mergeIn(["sourceMaps", action.source.id], action.value.sourceMap);
 	      }
 	      break;
 	
 	    case "SELECT_SOURCE":
 	      return state.set("selectedLocation", {
@@ -21523,22 +21547,22 @@ var Debugger =
 	  getSelectedSource,
 	  getSelectedLocation,
 	  getPendingSelectedLocation,
 	  getSourceMap,
 	  getPrettySource
 	};
 
 /***/ },
-/* 191 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	
-	var Immutable = __webpack_require__(192);
+/* 192 */
+/***/ function(module, exports, __webpack_require__) {
+
+	
+	
+	var Immutable = __webpack_require__(193);
 	
 	// When our app state is fully types, we should be able to get rid of
 	// this function. This is only temporarily necessary to support
 	// converting typed objects to immutable.js, which usually happens in
 	// reducers.
 	function fromJS(value) {
 	  if (Array.isArray(value)) {
 	    return Immutable.Seq(value).map(fromJS).toList();
@@ -21567,17 +21591,17 @@ var Debugger =
 	  // it's a plain object because we might be objects from other JS
 	  // contexts so `Object !== Object`.
 	  return Immutable.Seq(value).map(fromJS).toMap();
 	}
 	
 	module.exports = fromJS;
 
 /***/ },
-/* 192 */
+/* 193 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/**
 	 *  Copyright (c) 2014-2015, Facebook, Inc.
 	 *  All rights reserved.
 	 *
 	 *  This source code is licensed under the BSD-style license found in the
 	 *  LICENSE file in the root directory of this source tree. An additional grant
@@ -26553,57 +26577,57 @@ var Debugger =
 	  };
 	
 	  return Immutable;
 	
 	}));
 
 
 /***/ },
-/* 193 */
+/* 194 */
 /***/ function(module, exports, __webpack_require__) {
 
 	
 	
 	// When Flow 0.29 is released (very soon), we can use this Record type
 	// instead of the builtin immutable.js Record type. This is better
 	// because all the fields are actually typed, unlike the builtin one.
 	// This depends on a performance fix that will go out in 0.29 though;
 	
-	var I = __webpack_require__(192);
+	var I = __webpack_require__(193);
 	
 	/**
 	 * Make an immutable record type
 	 *
 	 * @param spec - the keys and their default values @return a state
 	 * record factory function
 	 */
 	function makeRecord(spec) {
 	  return I.Record(spec);
 	}
 	
 	module.exports = makeRecord;
 
 /***/ },
-/* 194 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	/* 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/. */
-	
-	var fromJS = __webpack_require__(191);
-	
-	var _require = __webpack_require__(175);
+/* 195 */
+/***/ function(module, exports, __webpack_require__) {
+
+	
+	/* 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/. */
+	
+	var fromJS = __webpack_require__(192);
+	
+	var _require = __webpack_require__(176);
 	
 	var updateObj = _require.updateObj;
 	
-	var I = __webpack_require__(192);
-	var makeRecord = __webpack_require__(193);
+	var I = __webpack_require__(193);
+	var makeRecord = __webpack_require__(194);
 	
 	var State = makeRecord({
 	  breakpoints: I.Map(),
 	  breakpointsDisabled: false
 	});
 	
 	// Return the first argument that is a string, or null if nothing is a
 	// string.
@@ -26767,26 +26791,26 @@ var Debugger =
 	  getBreakpoint,
 	  getBreakpoints,
 	  getBreakpointsForSource,
 	  getBreakpointsDisabled,
 	  getBreakpointsLoading
 	};
 
 /***/ },
-/* 195 */
+/* 196 */
 /***/ function(module, exports, __webpack_require__) {
 
 	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
 	
 	/* 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/. */
 	
-	var constants = __webpack_require__(189);
+	var constants = __webpack_require__(190);
 	var initialState = [];
 	
 	function update() {
 	  var state = arguments.length <= 0 || arguments[0] === undefined ? initialState : arguments[0];
 	  var action = arguments[1];
 	  var seqId = action.seqId;
 	
 	
@@ -26804,26 +26828,26 @@ var Debugger =
 	  }
 	
 	  return state;
 	}
 	
 	module.exports = update;
 
 /***/ },
-/* 196 */
-/***/ function(module, exports, __webpack_require__) {
-
-	/* 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/. */
-	
-	var constants = __webpack_require__(189);
-	var Immutable = __webpack_require__(192);
-	var fromJS = __webpack_require__(191);
+/* 197 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* 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/. */
+	
+	var constants = __webpack_require__(190);
+	var Immutable = __webpack_require__(193);
+	var fromJS = __webpack_require__(192);
 	
 	var initialState = fromJS({
 	  tabs: {},
 	  selectedTab: null
 	});
 	
 	function update() {
 	  var state = arguments.length <= 0 || arguments[0] === undefined ? initialState : arguments[0];
@@ -26859,25 +26883,25 @@ var Debugger =
 	  }
 	
 	  return id;
 	}
 	
 	module.exports = update;
 
 /***/ },
-/* 197 */
-/***/ function(module, exports, __webpack_require__) {
-
-	/* 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/. */
-	
-	var constants = __webpack_require__(189);
-	var fromJS = __webpack_require__(191);
+/* 198 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* 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/. */
+	
+	var constants = __webpack_require__(190);
+	var fromJS = __webpack_require__(192);
 	
 	var initialState = fromJS({
 	  pause: null,
 	  isWaitingOnBreak: false,
 	  frames: null,
 	  selectedFrameId: null,
 	  loadedObjects: {},
 	  shouldPauseOnExceptions: false,
@@ -27025,26 +27049,26 @@ var Debugger =
 	  getIsWaitingOnBreak,
 	  getShouldPauseOnExceptions,
 	  getShouldIgnoreCaughtExceptions,
 	  getFrames,
 	  getSelectedFrame
 	};
 
 /***/ },
-/* 198 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	
-	var URL = __webpack_require__(199);
-	var path = __webpack_require__(204);
-	var sources = __webpack_require__(190);
-	var pause = __webpack_require__(197);
-	var breakpoints = __webpack_require__(194);
+/* 199 */
+/***/ function(module, exports, __webpack_require__) {
+
+	
+	
+	var URL = __webpack_require__(200);
+	var path = __webpack_require__(205);
+	var sources = __webpack_require__(191);
+	var pause = __webpack_require__(198);
+	var breakpoints = __webpack_require__(195);
 	
 	function getTabs(state) {
 	  return state.tabs.get("tabs");
 	}
 	
 	function getSelectedTab(state) {
 	  return state.tabs.get("selectedTab");
 	}
@@ -27099,17 +27123,17 @@ var Debugger =
 	  getIsWaitingOnBreak: pause.getIsWaitingOnBreak,
 	  getShouldPauseOnExceptions: pause.getShouldPauseOnExceptions,
 	  getShouldIgnoreCaughtExceptions: pause.getShouldIgnoreCaughtExceptions,
 	  getFrames: pause.getFrames,
 	  getSelectedFrame: pause.getSelectedFrame
 	};
 
 /***/ },
-/* 199 */
+/* 200 */
 /***/ function(module, exports, __webpack_require__) {
 
 	// Copyright Joyent, Inc. and other Node contributors.
 	//
 	// Permission is hereby granted, free of charge, to any person obtaining a
 	// copy of this software and associated documentation files (the
 	// "Software"), to deal in the Software without restriction, including
 	// without limitation the rights to use, copy, modify, merge, publish,
@@ -27123,17 +27147,17 @@ var Debugger =
 	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
 	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 	// USE OR OTHER DEALINGS IN THE SOFTWARE.
 	
-	var punycode = __webpack_require__(200);
+	var punycode = __webpack_require__(201);
 	
 	exports.parse = urlParse;
 	exports.resolve = urlResolve;
 	exports.resolveObject = urlResolveObject;
 	exports.format = urlFormat;
 	
 	exports.Url = Url;
 	
@@ -27195,17 +27219,17 @@ var Debugger =
 	      'gopher': true,
 	      'file': true,
 	      'http:': true,
 	      'https:': true,
 	      'ftp:': true,
 	      'gopher:': true,
 	      'file:': true
 	    },
-	    querystring = __webpack_require__(201);
+	    querystring = __webpack_require__(202);
 	
 	function urlParse(url, parseQueryString, slashesDenoteHost) {
 	  if (url && isObject(url) && url instanceof Url) return url;
 	
 	  var u = new Url;
 	  u.parse(url, parseQueryString, slashesDenoteHost);
 	  return u;
 	}
@@ -27812,17 +27836,17 @@ var Debugger =
 	  return arg === null;
 	}
 	function isNullOrUndefined(arg) {
 	  return  arg == null;
 	}
 
 
 /***/ },
-/* 200 */
+/* 201 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */
 	;(function(root) {
 	
 		/** Detect free variables */
 		var freeExports = typeof exports == 'object' && exports &&
 			!exports.nodeType && exports;
@@ -28347,27 +28371,27 @@ var Debugger =
 			root.punycode = punycode;
 		}
 	
 	}(this));
 	
 	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(101)(module), (function() { return this; }())))
 
 /***/ },
-/* 201 */
+/* 202 */
 /***/ function(module, exports, __webpack_require__) {
 
 	'use strict';
 	
-	exports.decode = exports.parse = __webpack_require__(202);
-	exports.encode = exports.stringify = __webpack_require__(203);
-
-
-/***/ },
-/* 202 */
+	exports.decode = exports.parse = __webpack_require__(203);
+	exports.encode = exports.stringify = __webpack_require__(204);
+
+
+/***/ },
+/* 203 */
 /***/ function(module, exports) {
 
 	// Copyright Joyent, Inc. and other Node contributors.
 	//
 	// Permission is hereby granted, free of charge, to any person obtaining a
 	// copy of this software and associated documentation files (the
 	// "Software"), to deal in the Software without restriction, including
 	// without limitation the rights to use, copy, modify, merge, publish,
@@ -28443,17 +28467,17 @@ var Debugger =
 	    }
 	  }
 	
 	  return obj;
 	};
 
 
 /***/ },
-/* 203 */
+/* 204 */
 /***/ function(module, exports) {
 
 	// Copyright Joyent, Inc. and other Node contributors.
 	//
 	// Permission is hereby granted, free of charge, to any person obtaining a
 	// copy of this software and associated documentation files (the
 	// "Software"), to deal in the Software without restriction, including
 	// without limitation the rights to use, copy, modify, merge, publish,
@@ -28513,17 +28537,17 @@ var Debugger =
 	
 	  if (!name) return '';
 	  return encodeURIComponent(stringifyPrimitive(name)) + eq +
 	         encodeURIComponent(stringifyPrimitive(obj));
 	};
 
 
 /***/ },
-/* 204 */
+/* 205 */
 /***/ function(module, exports) {
 
 	function basename(path) {
 	  return path.split("/").pop();
 	}
 	
 	function dirname(path) {
 	  var idx = path.lastIndexOf("/");
@@ -28538,33 +28562,33 @@ var Debugger =
 	  return str[0] === "/";
 	}
 	
 	module.exports = {
 	  basename, dirname, isURL, isAbsolute
 	};
 
 /***/ },
-/* 205 */
+/* 206 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	
 	var _require = __webpack_require__(15);
 	
 	var connect = _require.connect;
 	
-	var classnames = __webpack_require__(206);
-	
-	var _require2 = __webpack_require__(198);
+	var classnames = __webpack_require__(207);
+	
+	var _require2 = __webpack_require__(199);
 	
 	var getTabs = _require2.getTabs;
 	
 	
-	__webpack_require__(207);
+	__webpack_require__(208);
 	var dom = React.DOM;
 	
 	var githubUrl = "https://github.com/devtools-html/debugger.html/blob/master";
 	
 	function getTabsByBrowser(tabs, browser) {
 	  return tabs.valueSeq().filter(tab => tab.get("browser") == browser);
 	}
 	
@@ -28592,17 +28616,17 @@ var Debugger =
 	  var chromeTabs = getTabsByBrowser(tabs, "chrome");
 	
 	  return dom.div({ className: "tabs theme-light" }, renderTabs("Firefox Tabs", firefoxTabs, "firefox-tab"), renderTabs("Chrome Tabs", chromeTabs, "chrome-tab"), renderMessage(tabs.isEmpty()));
 	}
 	
 	module.exports = connect(state => ({ tabs: getTabs(state) }))(Tabs);
 
 /***/ },
-/* 206 */
+/* 207 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
 	  Copyright (c) 2016 Jed Watson.
 	  Licensed under the MIT License (MIT), see
 	  http://jedwatson.github.io/classnames
 	*/
 	/* global define */
@@ -28646,84 +28670,84 @@ var Debugger =
 			}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 		} else {
 			window.classNames = classNames;
 		}
 	}());
 
 
 /***/ },
-/* 207 */
+/* 208 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 208 */,
 /* 209 */,
 /* 210 */,
-/* 211 */
+/* 211 */,
+/* 212 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	var createFactory = React.createFactory;
 	
 	var _require = __webpack_require__(15);
 	
 	var connect = _require.connect;
 	
 	var _require2 = __webpack_require__(2);
 	
 	var bindActionCreators = _require2.bindActionCreators;
 	
-	var _require3 = __webpack_require__(212);
+	var _require3 = __webpack_require__(213);
 	
 	var Services = _require3.Services;
 	
-	var classnames = __webpack_require__(206);
-	var actions = __webpack_require__(213);
+	var classnames = __webpack_require__(207);
+	var actions = __webpack_require__(214);
 	
 	var _require4 = __webpack_require__(46);
 	
 	var isFirefoxPanel = _require4.isFirefoxPanel;
 	
 	
-	__webpack_require__(224);
+	__webpack_require__(225);
 	
 	// Using this static variable allows webpack to know at compile-time
 	// to avoid this require and not include it at all in the output.
 	if (false) {
 	  require("../lib/themes/light-theme.css");
 	}
 	
-	var Sources = createFactory(__webpack_require__(226));
-	var Editor = createFactory(__webpack_require__(261));
-	var SplitBox = createFactory(__webpack_require__(266));
-	var RightSidebar = createFactory(__webpack_require__(270));
-	var SourceTabs = createFactory(__webpack_require__(347));
-	var SourceFooter = createFactory(__webpack_require__(352));
-	var Svg = __webpack_require__(234);
-	var Autocomplete = createFactory(__webpack_require__(355));
-	
-	var _require5 = __webpack_require__(198);
+	var Sources = createFactory(__webpack_require__(227));
+	var Editor = createFactory(__webpack_require__(262));
+	var SplitBox = createFactory(__webpack_require__(267));
+	var RightSidebar = createFactory(__webpack_require__(271));
+	var SourceTabs = createFactory(__webpack_require__(348));
+	var SourceFooter = createFactory(__webpack_require__(353));
+	var Svg = __webpack_require__(235);
+	var Autocomplete = createFactory(__webpack_require__(356));
+	
+	var _require5 = __webpack_require__(199);
 	
 	var getSources = _require5.getSources;
 	var getSelectedSource = _require5.getSelectedSource;
 	
-	var _require6 = __webpack_require__(175);
+	var _require6 = __webpack_require__(176);
 	
 	var endTruncateStr = _require6.endTruncateStr;
 	
-	var _require7 = __webpack_require__(364);
+	var _require7 = __webpack_require__(365);
 	
 	var KeyShortcuts = _require7.KeyShortcuts;
 	
-	var _require8 = __webpack_require__(229);
+	var _require8 = __webpack_require__(230);
 	
 	var isHiddenSource = _require8.isHiddenSource;
 	var getURL = _require8.getURL;
 	
 	
 	function searchResults(sources) {
 	  function getSourcePath(source) {
 	    var _getURL = getURL(source);
@@ -28815,17 +28839,17 @@ var Debugger =
 	    }));
 	  }
 	});
 	
 	module.exports = connect(state => ({ sources: getSources(state),
 	  selectedSource: getSelectedSource(state) }), dispatch => bindActionCreators(actions, dispatch))(App);
 
 /***/ },
-/* 212 */
+/* 213 */
 /***/ function(module, exports) {
 
 	/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
@@ -29430,59 +29454,59 @@ var Debugger =
 	exports.Services = Services;
 	// This is exported to silence eslint and, at some point, perhaps to
 	// provide it when loading devtools.js in order to install the default
 	// preferences.
 	exports.pref = pref;
 
 
 /***/ },
-/* 213 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	
-	var breakpoints = __webpack_require__(214);
-	var eventListeners = __webpack_require__(217);
-	var sources = __webpack_require__(218);
-	var tabs = __webpack_require__(221);
-	var pause = __webpack_require__(222);
-	var navigation = __webpack_require__(223);
+/* 214 */
+/***/ function(module, exports, __webpack_require__) {
+
+	
+	
+	var breakpoints = __webpack_require__(215);
+	var eventListeners = __webpack_require__(218);
+	var sources = __webpack_require__(219);
+	var tabs = __webpack_require__(222);
+	var pause = __webpack_require__(223);
+	var navigation = __webpack_require__(224);
 	
 	module.exports = Object.assign(navigation, breakpoints, eventListeners, sources, tabs, pause);
 
 /***/ },
-/* 214 */
+/* 215 */
 /***/ function(module, exports, __webpack_require__) {
 
 	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"); } }; }();
 	
 	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) { return step("next", value); }, function (err) { return 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
 	 */
 	
-	var constants = __webpack_require__(189);
-	
-	var _require = __webpack_require__(183);
+	var constants = __webpack_require__(190);
+	
+	var _require = __webpack_require__(184);
 	
 	var PROMISE = _require.PROMISE;
 	
-	var _require2 = __webpack_require__(198);
+	var _require2 = __webpack_require__(199);
 	
 	var getBreakpoint = _require2.getBreakpoint;
 	var getBreakpoints = _require2.getBreakpoints;
 	
-	var _require3 = __webpack_require__(215);
+	var _require3 = __webpack_require__(216);
 	
 	var getOriginalLocation = _require3.getOriginalLocation;
 	var getGeneratedLocation = _require3.getGeneratedLocation;
 	
 	/**
 	 * Argument parameters via Thunk middleware for {@link https://github.com/gaearon/redux-thunk|Redux Thunk}
 	 *
 	 * @memberof actions/breakpoints
@@ -29692,17 +29716,17 @@ var Debugger =
 	  addBreakpoint,
 	  disableBreakpoint,
 	  removeBreakpoint,
 	  toggleAllBreakpoints,
 	  setBreakpointCondition
 	};
 
 /***/ },
-/* 215 */
+/* 216 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var getOriginalSources = (() => {
 	  var _ref = _asyncToGenerator(function* (state, source) {
 	    var originalSourceUrls = yield getOriginalSourceUrls(source);
 	    return originalSourceUrls.map(function (url) {
 	      return getSourceByURL(state, url);
 	    });
@@ -29790,26 +29814,26 @@ var Debugger =
 	
 	  return function getOriginalSourceTexts(_x7, _x8, _x9) {
 	    return _ref4.apply(this, arguments);
 	  };
 	})();
 	
 	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) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
 	
-	var _require = __webpack_require__(175);
+	var _require = __webpack_require__(176);
 	
 	var workerTask = _require.workerTask;
 	
-	var _require2 = __webpack_require__(216);
+	var _require2 = __webpack_require__(217);
 	
 	var makeOriginalSource = _require2.makeOriginalSource;
 	var getGeneratedSourceId = _require2.getGeneratedSourceId;
 	
-	var _require3 = __webpack_require__(198);
+	var _require3 = __webpack_require__(199);
 	
 	var getSource = _require3.getSource;
 	var getSourceByURL = _require3.getSourceByURL;
 	
 	var _require4 = __webpack_require__(46);
 	
 	var isEnabled = _require4.isEnabled;
 	var getValue = _require4.getValue;
@@ -29894,17 +29918,17 @@ var Debugger =
 	  getGeneratedSourceId,
 	  createSourceMap,
 	  clearData,
 	  restartWorker,
 	  destroy
 	};
 
 /***/ },
-/* 216 */
+/* 217 */
 /***/ function(module, exports) {
 
 	
 	function getGeneratedSourceId(originalSource) {
 	  var match = originalSource.id.match(/(.*)\/originalSource/);
 	  return match ? match[1] : null;
 	}
 	
@@ -29923,37 +29947,37 @@ var Debugger =
 	}
 	
 	module.exports = {
 	  makeOriginalSource,
 	  getGeneratedSourceId
 	};
 
 /***/ },
-/* 217 */
+/* 218 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* 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/. */
 	/* global window gThreadClient setNamedTimeout services EVENTS */
 	/* eslint no-shadow: 0  */
 	
 	/**
 	 * Redux actions for the event listeners state
 	 * @module actions/event-listeners
 	 */
 	
-	var constants = __webpack_require__(189);
-	
-	var _require = __webpack_require__(175);
+	var constants = __webpack_require__(190);
+	
+	var _require = __webpack_require__(176);
 	
 	var asPaused = _require.asPaused;
 	
-	var _require2 = __webpack_require__(185);
+	var _require2 = __webpack_require__(186);
 	
 	var reportException = _require2.reportException;
 	
 	var _require3 = __webpack_require__(97);
 	
 	var Task = _require3.Task;
 	
 	// delay is in ms
@@ -30067,17 +30091,17 @@ var Debugger =
 	      });
 	    });
 	  };
 	}
 	
 	module.exports = { updateEventBreakpoints, fetchEventListeners };
 
 /***/ },
-/* 218 */
+/* 219 */
 /***/ function(module, exports, __webpack_require__) {
 
 	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 _prettyPrintSource = (() => {
 	  var _ref = _asyncToGenerator(function* (_ref2) {
 	    var source = _ref2.source;
 	    var sourceText = _ref2.sourceText;
@@ -30123,106 +30147,111 @@ var Debugger =
 	
 	/**
 	 * Redux actions for the sources state
 	 * @module actions/sources
 	 */
 	
 	var defer = __webpack_require__(112);
 	
-	var _require = __webpack_require__(183);
+	var _require = __webpack_require__(184);
 	
 	var PROMISE = _require.PROMISE;
 	
 	var _require2 = __webpack_require__(97);
 	
 	var Task = _require2.Task;
 	
-	var _require3 = __webpack_require__(219);
+	var _require3 = __webpack_require__(220);
 	
 	var isJavaScript = _require3.isJavaScript;
 	
-	var _require4 = __webpack_require__(174);
+	var _require4 = __webpack_require__(175);
 	
 	var networkRequest = _require4.networkRequest;
 	
-	var _require5 = __webpack_require__(175);
+	var _require5 = __webpack_require__(176);
 	
 	var workerTask = _require5.workerTask;
 	
-	var _require6 = __webpack_require__(220);
+	var _require6 = __webpack_require__(221);
 	
 	var updateFrameLocations = _require6.updateFrameLocations;
 	
 	
-	var constants = __webpack_require__(189);
+	var constants = __webpack_require__(190);
 	var invariant = __webpack_require__(24);
 	
 	var _require7 = __webpack_require__(46);
 	
 	var isEnabled = _require7.isEnabled;
 	
-	var _require8 = __webpack_require__(215);
+	var _require8 = __webpack_require__(216);
 	
 	var createOriginalSources = _require8.createOriginalSources;
 	var getOriginalSourceTexts = _require8.getOriginalSourceTexts;
 	var createSourceMap = _require8.createSourceMap;
 	var makeOriginalSource = _require8.makeOriginalSource;
 	var getGeneratedSource = _require8.getGeneratedSource;
 	
-	var _require9 = __webpack_require__(198);
+	var _require9 = __webpack_require__(199);
 	
 	var getSource = _require9.getSource;
 	var getSourceByURL = _require9.getSourceByURL;
 	var getSourceText = _require9.getSourceText;
 	var getPendingSelectedLocation = _require9.getPendingSelectedLocation;
 	var getSourceMap = _require9.getSourceMap;
 	var getSourceMapURL = _require9.getSourceMapURL;
 	var getFrames = _require9.getFrames;
 	
 	
 	function _shouldSourceMap(generatedSource) {
 	  return isEnabled("sourceMaps") && generatedSource.sourceMapURL;
 	}
 	
-	function _addSource(source) {
-	  return {
-	    type: constants.ADD_SOURCE,
-	    source
-	  };
-	}
-	
 	function newSource(source) {
 	  return _ref4 => {
 	    var dispatch = _ref4.dispatch;
 	    var getState = _ref4.getState;
 	
 	    if (_shouldSourceMap(source)) {
 	      dispatch(loadSourceMap(source));
 	    }
 	
-	    dispatch(_addSource(source));
+	    dispatch({
+	      type: constants.ADD_SOURCE,
+	      source
+	    });
 	
 	    // If a request has been made to show this source, go ahead and
 	    // select it.
 	    var pendingLocation = getPendingSelectedLocation(getState());
 	    if (pendingLocation && pendingLocation.url === source.url) {
 	      dispatch(selectSource(source.id, { line: pendingLocation.line }));
 	    }
 	  };
 	}
 	
+	function newSources(sources) {
+	  return _ref5 => {
+	    var dispatch = _ref5.dispatch;
+	    var getState = _ref5.getState;
+	
+	    sources.filter(source => !getSource(getState(), source.id)).forEach(source => dispatch(newSource(source)));
+	  };
+	}
+	
 	/**
 	 * @memberof actions/sources
 	 * @static
 	 */
 	function loadSourceMap(generatedSource) {
-	  return _ref5 => {
-	    var dispatch = _ref5.dispatch;
-	    var getState = _ref5.getState;
+	  return _ref6 => {
+	    var dispatch = _ref6.dispatch;
+	    var getState = _ref6.getState;
 	
 	    var sourceMap = getSourceMap(getState(), generatedSource.id);
 	    if (sourceMap) {
 	      return;
 	    }
 	
 	    dispatch({
 	      type: constants.LOAD_SOURCE_MAP,
@@ -30250,19 +30279,19 @@ var Debugger =
 	 * debugger.
 	 *
 	 * @memberof actions/sources
 	 * @static
 	 */
 	function selectSourceURL(url) {
 	  var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
 	
-	  return _ref7 => {
-	    var dispatch = _ref7.dispatch;
-	    var getState = _ref7.getState;
+	  return _ref8 => {
+	    var dispatch = _ref8.dispatch;
+	    var getState = _ref8.getState;
 	
 	    var source = getSourceByURL(getState(), url);
 	    if (source) {
 	      dispatch(selectSource(source.get("id"), options));
 	    } else {
 	      dispatch({
 	        type: constants.SELECT_SOURCE_URL,
 	        url: url,
@@ -30275,20 +30304,20 @@ var Debugger =
 	
 	/**
 	 * @memberof actions/sources
 	 * @static
 	 */
 	function selectSource(id) {
 	  var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
 	
-	  return _ref8 => {
-	    var dispatch = _ref8.dispatch;
-	    var getState = _ref8.getState;
-	    var client = _ref8.client;
+	  return _ref9 => {
+	    var dispatch = _ref9.dispatch;
+	    var getState = _ref9.getState;
+	    var client = _ref9.client;
 	
 	    if (!client) {
 	      // No connection, do nothing. This happens when the debugger is
 	      // shut down too fast and it tries to display a default source.
 	      return;
 	    }
 	
 	    var source = getSource(getState(), id).toJS();
@@ -30325,19 +30354,19 @@ var Debugger =
 	 *        The source form.
 	 * @param bool shouldBlackBox
 	 *        True to black box the source, false to un-black box it.
 	 * @returns {Promise}
 	 *          A promize that resolves to [aSource, isBlackBoxed] or rejects to
 	 *          [aSource, error].
 	 */
 	function blackbox(source, shouldBlackBox) {
-	  return _ref9 => {
-	    var dispatch = _ref9.dispatch;
-	    var client = _ref9.client;
+	  return _ref10 => {
+	    var dispatch = _ref10.dispatch;
+	    var client = _ref10.client;
 	
 	    dispatch({
 	      type: constants.BLACKBOX,
 	      source: source,
 	      [PROMISE]: Task.spawn(function* () {
 	        yield shouldBlackBox ? client.blackBox(source.id) : client.unblackBox(source.id);
 	        return {
 	          isBlackBoxed: shouldBlackBox
@@ -30355,35 +30384,38 @@ var Debugger =
 	 * @memberof actions/sources
 	 * @static
 	 * @param string id The source form from the RDP.
 	 * @returns Promise
 	 *          A promise that resolves to [aSource, prettyText] or rejects to
 	 *          [aSource, error].
 	 */
 	function togglePrettyPrint(id) {
-	  return _ref10 => {
-	    var dispatch = _ref10.dispatch;
-	    var getState = _ref10.getState;
-	    var client = _ref10.client;
+	  return _ref11 => {
+	    var dispatch = _ref11.dispatch;
+	    var getState = _ref11.getState;
+	    var client = _ref11.client;
 	
 	    var source = getSource(getState(), id).toJS();
 	    var sourceText = getSourceText(getState(), id).toJS();
 	
 	    if (sourceText.loading) {
 	      return;
 	    }
 	
 	    if (!isEnabled("prettyPrint") || source.isPrettyPrinted) {
 	      return {};
 	    }
 	
 	    var url = source.url + ":formatted";
 	    var originalSource = makeOriginalSource({ url, source });
-	    dispatch(_addSource(originalSource));
+	    dispatch({
+	      type: constants.ADD_SOURCE,
+	      source: originalSource
+	    });
 	
 	    return dispatch({
 	      type: constants.TOGGLE_PRETTY_PRINT,
 	      source,
 	      originalSource,
 	      [PROMISE]: _asyncToGenerator(function* () {
 	        var state = getState();
 	        var text = yield _prettyPrintSource({ source, sourceText, url });
@@ -30407,20 +30439,20 @@ var Debugger =
 	  };
 	}
 	
 	/**
 	 * @memberof actions/sources
 	 * @static
 	 */
 	function loadSourceText(source) {
-	  return _ref12 => {
-	    var dispatch = _ref12.dispatch;
-	    var getState = _ref12.getState;
-	    var client = _ref12.client;
+	  return _ref13 => {
+	    var dispatch = _ref13.dispatch;
+	    var getState = _ref13.getState;
+	    var client = _ref13.client;
 	
 	    // Fetch the source text only once.
 	    var textInfo = getSourceText(getState(), source.id);
 	    if (textInfo) {
 	      // It's already loaded or is loading
 	      return Promise.resolve(textInfo);
 	    }
 	
@@ -30467,36 +30499,36 @@ var Debugger =
 	 * @static
 	 * @param array actors
 	 *        The urls for the sources to fetch. If fetching a source's text
 	 *        takes too long, it will be discarded.
 	 * @returns {Promise}
 	 *         A promise that is resolved after source texts have been fetched.
 	 */
 	function getTextForSources(actors) {
-	  return _ref14 => {
-	    var dispatch = _ref14.dispatch;
-	    var getState = _ref14.getState;
+	  return _ref15 => {
+	    var dispatch = _ref15.dispatch;
+	    var getState = _ref15.getState;
 	
 	    var deferred = defer();
 	    var pending = new Set(actors);
 	    var fetched = [];
 	
 	    // Can't use promise.all, because if one fetch operation is rejected, then
 	    // everything is considered rejected, thus no other subsequent source will
 	    // be getting fetched. We don't want that. Something like Q's allSettled
 	    // would work like a charm here.
 	
 	    // Try to fetch as many sources as possible.
 	
 	    var _loop = function (actor) {
 	      var source = getSource(getState(), actor);
-	      dispatch(loadSourceText(source)).then(_ref23 => {
-	        var text = _ref23.text;
-	        var contentType = _ref23.contentType;
+	      dispatch(loadSourceText(source)).then(_ref24 => {
+	        var text = _ref24.text;
+	        var contentType = _ref24.contentType;
 	
 	        onFetch([source, text, contentType]);
 	      }, err => {
 	        onError(source, err);
 	      });
 	    };
 	
 	    for (var actor of actors) {
@@ -30507,79 +30539,80 @@ var Debugger =
 	
 	    /* Called if fetching a source takes too long. */
 	    function onTimeout() {
 	      pending = new Set();
 	      maybeFinish();
 	    }
 	
 	    /* Called if fetching a source finishes successfully. */
-	    function onFetch(_ref15) {
-	      var _ref16 = _slicedToArray(_ref15, 3);
-	
-	      var aSource = _ref16[0];
-	      var aText = _ref16[1];
-	      var aContentType = _ref16[2];
+	    function onFetch(_ref16) {
+	      var _ref17 = _slicedToArray(_ref16, 3);
+	
+	      var aSource = _ref17[0];
+	      var aText = _ref17[1];
+	      var aContentType = _ref17[2];
 	
 	      // If fetching the source has previously timed out, discard it this time.
 	      if (!pending.has(aSource.actor)) {
 	        return;
 	      }
 	      pending.delete(aSource.actor);
 	      fetched.push([aSource.actor, aText, aContentType]);
 	      maybeFinish();
 	    }
 	
 	    /* Called if fetching a source failed because of an error. */
-	    function onError(_ref17) {
-	      var _ref18 = _slicedToArray(_ref17, 2);
-	
-	      var aSource = _ref18[0];
-	      var aError = _ref18[1];
+	    function onError(_ref18) {
+	      var _ref19 = _slicedToArray(_ref18, 2);
+	
+	      var aSource = _ref19[0];
+	      var aError = _ref19[1];
 	
 	      pending.delete(aSource.actor);
 	      maybeFinish();
 	    }
 	
 	    /* Called every time something interesting
 	     *  happens while fetching sources.
 	     */
 	    function maybeFinish() {
 	      if (pending.size == 0) {
 	        // Sort the fetched sources alphabetically by their url.
-	        deferred.resolve(fetched.sort((_ref19, _ref20) => {
-	          var _ref22 = _slicedToArray(_ref19, 1);
-	
-	          var aFirst = _ref22[0];
-	
-	          var _ref21 = _slicedToArray(_ref20, 1);
-	
-	          var aSecond = _ref21[0];
+	        deferred.resolve(fetched.sort((_ref20, _ref21) => {
+	          var _ref23 = _slicedToArray(_ref20, 1);
+	
+	          var aFirst = _ref23[0];
+	
+	          var _ref22 = _slicedToArray(_ref21, 1);
+	
+	          var aSecond = _ref22[0];
 	          return aFirst > aSecond;
 	        }));
 	      }
 	    }
 	
 	    return deferred.promise;
 	  };
 	}
 	
 	module.exports = {
 	  newSource,
+	  newSources,
 	  selectSource,
 	  selectSourceURL,
 	  closeTab,
 	  blackbox,
 	  togglePrettyPrint,
 	  loadSourceText,
 	  getTextForSources
 	};
 
 /***/ },
-/* 219 */
+/* 220 */
 /***/ function(module, exports) {
 
 	
 	/**
 	 * Trims the query part or reference identifier of a url string, if necessary.
 	 *
 	 * @param string url - The source url.
 	 * @return string - The shortened url.
@@ -30612,17 +30645,17 @@ var Debugger =
 	}
 	
 	module.exports = {
 	  isJavaScript,
 	  isPretty
 	};
 
 /***/ },
-/* 220 */
+/* 221 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var updateFrameLocation = (() => {
 	  var _ref = _asyncToGenerator(function* (state, frame) {
 	    var originalLocation = yield getOriginalLocation(state, frame.location);
 	
 	    return Frame.update(frame, {
 	      $merge: { location: Location(originalLocation) }
@@ -30648,44 +30681,44 @@ var Debugger =
 	
 	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) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
 	
 	var _require = __webpack_require__(114);
 	
 	var Location = _require.Location;
 	var Frame = _require.Frame;
 	
-	var _require2 = __webpack_require__(215);
+	var _require2 = __webpack_require__(216);
 	
 	var getOriginalLocation = _require2.getOriginalLocation;
 	
-	var _require3 = __webpack_require__(175);
+	var _require3 = __webpack_require__(176);
 	
 	var asyncMap = _require3.asyncMap;
 	
 	
 	module.exports = {
 	  updateFrameLocations
 	};
 
 /***/ },
-/* 221 */
+/* 222 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* 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/. */
 	/* global window */
 	
 	/**
 	 * Redux actions for the pause state
 	 * @module actions/tabs
 	 */
 	
-	var constants = __webpack_require__(189);
+	var constants = __webpack_require__(190);
 	
 	/**
 	 * @typedef {Object} TabAction
 	 * @memberof actions/tabs
 	 * @static
 	 * @property {number} type The type of Action
 	 * @property {number} value The payload of the Action
 	 */
@@ -30719,36 +30752,36 @@ var Debugger =
 	}
 	
 	module.exports = {
 	  newTabs,
 	  selectTab
 	};
 
 /***/ },
-/* 222 */
+/* 223 */
 /***/ function(module, exports, __webpack_require__) {
 
 	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) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
 	
-	var constants = __webpack_require__(189);
-	
-	var _require = __webpack_require__(218);
+	var constants = __webpack_require__(190);
+	
+	var _require = __webpack_require__(219);
 	
 	var selectSource = _require.selectSource;
 	
-	var _require2 = __webpack_require__(183);
+	var _require2 = __webpack_require__(184);
 	
 	var PROMISE = _require2.PROMISE;
 	
-	var _require3 = __webpack_require__(198);
+	var _require3 = __webpack_require__(199);
 	
 	var getExpressions = _require3.getExpressions;
 	
-	var _require4 = __webpack_require__(220);
+	var _require4 = __webpack_require__(221);
 	
 	var updateFrameLocations = _require4.updateFrameLocations;
 	
 	/**
 	 * Redux actions for the pause state
 	 * @module actions/pause
 	 */
 	
@@ -31047,22 +31080,22 @@ var Debugger =
 	  stepOver,
 	  resume,
 	  breakOnNext,
 	  selectFrame,
 	  loadObjectProperties
 	};
 
 /***/ },
-/* 223 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var constants = __webpack_require__(189);
-	
-	var _require = __webpack_require__(215);
+/* 224 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var constants = __webpack_require__(190);
+	
+	var _require = __webpack_require__(216);
 	
 	var clearData = _require.clearData;
 	
 	/**
 	 * Redux actions for the navigation state
 	 * @module actions/navigation
 	 */
 	
@@ -31096,50 +31129,50 @@ var Debugger =
 	}
 	
 	module.exports = {
 	  willNavigate,
 	  navigated
 	};
 
 /***/ },
-/* 224 */
+/* 225 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 225 */,
-/* 226 */
+/* 226 */,
+/* 227 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	
-	var ImPropTypes = __webpack_require__(227);
+	var ImPropTypes = __webpack_require__(228);
 	
 	var _require = __webpack_require__(2);
 	
 	var bindActionCreators = _require.bindActionCreators;
 	
 	var _require2 = __webpack_require__(15);
 	
 	var connect = _require2.connect;
 	
-	var SourcesTree = React.createFactory(__webpack_require__(228));
-	var actions = __webpack_require__(213);
-	
-	var _require3 = __webpack_require__(198);
+	var SourcesTree = React.createFactory(__webpack_require__(229));
+	var actions = __webpack_require__(214);
+	
+	var _require3 = __webpack_require__(199);
 	
 	var getSelectedSource = _require3.getSelectedSource;
 	var getSources = _require3.getSources;
 	
 	
-	__webpack_require__(259);
+	__webpack_require__(260);
 	
 	var Sources = React.createClass({
 	  propTypes: {
 	    sources: ImPropTypes.map.isRequired,
 	    selectSource: PropTypes.func.isRequired
 	  },
 	
 	  displayName: "Sources",
@@ -31153,28 +31186,28 @@ var Debugger =
 	    return dom.div({ className: "sources-panel" }, dom.div({ className: "sources-header" }, "Sources"), SourcesTree({ sources, selectSource }));
 	  }
 	});
 	
 	module.exports = connect(state => ({ selectedSource: getSelectedSource(state),
 	  sources: getSources(state) }), dispatch => bindActionCreators(actions, dispatch))(Sources);
 
 /***/ },
-/* 227 */
+/* 228 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/**
 	 * This is a straight rip-off of the React.js ReactPropTypes.js proptype validators,
 	 * modified to make it possible to validate Immutable.js data.
 	 *     ImmutableTypes.listOf is patterned after React.PropTypes.arrayOf, but for Immutable.List
 	 *     ImmutableTypes.shape  is based on React.PropTypes.shape, but for any Immutable.Iterable
 	 */
 	"use strict";
 	
-	var Immutable = __webpack_require__(192);
+	var Immutable = __webpack_require__(193);
 	
 	var ANONYMOUS = "<<anonymous>>";
 	
 	var ImmutablePropTypes = {
 	  listOf: createListOfTypeChecker,
 	  mapOf: createMapOfTypeChecker,
 	  orderedMapOf: createOrderedMapOfTypeChecker,
 	  setOf: createSetOfTypeChecker,
@@ -31357,42 +31390,42 @@ var Debugger =
 	
 	function createMapContainsChecker(shapeTypes) {
 	  return createShapeTypeChecker(shapeTypes, "Map", Immutable.Map.isMap);
 	}
 	
 	module.exports = ImmutablePropTypes;
 
 /***/ },
-/* 228 */
+/* 229 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	
-	var classnames = __webpack_require__(206);
-	var ImPropTypes = __webpack_require__(227);
-	
-	var _require = __webpack_require__(192);
+	var classnames = __webpack_require__(207);
+	var ImPropTypes = __webpack_require__(228);
+	
+	var _require = __webpack_require__(193);
 	
 	var Set = _require.Set;
 	
-	var _require2 = __webpack_require__(229);
+	var _require2 = __webpack_require__(230);
 	
 	var nodeHasChildren = _require2.nodeHasChildren;
 	var createParentMap = _require2.createParentMap;
 	var addToTree = _require2.addToTree;
 	var collapseTree = _require2.collapseTree;
 	var createTree = _require2.createTree;
 	
-	var ManagedTree = React.createFactory(__webpack_require__(230));
-	var Svg = __webpack_require__(234);
-	
-	var _require3 = __webpack_require__(175);
+	var ManagedTree = React.createFactory(__webpack_require__(231));
+	var Svg = __webpack_require__(235);
+	
+	var _require3 = __webpack_require__(176);
 	
 	var throttle = _require3.throttle;
 	
 	
 	var SourcesTree = React.createClass({
 	  propTypes: {
 	    sources: ImPropTypes.map.isRequired,
 	    selectSource: PropTypes.func.isRequired
@@ -31526,26 +31559,26 @@ var Debugger =
 	      }
 	    }, tree);
 	  }
 	});
 	
 	module.exports = SourcesTree;
 
 /***/ },
-/* 229 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var URL = __webpack_require__(199);
-	
-	var _require = __webpack_require__(185);
+/* 230 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var URL = __webpack_require__(200);
+	
+	var _require = __webpack_require__(186);
 	
 	var assert = _require.assert;
 	
-	var _require2 = __webpack_require__(219);
+	var _require2 = __webpack_require__(220);
 	
 	var isPretty = _require2.isPretty;
 	
 	
 	var IGNORED_URLS = ["debugger eval code", "XStringBundle"];
 	
 	function isHiddenSource(source) {
 	  var url = source.get("url");
@@ -31725,22 +31758,22 @@ var Debugger =
 	  addToTree,
 	  collapseTree,
 	  createTree,
 	  getURL,
 	  isHiddenSource
 	};
 
 /***/ },
-/* 230 */
+/* 231 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
-	var Tree = React.createFactory(__webpack_require__(231));
-	__webpack_require__(232);
+	var Tree = React.createFactory(__webpack_require__(232));
+	__webpack_require__(233);
 	
 	var ManagedTree = React.createClass({
 	  propTypes: Tree.propTypes,
 	
 	  displayName: "ManagedTree",
 	
 	  getInitialState() {
 	    return { expanded: new Set(),
@@ -31805,17 +31838,17 @@ var Debugger =
 	
 	    return Tree(props);
 	  }
 	});
 	
 	module.exports = ManagedTree;
 
 /***/ },
-/* 231 */
+/* 232 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* 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/. */
 	
 	const { DOM: dom, createClass, createFactory, PropTypes } = __webpack_require__(17);
 	// const { ViewHelpers } =
@@ -32405,62 +32438,62 @@ var Debugger =
 	    }
 	
 	    this._focus(parentIndex, parent);
 	  }),
 	});
 
 
 /***/ },
-/* 232 */
+/* 233 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 233 */,
-/* 234 */
+/* 234 */,
+/* 235 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/**
 	 * This file maps the SVG React Components in the public/images directory.
 	 */
-	var Svg = __webpack_require__(235);
+	var Svg = __webpack_require__(236);
 	module.exports = Svg;
 
 /***/ },
-/* 235 */
+/* 236 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
-	var InlineSVG = __webpack_require__(236);
+	var InlineSVG = __webpack_require__(237);
 	
 	var svg = {
-	  "angle-brackets": __webpack_require__(237),
-	  "arrow": __webpack_require__(238),
-	  "blackBox": __webpack_require__(239),
-	  "breakpoint": __webpack_require__(240),
-	  "close": __webpack_require__(241),
-	  "disableBreakpoints": __webpack_require__(242),
-	  "domain": __webpack_require__(243),
-	  "file": __webpack_require__(244),
-	  "folder": __webpack_require__(245),
-	  "globe": __webpack_require__(246),
-	  "magnifying-glass": __webpack_require__(247),
-	  "pause": __webpack_require__(248),
-	  "pause-circle": __webpack_require__(249),
-	  "pause-exceptions": __webpack_require__(250),
-	  "prettyPrint": __webpack_require__(251),
-	  "resume": __webpack_require__(252),
-	  "settings": __webpack_require__(253),
-	  "stepIn": __webpack_require__(254),
-	  "stepOut": __webpack_require__(255),
-	  "stepOver": __webpack_require__(256),
-	  "subSettings": __webpack_require__(257),
-	  "worker": __webpack_require__(258)
+	  "angle-brackets": __webpack_require__(238),
+	  "arrow": __webpack_require__(239),
+	  "blackBox": __webpack_require__(240),
+	  "breakpoint": __webpack_require__(241),
+	  "close": __webpack_require__(242),
+	  "disableBreakpoints": __webpack_require__(243),
+	  "domain": __webpack_require__(244),
+	  "file": __webpack_require__(245),
+	  "folder": __webpack_require__(246),
+	  "globe": __webpack_require__(247),
+	  "magnifying-glass": __webpack_require__(248),
+	  "pause": __webpack_require__(249),
+	  "pause-circle": __webpack_require__(250),
+	  "pause-exceptions": __webpack_require__(251),
+	  "prettyPrint": __webpack_require__(252),
+	  "resume": __webpack_require__(253),
+	  "settings": __webpack_require__(254),
+	  "stepIn": __webpack_require__(255),
+	  "stepOut": __webpack_require__(256),
+	  "stepOver": __webpack_require__(257),
+	  "subSettings": __webpack_require__(258),
+	  "worker": __webpack_require__(259)
 	};
 	
 	module.exports = function (name, props) {
 	  // eslint-disable-line
 	  if (!svg[name]) {
 	    throw new Error("Unknown SVG: " + name);
 	  }
 	  var className = name;
@@ -32470,17 +32503,17 @@ var Debugger =
 	  if (name === "subSettings") {
 	    className = "";
 	  }
 	  props = Object.assign({}, props, { className, src: svg[name] });
 	  return React.createElement(InlineSVG, props);
 	};
 
 /***/ },
-/* 236 */
+/* 237 */
 /***/ function(module, exports, __webpack_require__) {
 
 	'use strict';
 	
 	Object.defineProperty(exports, '__esModule', {
 	    value: true
 	});
 	
@@ -32626,194 +32659,194 @@ var Debugger =
 	
 	    return InlineSVG;
 	})(_react2['default'].Component);
 	
 	exports['default'] = InlineSVG;
 	module.exports = exports['default'];
 
 /***/ },
-/* 237 */
+/* 238 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"-1 73 16 11\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><g id=\"Shape-Copy-3-+-Shape-Copy-4\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(0.000000, 74.000000)\"><path d=\"M0.749321284,4.16081709 L4.43130681,0.242526751 C4.66815444,-0.00952143591 5.06030999,-0.0211407611 5.30721074,0.216574262 C5.55411149,0.454289284 5.56226116,0.851320812 5.32541353,1.103369 L1.95384971,4.69131519 L5.48809879,8.09407556 C5.73499955,8.33179058 5.74314922,8.72882211 5.50630159,8.9808703 C5.26945396,9.23291849 4.87729841,9.24453781 4.63039766,9.00682279 L0.827097345,5.34502101 C0.749816996,5.31670099 0.677016974,5.27216098 0.613753508,5.21125118 C0.427367989,5.03179997 0.377040713,4.7615583 0.465458792,4.53143559 C0.492371834,4.43667624 0.541703274,4.34676528 0.613628034,4.27022448 C0.654709457,4.22650651 0.70046335,4.19002189 0.749321284,4.16081709 Z\" id=\"Shape-Copy-3\" stroke=\"#FFFFFF\" stroke-width=\"0.05\" fill=\"#DDE1E4\"></path><path d=\"M13.7119065,5.44453032 L9.77062746,9.09174784 C9.51677479,9.3266604 9.12476399,9.31089603 8.89504684,9.05653714 C8.66532968,8.80217826 8.68489539,8.40554539 8.93874806,8.17063283 L12.5546008,4.82456128 L9.26827469,1.18571135 C9.03855754,0.931352463 9.05812324,0.534719593 9.31197591,0.299807038 C9.56582858,0.0648944831 9.95783938,0.0806588502 10.1875565,0.335017737 L13.72891,4.25625178 C13.8013755,4.28980469 13.8684335,4.3382578 13.9254821,4.40142604 C14.0883019,4.58171146 14.1258883,4.83347168 14.0435812,5.04846202 C14.0126705,5.15680232 13.9526426,5.2583679 13.8641331,5.34027361 C13.8174417,5.38348136 13.7660763,5.41820853 13.7119065,5.44453032 Z\" id=\"Shape-Copy-4\" stroke=\"#FFFFFF\" stroke-width=\"0.05\" fill=\"#DDE1E4\"></path></g></svg>"
 
 /***/ },
-/* 238 */
+/* 239 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 16 16\"><path d=\"M8 13.4c-.5 0-.9-.2-1.2-.6L.4 5.2C0 4.7-.1 4.3.2 3.7S1 3 1.6 3h12.8c.6 0 1.2.1 1.4.7.3.6.2 1.1-.2 1.6l-6.4 7.6c-.3.4-.7.5-1.2.5z\"></path></svg>"
 
 /***/ },
-/* 239 */
+/* 240 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"##4A464C\"><g fill-rule=\"evenodd\"><circle cx=\"8\" cy=\"8.5\" r=\"1.5\"></circle><path d=\"M15.498 8.28l-.001-.03v-.002-.004l-.002-.018-.004-.031c0-.002 0-.002 0 0l-.004-.035.006.082c-.037-.296-.133-.501-.28-.661-.4-.522-.915-1.042-1.562-1.604-1.36-1.182-2.74-1.975-4.178-2.309a6.544 6.544 0 0 0-2.755-.042c-.78.153-1.565.462-2.369.91C3.252 5.147 2.207 6 1.252 7.035c-.216.233-.36.398-.499.577-.338.437-.338 1 0 1.437.428.552.941 1.072 1.59 1.635 1.359 1.181 2.739 1.975 4.177 2.308.907.21 1.829.223 2.756.043.78-.153 1.564-.462 2.369-.91 1.097-.612 2.141-1.464 3.097-2.499.217-.235.36-.398.498-.578.12-.128.216-.334.248-.554 0 .01 0 .01-.008.04l.013-.079-.001.011.003-.031.001-.017v.005l.001-.02v.008l.002-.03.001-.05-.001-.044v-.004-.004zm-.954.045v.007l.001.004V8.33v.012l-.001.01v-.005-.005l.002-.015-.001.008c-.002.014-.002.014 0 0l-.007.084c.003-.057-.004-.041-.014-.031-.143.182-.27.327-.468.543-.89.963-1.856 1.752-2.86 2.311-.724.404-1.419.677-2.095.81a5.63 5.63 0 0 1-2.374-.036c-1.273-.295-2.523-1.014-3.774-2.101-.604-.525-1.075-1.001-1.457-1.496-.054-.07-.054-.107 0-.177.117-.152.244-.298.442-.512.89-.963 1.856-1.752 2.86-2.311.724-.404 1.419-.678 2.095-.81a5.631 5.631 0 0 1 2.374.036c1.272.295 2.523 1.014 3.774 2.101.603.524 1.074 1 1.457 1.496.035.041.043.057.046.076 0 .01 0 .01.008.043l-.009-.047.003.02-.002-.013v-.008.016c0-.004 0-.004 0 0v-.004z\"></path></g></svg>"
 
 /***/ },
-/* 240 */
+/* 241 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 33 12\"><path id=\"base-path\" d=\"M27.1,0H1C0.4,0,0,0.4,0,1v10c0,0.6,0.4,1,1,1h26.1 c0.6,0,1.2-0.3,1.5-0.7L33,6l-4.4-5.3C28.2,0.3,27.7,0,27.1,0z\"></path></svg>"
 
 /***/ },
-/* 241 */
+/* 242 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 6 6\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><path d=\"M1.35191454,5.27895256 L5.31214367,1.35518468 C5.50830675,1.16082764 5.50977084,0.844248536 5.3154138,0.648085456 C5.12105677,0.451922377 4.80447766,0.450458288 4.60831458,0.644815324 L0.648085456,4.56858321 C0.451922377,4.76294025 0.450458288,5.07951935 0.644815324,5.27568243 C0.83917236,5.47184551 1.15575146,5.4733096 1.35191454,5.27895256 L1.35191454,5.27895256 Z\" id=\"Line\" stroke=\"none\" fill=\"#696969\" fill-rule=\"evenodd\"></path><path d=\"M5.31214367,4.56858321 L1.35191454,0.644815324 C1.15575146,0.450458288 0.83917236,0.451922377 0.644815324,0.648085456 C0.450458288,0.844248536 0.451922377,1.16082764 0.648085456,1.35518468 L4.60831458,5.27895256 C4.80447766,5.4733096 5.12105677,5.47184551 5.3154138,5.27568243 C5.50977084,5.07951935 5.50830675,4.76294025 5.31214367,4.56858321 L5.31214367,4.56858321 Z\" id=\"Line-Copy-2\" stroke=\"none\" fill=\"#696969\" fill-rule=\"evenodd\"></path></svg>"
 
 /***/ },
-/* 242 */
+/* 243 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"##4A464C\"><g fill-rule=\"evenodd\"><path d=\"M3.233 11.25l-.417 1H1.712C.763 12.25 0 11.574 0 10.747V6.503C0 5.675.755 5 1.712 5h4.127l-.417 1H1.597C1.257 6 1 6.225 1 6.503v4.244c0 .277.267.503.597.503h1.636zM7.405 11.27L7 12.306c.865.01 2.212-.024 2.315-.04.112-.016.112-.016.185-.035.075-.02.156-.046.251-.082.152-.056.349-.138.592-.244.415-.182.962-.435 1.612-.744l.138-.066a179.35 179.35 0 0 0 2.255-1.094c1.191-.546 1.191-2.074-.025-2.632l-.737-.34a3547.554 3547.554 0 0 0-3.854-1.78c-.029.11-.065.222-.11.336l-.232.596c.894.408 4.56 2.107 4.56 2.107.458.21.458.596 0 .806L9.197 11.27H7.405zM4.462 14.692l5-12a.5.5 0 1 0-.924-.384l-5 12a.5.5 0 1 0 .924.384z\"></path></g></svg>"
 
 /***/ },
-/* 243 */
+/* 244 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"#DDE1E4\"><path d=\"M9.05 4.634l-2.144.003-.116.116v1.445l.92.965.492.034.116-.116v-.617L9.13 5.7l.035-.95M12.482 10.38l-1.505-1.462H9.362l-.564.516-.034 1.108.72.768 1.323.034-.117-.116v1.2l.972 1.02.315.034.116-.116v-1.154l.422-.374.034-.927-.117.117h.26l.408-.36V10.5l-.125-.124-.575-.033\"></path><path d=\"M8.47 15.073c-3.088 0-5.6-2.513-5.6-5.602V9.4v-.003c0-.018 0-.018.002-.034l.182-.088.724.587.49.033.497.543-.034.9.317.383h.47l.114.096-.032 1.9.524.553h.105l.025-.338 1.004-.95.054-.474.53-.462v-.888l-.588-.038-1.118-1.155H4.48l-.154-.09V9.01l.155-.1h1.164v-.273l.12-.115.7.033.494-.443.034-.746-.624-.655h-.724v.28l-.11.07H4.64l-.114-.09.025-.64.48-.43v-.244h-.382c-.102 0-.152-.128-.08-.2 1.04-1.01 2.428-1.59 3.903-1.59 1.374 0 2.672.5 3.688 1.39.08.068.03.198-.075.198l-1.144-.034-.81.803.52.523v.16l-.382.388h-.158l-.176-.177v-.16l.076-.074-.252-.252-.37.362.53.53c.072.072.005.194-.096.194l-.752-.005v.844h.783L9.885 8l.16-.143h.16l.62.61v.267l.58.027.003.002V8.76l.18-.03 1.234 1.24.753-.708h.382l.116.108c0 .02.003.016.003.036v.065c0 3.09-2.515 5.603-5.605 5.603M8.47 3C4.904 3 2 5.903 2 9.47c0 3.57 2.903 6.472 6.47 6.472 3.57 0 6.472-2.903 6.472-6.47C14.942 5.9 12.04 3 8.472 3\"></path></svg>"
 
 /***/ },
-/* 244 */
+/* 245 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"#DDE1E4\"><path d=\"M4 2v12h9V4.775L9.888 2H4zm0-1h5.888c.246 0 .483.09.666.254l3.112 2.774c.212.19.334.462.334.747V14c0 .552-.448 1-1 1H4c-.552 0-1-.448-1-1V2c0-.552.448-1 1-1z\"></path><path d=\"M9 1.5v4c0 .325.306.564.62.485l4-1c.27-.067.432-.338.365-.606-.067-.27-.338-.432-.606-.365l-4 1L10 5.5v-4c0-.276-.224-.5-.5-.5s-.5.224-.5.5z\"></path></svg>"
 
 /***/ },
-/* 245 */
+/* 246 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"#DDE1E5\"><path d=\"M2 5.193v7.652c0 .003-.002 0 .007 0H14v-7.69c0-.003.002 0-.007 0h-7.53v-2.15c0-.002-.004-.005-.01-.005H2.01C2 3 2 3 2 3.005V5.193zm-1 0V3.005C1 2.45 1.444 2 2.01 2h4.442c.558 0 1.01.45 1.01 1.005v1.15h6.53c.557 0 1.008.44 1.008 1v7.69c0 .553-.45 1-1.007 1H2.007c-.556 0-1.007-.44-1.007-1V5.193zM6.08 4.15H2v1h4.46v-1h-.38z\" fill-rule=\"evenodd\"></path></svg>"
 
 /***/ },
-/* 246 */
+/* 247 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"14 6 13 12\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><g id=\"world\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(14.000000, 6.000000)\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M6.35076107,0.354 C3.25095418,0.354 0.729,2.87582735 0.729,5.9758879 C0.729,9.07544113 3.25082735,11.5972685 6.35076107,11.5972685 C9.45044113,11.5972685 11.9723953,9.07544113 11.9723953,5.97576107 C11.9723953,2.87582735 9.45044113,0.354 6.35076107,0.354 L6.35076107,0.354 Z M6.35076107,10.8289121 C3.67445071,10.8289121 1.49722956,8.65181776 1.49722956,5.97576107 C1.49722956,5.9443064 1.49900522,5.91335907 1.49976622,5.88215806 L2.20090094,6.4213266 L2.56313696,6.4213266 L2.97268183,6.8306178 L2.97268183,7.68217686 L3.32324919,8.03287105 L3.73926255,8.03287105 L3.73926255,9.79940584 L4.27386509,10.3361645 L4.4591686,10.3361645 L4.4591686,10.000183 L5.37655417,9.08343163 L5.37655417,8.73400577 L5.85585737,8.25203907 L5.85585737,7.37206934 L5.32518666,7.37206934 L4.28439226,6.33140176 L2.82225748,6.33140176 L2.82225748,5.56938704 L3.96286973,5.56938704 L3.96286973,5.23949352 L4.65068695,5.23949352 L5.11477015,4.77667865 L5.11477015,4.03001076 L4.49087694,3.40662489 L3.75359472,3.40662489 L3.75359472,3.78725175 L2.96228149,3.78725175 L2.96228149,3.28385021 L3.42217919,2.82319151 L3.42217919,2.49786399 L2.97001833,2.49786399 C3.84466106,1.64744643 5.03714814,1.12222956 6.35063424,1.12222956 C7.57292716,1.12222956 8.69020207,1.57730759 9.54442463,2.32587797 L8.46164839,2.32587797 L7.680355,3.10666403 L8.21508437,3.64088607 L7.87238068,3.98257509 L7.7165025,3.82669692 L7.85297518,3.68946324 L7.78930484,3.62566607 L7.78943167,3.62566607 L7.56011699,3.39559038 L7.55986332,3.39571722 L7.49758815,3.33318838 L7.01904595,3.78585658 L7.55910232,4.32654712 L6.8069806,4.32198112 L6.8069806,5.25864535 L7.66716433,5.25864535 L7.6723645,4.72112565 L7.81289584,4.57996014 L8.31819988,5.08653251 L8.31819988,5.41921636 L9.00703176,5.41921636 L9.03366676,5.39321553 L9.03430093,5.39194719 L10.195587,6.55259911 L10.8637451,5.88520206 L11.2018828,5.88520206 C11.2023901,5.9153884 11.2041658,5.94532107 11.2041658,5.97563424 C11.2040389,8.65181776 9.0269446,10.8289121 6.35076107,10.8289121 L6.35076107,10.8289121 Z\" id=\"Shape\" stroke=\"#DDE1E5\" stroke-width=\"0.25\" fill=\"#DDE1E5\"></path><polygon id=\"Shape\" stroke=\"#DDE1E5\" stroke-width=\"0.25\" fill=\"#DDE1E5\" points=\"6.50676608 1.61523076 4.52892694 1.61789426 4.52892694 2.95192735 5.34560683 3.76733891 5.72496536 3.76733891 5.72496536 3.1967157 6.50676608 2.41592965\"></polygon><polygon id=\"Shape\" stroke=\"#DDE1E5\" stroke-width=\"0.25\" fill=\"#DDE1E5\" points=\"9.59959714 6.88718547 8.28623788 5.57268471 8.28623788 5.57002121 6.79607294 5.57002121 6.35101474 6.01469891 6.35101474 6.96201714 6.98429362 7.59466185 8.12909136 7.59466185 8.12909136 8.70343893 8.99434843 9.56882283 9.20971144 9.56882283 9.20971144 8.50329592 9.63029081 8.08271655 9.63029081 7.3026915 9.87025949 7.3026915 10.1711082 7.00082814 10.0558167 6.88718547\"></polygon></g></svg>"
 
 /***/ },
-/* 247 */
+/* 248 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"488 384 14 14\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><path d=\"M495.5,391.5 L500.200877,396.200877\" id=\"Line\" stroke=\"#4A90E2\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\"></path><ellipse id=\"Oval-6\" stroke=\"#4A90E2\" stroke-width=\"1.25\" fill=\"#FFFFFF\" fill-rule=\"evenodd\" cx=\"493.5\" cy=\"389.5\" rx=\"4.5\" ry=\"4.5\"></ellipse></svg>"
 
 /***/ },
-/* 248 */
+/* 249 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"#4A464C\"><g fill-rule=\"evenodd\"><path d=\"M6.5 12.003l.052-9a.5.5 0 1 0-1-.006l-.052 9a.5.5 0 1 0 1 .006zM13 11.997l-.05-9a.488.488 0 0 0-.477-.497.488.488 0 0 0-.473.503l.05 9a.488.488 0 0 0 .477.497.488.488 0 0 0 .473-.503z\"></path></g></svg>"
 
 /***/ },
-/* 249 */
+/* 250 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"975 569 11 11\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><g id=\"Pause-circle\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(976.000000, 570.000000)\"><path d=\"M4.5,0.538639227 C2.3152037,0.538639227 0.538639227,2.31614868 0.538639227,4.5 C0.538639227,6.6847963 2.3152037,8.46136077 4.5,8.46136077 C6.6847963,8.46136077 8.46136077,6.6847963 8.46136077,4.5 C8.46136077,2.31614868 6.6847963,0.538639227 4.5,0.538639227 M4.5,9 C2.01847963,9 0,6.98152037 0,4.5 C0,2.01847963 2.01847963,0 4.5,0 C6.98152037,0 9,2.01847963 9,4.5 C9,6.98152037 6.98152037,9 4.5,9\" id=\"Fill-1-Copy\" stroke=\"#4990E2\" stroke-width=\"0.5\" fill=\"#4990E2\"></path><path d=\"M3,3 L3,6.5\" id=\"Line\" stroke=\"#4990E2\" stroke-width=\"1.15\" stroke-linecap=\"round\"></path><path d=\"M6,3 L6,6.5\" id=\"Line\" stroke=\"#4990E2\" stroke-width=\"1.15\" stroke-linecap=\"round\"></path></g></svg>"
 
 /***/ },
-/* 250 */
+/* 251 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10.483 13.995H5.517l-3.512-3.512V5.516l3.512-3.512h4.966l3.512 3.512v4.967l-3.512 3.512zm4.37-9.042l-3.807-3.805A.503.503 0 0 0 10.691 1H5.309a.503.503 0 0 0-.356.148L1.147 4.953A.502.502 0 0 0 1 5.308v5.383c0 .134.053.262.147.356l3.806 3.806a.503.503 0 0 0 .356.147h5.382a.503.503 0 0 0 .355-.147l3.806-3.806A.502.502 0 0 0 15 10.69V5.308a.502.502 0 0 0-.147-.355z\"></path><path d=\"M10 10.5a.5.5 0 1 0 1 0v-5a.5.5 0 1 0-1 0v5zM5 10.5a.5.5 0 1 0 1 0v-5a.5.5 0 0 0-1 0v5z\"></path></svg>"
 
 /***/ },
-/* 251 */
+/* 252 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"##4A464C\"><path d=\"M4.525 13.21h-.472c-.574 0-.987-.154-1.24-.463-.253-.31-.38-.882-.38-1.719v-.573c0-.746-.097-1.265-.292-1.557-.196-.293-.51-.44-.945-.44v-.974c.435 0 .75-.146.945-.44.195-.292.293-.811.293-1.556v-.58c0-.833.126-1.404.379-1.712.253-.31.666-.464 1.24-.464h.472v.783h-.179c-.37 0-.628.08-.774.24-.145.159-.218.54-.218 1.141v.383c0 .824-.096 1.432-.287 1.823-.191.39-.516.679-.974.866.458.191.783.482.974.873.191.39.287.998.287 1.823v.382c0 .602.073.982.218 1.142.146.16.404.239.774.239h.18v.783zm9.502-4.752c-.43 0-.744.147-.942.44-.197.292-.296.811-.296 1.557v.573c0 .837-.125 1.41-.376 1.719-.251.309-.664.463-1.237.463h-.478v-.783h.185c.37 0 .628-.08.774-.24.145-.159.218-.539.218-1.14v-.383c0-.825.096-1.433.287-1.823.191-.39.516-.682.974-.873-.458-.187-.783-.476-.974-.866-.191-.391-.287-.999-.287-1.823v-.383c0-.602-.073-.982-.218-1.142-.146-.159-.404-.239-.774-.239h-.185v-.783h.478c.573 0 .986.155 1.237.464.25.308.376.88.376 1.712v.58c0 .673.088 1.174.263 1.503.176.329.5.493.975.493v.974z\" fill-rule=\"evenodd\"></path></svg>"
 
 /***/ },
-/* 252 */
+/* 253 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"#696969\"><path d=\"M6.925 12.5l7.4-5-7.4-5v10zM6 12.5v-10c0-.785.8-1.264 1.415-.848l7.4 5c.58.392.58 1.304 0 1.696l-7.4 5C6.8 13.764 6 13.285 6 12.5z\" fill-rule=\"evenodd\"></path></svg>"
 
 /***/ },
-/* 253 */
+/* 254 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 33 12\"><path id=\"base-path\" d=\"M27.1,0H1C0.4,0,0,0.4,0,1v10c0,0.6,0.4,1,1,1h26.1 c0.6,0,1.2-0.3,1.5-0.7L33,6l-4.4-5.3C28.2,0.3,27.7,0,27.1,0z\"></path></svg>"
 
 /***/ },
-/* 254 */
+/* 255 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"#4A464C\"><g fill-rule=\"evenodd\"><path d=\"M1.5 14.042h4.095a.5.5 0 0 0 0-1H1.5a.5.5 0 1 0 0 1zM7.983 2a.5.5 0 0 1 .517.5v7.483l3.136-3.326a.5.5 0 1 1 .728.686l-4 4.243a.499.499 0 0 1-.73-.004L3.635 7.343a.5.5 0 0 1 .728-.686L7.5 9.983V3H1.536C1.24 3 1 2.776 1 2.5s.24-.5.536-.5h6.447zM10.5 14.042h4.095a.5.5 0 0 0 0-1H10.5a.5.5 0 1 0 0 1z\"></path></g></svg>"
 
 /***/ },
-/* 255 */
+/* 256 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"##4A464C\"><g fill-rule=\"evenodd\"><path d=\"M5 13.5H1a.5.5 0 1 0 0 1h4a.5.5 0 1 0 0-1zM12 13.5H8a.5.5 0 1 0 0 1h4a.5.5 0 1 0 0-1zM6.11 5.012A.427.427 0 0 1 6.21 5h7.083L9.646 1.354a.5.5 0 1 1 .708-.708l4.5 4.5a.498.498 0 0 1 0 .708l-4.5 4.5a.5.5 0 0 1-.708-.708L13.293 6H6.5v5.5a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .61-.488z\"></path></g></svg>"
 
 /***/ },
-/* 256 */
+/* 257 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"#4A464C\"><g fill-rule=\"evenodd\"><path d=\"M13.297 6.912C12.595 4.39 10.167 2.5 7.398 2.5A5.898 5.898 0 0 0 1.5 8.398a.5.5 0 0 0 1 0A4.898 4.898 0 0 1 7.398 3.5c2.75 0 5.102 2.236 5.102 4.898v.004L8.669 7.029a.5.5 0 0 0-.338.942l4.462 1.598a.5.5 0 0 0 .651-.34.506.506 0 0 0 .02-.043l2-5a.5.5 0 1 0-.928-.372l-1.24 3.098z\"></path><circle cx=\"7\" cy=\"12\" r=\"1\"></circle></g></svg>"
 
 /***/ },
-/* 257 */
+/* 258 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"#696969\"><path d=\"M12.219 7c.345 0 .635.117.869.352.234.234.351.524.351.869 0 .351-.118.652-.356.903-.238.25-.526.376-.864.376-.332 0-.615-.125-.85-.376a1.276 1.276 0 0 1-.351-.903A1.185 1.185 0 0 1 12.218 7zM8.234 7c.345 0 .635.117.87.352.234.234.351.524.351.869 0 .351-.119.652-.356.903-.238.25-.526.376-.865.376-.332 0-.613-.125-.844-.376a1.286 1.286 0 0 1-.347-.903c0-.352.114-.643.342-.874.228-.231.51-.347.85-.347zM4.201 7c.339 0 .627.117.864.352.238.234.357.524.357.869 0 .351-.119.652-.357.903-.237.25-.525.376-.864.376-.338 0-.623-.125-.854-.376A1.286 1.286 0 0 1 3 8.221 1.185 1.185 0 0 1 4.201 7z\" fill-rule=\"evenodd\"></path></svg>"
 
 /***/ },
-/* 258 */
+/* 259 */
 /***/ function(module, exports) {
 
 	module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"#DDE1E4\"><path fill-rule=\"evenodd\" d=\"M8.5 8.793L5.854 6.146l-.04-.035L7.5 4.426c.2-.2.3-.4.3-.6 0-.2-.1-.4-.2-.6l-1-1c-.4-.3-.9-.3-1.2 0l-4.1 4.1c-.2.2-.3.4-.3.6 0 .2.1.4.2.6l1 1c.3.3.9.3 1.2 0l1.71-1.71.036.04L7.793 9.5l-3.647 3.646c-.195.196-.195.512 0 .708.196.195.512.195.708 0L8.5 10.207l3.646 3.647c.196.195.512.195.708 0 .195-.196.195-.512 0-.708L9.207 9.5l2.565-2.565L13.3 8.5c.1.1 2.3 1.1 2.7.7.4-.4-.3-2.7-.5-2.9l-1.1-1.1c.1-.1.2-.4.2-.6 0-.2-.1-.4-.2-.6l-.4-.4c-.3-.3-.8-.3-1.1 0l-1.5-1.4c-.2-.2-.3-.2-.5-.2s-.3.1-.5.2L9.2 3.4c-.2.1-.2.2-.2.4s.1.4.2.5l1.874 1.92L8.5 8.792z\"></path></svg>"
 
 /***/ },
-/* 259 */
+/* 260 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 260 */,
-/* 261 */
+/* 261 */,
+/* 262 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	var ReactDOM = __webpack_require__(25);
-	var ImPropTypes = __webpack_require__(227);
+	var ImPropTypes = __webpack_require__(228);
 	
 	var _require = __webpack_require__(2);
 	
 	var bindActionCreators = _require.bindActionCreators;
 	
 	var _require2 = __webpack_require__(15);
 	
 	var connect = _require2.connect;
 	
-	var SourceEditor = __webpack_require__(262);
+	var SourceEditor = __webpack_require__(263);
 	
 	var _require3 = __webpack_require__(45);
 	
 	var debugGlobal = _require3.debugGlobal;
 	
-	var _require4 = __webpack_require__(198);
+	var _require4 = __webpack_require__(199);
 	
 	var getSourceText = _require4.getSourceText;
 	var getBreakpointsForSource = _require4.getBreakpointsForSource;
 	var getSelectedLocation = _require4.getSelectedLocation;
 	var getSelectedFrame = _require4.getSelectedFrame;
 	
-	var _require5 = __webpack_require__(194);
+	var _require5 = __webpack_require__(195);
 	
 	var makeLocationId = _require5.makeLocationId;
 	
-	var actions = __webpack_require__(213);
-	var Breakpoint = React.createFactory(__webpack_require__(263));
+	var actions = __webpack_require__(214);
+	var Breakpoint = React.createFactory(__webpack_require__(264));
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	
 	
-	__webpack_require__(264);
+	__webpack_require__(265);
 	
 	function isTextForSource(sourceText) {
 	  return !sourceText.get("loading") && !sourceText.get("error");
 	}
 	
 	/**
 	 * Forces the breakpoint gutter to be the same size as the line
 	 * numbers gutter. Editor CSS will absolutely position the gutter
@@ -33033,29 +33066,29 @@ var Debugger =
 	    selectedLocation,
 	    sourceText: getSourceText(state, sourceId),
 	    breakpoints: getBreakpointsForSource(state, sourceId),
 	    selectedFrame: getSelectedFrame(state)
 	  };
 	}, dispatch => bindActionCreators(actions, dispatch))(Editor);
 
 /***/ },
-/* 262 */
+/* 263 */
 /***/ function(module, exports) {
 
 	module.exports = devtoolsRequire('devtools/client/sourceeditor/editor');
 
 /***/ },
-/* 263 */
+/* 264 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	var PropTypes = React.PropTypes;
 	
-	var classnames = __webpack_require__(206);
+	var classnames = __webpack_require__(207);
 	
 	function makeMarker(isDisabled) {
 	  var marker = document.createElement("div");
 	  marker.className = classnames("editor new-breakpoint", { "breakpoint-disabled": isDisabled });
 	
 	  var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
 	  svg.setAttribute("viewBox", "0 0 60 12");
 	  svg.setAttribute("preserveAspectRatio", "none");
@@ -33115,34 +33148,34 @@ var Debugger =
 	  render() {
 	    return null;
 	  }
 	});
 	
 	module.exports = Breakpoint;
 
 /***/ },
-/* 264 */
+/* 265 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 265 */,
-/* 266 */
+/* 266 */,
+/* 267 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* 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/. */
 	
 	var React = __webpack_require__(17);
 	var ReactDOM = __webpack_require__(25);
-	var Draggable = React.createFactory(__webpack_require__(267));
-	__webpack_require__(268);
+	var Draggable = React.createFactory(__webpack_require__(268));
+	__webpack_require__(269);
 	
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	
 	
 	var SplitBox = React.createClass({
 	  propTypes: {
 	    left: PropTypes.any.isRequired,
@@ -33171,26 +33204,26 @@ var Debugger =
 	    var left = _props.left;
 	    var right = _props.right;
 	    var rightFlex = _props.rightFlex;
 	    var width = this.state.width;
 	
 	
 	    return dom.div({ className: "split-box",
 	      style: this.props.style }, dom.div({ className: rightFlex ? "uncontrolled" : "controlled",
-	      style: { width: rightFlex ? null : width } }, left), Draggable({ className: "splitter",
-	      onMove: x => this.onMove(x) }), dom.div({ className: rightFlex ? "controlled" : "uncontrolled",
+	      style: { width: rightFlex ? null : width } }, left), dom.div({ className: "splitter" }, Draggable({ className: "splitter-handle",
+	      onMove: x => this.onMove(x) })), dom.div({ className: rightFlex ? "controlled" : "uncontrolled",
 	      style: { width: rightFlex ? width : null } }, right));
 	  }
 	});
 	
 	module.exports = SplitBox;
 
 /***/ },
-/* 267 */
+/* 268 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	var ReactDOM = __webpack_require__(25);
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	
 	
@@ -33234,69 +33267,69 @@ var Debugger =
 	      onMouseDown: this.startDragging
 	    });
 	  }
 	});
 	
 	module.exports = Draggable;
 
 /***/ },
-/* 268 */
+/* 269 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 269 */,
-/* 270 */
+/* 270 */,
+/* 271 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	
 	var _require = __webpack_require__(15);
 	
 	var connect = _require.connect;
 	
 	var _require2 = __webpack_require__(2);
 	
 	var bindActionCreators = _require2.bindActionCreators;
 	
-	var _require3 = __webpack_require__(198);
+	var _require3 = __webpack_require__(199);
 	
 	var getPause = _require3.getPause;
 	var getIsWaitingOnBreak = _require3.getIsWaitingOnBreak;
 	var getBreakpointsDisabled = _require3.getBreakpointsDisabled;
 	var getShouldPauseOnExceptions = _require3.getShouldPauseOnExceptions;
 	var getShouldIgnoreCaughtExceptions = _require3.getShouldIgnoreCaughtExceptions;
 	var getBreakpoints = _require3.getBreakpoints;
 	var getBreakpointsLoading = _require3.getBreakpointsLoading;
 	
 	var _require4 = __webpack_require__(46);
 	
 	var isEnabled = _require4.isEnabled;
 	
-	var Svg = __webpack_require__(234);
-	var ImPropTypes = __webpack_require__(227);
-	
-	var _require5 = __webpack_require__(212);
+	var Svg = __webpack_require__(235);
+	var ImPropTypes = __webpack_require__(228);
+	
+	var _require5 = __webpack_require__(213);
 	
 	var Services = _require5.Services;
 	
 	var shiftKey = Services.appinfo.OS === "Darwin" ? "\u21E7" : "Shift+";
 	var ctrlKey = Services.appinfo.OS === "Linux" ? "Ctrl+" : "";
 	
-	var actions = __webpack_require__(213);
-	var Breakpoints = React.createFactory(__webpack_require__(271));
-	var Expressions = React.createFactory(__webpack_require__(274));
-	var Scopes = React.createFactory(__webpack_require__(307));
-	var Frames = React.createFactory(__webpack_require__(339));
-	var Accordion = React.createFactory(__webpack_require__(342));
-	__webpack_require__(345);
+	var actions = __webpack_require__(214);
+	var Breakpoints = React.createFactory(__webpack_require__(272));
+	var Expressions = React.createFactory(__webpack_require__(275));
+	var Scopes = React.createFactory(__webpack_require__(308));
+	var Frames = React.createFactory(__webpack_require__(340));
+	var Accordion = React.createFactory(__webpack_require__(343));
+	__webpack_require__(346);
 	
 	function debugBtn(onClick, type, className, tooltip) {
 	  className = `${ type } ${ className }`;
 	  return dom.span({ onClick, className, key: type }, Svg(type, { title: tooltip }));
 	}
 	
 	var RightSidebar = React.createClass({
 	  propTypes: {
@@ -33474,59 +33507,59 @@ var Debugger =
 	    shouldIgnoreCaughtExceptions: getShouldIgnoreCaughtExceptions(state),
 	    breakpointsDisabled: getBreakpointsDisabled(state),
 	    breakpoints: getBreakpoints(state),
 	    breakpointsLoading: getBreakpointsLoading(state)
 	  };
 	}, dispatch => bindActionCreators(actions, dispatch))(RightSidebar);
 
 /***/ },
-/* 271 */
+/* 272 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	
 	var _require = __webpack_require__(15);
 	
 	var connect = _require.connect;
 	
 	var _require2 = __webpack_require__(2);
 	
 	var bindActionCreators = _require2.bindActionCreators;
 	
-	var ImPropTypes = __webpack_require__(227);
-	var classnames = __webpack_require__(206);
-	var actions = __webpack_require__(213);
-	
-	var _require3 = __webpack_require__(198);
+	var ImPropTypes = __webpack_require__(228);
+	var classnames = __webpack_require__(207);
+	var actions = __webpack_require__(214);
+	
+	var _require3 = __webpack_require__(199);
 	
 	var getSource = _require3.getSource;
 	var getPause = _require3.getPause;
 	var getBreakpoints = _require3.getBreakpoints;
 	
-	var _require4 = __webpack_require__(194);
+	var _require4 = __webpack_require__(195);
 	
 	var makeLocationId = _require4.makeLocationId;
 	
-	var _require5 = __webpack_require__(175);
+	var _require5 = __webpack_require__(176);
 	
 	var truncateStr = _require5.truncateStr;
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	
-	var _require6 = __webpack_require__(175);
+	var _require6 = __webpack_require__(176);
 	
 	var endTruncateStr = _require6.endTruncateStr;
 	
-	var _require7 = __webpack_require__(204);
+	var _require7 = __webpack_require__(205);
 	
 	var basename = _require7.basename;
 	
 	
-	__webpack_require__(272);
+	__webpack_require__(273);
 	
 	function isCurrentlyPausedAtBreakpoint(state, breakpoint) {
 	  var pause = getPause(state);
 	  if (!pause || pause.get("isInterrupted")) {
 	    return false;
 	  }
 	
 	  var bpId = makeLocationId(breakpoint.location);
@@ -33614,53 +33647,53 @@ var Debugger =
 	  }).filter(bp => bp.location.source);
 	}
 	
 	module.exports = connect((state, props) => ({
 	  breakpoints: _getBreakpoints(state)
 	}), dispatch => bindActionCreators(actions, dispatch))(Breakpoints);
 
 /***/ },
-/* 272 */
+/* 273 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 273 */,
-/* 274 */
+/* 274 */,
+/* 275 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	
 	var _require = __webpack_require__(15);
 	
 	var connect = _require.connect;
 	
 	var _require2 = __webpack_require__(2);
 	
 	var bindActionCreators = _require2.bindActionCreators;
 	
-	var ImPropTypes = __webpack_require__(227);
+	var ImPropTypes = __webpack_require__(228);
 	// const classnames = require("classnames");
-	var Svg = __webpack_require__(234);
-	var actions = __webpack_require__(213);
-	
-	var _require3 = __webpack_require__(198);
+	var Svg = __webpack_require__(235);
+	var actions = __webpack_require__(214);
+	
+	var _require3 = __webpack_require__(199);
 	
 	var getExpressions = _require3.getExpressions;
 	var getPause = _require3.getPause;
 	
-	var Rep = React.createFactory(__webpack_require__(275));
+	var Rep = React.createFactory(__webpack_require__(276));
 	// const { truncateStr } = require("../utils/utils");
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	
 	
-	__webpack_require__(305);
+	__webpack_require__(306);
 	
 	var Expressions = React.createClass({
 	  propTypes: {
 	    expressions: ImPropTypes.list,
 	    addExpression: PropTypes.func,
 	    updateExpression: PropTypes.func,
 	    deleteExpression: PropTypes.func
 	  },
@@ -33753,76 +33786,76 @@ var Debugger =
 	      onKeyPress: e => this.inputKeyPress(e, {}) }), expressions.toSeq().map(expression => this.renderExpressionContainer(expression)));
 	  }
 	});
 	
 	module.exports = connect(state => ({ pauseInfo: getPause(state),
 	  expressions: getExpressions(state) }), dispatch => bindActionCreators(actions, dispatch))(Expressions);
 
 /***/ },
-/* 275 */
+/* 276 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
-	var Rep = React.createFactory(__webpack_require__(276).Rep);
-	var Grip = __webpack_require__(302).Grip;
-	
-	__webpack_require__(303);
+	var Rep = React.createFactory(__webpack_require__(277).Rep);
+	var Grip = __webpack_require__(303).Grip;
+	
+	__webpack_require__(304);
 	
 	function renderRep(_ref) {
 	  var object = _ref.object;
 	  var mode = _ref.mode;
 	
 	  return Rep({ object, defaultRep: Grip, mode });
 	}
 	
 	module.exports = renderRep;
 
 /***/ },
-/* 276 */
+/* 277 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // Dependencies
 	  const React = __webpack_require__(17);
 	
-	  const { isGrip } = __webpack_require__(277);
+	  const { isGrip } = __webpack_require__(278);
 	
 	  // Load all existing rep templates
-	  const { Undefined } = __webpack_require__(278);
-	  const { Null } = __webpack_require__(280);
-	  const { StringRep } = __webpack_require__(281);
-	  const { Number } = __webpack_require__(282);
-	  const { ArrayRep } = __webpack_require__(283);
-	  const { Obj } = __webpack_require__(285);
+	  const { Undefined } = __webpack_require__(279);
+	  const { Null } = __webpack_require__(281);
+	  const { StringRep } = __webpack_require__(282);
+	  const { Number } = __webpack_require__(283);
+	  const { ArrayRep } = __webpack_require__(284);
+	  const { Obj } = __webpack_require__(286);
 	
 	  // DOM types (grips)
-	  const { Attribute } = __webpack_require__(287);
-	  const { DateTime } = __webpack_require__(289);
-	  const { Document } = __webpack_require__(290);
-	  const { Event } = __webpack_require__(292);
-	  const { Func } = __webpack_require__(293);
-	  const { NamedNodeMap } = __webpack_require__(294);
-	  const { RegExp } = __webpack_require__(295);
-	  const { StyleSheet } = __webpack_require__(296);
-	  const { TextNode } = __webpack_require__(297);
-	  const { Window } = __webpack_require__(298);
-	  const { ObjectWithText } = __webpack_require__(299);
-	  const { ObjectWithURL } = __webpack_require__(300);
-	  const { GripArray } = __webpack_require__(301);
-	  const { Grip } = __webpack_require__(302);
+	  const { Attribute } = __webpack_require__(288);
+	  const { DateTime } = __webpack_require__(290);
+	  const { Document } = __webpack_require__(291);
+	  const { Event } = __webpack_require__(293);
+	  const { Func } = __webpack_require__(294);
+	  const { NamedNodeMap } = __webpack_require__(295);
+	  const { RegExp } = __webpack_require__(296);
+	  const { StyleSheet } = __webpack_require__(297);
+	  const { TextNode } = __webpack_require__(298);
+	  const { Window } = __webpack_require__(299);
+	  const { ObjectWithText } = __webpack_require__(300);
+	  const { ObjectWithURL } = __webpack_require__(301);
+	  const { GripArray } = __webpack_require__(302);
+	  const { Grip } = __webpack_require__(303);
 	
 	  // List of all registered template.
 	  // XXX there should be a way for extensions to register a new
 	  // or modify an existing rep.
 	  let reps = [
 	    RegExp,
 	    StyleSheet,
 	    Event,
@@ -33906,17 +33939,17 @@ var Debugger =
 	  }
 	
 	  // Exports from this module
 	  exports.Rep = Rep;
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 277 */
+/* 278 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
@@ -33993,33 +34026,33 @@ var Debugger =
 	  exports.createFactories = createFactories;
 	  exports.isGrip = isGrip;
 	  exports.cropString = cropString;
 	  exports.cropMultipleLines = cropMultipleLines;
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 278 */
+/* 279 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // Dependencies
 	  const React = __webpack_require__(17);
-	  const { createFactories } = __webpack_require__(277);
-	  const { ObjectBox } = createFactories(__webpack_require__(279));
+	  const { createFactories } = __webpack_require__(278);
+	  const { ObjectBox } = createFactories(__webpack_require__(280));
 	
 	  /**
 	   * Renders undefined value
 	   */
 	  const Undefined = React.createClass({
 	    displayName: "UndefinedRep",
 	
 	    render: function () {
@@ -34044,17 +34077,17 @@ var Debugger =
 	  exports.Undefined = {
 	    rep: Undefined,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 279 */
+/* 280 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
@@ -34085,33 +34118,33 @@ var Debugger =
 	  });
 	
 	  // Exports from this module
 	  exports.ObjectBox = ObjectBox;
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 280 */
+/* 281 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // Dependencies
 	  const React = __webpack_require__(17);
-	  const { createFactories } = __webpack_require__(277);
-	  const { ObjectBox } = createFactories(__webpack_require__(279));
+	  const { createFactories } = __webpack_require__(278);
+	  const { ObjectBox } = createFactories(__webpack_require__(280));
 	
 	  /**
 	   * Renders null value
 	   */
 	  const Null = React.createClass({
 	    displayName: "NullRep",
 	
 	    render: function () {
@@ -34136,33 +34169,33 @@ var Debugger =
 	  exports.Null = {
 	    rep: Null,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 281 */
+/* 282 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // Dependencies
 	  const React = __webpack_require__(17);
-	  const { createFactories, cropMultipleLines } = __webpack_require__(277);
-	  const { ObjectBox } = createFactories(__webpack_require__(279));
+	  const { createFactories, cropMultipleLines } = __webpack_require__(278);
+	  const { ObjectBox } = createFactories(__webpack_require__(280));
 	
 	  /**
 	   * Renders a string. String value is enclosed within quotes.
 	   */
 	  const StringRep = React.createClass({
 	    displayName: "StringRep",
 	
 	    render: function () {
@@ -34193,33 +34226,33 @@ var Debugger =
 	  exports.StringRep = {
 	    rep: StringRep,
 	    supportsObject: supportsObject,
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 282 */
+/* 283 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // Dependencies
 	  const React = __webpack_require__(17);
-	  const { createFactories } = __webpack_require__(277);
-	  const { ObjectBox } = createFactories(__webpack_require__(279));
+	  const { createFactories } = __webpack_require__(278);
+	  const { ObjectBox } = createFactories(__webpack_require__(280));
 	
 	  /**
 	   * Renders a number
 	   */
 	  const Number = React.createClass({
 	    displayName: "Number",
 	
 	    stringify: function (object) {
@@ -34245,34 +34278,34 @@ var Debugger =
 	  exports.Number = {
 	    rep: Number,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 283 */
+/* 284 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // Dependencies
 	  const React = __webpack_require__(17);
-	  const { createFactories } = __webpack_require__(277);
-	  const { ObjectBox } = createFactories(__webpack_require__(279));
-	  const { Caption } = createFactories(__webpack_require__(284));
+	  const { createFactories } = __webpack_require__(278);
+	  const { ObjectBox } = createFactories(__webpack_require__(280));
+	  const { Caption } = createFactories(__webpack_require__(285));
 	
 	  // Shortcuts
 	  const DOM = React.DOM;
 	
 	  /**
 	   * Renders an array. The array is enclosed by left and right bracket
 	   * and the max number of rendered items depends on the current mode.
 	   */
@@ -34418,17 +34451,17 @@ var Debugger =
 	
 	  /**
 	   * Renders array item. Individual values are separated by a comma.
 	   */
 	  let ItemRep = React.createFactory(React.createClass({
 	    displayName: "ItemRep",
 	
 	    render: function () {
-	      const { Rep } = createFactories(__webpack_require__(276));
+	      const { Rep } = createFactories(__webpack_require__(277));
 	
 	      let object = this.props.object;
 	      let delim = this.props.delim;
 	      return (
 	        DOM.span({},
 	          Rep({object: object}),
 	          delim
 	        )
@@ -34460,17 +34493,17 @@ var Debugger =
 	  exports.ArrayRep = {
 	    rep: ArrayRep,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 284 */
+/* 285 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
@@ -34497,34 +34530,34 @@ var Debugger =
 	  });
 	
 	  // Exports from this module
 	  exports.Caption = Caption;
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 285 */
+/* 286 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	"use strict";
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // Dependencies
 	  const React = __webpack_require__(17);
-	  const { createFactories } = __webpack_require__(277);
-	  const { ObjectBox } = createFactories(__webpack_require__(279));
-	  const { Caption } = createFactories(__webpack_require__(284));
-	  const { PropRep } = createFactories(__webpack_require__(286));
+	  const { createFactories } = __webpack_require__(278);
+	  const { ObjectBox } = createFactories(__webpack_require__(280));
+	  const { Caption } = createFactories(__webpack_require__(285));
+	  const { PropRep } = createFactories(__webpack_require__(287));
 	  // Shortcuts
 	  const { span } = React.DOM;
 	  /**
 	   * Renders an object. An object is represented by a list of its
 	   * properties enclosed in curly brackets.
 	   */
 	  const Obj = React.createClass({
 	    displayName: "Obj",
@@ -34666,30 +34699,30 @@ var Debugger =
 	  exports.Obj = {
 	    rep: Obj,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 286 */
+/* 287 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  const React = __webpack_require__(17);
-	  const { createFactories } = __webpack_require__(277);
+	  const { createFactories } = __webpack_require__(278);
 	
 	  const { span } = React.DOM;
 	
 	  /**
 	   * Property for Obj (local JS objects) and Grip (remote JS objects)
 	   * reps. It's used to render object properties.
 	   */
 	  let PropRep = React.createFactory(React.createClass({
@@ -34700,17 +34733,17 @@ var Debugger =
 	      name: React.PropTypes.string,
 	      // Equal character rendered between property name and value.
 	      equal: React.PropTypes.string,
 	      // Delimiter character used to separate individual properties.
 	      delim: React.PropTypes.string,
 	    },
 	
 	    render: function () {
-	      let { Rep } = createFactories(__webpack_require__(276));
+	      let { Rep } = createFactories(__webpack_require__(277));
 	
 	      return (
 	        span({},
 	          span({
 	            "className": "nodeName"},
 	            this.props.name),
 	          span({
 	            "className": "objectEqual",
@@ -34729,35 +34762,35 @@ var Debugger =
 	  }));
 	
 	  // Exports from this module
 	  exports.PropRep = PropRep;
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 287 */
+/* 288 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // ReactJS
 	  const React = __webpack_require__(17);
 	
 	  // Reps
-	  const { createFactories, isGrip } = __webpack_require__(277);
-	  const { ObjectLink } = createFactories(__webpack_require__(288));
-	  const { StringRep } = __webpack_require__(281);
+	  const { createFactories, isGrip } = __webpack_require__(278);
+	  const { ObjectLink } = createFactories(__webpack_require__(289));
+	  const { StringRep } = __webpack_require__(282);
 	
 	  // Shortcuts
 	  const { span } = React.DOM;
 	  const { rep: StringRepFactory } = createFactories(StringRep);
 	
 	  /**
 	   * Renders DOM attribute
 	   */
@@ -34805,17 +34838,17 @@ var Debugger =
 	  exports.Attribute = {
 	    rep: Attribute,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 288 */
+/* 289 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
@@ -34847,34 +34880,34 @@ var Debugger =
 	  });
 	
 	  // Exports from this module
 	  exports.ObjectLink = ObjectLink;
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 289 */
+/* 290 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // ReactJS
 	  const React = __webpack_require__(17);
 	
 	  // Reps
-	  const { createFactories, isGrip } = __webpack_require__(277);
-	  const { ObjectLink } = createFactories(__webpack_require__(288));
+	  const { createFactories, isGrip } = __webpack_require__(278);
+	  const { ObjectLink } = createFactories(__webpack_require__(289));
 	
 	  // Shortcuts
 	  const { span } = React.DOM;
 	
 	  /**
 	   * Used to render JS built-in Date() object.
 	   */
 	  let DateTime = React.createClass({
@@ -34914,35 +34947,35 @@ var Debugger =
 	  exports.DateTime = {
 	    rep: DateTime,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 290 */
+/* 291 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // ReactJS
 	  const React = __webpack_require__(17);
 	
 	  // Reps
-	  const { createFactories, isGrip } = __webpack_require__(277);
-	  const { ObjectBox } = createFactories(__webpack_require__(279));
-	  const { getFileName } = __webpack_require__(291);
+	  const { createFactories, isGrip } = __webpack_require__(278);
+	  const { ObjectBox } = createFactories(__webpack_require__(280));
+	  const { getFileName } = __webpack_require__(292);
 	
 	  // Shortcuts
 	  const { span } = React.DOM;
 	
 	  /**
 	   * Renders DOM document object.
 	   */
 	  let Document = React.createClass({
@@ -34992,17 +35025,17 @@ var Debugger =
 	  exports.Document = {
 	    rep: Document,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 291 */
+/* 292 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	/* global URLSearchParams */
@@ -35079,34 +35112,34 @@ var Debugger =
 	  // Exports from this module
 	  exports.parseURLParams = parseURLParams;
 	  exports.parseURLEncodedText = parseURLEncodedText;
 	  exports.getFileName = getFileName;
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 292 */
+/* 293 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // ReactJS
 	  const React = __webpack_require__(17);
 	
 	  // Reps
-	  const { createFactories, isGrip } = __webpack_require__(277);
-	  const { ObjectLink } = createFactories(__webpack_require__(288));
+	  const { createFactories, isGrip } = __webpack_require__(278);
+	  const { ObjectLink } = createFactories(__webpack_require__(289));
 	
 	  /**
 	   * Renders DOM event objects.
 	   */
 	  let Event = React.createClass({
 	    displayName: "event",
 	
 	    propTypes: {
@@ -35154,34 +35187,34 @@ var Debugger =
 	  exports.Event = {
 	    rep: Event,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 293 */
+/* 294 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // ReactJS
 	  const React = __webpack_require__(17);
 	
 	  // Reps
-	  const { createFactories, isGrip, cropString } = __webpack_require__(277);
-	  const { ObjectLink } = createFactories(__webpack_require__(288));
+	  const { createFactories, isGrip, cropString } = __webpack_require__(278);
+	  const { ObjectLink } = createFactories(__webpack_require__(289));
 	
 	  /**
 	   * This component represents a template for Function objects.
 	   */
 	  let Func = React.createClass({
 	    displayName: "Func",
 	
 	    propTypes: {
@@ -35219,35 +35252,35 @@ var Debugger =
 	  exports.Func = {
 	    rep: Func,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 294 */
+/* 295 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // ReactJS
 	  const React = __webpack_require__(17);
 	
 	  // Reps
-	  const { createFactories, isGrip } = __webpack_require__(277);
-	  const { ObjectLink } = createFactories(__webpack_require__(288));
-	  const { Caption } = createFactories(__webpack_require__(284));
+	  const { createFactories, isGrip } = __webpack_require__(278);
+	  const { ObjectLink } = createFactories(__webpack_require__(289));
+	  const { Caption } = createFactories(__webpack_require__(285));
 	
 	  // Shortcuts
 	  const { span } = React.DOM;
 	
 	  /**
 	   * Used to render a map of values provided as a grip.
 	   */
 	  let NamedNodeMap = React.createClass({
@@ -35355,17 +35388,17 @@ var Debugger =
 	    displayName: "PropRep",
 	
 	    propTypes: {
 	      equal: React.PropTypes.string,
 	      delim: React.PropTypes.string,
 	    },
 	
 	    render: function () {
-	      const { Rep } = createFactories(__webpack_require__(276));
+	      const { Rep } = createFactories(__webpack_require__(277));
 	
 	      return (
 	        span({},
 	          span({
 	            className: "nodeName"},
 	            "$prop.name"
 	          ),
 	          span({
@@ -35398,34 +35431,34 @@ var Debugger =
 	  exports.NamedNodeMap = {
 	    rep: NamedNodeMap,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 295 */
+/* 296 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // ReactJS
 	  const React = __webpack_require__(17);
 	
 	  // Reps
-	  const { createFactories, isGrip } = __webpack_require__(277);
-	  const { ObjectLink } = createFactories(__webpack_require__(288));
+	  const { createFactories, isGrip } = __webpack_require__(278);
+	  const { ObjectLink } = createFactories(__webpack_require__(289));
 	
 	  // Shortcuts
 	  const { span } = React.DOM;
 	
 	  /**
 	   * Renders a grip object with regular expression.
 	   */
 	  let RegExp = React.createClass({
@@ -35473,35 +35506,35 @@ var Debugger =
 	  exports.RegExp = {
 	    rep: RegExp,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 296 */
+/* 297 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // ReactJS
 	  const React = __webpack_require__(17);
 	
 	  // Reps
-	  const { createFactories, isGrip } = __webpack_require__(277);
-	  const { ObjectBox } = createFactories(__webpack_require__(279));
-	  const { getFileName } = __webpack_require__(291);
+	  const { createFactories, isGrip } = __webpack_require__(278);
+	  const { ObjectBox } = createFactories(__webpack_require__(280));
+	  const { getFileName } = __webpack_require__(292);
 	
 	  // Shortcuts
 	  const DOM = React.DOM;
 	
 	  /**
 	   * Renders a grip representing CSSStyleSheet
 	   */
 	  let StyleSheet = React.createClass({
@@ -35546,34 +35579,34 @@ var Debugger =
 	  exports.StyleSheet = {
 	    rep: StyleSheet,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 297 */
+/* 298 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // ReactJS
 	  const React = __webpack_require__(17);
 	
 	  // Reps
-	  const { createFactories, isGrip, cropMultipleLines } = __webpack_require__(277);
-	  const { ObjectLink } = createFactories(__webpack_require__(288));
+	  const { createFactories, isGrip, cropMultipleLines } = __webpack_require__(278);
+	  const { ObjectLink } = createFactories(__webpack_require__(289));
 	
 	  // Shortcuts
 	  const DOM = React.DOM;
 	
 	  /**
 	   * Renders DOM #text node.
 	   */
 	  let TextNode = React.createClass({
@@ -35633,34 +35666,34 @@ var Debugger =
 	  exports.TextNode = {
 	    rep: TextNode,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 298 */
+/* 299 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // ReactJS
 	  const React = __webpack_require__(17);
 	
 	  // Reps
-	  const { createFactories, isGrip, cropString } = __webpack_require__(277);
-	  const { ObjectBox } = createFactories(__webpack_require__(279));
+	  const { createFactories, isGrip, cropString } = __webpack_require__(278);
+	  const { ObjectBox } = createFactories(__webpack_require__(280));
 	
 	  // Shortcuts
 	  const DOM = React.DOM;
 	
 	  /**
 	   * Renders a grip representing a window.
 	   */
 	  let Window = React.createClass({
@@ -35701,34 +35734,34 @@ var Debugger =
 	  exports.Window = {
 	    rep: Window,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 299 */
+/* 300 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // ReactJS
 	  const React = __webpack_require__(17);
 	
 	  // Reps
-	  const { createFactories, isGrip } = __webpack_require__(277);
-	  const { ObjectLink } = createFactories(__webpack_require__(288));
+	  const { createFactories, isGrip } = __webpack_require__(278);
+	  const { ObjectLink } = createFactories(__webpack_require__(289));
 	
 	  // Shortcuts
 	  const { span } = React.DOM;
 	
 	  /**
 	   * Renders a grip object with textual data.
 	   */
 	  let ObjectWithText = React.createClass({
@@ -35772,34 +35805,34 @@ var Debugger =
 	  exports.ObjectWithText = {
 	    rep: ObjectWithText,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 300 */
+/* 301 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // ReactJS
 	  const React = __webpack_require__(17);
 	
 	  // Reps
-	  const { createFactories, isGrip } = __webpack_require__(277);
-	  const { ObjectLink } = createFactories(__webpack_require__(288));
+	  const { createFactories, isGrip } = __webpack_require__(278);
+	  const { ObjectLink } = createFactories(__webpack_require__(289));
 	
 	  // Shortcuts
 	  const { span } = React.DOM;
 	
 	  /**
 	   * Renders a grip object with URL data.
 	   */
 	  let ObjectWithURL = React.createClass({
@@ -35843,34 +35876,34 @@ var Debugger =
 	  exports.ObjectWithURL = {
 	    rep: ObjectWithURL,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 301 */
+/* 302 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // Dependencies
 	  const React = __webpack_require__(17);
-	  const { createFactories, isGrip } = __webpack_require__(277);
-	  const { ObjectBox } = createFactories(__webpack_require__(279));
-	  const { Caption } = createFactories(__webpack_require__(284));
+	  const { createFactories, isGrip } = __webpack_require__(278);
+	  const { ObjectBox } = createFactories(__webpack_require__(280));
+	  const { Caption } = createFactories(__webpack_require__(285));
 	
 	  // Shortcuts
 	  const { a, span } = React.DOM;
 	
 	  /**
 	   * Renders an array. The array is enclosed by left and right bracket
 	   * and the max number of rendered items depends on the current mode.
 	   */
@@ -35992,17 +36025,17 @@ var Debugger =
 	  let GripArrayItem = React.createFactory(React.createClass({
 	    displayName: "GripArrayItem",
 	
 	    propTypes: {
 	      delim: React.PropTypes.string,
 	    },
 	
 	    render: function () {
-	      let { Rep } = createFactories(__webpack_require__(276));
+	      let { Rep } = createFactories(__webpack_require__(277));
 	
 	      return (
 	        span({},
 	          Rep(Object.assign({}, this.props, {
 	            mode: "tiny"
 	          })),
 	          this.props.delim
 	        )
@@ -36037,35 +36070,35 @@ var Debugger =
 	  exports.GripArray = {
 	    rep: GripArray,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 302 */
+/* 303 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	// Make this available to both AMD and CJS environments
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	  // ReactJS
 	  const React = __webpack_require__(17);
 	  // Dependencies
-	  const { createFactories, isGrip } = __webpack_require__(277);
-	  const { ObjectBox } = createFactories(__webpack_require__(279));
-	  const { Caption } = createFactories(__webpack_require__(284));
-	  const { PropRep } = createFactories(__webpack_require__(286));
+	  const { createFactories, isGrip } = __webpack_require__(278);
+	  const { ObjectBox } = createFactories(__webpack_require__(280));
+	  const { Caption } = createFactories(__webpack_require__(285));
+	  const { PropRep } = createFactories(__webpack_require__(287));
 	  // Shortcuts
 	  const { span } = React.DOM;
 	
 	  /**
 	   * Renders generic grip. Grip is client representation
 	   * of remote JS object and is used as an input object
 	   * for this rep component.
 	   */
@@ -36224,59 +36257,59 @@ var Debugger =
 	  exports.Grip = {
 	    rep: Grip,
 	    supportsObject: supportsObject
 	  };
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
-/* 303 */
+/* 304 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 304 */,
-/* 305 */
+/* 305 */,
+/* 306 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 306 */,
-/* 307 */
+/* 307 */,
+/* 308 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	
 	var _require = __webpack_require__(2);
 	
 	var bindActionCreators = _require.bindActionCreators;
 	
 	var _require2 = __webpack_require__(15);
 	
 	var connect = _require2.connect;
 	
-	var ImPropTypes = __webpack_require__(227);
-	var actions = __webpack_require__(213);
-	
-	var _require3 = __webpack_require__(198);
+	var ImPropTypes = __webpack_require__(228);
+	var actions = __webpack_require__(214);
+	
+	var _require3 = __webpack_require__(199);
 	
 	var getSelectedFrame = _require3.getSelectedFrame;
 	var getLoadedObjects = _require3.getLoadedObjects;
 	var getPause = _require3.getPause;
 	
-	var ObjectInspector = React.createFactory(__webpack_require__(308));
+	var ObjectInspector = React.createFactory(__webpack_require__(309));
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	
-	var toPairs = __webpack_require__(312);
-	
-	__webpack_require__(337);
+	var toPairs = __webpack_require__(313);
+	
+	__webpack_require__(338);
 	
 	function info(text) {
 	  return dom.div({ className: "pane-info" }, text);
 	}
 	
 	// Create the tree nodes representing all the variables and arguments
 	// for the bindings from a scope.
 	function getBindingVariables(bindings, parentName) {
@@ -36446,24 +36479,24 @@ var Debugger =
 	
 	module.exports = connect(state => ({
 	  pauseInfo: getPause(state),
 	  selectedFrame: getSelectedFrame(state),
 	  loadedObjects: getLoadedObjects(state)
 	}), dispatch => bindActionCreators(actions, dispatch))(Scopes);
 
 /***/ },
-/* 308 */
+/* 309 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
-	var classnames = __webpack_require__(206);
-	var ManagedTree = React.createFactory(__webpack_require__(230));
-	var Arrow = React.createFactory(__webpack_require__(309));
-	var Rep = __webpack_require__(275);
+	var classnames = __webpack_require__(207);
+	var ManagedTree = React.createFactory(__webpack_require__(231));
+	var Arrow = React.createFactory(__webpack_require__(310));
+	var Rep = __webpack_require__(276);
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	
 	// This implements a component that renders an interactive inspector
 	// for looking at JavaScript objects. It expects descriptions of
 	// objects from the protocol, and will dynamically fetch child
 	// properties as objects are expanded.
 	//
@@ -36635,49 +36668,49 @@ var Debugger =
 	      renderItem: this.renderItem
 	    });
 	  }
 	});
 	
 	module.exports = ObjectInspector;
 
 /***/ },
-/* 309 */
+/* 310 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
-	var InlineSVG = __webpack_require__(236);
+	var InlineSVG = __webpack_require__(237);
 	var dom = React.DOM;
 	
-	__webpack_require__(310);
+	__webpack_require__(311);
 	
 	// This is inline because it's much faster. We need to revisit how we
 	// load SVGs, at least for components that render them several times.
 	var Arrow = props => {
 	  var className = "arrow " + (props.className || "");
 	  return dom.span(Object.assign({}, props, { className }), React.createElement(InlineSVG, {
-	    src: __webpack_require__(238)
+	    src: __webpack_require__(239)
 	  }));
 	};
 	
 	module.exports = Arrow;
 
 /***/ },
-/* 310 */
+/* 311 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 311 */,
-/* 312 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var createToPairs = __webpack_require__(313),
-	    keys = __webpack_require__(323);
+/* 312 */,
+/* 313 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var createToPairs = __webpack_require__(314),
+	    keys = __webpack_require__(324);
 	
 	/**
 	 * Creates an array of own enumerable string keyed-value pairs for `object`
 	 * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
 	 * entries are returned.
 	 *
 	 * @static
 	 * @memberOf _
@@ -36699,23 +36732,23 @@ var Debugger =
 	 * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
 	 */
 	var toPairs = createToPairs(keys);
 	
 	module.exports = toPairs;
 
 
 /***/ },
-/* 313 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var baseToPairs = __webpack_require__(314),
-	    getTag = __webpack_require__(316),
-	    mapToArray = __webpack_require__(321),
-	    setToPairs = __webpack_require__(322);
+/* 314 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var baseToPairs = __webpack_require__(315),
+	    getTag = __webpack_require__(317),
+	    mapToArray = __webpack_require__(322),
+	    setToPairs = __webpack_require__(323);
 	
 	/** `Object#toString` result references. */
 	var mapTag = '[object Map]',
 	    setTag = '[object Set]';
 	
 	/**
 	 * Creates a `_.toPairs` or `_.toPairsIn` function.
 	 *
@@ -36735,20 +36768,20 @@ var Debugger =
 	    return baseToPairs(object, keysFunc(object));
 	  };
 	}
 	
 	module.exports = createToPairs;
 
 
 /***/ },
-/* 314 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var arrayMap = __webpack_require__(315);
+/* 315 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var arrayMap = __webpack_require__(316);
 	
 	/**
 	 * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
 	 * of key-value pairs for `object` corresponding to the property names of `props`.
 	 *
 	 * @private
 	 * @param {Object} object The object to query.
 	 * @param {Array} props The property names to get values for.
@@ -36759,17 +36792,17 @@ var Debugger =
 	    return [key, object[key]];
 	  });
 	}
 	
 	module.exports = baseToPairs;
 
 
 /***/ },
-/* 315 */
+/* 316 */
 /***/ function(module, exports) {
 
 	/**
 	 * A specialized version of `_.map` for arrays without support for iteratee
 	 * shorthands.
 	 *
 	 * @private
 	 * @param {Array} [array] The array to iterate over.
@@ -36786,24 +36819,24 @@ var Debugger =
 	  }
 	  return result;
 	}
 	
 	module.exports = arrayMap;
 
 
 /***/ },
-/* 316 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var DataView = __webpack_require__(317),
+/* 317 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var DataView = __webpack_require__(318),
 	    Map = __webpack_require__(82),
-	    Promise = __webpack_require__(318),
-	    Set = __webpack_require__(319),
-	    WeakMap = __webpack_require__(320),
+	    Promise = __webpack_require__(319),
+	    Set = __webpack_require__(320),
+	    WeakMap = __webpack_require__(321),
 	    toSource = __webpack_require__(68);
 	
 	/** `Object#toString` result references. */
 	var mapTag = '[object Map]',
 	    objectTag = '[object Object]',
 	    promiseTag = '[object Promise]',
 	    setTag = '[object Set]',
 	    weakMapTag = '[object WeakMap]';
@@ -36862,69 +36895,69 @@ var Debugger =
 	    return result;
 	  };
 	}
 	
 	module.exports = getTag;
 
 
 /***/ },
-/* 317 */
+/* 318 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var getNative = __webpack_require__(60),
 	    root = __webpack_require__(66);
 	
 	/* Built-in method references that are verified to be native. */
 	var DataView = getNative(root, 'DataView');
 	
 	module.exports = DataView;
 
 
 /***/ },
-/* 318 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var getNative = __webpack_require__(60),
-	    root = __webpack_require__(66);
-	
-	/* Built-in method references that are verified to be native. */
-	var Promise = getNative(root, 'Promise');
-	
-	module.exports = Promise;
-
-
-/***/ },
 /* 319 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var getNative = __webpack_require__(60),
 	    root = __webpack_require__(66);
 	
 	/* Built-in method references that are verified to be native. */
-	var Set = getNative(root, 'Set');
-	
-	module.exports = Set;
+	var Promise = getNative(root, 'Promise');
+	
+	module.exports = Promise;
 
 
 /***/ },
 /* 320 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var getNative = __webpack_require__(60),
 	    root = __webpack_require__(66);
 	
 	/* Built-in method references that are verified to be native. */
-	var WeakMap = getNative(root, 'WeakMap');
-	
-	module.exports = WeakMap;
+	var Set = getNative(root, 'Set');
+	
+	module.exports = Set;
 
 
 /***/ },
 /* 321 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var getNative = __webpack_require__(60),
+	    root = __webpack_require__(66);
+	
+	/* Built-in method references that are verified to be native. */
+	var WeakMap = getNative(root, 'WeakMap');
+	
+	module.exports = WeakMap;
+
+
+/***/ },
+/* 322 */
 /***/ function(module, exports) {
 
 	/**
 	 * Converts `map` to its key-value pairs.
 	 *
 	 * @private
 	 * @param {Object} map The map to convert.
 	 * @returns {Array} Returns the key-value pairs.
@@ -36938,17 +36971,17 @@ var Debugger =
 	  });
 	  return result;
 	}
 	
 	module.exports = mapToArray;
 
 
 /***/ },
-/* 322 */
+/* 323 */
 /***/ function(module, exports) {
 
 	/**
 	 * Converts `set` to its value-value pairs.
 	 *
 	 * @private
 	 * @param {Object} set The set to convert.
 	 * @returns {Array} Returns the value-value pairs.
@@ -36962,25 +36995,25 @@ var Debugger =
 	  });
 	  return result;
 	}
 	
 	module.exports = setToPairs;
 
 
 /***/ },
-/* 323 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var baseHas = __webpack_require__(324),
-	    baseKeys = __webpack_require__(325),
-	    indexKeys = __webpack_require__(326),
-	    isArrayLike = __webpack_require__(330),
-	    isIndex = __webpack_require__(335),
-	    isPrototype = __webpack_require__(336);
+/* 324 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var baseHas = __webpack_require__(325),
+	    baseKeys = __webpack_require__(326),
+	    indexKeys = __webpack_require__(327),
+	    isArrayLike = __webpack_require__(331),
+	    isIndex = __webpack_require__(336),
+	    isPrototype = __webpack_require__(337);
 	
 	/**
 	 * Creates an array of the own enumerable property names of `object`.
 	 *
 	 * **Note:** Non-object values are coerced to objects. See the
 	 * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
 	 * for more details.
 	 *
@@ -37024,17 +37057,17 @@ var Debugger =
 	  }
 	  return result;
 	}
 	
 	module.exports = keys;
 
 
 /***/ },
-/* 324 */
+/* 325 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var getPrototype = __webpack_require__(5);
 	
 	/** Used for built-in method references. */
 	var objectProto = Object.prototype;
 	
 	/** Used to check objects for own properties. */
@@ -37056,17 +37089,17 @@ var Debugger =
 	    (hasOwnProperty.call(object, key) ||
 	      (typeof object == 'object' && key in object && getPrototype(object) === null));
 	}
 	
 	module.exports = baseHas;
 
 
 /***/ },
-/* 325 */
+/* 326 */
 /***/ function(module, exports) {
 
 	/* Built-in method references for those with the same name as other `lodash` methods. */
 	var nativeKeys = Object.keys;
 	
 	/**
 	 * The base implementation of `_.keys` which doesn't skip the constructor
 	 * property of prototypes or treat sparse arrays as dense.
@@ -37078,24 +37111,24 @@ var Debugger =
 	function baseKeys(object) {
 	  return nativeKeys(Object(object));
 	}
 	
 	module.exports = baseKeys;
 
 
 /***/ },
-/* 326 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var baseTimes = __webpack_require__(327),
-	    isArguments = __webpack_require__(328),
+/* 327 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var baseTimes = __webpack_require__(328),
+	    isArguments = __webpack_require__(329),
 	    isArray = __webpack_require__(52),
-	    isLength = __webpack_require__(333),
-	    isString = __webpack_require__(334);
+	    isLength = __webpack_require__(334),
+	    isString = __webpack_require__(335);
 	
 	/**
 	 * Creates an array of index keys for `object` values of arrays,
 	 * `arguments` objects, and strings, otherwise `null` is returned.
 	 *
 	 * @private
 	 * @param {Object} object The object to query.
 	 * @returns {Array|null} Returns index keys, else `null`.
@@ -37108,17 +37141,17 @@ var Debugger =
 	  }
 	  return null;
 	}
 	
 	module.exports = indexKeys;
 
 
 /***/ },
-/* 327 */
+/* 328 */
 /***/ function(module, exports) {
 
 	/**
 	 * The base implementation of `_.times` without support for iteratee shorthands
 	 * or max array length checks.
 	 *
 	 * @private
 	 * @param {number} n The number of times to invoke `iteratee`.
@@ -37134,20 +37167,20 @@ var Debugger =
 	  }
 	  return result;
 	}
 	
 	module.exports = baseTimes;
 
 
 /***/ },
-/* 328 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isArrayLikeObject = __webpack_require__(329);
+/* 329 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isArrayLikeObject = __webpack_require__(330);
 	
 	/** `Object#toString` result references. */
 	var argsTag = '[object Arguments]';
 	
 	/** Used for built-in method references. */
 	var objectProto = Object.prototype;
 	
 	/** Used to check objects for own properties. */
@@ -37186,20 +37219,20 @@ var Debugger =
 	  return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
 	    (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
 	}
 	
 	module.exports = isArguments;
 
 
 /***/ },
-/* 329 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isArrayLike = __webpack_require__(330),
+/* 330 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isArrayLike = __webpack_require__(331),
 	    isObjectLike = __webpack_require__(7);
 	
 	/**
 	 * This method is like `_.isArrayLike` except that it also checks if `value`
 	 * is an object.
 	 *
 	 * @static
 	 * @memberOf _
@@ -37225,22 +37258,22 @@ var Debugger =
 	function isArrayLikeObject(value) {
 	  return isObjectLike(value) && isArrayLike(value);
 	}
 	
 	module.exports = isArrayLikeObject;
 
 
 /***/ },
-/* 330 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var getLength = __webpack_require__(331),
+/* 331 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var getLength = __webpack_require__(332),
 	    isFunction = __webpack_require__(62),
-	    isLength = __webpack_require__(333);
+	    isLength = __webpack_require__(334);
 	
 	/**
 	 * Checks if `value` is array-like. A value is considered array-like if it's
 	 * not a function and has a `value.length` that's an integer greater than or
 	 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 	 *
 	 * @static
 	 * @memberOf _
@@ -37265,20 +37298,20 @@ var Debugger =
 	function isArrayLike(value) {
 	  return value != null && isLength(getLength(value)) && !isFunction(value);
 	}
 	
 	module.exports = isArrayLike;
 
 
 /***/ },
-/* 331 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var baseProperty = __webpack_require__(332);
+/* 332 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var baseProperty = __webpack_require__(333);
 	
 	/**
 	 * Gets the "length" property value of `object`.
 	 *
 	 * **Note:** This function is used to avoid a
 	 * [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) that affects
 	 * Safari on at least iOS 8.1-8.3 ARM64.
 	 *
@@ -37287,17 +37320,17 @@ var Debugger =
 	 * @returns {*} Returns the "length" value.
 	 */
 	var getLength = baseProperty('length');
 	
 	module.exports = getLength;
 
 
 /***/ },
-/* 332 */
+/* 333 */
 /***/ function(module, exports) {
 
 	/**
 	 * The base implementation of `_.property` without support for deep paths.
 	 *
 	 * @private
 	 * @param {string} key The key of the property to get.
 	 * @returns {Function} Returns the new accessor function.
@@ -37307,17 +37340,17 @@ var Debugger =
 	    return object == null ? undefined : object[key];
 	  };
 	}
 	
 	module.exports = baseProperty;
 
 
 /***/ },
-/* 333 */
+/* 334 */
 /***/ function(module, exports) {
 
 	/** Used as references for various `Number` constants. */
 	var MAX_SAFE_INTEGER = 9007199254740991;
 	
 	/**
 	 * Checks if `value` is a valid array-like length.
 	 *
@@ -37349,17 +37382,17 @@ var Debugger =
 	  return typeof value == 'number' &&
 	    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
 	}
 	
 	module.exports = isLength;
 
 
 /***/ },
-/* 334 */
+/* 335 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var isArray = __webpack_require__(52),
 	    isObjectLike = __webpack_require__(7);
 	
 	/** `Object#toString` result references. */
 	var stringTag = '[object String]';
 	
@@ -37395,17 +37428,17 @@ var Debugger =
 	  return typeof value == 'string' ||
 	    (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag);
 	}
 	
 	module.exports = isString;
 
 
 /***/ },
-/* 335 */
+/* 336 */
 /***/ function(module, exports) {
 
 	/** Used as references for various `Number` constants. */
 	var MAX_SAFE_INTEGER = 9007199254740991;
 	
 	/** Used to detect unsigned integer values. */
 	var reIsUint = /^(?:0|[1-9]\d*)$/;
 	
@@ -37423,17 +37456,17 @@ var Debugger =
 	    (typeof value == 'number' || reIsUint.test(value)) &&
 	    (value > -1 && value % 1 == 0 && value < length);
 	}
 	
 	module.exports = isIndex;
 
 
 /***/ },
-/* 336 */
+/* 337 */
 /***/ function(module, exports) {
 
 	/** Used for built-in method references. */
 	var objectProto = Object.prototype;
 	
 	/**
 	 * Checks if `value` is likely a prototype object.
 	 *
@@ -37447,57 +37480,57 @@ var Debugger =
 	
 	  return value === proto;
 	}
 	
 	module.exports = isPrototype;
 
 
 /***/ },
-/* 337 */
+/* 338 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 338 */,
-/* 339 */
+/* 339 */,
+/* 340 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	var dom = React.DOM;
 	var div = dom.div;
 	
 	var _require = __webpack_require__(2);
 	
 	var bindActionCreators = _require.bindActionCreators;
 	
 	var _require2 = __webpack_require__(15);
 	
 	var connect = _require2.connect;
 	
-	var actions = __webpack_require__(213);
-	
-	var _require3 = __webpack_require__(175);
+	var actions = __webpack_require__(214);
+	
+	var _require3 = __webpack_require__(176);
 	
 	var endTruncateStr = _require3.endTruncateStr;
 	
-	var _require4 = __webpack_require__(204);
+	var _require4 = __webpack_require__(205);
 	
 	var basename = _require4.basename;
 	
-	var _require5 = __webpack_require__(198);
+	var _require5 = __webpack_require__(199);
 	
 	var getFrames = _require5.getFrames;
 	var getSelectedFrame = _require5.getSelectedFrame;
 	var getSource = _require5.getSource;
 	
 	
 	if (typeof window == "object") {
-	  __webpack_require__(340);
+	  __webpack_require__(341);
 	}
 	
 	function renderFrameTitle(frame) {
 	  return div({ className: "title" }, endTruncateStr(frame.displayName, 40));
 	}
 	
 	function renderFrameLocation(frame) {
 	  var url = frame.source.url ? basename(frame.source.url) : "";
@@ -37528,36 +37561,36 @@ var Debugger =
 	    return Object.assign({}, frame, {
 	      source: getSource(state, frame.location.sourceId).toJS()
 	    });
 	  }),
 	  selectedFrame: getSelectedFrame(state)
 	}), dispatch => bindActionCreators(actions, dispatch))(Frames);
 
 /***/ },
-/* 340 */
+/* 341 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 341 */,
-/* 342 */
+/* 342 */,
+/* 343 */
 /***/ function(module, exports, __webpack_require__) {
 
 	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
 	
 	var React = __webpack_require__(17);
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	var div = dom.div;
 	
-	var Svg = __webpack_require__(234);
-	
-	__webpack_require__(343);
+	var Svg = __webpack_require__(235);
+	
+	__webpack_require__(344);
 	
 	var Accordion = React.createClass({
 	  propTypes: {
 	    items: PropTypes.array
 	  },
 	
 	  displayName: "Accordion",
 	
@@ -37597,70 +37630,70 @@ var Debugger =
 	  render: function () {
 	    return div({ className: "accordion" }, this.props.items.map(this.renderContainer));
 	  }
 	});
 	
 	module.exports = Accordion;
 
 /***/ },
-/* 343 */
+/* 344 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 344 */,
-/* 345 */
+/* 345 */,
+/* 346 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 346 */,
-/* 347 */
+/* 347 */,
+/* 348 */
 /***/ function(module, exports, __webpack_require__) {
 
 	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
 	
 	var React = __webpack_require__(17);
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	
-	var ImPropTypes = __webpack_require__(227);
+	var ImPropTypes = __webpack_require__(228);
 	
 	var _require = __webpack_require__(15);
 	
 	var connect = _require.connect;
 	
 	var _require2 = __webpack_require__(2);
 	
 	var bindActionCreators = _require2.bindActionCreators;
 	
-	var Svg = __webpack_require__(234);
-	
-	var _require3 = __webpack_require__(198);
+	var Svg = __webpack_require__(235);
+	
+	var _require3 = __webpack_require__(199);
 	
 	var getSelectedSource = _require3.getSelectedSource;
 	var getSourceTabs = _require3.getSourceTabs;
 	
-	var _require4 = __webpack_require__(175);
+	var _require4 = __webpack_require__(176);
 	
 	var endTruncateStr = _require4.endTruncateStr;
 	
-	var classnames = __webpack_require__(206);
-	var actions = __webpack_require__(213);
+	var classnames = __webpack_require__(207);
+	var actions = __webpack_require__(214);
 	
 	var _require5 = __webpack_require__(46);
 	
 	var isEnabled = _require5.isEnabled;
 	
 	
-	__webpack_require__(348);
-	__webpack_require__(350);
+	__webpack_require__(349);
+	__webpack_require__(351);
 	
 	/**
 	 * TODO: this is a placeholder function
 	 */
 	function getFilename(url) {
 	  if (!url) {
 	    return "";
 	  }
@@ -37832,73 +37865,73 @@ var Debugger =
 	});
 	
 	module.exports = connect(state => ({
 	  selectedSource: getSelectedSource(state),
 	  sourceTabs: getSourceTabs(state)
 	}), dispatch => bindActionCreators(actions, dispatch))(SourceTabs);
 
 /***/ },
-/* 348 */
+/* 349 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 349 */,
-/* 350 */
+/* 350 */,
+/* 351 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 351 */,
-/* 352 */
+/* 352 */,
+/* 353 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	
 	var _require = __webpack_require__(15);
 	
 	var connect = _require.connect;
 	
 	var _require2 = __webpack_require__(2);
 	
 	var bindActionCreators = _require2.bindActionCreators;
 	
-	var actions = __webpack_require__(213);
+	var actions = __webpack_require__(214);
 	
 	var _require3 = __webpack_require__(46);
 	
 	var isEnabled = _require3.isEnabled;
 	
-	var _require4 = __webpack_require__(198);
+	var _require4 = __webpack_require__(199);
 	
 	var getSelectedSource = _require4.getSelectedSource;
 	var getSourceText = _require4.getSourceText;
 	var getPrettySource = _require4.getPrettySource;
 	
-	var Svg = __webpack_require__(234);
-	var ImPropTypes = __webpack_require__(227);
-	var classnames = __webpack_require__(206);
-	
-	var _require5 = __webpack_require__(215);
+	var Svg = __webpack_require__(235);
+	var ImPropTypes = __webpack_require__(228);
+	var classnames = __webpack_require__(207);
+	
+	var _require5 = __webpack_require__(216);
 	
 	var isMapped = _require5.isMapped;
 	var getGeneratedSourceId = _require5.getGeneratedSourceId;
 	var isOriginal = _require5.isOriginal;
 	
-	var _require6 = __webpack_require__(219);
+	var _require6 = __webpack_require__(220);
 	
 	var isPretty = _require6.isPretty;
 	
 	
-	__webpack_require__(353);
+	__webpack_require__(354);
 	
 	function debugBtn(onClick, type) {
 	  var className = arguments.length <= 2 || arguments[2] === undefined ? "active" : arguments[2];
 	  var tooltip = arguments[3];
 	
 	  className = `${ type } ${ className }`;
 	  return dom.span({ onClick, className, key: type }, Svg(type, { title: tooltip }));
 	}
@@ -37973,37 +38006,37 @@ var Debugger =
 	  return {
 	    selectedSource,
 	    sourceText: getSourceText(state, selectedId),
 	    prettySource: getPrettySource(state, selectedId)
 	  };
 	}, dispatch => bindActionCreators(actions, dispatch))(SourceFooter);
 
 /***/ },
-/* 353 */
+/* 354 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 354 */,
-/* 355 */
+/* 355 */,
+/* 356 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var React = __webpack_require__(17);
 	var dom = React.DOM;
 	var PropTypes = React.PropTypes;
 	
-	var _require = __webpack_require__(356);
+	var _require = __webpack_require__(357);
 	
 	var filter = _require.filter;
 	
-	var classnames = __webpack_require__(206);
-	__webpack_require__(362);
-	var Svg = __webpack_require__(234);
+	var classnames = __webpack_require__(207);
+	__webpack_require__(363);
+	var Svg = __webpack_require__(235);
 	
 	var INITIAL_SELECTED_INDEX = 0;
 	
 	var Autocomplete = React.createClass({
 	  propTypes: {
 	    selectItem: PropTypes.func,
 	    items: PropTypes.array
 	  },
@@ -38104,31 +38137,31 @@ var Debugger =
 	      })
 	    }, new Svg("magnifying-glass"), this.renderInput(), dom.ul({ className: "results", ref: "results" }, searchResults.map(this.renderSearchItem)));
 	  }
 	});
 	
 	module.exports = Autocomplete;
 
 /***/ },
-/* 356 */
+/* 357 */
 /***/ function(module, exports, __webpack_require__) {
 
 	(function() {
 	  var PathSeparator, filter, legacy_scorer, matcher, prepQueryCache, scorer;
 	
-	  scorer = __webpack_require__(357);
-	
-	  legacy_scorer = __webpack_require__(359);
-	
-	  filter = __webpack_require__(360);
-	
-	  matcher = __webpack_require__(361);
-	
-	  PathSeparator = __webpack_require__(358).sep;
+	  scorer = __webpack_require__(358);
+	
+	  legacy_scorer = __webpack_require__(360);
+	
+	  filter = __webpack_require__(361);
+	
+	  matcher = __webpack_require__(362);
+	
+	  PathSeparator = __webpack_require__(359).sep;
 	
 	  prepQueryCache = null;
 	
 	  module.exports = {
 	    filter: function(candidates, query, options) {
 	      if (!((query != null ? query.length : void 0) && (candidates != null ? candidates.length : void 0))) {
 	        return [];
 	      }
@@ -38193,23 +38226,23 @@ var Debugger =
 	      return matches;
 	    }
 	  };
 	
 	}).call(this);
 
 
 /***/ },
-/* 357 */
+/* 358 */
 /***/ function(module, exports, __webpack_require__) {
 
 	(function() {
 	  var AcronymResult, PathSeparator, Query, basenameScore, coreChars, countDir, doScore, emptyAcronymResult, file_coeff, isMatch, isSeparator, isWordEnd, isWordStart, miss_coeff, opt_char_re, pos_bonus, scoreAcronyms, scoreCharacter, scoreConsecutives, scoreExact, scoreExactMatch, scorePattern, scorePosition, scoreSize, tau_depth, tau_size, truncatedUpperCase, wm;
 	
-	  PathSeparator = __webpack_require__(358).sep;
+	  PathSeparator = __webpack_require__(359).sep;
 	
 	  wm = 150;
 	
 	  pos_bonus = 20;
 	
 	  tau_depth = 13;
 	
 	  tau_size = 85;
@@ -38586,17 +38619,17 @@ var Debugger =
 	    }
 	    return upper;
 	  };
 	
 	}).call(this);
 
 
 /***/ },
-/* 358 */
+/* 359 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* WEBPACK VAR INJECTION */(function(process) {// Copyright Joyent, Inc. and other Node contributors.
 	//
 	// Permission is hereby granted, free of charge, to any person obtaining a
 	// copy of this software and associated documentation files (the
 	// "Software"), to deal in the Software without restriction, including
 	// without limitation the rights to use, copy, modify, merge, publish,
@@ -38817,23 +38850,23 @@ var Debugger =
 	        if (start < 0) start = str.length + start;
 	        return str.substr(start, len);
 	    }
 	;
 	
 	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(35)))
 
 /***/ },
-/* 359 */
+/* 360 */
 /***/ function(module, exports, __webpack_require__) {
 
 	(function() {
 	  var PathSeparator, queryIsLastPathSegment;
 	
-	  PathSeparator = __webpack_require__(358).sep;
+	  PathSeparator = __webpack_require__(359).sep;
 	
 	  exports.basenameScore = function(string, query, score) {
 	    var base, depth, index, lastCharacter, segmentCount, slashCount;
 	    index = string.length - 1;
 	    while (string[index] === PathSeparator) {
 	      index--;
 	    }
 	    slashCount = 0;
@@ -38951,35 +38984,35 @@ var Debugger =
 	    }
 	    return matches;
 	  };
 	
 	}).call(this);
 
 
 /***/ },
-/* 360 */
+/* 361 */
 /***/ function(module, exports, __webpack_require__) {
 
 	(function() {
 	  var PathSeparator, legacy_scorer, pluckCandidates, scorer, sortCandidates;
 	
-	  scorer = __webpack_require__(357);
-	
-	  legacy_scorer = __webpack_require__(359);
+	  scorer = __webpack_require__(358);
+	
+	  legacy_scorer = __webpack_require__(360);
 	
 	  pluckCandidates = function(a) {
 	    return a.candidate;
 	  };
 	
 	  sortCandidates = function(a, b) {
 	    return b.score - a.score;
 	  };
 	
-	  PathSeparator = __webpack_require__(358).sep;
+	  PathSeparator = __webpack_require__(359).sep;
 	
 	  module.exports = function(candidates, query, _arg) {
 	    var allowErrors, bAllowErrors, bKey, candidate, coreQuery, key, legacy, maxInners, maxResults, prepQuery, queryHasSlashes, score, scoredCandidates, spotLeft, string, _i, _j, _len, _len1, _ref;
 	    _ref = _arg != null ? _arg : {}, key = _ref.key, maxResults = _ref.maxResults, maxInners = _ref.maxInners, allowErrors = _ref.allowErrors, legacy = _ref.legacy;
 	    scoredCandidates = [];
 	    spotLeft = (maxInners != null) && maxInners > 0 ? maxInners : candidates.length;
 	    bAllowErrors = !!allowErrors;
 	    bKey = key != null;
@@ -39030,25 +39063,25 @@ var Debugger =
 	    }
 	    return candidates;
 	  };
 	
 	}).call(this);
 
 
 /***/ },
-/* 361 */
+/* 362 */
 /***/ function(module, exports, __webpack_require__) {
 
 	(function() {
 	  var PathSeparator, scorer;
 	
-	  PathSeparator = __webpack_require__(358).sep;
-	
-	  scorer = __webpack_require__(357);
+	  PathSeparator = __webpack_require__(359).sep;
+	
+	  scorer = __webpack_require__(358);
 	
 	  exports.basenameMatch = function(subject, subject_lw, prepQuery) {
 	    var basePos, depth, end;
 	    end = subject.length - 1;
 	    while (subject[end] === PathSeparator) {
 	      end--;
 	    }
 	    basePos = subject.lastIndexOf(PathSeparator, end);
@@ -39183,33 +39216,33 @@ var Debugger =
 	    matches.reverse();
 	    return matches;
 	  };
 	
 	}).call(this);
 
 
 /***/ },
-/* 362 */
+/* 363 */
 /***/ function(module, exports) {
 
 	// removed by extract-text-webpack-plugin
 
 /***/ },
-/* 363 */,
-/* 364 */
-/***/ function(module, exports, __webpack_require__) {
-
-	/* This Source Code Form is subject to the terms of the Mozilla Public
-	 * License, v. 2.0. If a copy of the MPL was not distributed with this
-	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-	
-	"use strict";
-	
-	const { Services } = __webpack_require__(212);
+/* 364 */,
+/* 365 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* This Source Code Form is subject to the terms of the Mozilla Public
+	 * License, v. 2.0. If a copy of the MPL was not distributed with this
+	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+	
+	"use strict";
+	
+	const { Services } = __webpack_require__(213);
 	const EventEmitter = __webpack_require__(111);
 	const isOSX = Services.appinfo.OS === "Darwin";
 	
 	// List of electron keys mapped to DOM API (DOM_VK_*) key code
 	const ElectronKeysMapping = {
 	  "F1": "DOM_VK_F1",
 	  "F2": "DOM_VK_F2",
 	  "F3": "DOM_VK_F3",
new file mode 100644
--- a/devtools/client/debugger/new/pretty-print-worker.js
+++ b/devtools/client/debugger/new/pretty-print-worker.js
@@ -41,17 +41,17 @@ var Debugger =
 /******/ 	return __webpack_require__(0);
 /******/ })
 /************************************************************************/
 /******/ ({
 
 /***/ 0:
 /***/ function(module, exports, __webpack_require__) {
 
-	var prettyFast = __webpack_require__(365);
+	var prettyFast = __webpack_require__(366);
 	
 	self.onmessage = function (msg) {
 	  var _prettyPrint = prettyPrint(msg.data);
 	
 	  var code = _prettyPrint.code;
 	  var mappings = _prettyPrint.mappings;
 	
 	  mappings = invertMappings(mappings);
@@ -95,17 +95,17 @@ var Debugger =
 	      mapping.name = m.name;
 	    }
 	    return mapping;
 	  });
 	}
 
 /***/ },
 
-/***/ 365:
+/***/ 366:
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2; fill-column: 80 -*- */
 	/*
 	 * Copyright 2013 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE.md or:
 	 * http://opensource.org/licenses/BSD-2-Clause
 	 */
@@ -117,18 +117,18 @@ var Debugger =
 	  } else if (typeof exports === "object") {
 	    module.exports = factory();
 	  } else {
 	    root.prettyFast = factory();
 	  }
 	}(this, function () {
 	  "use strict";
 	
-	  var acorn = this.acorn || __webpack_require__(366);
-	  var sourceMap = this.sourceMap || __webpack_require__(367);
+	  var acorn = this.acorn || __webpack_require__(367);
+	  var sourceMap = this.sourceMap || __webpack_require__(368);
 	  var SourceNode = sourceMap.SourceNode;
 	
 	  // If any of these tokens are seen before a "[" token, we know that "[" token
 	  // is the start of an array literal, rather than a property access.
 	  //
 	  // The only exception is "}", which would need to be disambiguated by
 	  // parsing. The majority of the time, an open bracket following a closing
 	  // curly is going to be an array literal, so we brush the complication under
@@ -977,17 +977,17 @@ var Debugger =
 	    return result.toStringWithSourceMap({ file: options.url });
 	  };
 	
 	}.bind(this)));
 
 
 /***/ },
 
-/***/ 366:
+/***/ 367:
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// Acorn is a tiny, fast JavaScript parser written in JavaScript.
 	//
 	// Acorn was written by Marijn Haverbeke and various contributors and
 	// released under an MIT license. The Unicode regexps (for identifiers
 	// and whitespace) were taken from [Esprima](http://esprima.org) by
 	// Ariya Hidayat.
@@ -3637,49 +3637,49 @@ var Debugger =
 	    return finishNode(node, "ComprehensionExpression");
 	  }
 	
 	});
 
 
 /***/ },
 
-/***/ 367:
+/***/ 368:
 /***/ function(module, exports, __webpack_require__) {
 
 	/*
 	 * Copyright 2009-2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE.txt or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
-	exports.SourceMapGenerator = __webpack_require__(368).SourceMapGenerator;
-	exports.SourceMapConsumer = __webpack_require__(374).SourceMapConsumer;
-	exports.SourceNode = __webpack_require__(376).SourceNode;
+	exports.SourceMapGenerator = __webpack_require__(369).SourceMapGenerator;
+	exports.SourceMapConsumer = __webpack_require__(375).SourceMapConsumer;
+	exports.SourceNode = __webpack_require__(377).SourceNode;
 
 
 /***/ },
 
-/***/ 368:
+/***/ 369:
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 	if (false) {
 	    var define = require('amdefine')(module, require);
 	}
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	
-	  var base64VLQ = __webpack_require__(369);
-	  var util = __webpack_require__(371);
-	  var ArraySet = __webpack_require__(372).ArraySet;
-	  var MappingList = __webpack_require__(373).MappingList;
+	  var base64VLQ = __webpack_require__(370);
+	  var util = __webpack_require__(372);
+	  var ArraySet = __webpack_require__(373).ArraySet;
+	  var MappingList = __webpack_require__(374).MappingList;
 	
 	  /**
 	   * An instance of the SourceMapGenerator represents a source map which is
 	   * being built incrementally. You may pass an object with the following
 	   * properties:
 	   *
 	   *   - file: The filename of the generated source.
 	   *   - sourceRoot: A root for all relative URLs in this source map.
@@ -4059,17 +4059,17 @@ var Debugger =
 	
 	  exports.SourceMapGenerator = SourceMapGenerator;
 	
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
 
-/***/ 369:
+/***/ 370:
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 *
@@ -4103,17 +4103,17 @@ var Debugger =
 	 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 	 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 	 */
 	if (false) {
 	    var define = require('amdefine')(module, require);
 	}
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	
-	  var base64 = __webpack_require__(370);
+	  var base64 = __webpack_require__(371);
 	
 	  // A single base 64 digit can contain 6 bits of data. For the base 64 variable
 	  // length quantities we use in the source map spec, the first bit is the sign,
 	  // the next four bits are the actual value, and the 6th bit is the
 	  // continuation bit. The continuation bit tells us whether there are more
 	  // digits in this value following this digit.
 	  //
 	  //   Continuation
@@ -4208,17 +4208,17 @@ var Debugger =
 	    aOutParam.rest = aStr.slice(i);
 	  };
 	
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
 
-/***/ 370:
+/***/ 371:
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
@@ -4257,17 +4257,17 @@ var Debugger =
 	    throw new TypeError("Not a valid base 64 digit: " + aChar);
 	  };
 	
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
 
-/***/ 371:
+/***/ 372:
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
@@ -4583,31 +4583,31 @@ var Debugger =
 	  };
 	  exports.compareByGeneratedPositions = compareByGeneratedPositions;
 	
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
 
-/***/ 372:
+/***/ 373:
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 	if (false) {
 	    var define = require('amdefine')(module, require);
 	}
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	
-	  var util = __webpack_require__(371);
+	  var util = __webpack_require__(372);
 	
 	  /**
 	   * A data structure which is a combination of an array and a set. Adding a new
 	   * member is O(1), testing for membership is O(1), and finding the index of an
 	   * element is O(1). Removing elements from the set is not supported. Only
 	   * strings are supported for membership.
 	   */
 	  function ArraySet() {
@@ -4687,31 +4687,31 @@ var Debugger =
 	
 	  exports.ArraySet = ArraySet;
 	
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
 
-/***/ 373:
+/***/ 374:
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2014 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 	if (false) {
 	    var define = require('amdefine')(module, require);
 	}
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	
-	  var util = __webpack_require__(371);
+	  var util = __webpack_require__(372);
 	
 	  /**
 	   * Determine whether mappingB is after mappingA with respect to generated
 	   * position.
 	   */
 	  function generatedPositionAfter(mappingA, mappingB) {
 	    // Optimized for most common case
 	    var lineA = mappingA.generatedLine;
@@ -4780,34 +4780,34 @@ var Debugger =
 	
 	  exports.MappingList = MappingList;
 	
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
 
-/***/ 374:
+/***/ 375:
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 	if (false) {
 	    var define = require('amdefine')(module, require);
 	}
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	
-	  var util = __webpack_require__(371);
-	  var binarySearch = __webpack_require__(375);
-	  var ArraySet = __webpack_require__(372).ArraySet;
-	  var base64VLQ = __webpack_require__(369);
+	  var util = __webpack_require__(372);
+	  var binarySearch = __webpack_require__(376);
+	  var ArraySet = __webpack_require__(373).ArraySet;
+	  var base64VLQ = __webpack_require__(370);
 	
 	  /**
 	   * A SourceMapConsumer instance represents a parsed source map which we can
 	   * query for information about the original file positions by giving it a file
 	   * position in the generated source.
 	   *
 	   * The only parameter is the raw source map (either as a JSON string, or
 	   * already parsed to an object). According to the spec, source maps have the
@@ -5362,17 +5362,17 @@ var Debugger =
 	
 	  exports.SourceMapConsumer = SourceMapConsumer;
 	
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
 
-/***/ 375:
+/***/ 376:
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
@@ -5449,32 +5449,32 @@ var Debugger =
 	    return recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare)
 	  };
 	
 	}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 
 
 /***/ },
 
-/***/ 376:
+/***/ 377:
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 	if (false) {
 	    var define = require('amdefine')(module, require);
 	}
 	!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) {
 	
-	  var SourceMapGenerator = __webpack_require__(368).SourceMapGenerator;
-	  var util = __webpack_require__(371);
+	  var SourceMapGenerator = __webpack_require__(369).SourceMapGenerator;
+	  var util = __webpack_require__(372);
 	
 	  // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other
 	  // operating systems these days (capturing the result).
 	  var REGEX_NEWLINE = /(\r?\n)/;
 	
 	  // Newline character code for charCodeAt() comparisons
 	  var NEWLINE_CODE = 10;
 	
--- a/devtools/client/debugger/new/source-map-worker.js
+++ b/devtools/client/debugger/new/source-map-worker.js
@@ -43,29 +43,29 @@ var Debugger =
 /************************************************************************/
 /******/ ({
 
 /***/ 0:
 /***/ function(module, exports, __webpack_require__) {
 
 	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 _require = __webpack_require__(377);
+	var _require = __webpack_require__(378);
 	
 	var SourceMapConsumer = _require.SourceMapConsumer;
 	var SourceNode = _require.SourceNode;
 	var SourceMapGenerator = _require.SourceMapGenerator;
 	
-	var _require2 = __webpack_require__(216);
+	var _require2 = __webpack_require__(217);
 	
 	var makeOriginalSource = _require2.makeOriginalSource;
 	var getGeneratedSourceId = _require2.getGeneratedSourceId;
 	
 	
-	var toPairs = __webpack_require__(312);
+	var toPairs = __webpack_require__(313);
 	
 	var sourceMapConsumers = new Map();
 	var sourceNodes = new Map();
 	
 	function _hasConsumer(sourceId) {
 	  return sourceMapConsumers.has(sourceId);
 	}
 	
@@ -652,17 +652,17 @@ var Debugger =
 	/* Built-in method references that are verified to be native. */
 	var Map = getNative(root, 'Map');
 	
 	module.exports = Map;
 
 
 /***/ },
 
-/***/ 216:
+/***/ 217:
 /***/ function(module, exports) {
 
 	
 	function getGeneratedSourceId(originalSource) {
 	  var match = originalSource.id.match(/(.*)\/originalSource/);
 	  return match ? match[1] : null;
 	}
 	
@@ -682,21 +682,21 @@ var Debugger =
 	
 	module.exports = {
 	  makeOriginalSource,
 	  getGeneratedSourceId
 	};
 
 /***/ },
 
-/***/ 312:
+/***/ 313:
 /***/ function(module, exports, __webpack_require__) {
 
-	var createToPairs = __webpack_require__(313),
-	    keys = __webpack_require__(323);
+	var createToPairs = __webpack_require__(314),
+	    keys = __webpack_require__(324);
 	
 	/**
 	 * Creates an array of own enumerable string keyed-value pairs for `object`
 	 * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
 	 * entries are returned.
 	 *
 	 * @static
 	 * @memberOf _
@@ -719,23 +719,23 @@ var Debugger =
 	 */
 	var toPairs = createToPairs(keys);
 	
 	module.exports = toPairs;
 
 
 /***/ },
 
-/***/ 313:
+/***/ 314:
 /***/ function(module, exports, __webpack_require__) {
 
-	var baseToPairs = __webpack_require__(314),
-	    getTag = __webpack_require__(316),
-	    mapToArray = __webpack_require__(321),
-	    setToPairs = __webpack_require__(322);
+	var baseToPairs = __webpack_require__(315),
+	    getTag = __webpack_require__(317),
+	    mapToArray = __webpack_require__(322),
+	    setToPairs = __webpack_require__(323);
 	
 	/** `Object#toString` result references. */
 	var mapTag = '[object Map]',
 	    setTag = '[object Set]';
 	
 	/**
 	 * Creates a `_.toPairs` or `_.toPairsIn` function.
 	 *
@@ -756,20 +756,20 @@ var Debugger =
 	  };
 	}
 	
 	module.exports = createToPairs;
 
 
 /***/ },
 
-/***/ 314:
+/***/ 315:
 /***/ function(module, exports, __webpack_require__) {
 
-	var arrayMap = __webpack_require__(315);
+	var arrayMap = __webpack_require__(316);
 	
 	/**
 	 * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
 	 * of key-value pairs for `object` corresponding to the property names of `props`.
 	 *
 	 * @private
 	 * @param {Object} object The object to query.
 	 * @param {Array} props The property names to get values for.
@@ -781,17 +781,17 @@ var Debugger =
 	  });
 	}
 	
 	module.exports = baseToPairs;
 
 
 /***/ },
 
-/***/ 315:
+/***/ 316:
 /***/ function(module, exports) {
 
 	/**
 	 * A specialized version of `_.map` for arrays without support for iteratee
 	 * shorthands.
 	 *
 	 * @private
 	 * @param {Array} [array] The array to iterate over.
@@ -809,24 +809,24 @@ var Debugger =
 	  return result;
 	}
 	
 	module.exports = arrayMap;
 
 
 /***/ },
 
-/***/ 316:
+/***/ 317:
 /***/ function(module, exports, __webpack_require__) {
 
-	var DataView = __webpack_require__(317),
+	var DataView = __webpack_require__(318),
 	    Map = __webpack_require__(82),
-	    Promise = __webpack_require__(318),
-	    Set = __webpack_require__(319),
-	    WeakMap = __webpack_require__(320),
+	    Promise = __webpack_require__(319),
+	    Set = __webpack_require__(320),
+	    WeakMap = __webpack_require__(321),
 	    toSource = __webpack_require__(68);
 	
 	/** `Object#toString` result references. */
 	var mapTag = '[object Map]',
 	    objectTag = '[object Object]',
 	    promiseTag = '[object Promise]',
 	    setTag = '[object Set]',
 	    weakMapTag = '[object WeakMap]';
@@ -886,73 +886,73 @@ var Debugger =
 	  };
 	}
 	
 	module.exports = getTag;
 
 
 /***/ },
 
-/***/ 317:
+/***/ 318:
 /***/ function(module, exports, __webpack_require__) {
 
 	var getNative = __webpack_require__(60),
 	    root = __webpack_require__(66);
 	
 	/* Built-in method references that are verified to be native. */
 	var DataView = getNative(root, 'DataView');
 	
 	module.exports = DataView;
 
 
 /***/ },
 
-/***/ 318:
+/***/ 319:
 /***/ function(module, exports, __webpack_require__) {
 
 	var getNative = __webpack_require__(60),
 	    root = __webpack_require__(66);
 	
 	/* Built-in method references that are verified to be native. */
 	var Promise = getNative(root, 'Promise');
 	
 	module.exports = Promise;
 
 
 /***/ },
 
-/***/ 319:
+/***/ 320:
 /***/ function(module, exports, __webpack_require__) {
 
 	var getNative = __webpack_require__(60),
 	    root = __webpack_require__(66);
 	
 	/* Built-in method references that are verified to be native. */
 	var Set = getNative(root, 'Set');
 	
 	module.exports = Set;
 
 
 /***/ },
 
-/***/ 320:
+/***/ 321:
 /***/ function(module, exports, __webpack_require__) {
 
 	var getNative = __webpack_require__(60),
 	    root = __webpack_require__(66);
 	
 	/* Built-in method references that are verified to be native. */
 	var WeakMap = getNative(root, 'WeakMap');
 	
 	module.exports = WeakMap;
 
 
 /***/ },
 
-/***/ 321:
+/***/ 322:
 /***/ function(module, exports) {
 
 	/**
 	 * Converts `map` to its key-value pairs.
 	 *
 	 * @private
 	 * @param {Object} map The map to convert.
 	 * @returns {Array} Returns the key-value pairs.
@@ -967,17 +967,17 @@ var Debugger =
 	  return result;
 	}
 	
 	module.exports = mapToArray;
 
 
 /***/ },
 
-/***/ 322:
+/***/ 323:
 /***/ function(module, exports) {
 
 	/**
 	 * Converts `set` to its value-value pairs.
 	 *
 	 * @private
 	 * @param {Object} set The set to convert.
 	 * @returns {Array} Returns the value-value pairs.
@@ -992,25 +992,25 @@ var Debugger =
 	  return result;
 	}
 	
 	module.exports = setToPairs;
 
 
 /***/ },
 
-/***/ 323:
+/***/ 324:
 /***/ function(module, exports, __webpack_require__) {
 
-	var baseHas = __webpack_require__(324),
-	    baseKeys = __webpack_require__(325),
-	    indexKeys = __webpack_require__(326),
-	    isArrayLike = __webpack_require__(330),
-	    isIndex = __webpack_require__(335),
-	    isPrototype = __webpack_require__(336);
+	var baseHas = __webpack_require__(325),
+	    baseKeys = __webpack_require__(326),
+	    indexKeys = __webpack_require__(327),
+	    isArrayLike = __webpack_require__(331),
+	    isIndex = __webpack_require__(336),
+	    isPrototype = __webpack_require__(337);
 	
 	/**
 	 * Creates an array of the own enumerable property names of `object`.
 	 *
 	 * **Note:** Non-object values are coerced to objects. See the
 	 * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
 	 * for more details.
 	 *
@@ -1055,17 +1055,17 @@ var Debugger =
 	  return result;
 	}
 	
 	module.exports = keys;
 
 
 /***/ },
 
-/***/ 324:
+/***/ 325:
 /***/ function(module, exports, __webpack_require__) {
 
 	var getPrototype = __webpack_require__(5);
 	
 	/** Used for built-in method references. */
 	var objectProto = Object.prototype;
 	
 	/** Used to check objects for own properties. */
@@ -1088,17 +1088,17 @@ var Debugger =
 	      (typeof object == 'object' && key in object && getPrototype(object) === null));
 	}
 	
 	module.exports = baseHas;
 
 
 /***/ },
 
-/***/ 325:
+/***/ 326:
 /***/ function(module, exports) {
 
 	/* Built-in method references for those with the same name as other `lodash` methods. */
 	var nativeKeys = Object.keys;
 	
 	/**
 	 * The base implementation of `_.keys` which doesn't skip the constructor
 	 * property of prototypes or treat sparse arrays as dense.
@@ -1111,24 +1111,24 @@ var Debugger =
 	  return nativeKeys(Object(object));
 	}
 	
 	module.exports = baseKeys;
 
 
 /***/ },
 
-/***/ 326:
+/***/ 327:
 /***/ function(module, exports, __webpack_require__) {
 
-	var baseTimes = __webpack_require__(327),
-	    isArguments = __webpack_require__(328),
+	var baseTimes = __webpack_require__(328),
+	    isArguments = __webpack_require__(329),
 	    isArray = __webpack_require__(52),
-	    isLength = __webpack_require__(333),
-	    isString = __webpack_require__(334);
+	    isLength = __webpack_require__(334),
+	    isString = __webpack_require__(335);
 	
 	/**
 	 * Creates an array of index keys for `object` values of arrays,
 	 * `arguments` objects, and strings, otherwise `null` is returned.
 	 *
 	 * @private
 	 * @param {Object} object The object to query.
 	 * @returns {Array|null} Returns index keys, else `null`.
@@ -1142,17 +1142,17 @@ var Debugger =
 	  return null;
 	}
 	
 	module.exports = indexKeys;
 
 
 /***/ },
 
-/***/ 327:
+/***/ 328:
 /***/ function(module, exports) {
 
 	/**
 	 * The base implementation of `_.times` without support for iteratee shorthands
 	 * or max array length checks.
 	 *
 	 * @private
 	 * @param {number} n The number of times to invoke `iteratee`.
@@ -1169,20 +1169,20 @@ var Debugger =
 	  return result;
 	}
 	
 	module.exports = baseTimes;
 
 
 /***/ },
 
-/***/ 328:
+/***/ 329:
 /***/ function(module, exports, __webpack_require__) {
 
-	var isArrayLikeObject = __webpack_require__(329);
+	var isArrayLikeObject = __webpack_require__(330);
 	
 	/** `Object#toString` result references. */
 	var argsTag = '[object Arguments]';
 	
 	/** Used for built-in method references. */
 	var objectProto = Object.prototype;
 	
 	/** Used to check objects for own properties. */
@@ -1222,20 +1222,20 @@ var Debugger =
 	    (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
 	}
 	
 	module.exports = isArguments;
 
 
 /***/ },
 
-/***/ 329:
+/***/ 330:
 /***/ function(module, exports, __webpack_require__) {
 
-	var isArrayLike = __webpack_require__(330),
+	var isArrayLike = __webpack_require__(331),
 	    isObjectLike = __webpack_require__(7);
 	
 	/**
 	 * This method is like `_.isArrayLike` except that it also checks if `value`
 	 * is an object.
 	 *
 	 * @static
 	 * @memberOf _
@@ -1262,22 +1262,22 @@ var Debugger =
 	  return isObjectLike(value) && isArrayLike(value);
 	}
 	
 	module.exports = isArrayLikeObject;
 
 
 /***/ },
 
-/***/ 330:
+/***/ 331:
 /***/ function(module, exports, __webpack_require__) {
 
-	var getLength = __webpack_require__(331),
+	var getLength = __webpack_require__(332),
 	    isFunction = __webpack_require__(62),
-	    isLength = __webpack_require__(333);
+	    isLength = __webpack_require__(334);
 	
 	/**
 	 * Checks if `value` is array-like. A value is considered array-like if it's
 	 * not a function and has a `value.length` that's an integer greater than or
 	 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 	 *
 	 * @static
 	 * @memberOf _
@@ -1303,20 +1303,20 @@ var Debugger =
 	  return value != null && isLength(getLength(value)) && !isFunction(value);
 	}
 	
 	module.exports = isArrayLike;
 
 
 /***/ },
 
-/***/ 331:
+/***/ 332:
 /***/ function(module, exports, __webpack_require__) {
 
-	var baseProperty = __webpack_require__(332);
+	var baseProperty = __webpack_require__(333);
 	
 	/**
 	 * Gets the "length" property value of `object`.
 	 *
 	 * **Note:** This function is used to avoid a
 	 * [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) that affects
 	 * Safari on at least iOS 8.1-8.3 ARM64.
 	 *
@@ -1326,17 +1326,17 @@ var Debugger =
 	 */
 	var getLength = baseProperty('length');
 	
 	module.exports = getLength;
 
 
 /***/ },
 
-/***/ 332:
+/***/ 333:
 /***/ function(module, exports) {
 
 	/**
 	 * The base implementation of `_.property` without support for deep paths.
 	 *
 	 * @private
 	 * @param {string} key The key of the property to get.
 	 * @returns {Function} Returns the new accessor function.
@@ -1347,17 +1347,17 @@ var Debugger =
 	  };
 	}
 	
 	module.exports = baseProperty;
 
 
 /***/ },
 
-/***/ 333:
+/***/ 334:
 /***/ function(module, exports) {
 
 	/** Used as references for various `Number` constants. */
 	var MAX_SAFE_INTEGER = 9007199254740991;
 	
 	/**
 	 * Checks if `value` is a valid array-like length.
 	 *
@@ -1390,17 +1390,17 @@ var Debugger =
 	    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
 	}
 	
 	module.exports = isLength;
 
 
 /***/ },
 
-/***/ 334:
+/***/ 335:
 /***/ function(module, exports, __webpack_require__) {
 
 	var isArray = __webpack_require__(52),
 	    isObjectLike = __webpack_require__(7);
 	
 	/** `Object#toString` result references. */
 	var stringTag = '[object String]';
 	
@@ -1437,17 +1437,17 @@ var Debugger =
 	    (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag);
 	}
 	
 	module.exports = isString;
 
 
 /***/ },
 
-/***/ 335:
+/***/ 336:
 /***/ function(module, exports) {
 
 	/** Used as references for various `Number` constants. */
 	var MAX_SAFE_INTEGER = 9007199254740991;
 	
 	/** Used to detect unsigned integer values. */
 	var reIsUint = /^(?:0|[1-9]\d*)$/;
 	
@@ -1466,17 +1466,17 @@ var Debugger =
 	    (value > -1 && value % 1 == 0 && value < length);
 	}
 	
 	module.exports = isIndex;
 
 
 /***/ },
 
-/***/ 336:
+/***/ 337:
 /***/ function(module, exports) {
 
 	/** Used for built-in method references. */
 	var objectProto = Object.prototype;
 	
 	/**
 	 * Checks if `value` is likely a prototype object.
 	 *
@@ -1491,45 +1491,45 @@ var Debugger =
 	  return value === proto;
 	}
 	
 	module.exports = isPrototype;
 
 
 /***/ },
 
-/***/ 377:
+/***/ 378:
 /***/ function(module, exports, __webpack_require__) {
 
 	/*
 	 * Copyright 2009-2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE.txt or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
-	exports.SourceMapGenerator = __webpack_require__(378).SourceMapGenerator;
-	exports.SourceMapConsumer = __webpack_require__(384).SourceMapConsumer;
-	exports.SourceNode = __webpack_require__(387).SourceNode;
+	exports.SourceMapGenerator = __webpack_require__(379).SourceMapGenerator;
+	exports.SourceMapConsumer = __webpack_require__(385).SourceMapConsumer;
+	exports.SourceNode = __webpack_require__(388).SourceNode;
 
 
 /***/ },
 
-/***/ 378:
+/***/ 379:
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 	
-	var base64VLQ = __webpack_require__(379);
-	var util = __webpack_require__(381);
-	var ArraySet = __webpack_require__(382).ArraySet;
-	var MappingList = __webpack_require__(383).MappingList;
+	var base64VLQ = __webpack_require__(380);
+	var util = __webpack_require__(382);
+	var ArraySet = __webpack_require__(383).ArraySet;
+	var MappingList = __webpack_require__(384).MappingList;
 	
 	/**
 	 * An instance of the SourceMapGenerator represents a source map which is
 	 * being built incrementally. You may pass an object with the following
 	 * properties:
 	 *
 	 *   - file: The filename of the generated source.
 	 *   - sourceRoot: A root for all relative URLs in this source map.
@@ -1917,17 +1917,17 @@ var Debugger =
 	    return JSON.stringify(this.toJSON());
 	  };
 	
 	exports.SourceMapGenerator = SourceMapGenerator;
 
 
 /***/ },
 
-/***/ 379:
+/***/ 380:
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 *
@@ -1957,17 +1957,17 @@ var Debugger =
 	 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 	 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 	 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 	 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 	 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 	 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 	 */
 	
-	var base64 = __webpack_require__(380);
+	var base64 = __webpack_require__(381);
 	
 	// A single base 64 digit can contain 6 bits of data. For the base 64 variable
 	// length quantities we use in the source map spec, the first bit is the sign,
 	// the next four bits are the actual value, and the 6th bit is the
 	// continuation bit. The continuation bit tells us whether there are more
 	// digits in this value following this digit.
 	//
 	//   Continuation
@@ -2064,17 +2064,17 @@ var Debugger =
 	
 	  aOutParam.value = fromVLQSigned(result);
 	  aOutParam.rest = aIndex;
 	};
 
 
 /***/ },
 
-/***/ 380:
+/***/ 381:
 /***/ function(module, exports) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
@@ -2138,17 +2138,17 @@ var Debugger =
 	
 	  // Invalid base64 digit.
 	  return -1;
 	};
 
 
 /***/ },
 
-/***/ 381:
+/***/ 382:
 /***/ function(module, exports) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
@@ -2562,27 +2562,27 @@ var Debugger =
 	
 	  return strcmp(mappingA.name, mappingB.name);
 	}
 	exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;
 
 
 /***/ },
 
-/***/ 382:
+/***/ 383:
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 	
-	var util = __webpack_require__(381);
+	var util = __webpack_require__(382);
 	var has = Object.prototype.hasOwnProperty;
 	
 	/**
 	 * A data structure which is a combination of an array and a set. Adding a new
 	 * member is O(1), testing for membership is O(1), and finding the index of an
 	 * element is O(1). Removing elements from the set is not supported. Only
 	 * strings are supported for membership.
 	 */
@@ -2673,27 +2673,27 @@ var Debugger =
 	  return this._array.slice();
 	};
 	
 	exports.ArraySet = ArraySet;
 
 
 /***/ },
 
-/***/ 383:
+/***/ 384:
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2014 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 	
-	var util = __webpack_require__(381);
+	var util = __webpack_require__(382);
 	
 	/**
 	 * Determine whether mappingB is after mappingA with respect to generated
 	 * position.
 	 */
 	function generatedPositionAfter(mappingA, mappingB) {
 	  // Optimized for most common case
 	  var lineA = mappingA.generatedLine;
@@ -2759,31 +2759,31 @@ var Debugger =
 	  return this._array;
 	};
 	
 	exports.MappingList = MappingList;
 
 
 /***/ },
 
-/***/ 384:
+/***/ 385:
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 	
-	var util = __webpack_require__(381);
-	var binarySearch = __webpack_require__(385);
-	var ArraySet = __webpack_require__(382).ArraySet;
-	var base64VLQ = __webpack_require__(379);
-	var quickSort = __webpack_require__(386).quickSort;
+	var util = __webpack_require__(382);
+	var binarySearch = __webpack_require__(386);
+	var ArraySet = __webpack_require__(383).ArraySet;
+	var base64VLQ = __webpack_require__(380);
+	var quickSort = __webpack_require__(387).quickSort;
 	
 	function SourceMapConsumer(aSourceMap) {
 	  var sourceMap = aSourceMap;
 	  if (typeof aSourceMap === 'string') {
 	    sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
 	  }
 	
 	  return sourceMap.sections != null
@@ -3848,17 +3848,17 @@ var Debugger =
 	    quickSort(this.__originalMappings, util.compareByOriginalPositions);
 	  };
 	
 	exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;
 
 
 /***/ },
 
-/***/ 385:
+/***/ 386:
 /***/ function(module, exports) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
@@ -3966,17 +3966,17 @@ var Debugger =
 	  }
 	
 	  return index;
 	};
 
 
 /***/ },
 
-/***/ 386:
+/***/ 387:
 /***/ function(module, exports) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
@@ -4087,28 +4087,28 @@ var Debugger =
 	 */
 	exports.quickSort = function (ary, comparator) {
 	  doQuickSort(ary, comparator, 0, ary.length - 1);
 	};
 
 
 /***/ },
 
-/***/ 387:
+/***/ 388:
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 	
-	var SourceMapGenerator = __webpack_require__(378).SourceMapGenerator;
-	var util = __webpack_require__(381);
+	var SourceMapGenerator = __webpack_require__(379).SourceMapGenerator;
+	var util = __webpack_require__(382);
 	
 	// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other
 	// operating systems these days (capturing the result).
 	var REGEX_NEWLINE = /(\r?\n)/;
 	
 	// Newline character code for charCodeAt() comparisons
 	var NEWLINE_CODE = 10;
 	
--- a/devtools/client/debugger/new/styles.css
+++ b/devtools/client/debugger/new/styles.css
@@ -422,25 +422,32 @@ ul.sources-list {
 
 .split-box .controlled {
   display: flex;
   overflow: auto;
 }
 
 .split-box .splitter {
   background-color: var(--theme-splitter-color);
-  border-bottom-width: 0;
-  border-color: white;
-  border-left-width: 0;
-  border-right-width: 0;
-  border-style: solid;
-  border-top-width: 0;
-  box-sizing: content-box;
+  flex: 0 0 1px;
+  position: relative;
+}
+
+/* The actual handle that users drag is a transparent element that's slightly wider than
+   the splitter element itself, so it's easier to grab it. */
+.split-box .splitter .splitter-handle {
   cursor: ew-resize;
-  flex: 0 0 1px;
+  position: absolute;
+  top: 0;
+  left: -4px;
+  width: 8px;
+  height: 100%;
+
+  /* Stack above the code-mirror editor so it's actually possible to grab the handle. */
+  z-index: 5;
 }
 
 .breakpoints-list .breakpoint {
   font-size: 12px;
   color: var(--theme-content-color1);
   margin: 0.25em 0;
   padding: 0.25em 0;
   line-height: 1em;
@@ -932,16 +939,23 @@ ul.sources-list {
 
 .dropdown ul {
   list-style: none;
   line-height: 2em;
   font-size: 0.8em;
   margin: 0;
   padding: 0;
 }
+.source-footer {
+  border-top: 1px solid var(--theme-splitter-color);
+  left: 0;
+  opacity: 1;
+  width: 100%;
+}
+
 .source-footer .prettyPrint.pretty {
   stroke: var(--theme-highlight-blue);
 }
 
 .autocomplete {
   width: 100%;
   padding: 20px;
 }
--- a/devtools/client/debugger/new/test/mochitest/.eslintrc
+++ b/devtools/client/debugger/new/test/mochitest/.eslintrc
@@ -42,21 +42,23 @@
     "waitForDispatch": false,
     "waitForThreadEvents": false,
     "waitForState": false,
     "waitForPaused": false,
     "waitForSources": false,
     "isPaused": false,
     "assertPausedLocation": false,
     "assertHighlightLocation": false,
+    "createDebuggerContext": false,
     "initDebugger": false,
     "invokeInTab": false,
     "findSource": false,
     "findElement": false,
     "findAllElements": false,
+    "openNewTabAndToolbox": false,
     "selectSource": false,
     "stepOver": false,
     "stepIn": false,
     "stepOut": false,
     "resume": false,
     "reload": false,
     "navigate": false,
     "removeBreakpoint": false,
--- a/devtools/client/debugger/new/test/mochitest/browser.ini
+++ b/devtools/client/debugger/new/test/mochitest/browser.ini
@@ -12,16 +12,18 @@ support-files =
   examples/doc-debugger-statements.html
   examples/code-exceptions.js
   examples/code-simple1.js
   examples/code-simple2.js
   examples/code-long.js
   examples/code-script-switching-02.js
   examples/code-script-switching-01.js
 
+[browser_dbg-breaking.js]
+[browser_dbg-breaking-from-console.js]
 [browser_dbg-editor-gutter.js]
 [browser_dbg-editor-mode.js]
 [browser_dbg-editor-select.js]
 [browser_dbg-editor-highlight.js]
 [browser_dbg-call-stack.js]
 [browser_dbg-pause-exceptions.js]
 [browser_dbg-chrome-create.js]
 [browser_dbg-chrome-debugging.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-breaking-from-console.js
@@ -0,0 +1,31 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests that `debugger` statements are hit before the debugger even
+// initializes and it properly highlights the right location in the
+// debugger.
+
+add_task(function* () {
+  const url = EXAMPLE_URL + "doc-script-switching.html";
+  const toolbox = yield 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 new Promise((resolve) => {
+    toolbox.on("jsdebugger-selected", resolve);
+  });
+  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");
+  is(dbg.win.cm.getValue(), "debugger");
+  const source = getSelectedSource(getState()).toJS();
+  assertPausedLocation(dbg, source, 1);
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-breaking.js
@@ -0,0 +1,33 @@
+/* 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", "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);
+  reload(dbg);
+  yield waitForPaused(dbg);
+  assertPausedLocation(dbg, "scripts.html", 18);
+  yield resume(dbg);
+
+  const paused = waitForPaused(dbg);
+
+  // Create an eval script that pauses itself.
+  invokeInTab("doEval");
+
+  yield paused;
+  yield resume(dbg);
+  const source = getSelectedSource(getState()).toJS();
+  // TODO: The url of an eval source should be null.
+  ok(source.url.indexOf("SOURCE") === 0, "It is an eval source");
+
+  yield addBreakpoint(dbg, source, 5);
+  invokeInTab("evaledFunc");
+  yield waitForPaused(dbg);
+  assertPausedLocation(dbg, source, 5);
+});
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-navigation.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-navigation.js
@@ -6,37 +6,42 @@ function countSources(dbg) {
   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",
-    "script-switching-01.js"
-  );
+  const dbg = yield initDebugger("doc-script-switching.html");
+  const { selectors: { getSelectedSource, getPause }, getState } = dbg;
 
   invokeInTab("firstCall");
   yield waitForPaused(dbg);
 
-  yield navigate(dbg, "doc-scripts.html", "simple1.js", "long.js");
+  yield navigate(dbg, "doc-scripts.html", "simple1.js");
   yield addBreakpoint(dbg, "simple1.js", 4);
   invokeInTab("main");
   yield waitForPaused(dbg);
   assertPausedLocation(dbg, "simple1.js", 4);
   is(countSources(dbg), 4, "4 sources are loaded.");
 
   yield navigate(dbg, "about:blank");
   yield waitForDispatch(dbg, "NAVIGATE");
   is(countSources(dbg), 0, "0 sources are loaded.");
+  ok(!getPause(getState()), "No pause state exists");
 
   yield 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");
+  ok(getSelectedSource(getState()).get("url").includes("long.js"),
+     "Selected source is long.js");
 });
--- a/devtools/client/debugger/new/test/mochitest/examples/code-simple1.js
+++ b/devtools/client/debugger/new/test/mochitest/examples/code-simple1.js
@@ -1,7 +1,31 @@
 function main() {
   // A comment so we can test that breakpoint sliding works across
   // multiple lines
   const func = foo(1, 2);
   const result = func();
   return result;
 }
+
+function doEval() {
+  eval("(" + function() {
+    debugger;
+
+    window.evaledFunc = function() {
+      var foo = 1;
+      var bar = 2;
+      return foo + bar;
+    };
+  }.toString() + ")()");
+}
+
+function doNamedEval() {
+  eval("(" + function() {
+    debugger;
+
+    window.evaledFunc = function() {
+      var foo = 1;
+      var bar = 2;
+      return foo + bar;
+    };
+  }.toString() + ")();\n //# sourceURL=evaled.js");
+}
--- a/devtools/client/debugger/new/test/mochitest/head.js
+++ b/devtools/client/debugger/new/test/mochitest/head.js
@@ -113,17 +113,17 @@ function waitForSources(dbg, ...sources)
   }));
 }
 
 function assertPausedLocation(dbg, source, line) {
   const { selectors: { getSelectedSource, getPause }, getState } = dbg;
   source = findSource(dbg, source);
 
   // Check the selected source
-  is(getSelectedSource(getState()).get("url"), source.url);
+  is(getSelectedSource(getState()).get("id"), source.id);
 
   // Check the pause location
   const location = getPause(getState()).getIn(["frame", "location"]);
   is(location.get("sourceId"), source.id);
   is(location.get("line"), line);
 
   // Check the debug line
   ok(dbg.win.cm.lineInfo(line - 1).wrapClass.includes("debug-line"),
@@ -167,35 +167,36 @@ function waitForPaused(dbg) {
       // source we are paused in.
       const sourceId = pause.getIn(["frame", "location", "sourceId"]);
       const sourceText = dbg.selectors.getSourceText(dbg.getState(), sourceId);
       return sourceText && !sourceText.get("loading");
     });
   });
 };
 
+function createDebuggerContext(toolbox) {
+  const win = toolbox.getPanel("jsdebugger").panelWin;
+  const store = win.Debugger.store;
+
+  return {
+    actions: win.Debugger.actions,
+    selectors: win.Debugger.selectors,
+    getState: store.getState,
+    store: store,
+    client: win.Debugger.client,
+    toolbox: toolbox,
+    win: win
+  };
+}
+
 function initDebugger(url, ...sources) {
   return Task.spawn(function* () {
     const toolbox = yield openNewTabAndToolbox(EXAMPLE_URL + url, "jsdebugger");
-    const win = toolbox.getPanel("jsdebugger").panelWin;
-    const store = win.Debugger.store;
-    const { getSources } = win.Debugger.selectors;
-
-    const dbg = {
-      actions: win.Debugger.actions,
-      selectors: win.Debugger.selectors,
-      getState: store.getState,
-      store: store,
-      client: win.Debugger.client,
-      toolbox: toolbox,
-      win: win
-    };
-
+    const dbg = createDebuggerContext(toolbox);
     yield waitForSources(dbg, ...sources);
-
     return dbg;
   });
 };
 
 window.resumeTest = undefined;
 function pauseTest() {
   info("Test paused. Invoke resumeTest to continue.");
   return new Promise(resolve => resumeTest = resolve);
@@ -251,18 +252,18 @@ function stepOut(dbg) {
 }
 
 function resume(dbg) {
   info("Resuming");
   dbg.actions.resume();
   return waitForThreadEvents(dbg, "resumed");
 }
 
-function reload(dbg) {
-  return dbg.client.reload();
+function reload(dbg, ...sources) {
+  return dbg.client.reload().then(() => waitForSources(...sources));
 }
 
 function navigate(dbg, url, ...sources) {
   dbg.client.navigate(url);
   return waitForSources(dbg, ...sources)
 }
 
 function addBreakpoint(dbg, source, line, col) {
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -629,17 +629,17 @@ var gDevToolsBrowser = exports.gDevTools
     }
     gDevToolsBrowser._trackedBrowserWindows.delete(win);
     win.removeEventListener("unload", this);
 
     BrowserMenus.removeMenus(win.document);
 
     // Destroy toolboxes for closed window
     for (let [target, toolbox] of gDevTools._toolboxes) {
-      if (toolbox.win == win) {
+      if (toolbox.win.top == win) {
         toolbox.destroy();
       }
     }
 
     // Destroy the Developer toolbar if it has been accessed
     let desc = Object.getOwnPropertyDescriptor(win, "DeveloperToolbar");
     if (desc && !desc.get) {
       win.DeveloperToolbar.destroy();
--- a/devtools/client/framework/target.js
+++ b/devtools/client/framework/target.js
@@ -614,16 +614,19 @@ TabTarget.prototype = {
 
     this.activeTab = null;
     this.activeConsole = null;
     this._client = null;
     this._tab = null;
     this._form = null;
     this._remote = null;
     this._root = null;
+    this._title = null;
+    this._url = null;
+    this.threadActor = null;
   },
 
   toString: function () {
     let id = this._tab ? this._tab : (this._form && this._form.actor);
     return `TabTarget:${id}`;
   },
 
   /**
--- a/devtools/client/framework/test/browser_toolbox_theme_registration.js
+++ b/devtools/client/framework/test/browser_toolbox_theme_registration.js
@@ -73,24 +73,26 @@ add_task(function* themeInOptionsPanel()
 
   onThemeSwithComplete = once(panelWin, "theme-switch-complete");
   // Select test theme again.
   testThemeOption.click();
   yield onThemeSwithComplete;
 });
 
 add_task(function* themeUnregistration() {
+  let panelWin = toolbox.getCurrentPanel().panelWin;
   let onUnRegisteredTheme = once(gDevTools, "theme-unregistered");
+  let onThemeSwitchComplete = once(panelWin, "theme-switch-complete");
   gDevTools.unregisterTheme("test-theme");
   yield onUnRegisteredTheme;
+  yield onThemeSwitchComplete;
 
   ok(!gDevTools.getThemeDefinitionMap().has("test-theme"),
     "theme removed from map");
 
-  let panelWin = toolbox.getCurrentPanel().panelWin;
   let doc = panelWin.frameElement.contentDocument;
   let themeBox = doc.getElementById("devtools-theme-box");
 
   // The default light theme must be selected now.
   is(themeBox.querySelector("#devtools-theme-box [value=light]").checked, true,
     "light theme must be selected");
 });
 
--- a/devtools/client/framework/toolbox-hosts.js
+++ b/devtools/client/framework/toolbox-hosts.js
@@ -168,16 +168,19 @@ BottomHost.prototype = {
    */
   destroy: function () {
     if (!this._destroyed) {
       this._destroyed = true;
 
       Services.prefs.setIntPref(this.heightPref, this.frame.height);
       this._nbox.removeChild(this._splitter);
       this._nbox.removeChild(this.frame);
+      this.frame = null;
+      this._nbox = null;
+      this._splitter = null;
     }
 
     return promise.resolve(null);
   }
 };
 
 /**
  * Host object for the in-browser sidebar
--- a/devtools/client/framework/toolbox-options.js
+++ b/devtools/client/framework/toolbox-options.js
@@ -93,34 +93,36 @@ OptionsPanel.prototype = {
     this.setupThemeList();
     yield this.populatePreferences();
     this.isReady = true;
     this.emit("ready");
     return this;
   }),
 
   _addListeners: function () {
-    gDevTools.on("pref-changed", this._prefChanged);
+    Services.prefs.addObserver("devtools.cache.disabled", this._prefChanged, false);
+    Services.prefs.addObserver("devtools.theme", this._prefChanged, false);
     gDevTools.on("theme-registered", this._themeRegistered);
     gDevTools.on("theme-unregistered", this._themeUnregistered);
   },
 
   _removeListeners: function () {
-    gDevTools.off("pref-changed", this._prefChanged);
+    Services.prefs.removeObserver("devtools.cache.disabled", this._prefChanged);
+    Services.prefs.removeObserver("devtools.theme", this._prefChanged);
     gDevTools.off("theme-registered", this._themeRegistered);
     gDevTools.off("theme-unregistered", this._themeUnregistered);
   },
 
-  _prefChanged: function (event, data) {
-    if (data.pref === "devtools.cache.disabled") {
+  _prefChanged: function (subject, topic, prefName) {
+    if (prefName === "devtools.cache.disabled") {
       let cacheDisabled = data.newValue;
       let cbx = this.panelDoc.getElementById("devtools-disable-cache");
 
       cbx.checked = cacheDisabled;
-    } else if (data.pref === "devtools.theme") {
+    } else if (prefName === "devtools.theme") {
       this.updateCurrentTheme();
     }
   },
 
   _themeRegistered: function (event, themeId) {
     this.setupThemeList();
   },
 
@@ -249,16 +251,17 @@ OptionsPanel.prototype = {
       toolsNotSupportedLabel.style.display = "none";
     }
 
     this.panelWin.focus();
   },
 
   setupThemeList: function () {
     let themeBox = this.panelDoc.getElementById("devtools-theme-box");
+    themeBox.innerHTML = "";
 
     let createThemeOption = theme => {
       let inputLabel = this.panelDoc.createElement("label");
       let inputRadio = this.panelDoc.createElement("input");
       inputRadio.setAttribute("type", "radio");
       inputRadio.setAttribute("value", theme.id);
       inputRadio.setAttribute("name", "devtools-theme-item");
       inputRadio.addEventListener("change", function (e) {
@@ -345,21 +348,21 @@ OptionsPanel.prototype = {
   },
 
   updateCurrentTheme: function () {
     let currentTheme = GetPref("devtools.theme");
     let themeBox = this.panelDoc.getElementById("devtools-theme-box");
     let themeRadioInput = themeBox.querySelector(`[value=${currentTheme}]`);
 
     if (themeRadioInput) {
-      themeRadioInput.click();
+      themeRadioInput.checked = true;
     } else {
       // If the current theme does not exist anymore, switch to light theme
       let lightThemeInputRadio = themeBox.querySelector("[value=light]");
-      lightThemeInputRadio.click();
+      lightThemeInputRadio.checked = true;
     }
   },
 
   /**
    * Disables JavaScript for the currently loaded tab. We force a page refresh
    * here because setting docShell.allowJavascript to true fails to block JS
    * execution from event listeners added using addEventListener(), AJAX calls
    * and timers. The page refresh prevents these things from being added in the
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -818,19 +818,17 @@ Toolbox.prototype = {
         continue;
       }
 
       let button = this.doc.createElementNS(HTML_NS, "button");
       button.id = "toolbox-dock-" + position;
       button.className = "toolbox-dock-button devtools-button";
       button.setAttribute("title", L10N.getStr("toolboxDockButtons." +
                                                   position + ".tooltip"));
-      button.addEventListener("click", () => {
-        this.switchHost(position);
-      });
+      button.addEventListener("click", this.switchHost.bind(this, position));
 
       dockBox.appendChild(button);
     }
   },
 
   _getMinimizeButtonShortcutTooltip: function () {
     let str = L10N.getStr("toolbox.minimize.key");
     let key = KeyShortcuts.parseElectronKey(this.win, str);
@@ -1131,19 +1129,17 @@ Toolbox.prototype = {
     radio.setAttribute("ordinal", toolDefinition.ordinal);
     radio.setAttribute("tooltiptext", toolDefinition.tooltip);
     if (toolDefinition.invertIconForLightTheme) {
       radio.setAttribute("icon-invertable", "light-theme");
     } else if (toolDefinition.invertIconForDarkTheme) {
       radio.setAttribute("icon-invertable", "dark-theme");
     }
 
-    radio.addEventListener("command", () => {
-      this.selectTool(id);
-    });
+    radio.addEventListener("command", this.selectTool.bind(this, id));
 
     // spacer lets us center the image and label, while allowing cropping
     let spacer = this.doc.createElement("spacer");
     spacer.setAttribute("flex", "1");
     radio.appendChild(spacer);
 
     if (toolDefinition.icon) {
       let image = this.doc.createElement("image");
@@ -2047,16 +2043,18 @@ Toolbox.prototype = {
    * Remove all UI elements, detach from target and clear up
    */
   destroy: function () {
     // If several things call destroy then we give them all the same
     // destruction promise so we're sure to destroy only once
     if (this._destroyer) {
       return this._destroyer;
     }
+    let deferred = defer();
+    this._destroyer = deferred.promise;
 
     this.emit("destroy");
 
     this._target.off("navigate", this._refreshHostTitle);
     this._target.off("frame-update", this._updateFrames);
     this.off("select", this._refreshHostTitle);
     this.off("host-changed", this._refreshHostTitle);
     this.off("ready", this._showDevEditionPromo);
@@ -2071,23 +2069,33 @@ Toolbox.prototype = {
       this._sourceMapService.destroy();
       this._sourceMapService = null;
     }
 
     if (this.webconsolePanel) {
       this._saveSplitConsoleHeight();
       this.webconsolePanel.removeEventListener("resize",
         this._saveSplitConsoleHeight);
+      this.webconsolePanel = null;
     }
-    this.closeButton.removeEventListener("click", this.destroy, true);
-    this.textboxContextMenuPopup.removeEventListener("popupshowing",
-      this._updateTextboxMenuItems, true);
-    this.tabbar.removeEventListener("focus", this._onTabbarFocus, true);
-    this.tabbar.removeEventListener("click", this._onTabbarFocus, true);
-    this.tabbar.removeEventListener("keypress", this._onTabbarArrowKeypress);
+    if (this.closeButton) {
+      this.closeButton.removeEventListener("click", this.destroy, true);
+      this.closeButton = null;
+    }
+    if (this.textboxContextMenuPopup) {
+      this.textboxContextMenuPopup.removeEventListener("popupshowing",
+        this._updateTextboxMenuItems, true);
+      this.textboxContextMenuPopup = null;
+    }
+    if (this.tabbar) {
+      this.tabbar.removeEventListener("focus", this._onTabbarFocus, true);
+      this.tabbar.removeEventListener("click", this._onTabbarFocus, true);
+      this.tabbar.removeEventListener("keypress", this._onTabbarArrowKeypress);
+      this.tabbar = null;
+    }
 
     let outstanding = [];
     for (let [id, panel] of this._toolPanels) {
       try {
         gDevTools.emit(id + "-destroy", this, panel);
         this.emit(id + "-destroy", panel);
 
         outstanding.push(panel.destroy());
@@ -2132,17 +2140,17 @@ Toolbox.prototype = {
       CommandUtils.destroyRequisition(this._requisition, this.target);
     }
     this._telemetry.toolClosed("toolbox");
     this._telemetry.destroy();
 
     // Finish all outstanding tasks (which means finish destroying panels and
     // then destroying the host, successfully or not) before destroying the
     // target.
-    this._destroyer = settleAll(outstanding)
+    deferred.resolve(settleAll(outstanding)
         .catch(console.error)
         .then(() => this.destroyHost())
         .catch(console.error)
         .then(() => {
           this._win = null;
 
           // Targets need to be notified that the toolbox is being torn down.
           // This is done after other destruction tasks since it may tear down
@@ -2166,17 +2174,17 @@ Toolbox.prototype = {
 
           // Force GC to prevent long GC pauses when running tests and to free up
           // memory in general when the toolbox is closed.
           if (flags.testing) {
             win.QueryInterface(Ci.nsIInterfaceRequestor)
               .getInterface(Ci.nsIDOMWindowUtils)
               .garbageCollect();
           }
-        }).then(null, console.error);
+        }).then(null, console.error));
 
     let leakCheckObserver = ({wrappedJSObject: barrier}) => {
       // Make the leak detector wait until this toolbox is properly destroyed.
       barrier.client.addBlocker("DevTools: Wait until toolbox is destroyed",
                                 this._destroyer);
     };
 
     let topic = "shutdown-leaks-before-check";
--- a/devtools/client/inspector/components/test/head.js
+++ b/devtools/client/inspector/components/test/head.js
@@ -12,45 +12,32 @@ Services.scriptloader.loadSubScript(
   this);
 
 Services.prefs.setIntPref("devtools.toolbox.footer.height", 350);
 registerCleanupFunction(() => {
   Services.prefs.clearUserPref("devtools.toolbox.footer.height");
 });
 
 /**
- * Simple DOM node accesor function that takes either a node or a string css
- * selector as argument and returns the corresponding node
- * FIXME: Delete this function and use inspector/test/head.js' getNode instead,
- * and fix all box model view tests to use nodeFronts instead of CPOWs.
- * @param {String|DOMNode} nodeOrSelector
- * @return {DOMNode}
- */
-function getNode(nodeOrSelector) {
-  return typeof nodeOrSelector === "string" ?
-    content.document.querySelector(nodeOrSelector) :
-    nodeOrSelector;
-}
-
-/**
  * Highlight a node and set the inspector's current selection to the node or
  * the first match of the given css selector.
- * @param {String|DOMNode} nodeOrSelector
+ * @param {String|NodeFront} selectorOrNodeFront
+ *        The selector for the node to be set, or the nodeFront
  * @param {InspectorPanel} inspector
  *        The instance of InspectorPanel currently loaded in the toolbox
  * @return a promise that resolves when the inspector is updated with the new
  * node
  */
-function selectAndHighlightNode(nodeOrSelector, inspector) {
-  info("Highlighting and selecting the node " + nodeOrSelector);
+function* selectAndHighlightNode(selectorOrNodeFront, inspector) {
+  info("Highlighting and selecting the node " + selectorOrNodeFront);
 
-  let node = getNode(nodeOrSelector);
+  let nodeFront = yield getNodeFront(selectorOrNodeFront, inspector);
   let updated = inspector.toolbox.once("highlighter-ready");
-  inspector.selection.setNode(node, "test-highlight");
-  return updated;
+  inspector.selection.setNodeFront(nodeFront, "test-highlight");
+  yield updated;
 }
 
 /**
  * Open the toolbox, with the inspector tool visible, and the computed view
  * sidebar tab selected to display the box model view.
  * @return a promise that resolves when the inspector is ready and the box model
  * view is visible and ready
  */
--- a/devtools/client/inspector/rules/test/doc_frame_script.js
+++ b/devtools/client/inspector/rules/test/doc_frame_script.js
@@ -11,20 +11,19 @@
 // then execute code upon receiving, and immediately send back a message.
 // This is so that chrome test code can execute code in content and wait for a
 // response this way:
 // let response = yield executeInContent(browser, "Test:msgName", data, true);
 // The response message should have the same name "Test:msgName"
 //
 // Some listeners do not send a response message back.
 
-var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+var {utils: Cu} = Components;
 
 var {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
-var {isContentStylesheet} = require("devtools/shared/inspector/css-logic");
 var defer = require("devtools/shared/defer");
 
 /**
  * Get a value for a given property name in a css rule in a stylesheet, given
  * their indexes
  * @param {Object} data Expects a data object with the following properties
  * - {Number} styleSheetIndex
  * - {Number} ruleIndex
@@ -45,42 +44,16 @@ addMessageListener("Test:GetRuleProperty
       value = rule.style.getPropertyValue(name);
     }
   }
 
   sendAsyncMessage("Test:GetRulePropertyValue", value);
 });
 
 /**
- * Get information about all the stylesheets that contain rules that apply to
- * a given node. The information contains the sheet href and whether or not the
- * sheet is a content sheet or not
- * @param {Object} objects Expects a 'target' CPOW object
- * @return {Array} A list of stylesheet info objects
- */
-addMessageListener("Test:GetStyleSheetsInfoForNode", function (msg) {
-  let target = msg.objects.target;
-  let sheets = [];
-
-  let domUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
-    .getService(Ci.inIDOMUtils);
-  let domRules = domUtils.getCSSStyleRules(target);
-
-  for (let i = 0, n = domRules.Count(); i < n; i++) {
-    let sheet = domRules.GetElementAt(i).parentStyleSheet;
-    sheets.push({
-      href: sheet.href,
-      isContentSheet: isContentStylesheet(sheet)
-    });
-  }
-
-  sendAsyncMessage("Test:GetStyleSheetsInfoForNode", sheets);
-});
-
-/**
  * Get the property value from the computed style for an element.
  * @param {Object} data Expects a data object with the following properties
  * - {String} selector: The selector used to obtain the element.
  * - {String} pseudo: pseudo id to query, or null.
  * - {String} name: name of the property
  * @return {String} The value, if found, null otherwise
  */
 addMessageListener("Test:GetComputedStylePropertyValue", function (msg) {
--- a/devtools/client/inspector/shared/test/browser_styleinspector_csslogic-content-stylesheets.js
+++ b/devtools/client/inspector/shared/test/browser_styleinspector_csslogic-content-stylesheets.js
@@ -20,61 +20,57 @@ var ssm = Components.classes["@mozilla.o
                             .getService(Ci.nsIScriptSecurityManager);
 const XUL_PRINCIPAL = ssm.createCodebasePrincipal(XUL_URI, {});
 
 add_task(function* () {
   requestLongerTimeout(2);
 
   info("Checking stylesheets on HTML document");
   yield addTab(TEST_URI_HTML);
-  let target = getNode("#target");
 
-  let {inspector} = yield openInspector();
+  let {inspector, testActor} = yield openInspector();
   yield selectNode("#target", inspector);
 
   info("Checking stylesheets");
-  yield checkSheets(target);
+  yield checkSheets("#target", testActor);
 
   info("Checking authored stylesheets");
   yield addTab(TEST_URI_AUTHOR);
 
   ({inspector} = yield openInspector());
-  target = getNode("#target");
   yield selectNode("#target", inspector);
-  yield checkSheets(target);
+  yield checkSheets("#target", testActor);
 
   info("Checking stylesheets on XUL document");
   info("Allowing XUL content");
   allowXUL();
   yield addTab(TEST_URI_XUL);
 
   ({inspector} = yield openInspector());
-  target = getNode("#target");
   yield selectNode("#target", inspector);
 
-  yield checkSheets(target);
+  yield checkSheets("#target", testActor);
   info("Disallowing XUL content");
   disallowXUL();
 });
 
 function allowXUL() {
   Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
     .addFromPrincipal(XUL_PRINCIPAL, "allowXULXBL",
       Ci.nsIPermissionManager.ALLOW_ACTION);
 }
 
 function disallowXUL() {
   Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
     .addFromPrincipal(XUL_PRINCIPAL, "allowXULXBL",
       Ci.nsIPermissionManager.DENY_ACTION);
 }
 
-function* checkSheets(target) {
-  let sheets = yield executeInContent("Test:GetStyleSheetsInfoForNode", {},
-    {target});
+function* checkSheets(targetSelector, testActor) {
+  let sheets = yield testActor.getStyleSheetsInfoForNode(targetSelector);
 
   for (let sheet of sheets) {
     if (!sheet.href ||
         /doc_content_stylesheet_/.test(sheet.href) ||
         // For the "authored" case.
         /^data:.*seagreen/.test(sheet.href)) {
       ok(sheet.isContentSheet,
         sheet.href + " identified as content stylesheet");
--- a/devtools/client/inspector/shared/test/doc_frame_script.js
+++ b/devtools/client/inspector/shared/test/doc_frame_script.js
@@ -11,20 +11,18 @@
 // then execute code upon receiving, and immediately send back a message.
 // This is so that chrome test code can execute code in content and wait for a
 // response this way:
 // let response = yield executeInContent(browser, "Test:MsgName", data, true);
 // The response message should have the same name "Test:MsgName"
 //
 // Some listeners do not send a response message back.
 
-var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
+var {utils: Cu} = Components;
 var {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
-var {isContentStylesheet} = require("devtools/shared/inspector/css-logic");
 var defer = require("devtools/shared/defer");
 
 /**
  * Get a value for a given property name in a css rule in a stylesheet, given
  * their indexes
  * @param {Object} data Expects a data object with the following properties
  * - {Number} styleSheetIndex
  * - {Number} ruleIndex
@@ -45,42 +43,16 @@ addMessageListener("Test:GetRuleProperty
       value = rule.style.getPropertyValue(name);
     }
   }
 
   sendAsyncMessage("Test:GetRulePropertyValue", value);
 });
 
 /**
- * Get information about all the stylesheets that contain rules that apply to
- * a given node. The information contains the sheet href and whether or not the
- * sheet is a content sheet or not
- * @param {Object} objects Expects a 'target' CPOW object
- * @return {Array} A list of stylesheet info objects
- */
-addMessageListener("Test:GetStyleSheetsInfoForNode", function (msg) {
-  let target = msg.objects.target;
-  let sheets = [];
-
-  let domUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
-    .getService(Ci.inIDOMUtils);
-  let domRules = domUtils.getCSSStyleRules(target);
-
-  for (let i = 0, n = domRules.Count(); i < n; i++) {
-    let sheet = domRules.GetElementAt(i).parentStyleSheet;
-    sheets.push({
-      href: sheet.href,
-      isContentSheet: isContentStylesheet(sheet)
-    });
-  }
-
-  sendAsyncMessage("Test:GetStyleSheetsInfoForNode", sheets);
-});
-
-/**
  * Get the property value from the computed style for an element.
  * @param {Object} data Expects a data object with the following properties
  * - {String} selector: The selector used to obtain the element.
  * - {String} pseudo: pseudo id to query, or null.
  * - {String} name: name of the property
  * @return {String} The value, if found, null otherwise
  */
 addMessageListener("Test:GetComputedStylePropertyValue", function (msg) {
--- a/devtools/client/inspector/test/browser_inspector_initialization.js
+++ b/devtools/client/inspector/test/browser_inspector_initialization.js
@@ -24,39 +24,38 @@ const HTML = `
 `;
 
 const TEST_URI = "data:text/html;charset=utf-8," + encodeURI(HTML);
 
 add_task(function* () {
   let tab = yield addTab(TEST_URI);
   let testActor = yield getTestActorWithoutToolbox(tab);
 
-  yield testToolboxInitialization(tab);
+  yield testToolboxInitialization(testActor, tab);
   yield testContextMenuInitialization(testActor);
   yield testContextMenuInspectorAlreadyOpen(testActor);
 });
 
-function* testToolboxInitialization(tab) {
+function* testToolboxInitialization(testActor, tab) {
   let target = TargetFactory.forTab(tab);
 
   info("Opening inspector with gDevTools.");
   let toolbox = yield gDevTools.showToolbox(target, "inspector");
   let inspector = toolbox.getCurrentPanel();
 
   ok(true, "Inspector started, and notification received.");
   ok(inspector, "Inspector instance is accessible.");
   ok(inspector.isReady, "Inspector instance is ready.");
   is(inspector.target.tab, tab, "Valid target.");
 
   yield selectNode("p", inspector);
   yield testMarkupView("p", inspector);
   yield testBreadcrumbs("p", inspector);
 
-  let span = getNode("span");
-  span.scrollIntoView();
+  yield testActor.scrollIntoView("span");
 
   yield selectNode("span", inspector);
   yield testMarkupView("span", inspector);
   yield testBreadcrumbs("span", inspector);
 
   info("Destroying toolbox");
   let destroyed = toolbox.once("destroyed");
   toolbox.destroy();
--- a/devtools/client/inspector/test/head.js
+++ b/devtools/client/inspector/test/head.js
@@ -62,51 +62,16 @@ registerCleanupFunction(function* () {
 });
 
 var navigateTo = function (toolbox, url) {
   let activeTab = toolbox.target.activeTab;
   return activeTab.navigateTo(url);
 };
 
 /**
- * Simple DOM node accesor function that takes either a node or a string css
- * selector as argument and returns the corresponding node
- * @param {String|DOMNode} nodeOrSelector
- * @param {Object} options
- *        An object containing any of the following options:
- *        - document: HTMLDocument that should be queried for the selector.
- *                    Default: content.document.
- *        - expectNoMatch: If true and a node matches the given selector, a
- *                         failure is logged for an unexpected match.
- *                         If false and nothing matches the given selector, a
- *                         failure is logged for a missing match.
- *                         Default: false.
- * @return {DOMNode}
- */
-function getNode(nodeOrSelector, options = {}) {
-  let document = options.document || content.document;
-  let noMatches = !!options.expectNoMatch;
-
-  if (typeof nodeOrSelector === "string") {
-    info("Looking for a node that matches selector " + nodeOrSelector);
-    let node = document.querySelector(nodeOrSelector);
-    if (noMatches) {
-      ok(!node, "Selector " + nodeOrSelector + " didn't match any nodes.");
-    } else {
-      ok(node, "Selector " + nodeOrSelector + " matched a node.");
-    }
-
-    return node;
-  }
-
-  info("Looking for a node but selector was not a string.");
-  return nodeOrSelector;
-}
-
-/**
  * Start the element picker and focus the content window.
  * @param {Toolbox} toolbox
  */
 var startPicker = Task.async(function* (toolbox) {
   info("Start the element picker");
   yield toolbox.highlighterUtils.startPicker();
   // Make sure the content window is focused since the picker does not focus
   // the content window by default.
--- a/devtools/client/shared/developer-toolbar.js
+++ b/devtools/client/shared/developer-toolbar.js
@@ -100,38 +100,38 @@ var CommandUtils = {
 
         if (command.tooltipText != null) {
           button.setAttribute("title", command.tooltipText);
         }
         else if (command.description != null) {
           button.setAttribute("title", command.description);
         }
 
-        button.addEventListener("click", () => {
-          requisition.updateExec(typed);
-        }, false);
+        button.addEventListener("click",
+          requisition.updateExec.bind(requisition, typed));
 
         button.addEventListener("keypress", (event) => {
           if (ViewHelpers.isSpaceOrReturn(event)) {
             event.preventDefault();
             requisition.updateExec(typed);
           }
         }, false);
 
         // Allow the command button to be toggleable
+        let onChange = null;
         if (command.state) {
           button.setAttribute("autocheck", false);
 
           /**
            * The onChange event should be called with an event object that
            * contains a target property which specifies which target the event
            * applies to. For legacy reasons the event object can also contain
            * a tab property.
            */
-          let onChange = (eventName, ev) => {
+          onChange = (eventName, ev) => {
             if (ev.target == target || ev.tab == target.tab) {
 
               let updateChecked = (checked) => {
                 if (checked) {
                   button.setAttribute("checked", true);
                 }
                 else if (button.hasAttribute("checked")) {
                   button.removeAttribute("checked");
@@ -150,22 +150,24 @@ var CommandUtils = {
               else {
                 updateChecked(reply);
               }
             }
           };
 
           command.state.onChange(target, onChange);
           onChange("", { target: target });
-          document.defaultView.addEventListener("unload", () => {
-            if (command.state.offChange) {
-              command.state.offChange(target, onChange);
-            }
-          }, false);
-        }
+        };
+        document.defaultView.addEventListener("unload", function (event) {
+          if (onChange && command.state.offChange) {
+            command.state.offChange(target, onChange);
+          }
+          button.remove();
+          button = null;
+        }, { once: true });
 
         requisition.clear();
 
         return button;
       });
     });
   },
 
--- a/devtools/client/shared/test/test-actor.js
+++ b/devtools/client/shared/test/test-actor.js
@@ -5,16 +5,17 @@
 "use strict";
 
 // A helper actor for inspector and markupview tests.
 
 var { Cc, Ci, Cu, Cr } = require("chrome");
 const {getRect, getElementFromPoint, getAdjustedQuads} = require("devtools/shared/layout/utils");
 const defer = require("devtools/shared/defer");
 const {Task} = require("devtools/shared/task");
+const {isContentStylesheet} = require("devtools/shared/inspector/css-logic");
 var DOMUtils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
 var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
             .getService(Ci.mozIJSSubScriptLoader);
 
 // Set up a dummy environment so that EventUtils works. We need to be careful to
 // pass a window object into each EventUtils method we call rather than having
 // it rely on the |window| global.
 let EventUtils = {};
@@ -139,16 +140,22 @@ var testSpec = protocol.generateActorSpe
       response: {}
     },
     synthesizeKey: {
       request: {
         args: Arg(0, "json")
       },
       response: {}
     },
+    scrollIntoView: {
+      request: {
+        args: Arg(0, "string")
+      },
+      response: {}
+    },
     hasPseudoClassLock: {
       request: {
         selector: Arg(0, "string"),
         pseudo: Arg(1, "string")
       },
       response: {
         value: RetVal("boolean")
       }
@@ -255,16 +262,24 @@ var testSpec = protocol.generateActorSpe
     },
     getNodeInfo: {
       request: {
         selector: Arg(0, "string")
       },
       response: {
         value: RetVal("json")
       }
+    },
+    getStyleSheetsInfoForNode: {
+      request: {
+        selector: Arg(0, "string")
+      },
+      response: {
+        value: RetVal("json")
+      }
     }
   }
 });
 
 var TestActor = exports.TestActor = protocol.ActorClassWithSpec(testSpec, {
   initialize: function (conn, tabActor, options) {
     this.conn = conn;
     this.tabActor = tabActor;
@@ -494,16 +509,25 @@ var TestActor = exports.TestActor = prot
   * back. Consumers should listen to specific events on the inspector/highlighter
   * to know when the event got synthesized.
   */
   synthesizeKey: function ({key, options, content}) {
     EventUtils.synthesizeKey(key, options, this.content);
   },
 
   /**
+   * Scroll an element into view.
+   * @param {String} selector The selector for the node to scroll into view.
+   */
+  scrollIntoView: function (selector) {
+    let node = this._querySelector(selector);
+    node.scrollIntoView();
+  },
+
+  /**
    * Check that an element currently has a pseudo-class lock.
    * @param {String} selector The node selector to get the pseudo-class from
    * @param {String} pseudo The pseudoclass to check for
    * @return {Boolean}
    */
   hasPseudoClassLock: function (selector, pseudo) {
     let node = this._querySelector(selector);
     return DOMUtils.hasPseudoClassLock(node, pseudo);
@@ -720,16 +744,42 @@ var TestActor = exports.TestActor = prot
         }),
         outerHTML: node.outerHTML,
         innerHTML: node.innerHTML,
         textContent: node.textContent
       };
     }
 
     return info;
+  },
+
+  /**
+   * Get information about the stylesheets which have CSS rules that apply to a given DOM
+   * element, identified by a selector.
+   * @param {String} selector The CSS selector to get the node (can be an array
+   * of selectors to get elements in an iframe).
+   * @return {Array} A list of stylesheet objects, each having the following properties:
+   * - {String} href.
+   * - {Boolean} isContentSheet.
+   */
+  getStyleSheetsInfoForNode: function (selector) {
+    let node = this._querySelector(selector);
+    let domRules = DOMUtils.getCSSStyleRules(node);
+
+    let sheets = [];
+
+    for (let i = 0, n = domRules.Count(); i < n; i++) {
+      let sheet = domRules.GetElementAt(i).parentStyleSheet;
+      sheets.push({
+        href: sheet.href,
+        isContentSheet: isContentStylesheet(sheet)
+      });
+    }
+
+    return sheets;
   }
 });
 
 var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSpec, {
   initialize: function (client, { testActor }, toolbox) {
     protocol.Front.prototype.initialize.call(this, client, { actor: testActor });
     this.manage(this);
     this.toolbox = toolbox;
--- a/devtools/client/shared/theme-switching.js
+++ b/devtools/client/shared/theme-switching.js
@@ -22,16 +22,17 @@
 
   // no-theme attributes allows to just est the platform attribute
   // to have per-platform CSS working correctly.
   if (documentElement.getAttribute("no-theme") === "true") {
     return;
   }
 
   let devtoolsStyleSheets = new WeakMap();
+  let gOldTheme = "";
 
   function forceStyle() {
     let computedStyle = window.getComputedStyle(documentElement);
     if (!computedStyle) {
       // Null when documentElement is not ready. This method is anyways not
       // required then as scrollbars would be in their state without flushing.
       return;
     }
@@ -78,20 +79,22 @@
   function notifyWindow() {
     window.dispatchEvent(new CustomEvent("theme-switch-complete", {}));
   }
 
   /*
    * Apply all the sheets from `newTheme` and remove all of the sheets
    * from `oldTheme`
    */
-  function switchTheme(newTheme, oldTheme) {
-    if (newTheme === oldTheme) {
+  function switchTheme(newTheme) {
+    if (newTheme === gOldTheme) {
       return;
     }
+    let oldTheme = gOldTheme;
+    gOldTheme = newTheme;
 
     let oldThemeDef = gDevTools.getThemeDefinition(oldTheme);
     let newThemeDef = gDevTools.getThemeDefinition(newTheme);
 
     // The theme might not be available anymore (e.g. uninstalled)
     // Use the default one.
     if (!newThemeDef) {
       newThemeDef = gDevTools.getThemeDefinition("light");
@@ -151,34 +154,32 @@
       }
 
       // Final notification for further theme-switching related logic.
       gDevTools.emit("theme-switched", window, newTheme, oldTheme);
       notifyWindow();
     }, console.error.bind(console));
   }
 
-  function handlePrefChange(event, data) {
-    if (data.pref == "devtools.theme") {
-      switchTheme(data.newValue, data.oldValue);
-    }
+  function handlePrefChange() {
+    switchTheme(Services.prefs.getCharPref("devtools.theme"));
   }
 
   const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
   const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
   const Services = require("Services");
   const { gDevTools } = require("devtools/client/framework/devtools");
   const StylesheetUtils = require("sdk/stylesheet/utils");
   const { watchCSS } = require("devtools/client/shared/css-reload");
 
   if (documentElement.hasAttribute("force-theme")) {
     switchTheme(documentElement.getAttribute("force-theme"));
   } else {
     switchTheme(Services.prefs.getCharPref("devtools.theme"));
 
-    gDevTools.on("pref-changed", handlePrefChange);
+    Services.prefs.addObserver("devtools.theme", handlePrefChange, false);
     window.addEventListener("unload", function () {
-      gDevTools.off("pref-changed", handlePrefChange);
-    });
+      Services.prefs.removeObserver("devtools.theme", handlePrefChange);
+    }, { once: true });
   }
 
   watchCSS(window);
 })();
--- a/devtools/client/webconsole/panel.js
+++ b/devtools/client/webconsole/panel.js
@@ -102,13 +102,17 @@ WebConsolePanel.prototype = {
   },
 
   destroy: function () {
     if (this._destroyer) {
       return this._destroyer;
     }
 
     this._destroyer = this.hud.destroy();
-    this._destroyer.then(() => this.emit("destroyed"));
+    this._destroyer.then(() => {
+      this._frameWindow = null;
+      this._toolbox = null;
+      this.emit("destroyed");
+    });
 
     return this._destroyer;
   },
 };
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -218,17 +218,33 @@ public:
   virtual ~StateObject() {}
   virtual void Enter() {}; // Entry action.
   virtual void Exit() {};  // Exit action.
   virtual void Step() {}   // Perform a 'cycle' of this state object.
   virtual State GetState() const = 0;
 
   // Event handlers for various events.
   // Return true if the event is handled by this state object.
-  virtual bool HandleDormant(bool aDormant) { return false; }
+  virtual bool HandleDormant(bool aDormant)
+  {
+    if (!aDormant) {
+      return true;
+    }
+    mMaster->mQueuedSeek.mTarget =
+      SeekTarget(mMaster->mCurrentPosition,
+                 SeekTarget::Accurate,
+                 MediaDecoderEventVisibility::Suppressed);
+    // SeekJob asserts |mTarget.IsValid() == !mPromise.IsEmpty()| so we
+    // need to create the promise even it is not used at all.
+    RefPtr<MediaDecoder::SeekPromise> unused =
+      mMaster->mQueuedSeek.mPromise.Ensure(__func__);
+    SetState(DECODER_STATE_DORMANT);
+    return true;
+  }
+
   virtual bool HandleCDMProxyReady() { return false; }
 
 protected:
   using Master = MediaDecoderStateMachine;
   explicit StateObject(Master* aPtr) : mMaster(aPtr) {}
   TaskQueue* OwnerThread() const { return mMaster->mTaskQueue; }
   MediaResource* Resource() const { return mMaster->mResource; }
   MediaDecoderReaderWrapper* Reader() const { return mMaster->mReader; }
@@ -403,16 +419,25 @@ public:
     mMaster->Reset();
     mMaster->mReader->ReleaseResources();
   }
 
   State GetState() const override
   {
     return DECODER_STATE_DORMANT;
   }
+
+  bool HandleDormant(bool aDormant) override
+  {
+    if (!aDormant) {
+      // Exit dormant state.
+      SetState(DECODER_STATE_DECODING_METADATA);
+    }
+    return true;
+  }
 };
 
 class MediaDecoderStateMachine::DecodingFirstFrameState
   : public MediaDecoderStateMachine::StateObject
 {
 public:
   explicit DecodingFirstFrameState(Master* aPtr) : StateObject(aPtr) {}
 
@@ -454,16 +479,36 @@ class MediaDecoderStateMachine::SeekingS
 {
 public:
   explicit SeekingState(Master* aPtr) : StateObject(aPtr) {}
 
   State GetState() const override
   {
     return DECODER_STATE_SEEKING;
   }
+
+  bool HandleDormant(bool aDormant) override
+  {
+    if (!aDormant) {
+      return true;
+    }
+    MOZ_ASSERT(!mMaster->mQueuedSeek.Exists());
+    MOZ_ASSERT(mMaster->mCurrentSeek.Exists());
+    // Because both audio and video decoders are going to be reset in this
+    // method later, we treat a VideoOnly seek task as a normal Accurate
+    // seek task so that while it is resumed, both audio and video playback
+    // are handled.
+    if (mMaster->mCurrentSeek.mTarget.IsVideoOnly()) {
+      mMaster->mCurrentSeek.mTarget.SetType(SeekTarget::Accurate);
+      mMaster->mCurrentSeek.mTarget.SetVideoOnly(false);
+    }
+    mMaster->mQueuedSeek = Move(mMaster->mCurrentSeek);
+    SetState(DECODER_STATE_DORMANT);
+    return true;
+  }
 };
 
 class MediaDecoderStateMachine::BufferingState
   : public MediaDecoderStateMachine::StateObject
 {
 public:
   explicit BufferingState(Master* aPtr) : StateObject(aPtr) {}
 
@@ -525,16 +570,21 @@ public:
   {
     MOZ_DIAGNOSTIC_ASSERT(false, "Shouldn't escape the SHUTDOWN state.");
   }
 
   State GetState() const override
   {
     return DECODER_STATE_SHUTDOWN;
   }
+
+  bool HandleDormant(bool aDormant) override
+  {
+    return true;
+  }
 };
 
 #define INIT_WATCHABLE(name, val) \
   name(val, "MediaDecoderStateMachine::" #name)
 #define INIT_MIRROR(name, val) \
   name(mTaskQueue, val, "MediaDecoderStateMachine::" #name " (Mirror)")
 #define INIT_CANONICAL(name, val) \
   name(mTaskQueue, val, "MediaDecoderStateMachine::" #name " (Canonical)")
@@ -1312,30 +1362,43 @@ void MediaDecoderStateMachine::MaybeStar
 void
 MediaDecoderStateMachine::MaybeStartBuffering()
 {
   MOZ_ASSERT(OnTaskQueue());
   // Buffering makes senses only after decoding first frames.
   MOZ_ASSERT(mSentFirstFrameLoadedEvent);
   MOZ_ASSERT(mState == DECODER_STATE_DECODING);
 
-  if (mPlayState == MediaDecoder::PLAY_STATE_PLAYING &&
-      mResource->IsExpectingMoreData()) {
-    bool shouldBuffer;
-    if (mReader->UseBufferingHeuristics()) {
-      shouldBuffer = HasLowDecodedData(EXHAUSTED_DATA_MARGIN_USECS) &&
-                     (JustExitedQuickBuffering() || HasLowUndecodedData());
-    } else {
-      MOZ_ASSERT(mReader->IsWaitForDataSupported());
-      shouldBuffer = (OutOfDecodedAudio() && mReader->IsWaitingAudioData()) ||
-                     (OutOfDecodedVideo() && mReader->IsWaitingVideoData());
-    }
-    if (shouldBuffer) {
-      SetState(DECODER_STATE_BUFFERING);
-    }
+  // Don't enter buffering when MediaDecoder is not playing.
+  if (mPlayState != MediaDecoder::PLAY_STATE_PLAYING) {
+    return;
+  }
+
+  // Don't enter buffering while prerolling so that the decoder has a chance to
+  // enqueue some decoded data before we give up and start buffering.
+  if (!IsPlaying()) {
+    return;
+  }
+
+  // No more data to download. No need to enter buffering.
+  if (!mResource->IsExpectingMoreData()) {
+    return;
+  }
+
+  bool shouldBuffer;
+  if (mReader->UseBufferingHeuristics()) {
+    shouldBuffer = HasLowDecodedData(EXHAUSTED_DATA_MARGIN_USECS) &&
+                   (JustExitedQuickBuffering() || HasLowUndecodedData());
+  } else {
+    MOZ_ASSERT(mReader->IsWaitForDataSupported());
+    shouldBuffer = (OutOfDecodedAudio() && mReader->IsWaitingAudioData()) ||
+                   (OutOfDecodedVideo() && mReader->IsWaitingVideoData());
+  }
+  if (shouldBuffer) {
+    SetState(DECODER_STATE_BUFFERING);
   }
 }
 
 void MediaDecoderStateMachine::UpdatePlaybackPositionInternal(int64_t aTime)
 {
   MOZ_ASSERT(OnTaskQueue());
   SAMPLE_LOG("UpdatePlaybackPositionInternal(%lld)", aTime);
 
@@ -1483,61 +1546,17 @@ MediaDecoderStateMachine::DispatchSetDor
     this, &MediaDecoderStateMachine::SetDormant, aDormant);
   OwnerThread()->Dispatch(r.forget());
 }
 
 void
 MediaDecoderStateMachine::SetDormant(bool aDormant)
 {
   MOZ_ASSERT(OnTaskQueue());
-
-  if (IsShutdown()) {
-    return;
-  }
-
-  if (mStateObj->HandleDormant(aDormant)) {
-    return;
-  }
-
-  bool wasDormant = mState == DECODER_STATE_DORMANT;
-  if (wasDormant == aDormant) {
-    return;
-  }
-
-  DECODER_LOG("SetDormant=%d", aDormant);
-
-  // Enter dormant state.
-  if (aDormant) {
-    if (mState == DECODER_STATE_SEEKING) {
-      MOZ_ASSERT(!mQueuedSeek.Exists());
-      MOZ_ASSERT(mCurrentSeek.Exists());
-      // Because both audio and video decoders are going to be reset in this
-      // method later, we treat a VideoOnly seek task as a normal Accurate
-      // seek task so that while it is resumed, both audio and video playback
-      // are handled.
-      if (mCurrentSeek.mTarget.IsVideoOnly()) {
-        mCurrentSeek.mTarget.SetType(SeekTarget::Accurate);
-        mCurrentSeek.mTarget.SetVideoOnly(false);
-      }
-      mQueuedSeek = Move(mCurrentSeek);
-    } else {
-      mQueuedSeek.mTarget = SeekTarget(mCurrentPosition,
-                                       SeekTarget::Accurate,
-                                       MediaDecoderEventVisibility::Suppressed);
-      // SeekJob asserts |mTarget.IsValid() == !mPromise.IsEmpty()| so we
-      // need to create the promise even it is not used at all.
-      RefPtr<MediaDecoder::SeekPromise> unused = mQueuedSeek.mPromise.Ensure(__func__);
-    }
-
-    SetState(DECODER_STATE_DORMANT);
-    return;
-  }
-
-  // Exit dormant state.
-  SetState(DECODER_STATE_DECODING_METADATA);
+  mStateObj->HandleDormant(aDormant);
 }
 
 RefPtr<ShutdownPromise>
 MediaDecoderStateMachine::Shutdown()
 {
   MOZ_ASSERT(OnTaskQueue());
 
   SetState(DECODER_STATE_SHUTDOWN);
--- a/image/test/reftest/reftest-stylo.list
+++ b/image/test/reftest/reftest-stylo.list
@@ -32,17 +32,17 @@ skip-if(B2G) include pngsuite-transparen
 skip-if(B2G) include pngsuite-zlib/reftest-stylo.list        
 # bug 783632
 
 # Disabled, lots of intermittents here
 # BMP tests
 #skip-if(Android) include bmp/reftest-stylo.list
 
 # ICO tests
-skip-if(Android) include ico/reftest-stylo.list
+#skip-if(Android) include ico/reftest-stylo.list
 
 # JPEG tests
 # include jpeg/reftest-stylo.list
 
 # GIF tests
 # include gif/reftest-stylo.list
 
 # APNG tests
--- a/js/xpconnect/src/XPCCallContext.cpp
+++ b/js/xpconnect/src/XPCCallContext.cpp
@@ -194,16 +194,17 @@ void
 XPCCallContext::SystemIsBeingShutDown()
 {
     // XXX This is pretty questionable since the per thread cleanup stuff
     // can be making this call on one thread for call contexts on another
     // thread.
     NS_WARNING("Shutting Down XPConnect even through there is a live XPCCallContext");
     mXPCJSContext = nullptr;
     mState = SYSTEM_SHUTDOWN;
+    mSet = nullptr;
     mInterface = nullptr;
 
     if (mPrevCallContext)
         mPrevCallContext->SystemIsBeingShutDown();
 }
 
 XPCCallContext::~XPCCallContext()
 {
--- a/js/xpconnect/src/XPCInlines.h
+++ b/js/xpconnect/src/XPCInlines.h
@@ -441,28 +441,16 @@ XPCNativeSet::MatchesSetUpToInterface(co
         if (cur != (*pp2))
             return false;
         if (cur == iface)
             return true;
     }
     return false;
 }
 
-inline void XPCNativeSet::Mark()
-{
-    mMarked = 1;
-}
-
-#ifdef DEBUG
-inline void XPCNativeSet::ASSERT_NotMarked()
-{
-    MOZ_ASSERT(!IsMarked(), "bad");
-}
-#endif
-
 /***************************************************************************/
 
 inline
 JSObject* XPCWrappedNativeTearOff::GetJSObjectPreserveColor() const
 {
     return mJSObject.getPtr();
 }
 
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -779,87 +779,25 @@ XPCJSContext::FinalizeCallback(JSFreeOp*
 
             break;
         }
         case JSFINALIZE_COLLECTION_END:
         {
             MOZ_ASSERT(!self->mGCIsRunning, "bad state");
             self->mGCIsRunning = true;
 
-            // We use this occasion to mark and sweep NativeInterfaces,
-            // NativeSets, and the WrappedNativeJSClasses...
-
-            // Do the marking...
-            XPCWrappedNativeScope::MarkAllWrappedNativesAndProtos();
-
-            // Mark the sets used in the call contexts. There is a small
-            // chance that a wrapper's set will change *while* a call is
-            // happening which uses that wrapper's old interfface set. So,
-            // we need to do this marking to avoid collecting those sets
-            // that might no longer be otherwise reachable from the wrappers
-            // or the wrapperprotos.
-
             // Skip this part if XPConnect is shutting down. We get into
             // bad locking problems with the thread iteration otherwise.
             if (!nsXPConnect::XPConnect()->IsShuttingDown()) {
 
                 // Mark those AutoMarkingPtr lists!
                 if (AutoMarkingPtr* roots = Get()->mAutoRoots)
                     roots->MarkAfterJSFinalizeAll();
-
-                XPCCallContext* ccxp = XPCJSContext::Get()->GetCallContext();
-                while (ccxp) {
-                    // Deal with the strictness of callcontext that
-                    // complains if you ask for a set when
-                    // it is in a state where the set could not
-                    // possibly be valid.
-                    if (ccxp->CanGetSet()) {
-                        XPCNativeSet* set = ccxp->GetSet();
-                        if (set)
-                            set->Mark();
-                    }
-                    ccxp = ccxp->GetPrevCallContext();
-                }
             }
 
-            // Do the sweeping. During a zone GC, only WrappedNativeProtos in
-            // collected zones will be marked. Therefore, some reachable
-            // NativeInterfaces will not be marked, so it is not safe to sweep
-            // them. We still need to unmark them, since the ones pointed to by
-            // WrappedNativeProtos in a zone being collected will be marked.
-            //
-            // Ideally, if NativeInterfaces from different zones were kept
-            // separate, we could sweep only the ones belonging to zones being
-            // collected. Currently, though, NativeInterfaces are shared between
-            // zones. This ought to be fixed.
-            bool doSweep = !isZoneGC;
-
-            if (doSweep) {
-                for (auto i = self->mClassInfo2NativeSetMap->Iter(); !i.Done(); i.Next()) {
-                    auto entry = static_cast<ClassInfo2NativeSetMap::Entry*>(i.Get());
-                    if (!entry->value->IsMarked())
-                        i.Remove();
-                }
-            }
-
-            for (auto i = self->mNativeSetMap->Iter(); !i.Done(); i.Next()) {
-                auto entry = static_cast<NativeSetMap::Entry*>(i.Get());
-                XPCNativeSet* set = entry->key_value;
-                if (set->IsMarked()) {
-                    set->Unmark();
-                } else if (doSweep) {
-                    XPCNativeSet::DestroyInstance(set);
-                    i.Remove();
-                }
-            }
-
-#ifdef DEBUG
-            XPCWrappedNativeScope::ASSERT_NoInterfaceSetsAreMarked();
-#endif
-
             // Now we are going to recycle any unused WrappedNativeTearoffs.
             // We do this by iterating all the live callcontexts
             // and marking the tearoffs in use. And then we
             // iterate over all the WrappedNative wrappers and sweep their
             // tearoffs.
             //
             // This allows us to perhaps minimize the growth of the
             // tearoffs. And also makes us not hold references to interfaces
--- a/js/xpconnect/src/XPCMaps.cpp
+++ b/js/xpconnect/src/XPCMaps.cpp
@@ -197,24 +197,51 @@ IID2NativeInterfaceMap::SizeOfIncludingT
     }
     return n;
 }
 
 /***************************************************************************/
 // implement ClassInfo2NativeSetMap...
 
 // static
+bool ClassInfo2NativeSetMap::Entry::Match(const PLDHashEntryHdr* aEntry,
+                                          const void* aKey)
+{
+    return static_cast<const Entry*>(aEntry)->key == aKey;
+}
+
+// static
+void ClassInfo2NativeSetMap::Entry::Clear(PLDHashTable* aTable,
+                                          PLDHashEntryHdr* aEntry)
+{
+    auto entry = static_cast<Entry*>(aEntry);
+    NS_RELEASE(entry->value);
+
+    entry->key = nullptr;
+    entry->value = nullptr;
+}
+
+const PLDHashTableOps ClassInfo2NativeSetMap::Entry::sOps =
+{
+    PLDHashTable::HashVoidPtrKeyStub,
+    Match,
+    PLDHashTable::MoveEntryStub,
+    Clear,
+    nullptr
+};
+
+// static
 ClassInfo2NativeSetMap*
 ClassInfo2NativeSetMap::newMap(int length)
 {
     return new ClassInfo2NativeSetMap(length);
 }
 
 ClassInfo2NativeSetMap::ClassInfo2NativeSetMap(int length)
-  : mTable(PLDHashTable::StubOps(), sizeof(Entry), length)
+  : mTable(&ClassInfo2NativeSetMap::Entry::sOps, sizeof(Entry), length)
 {
 }
 
 size_t
 ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
 {
     size_t n = mallocSizeOf(this);
     n += mTable.ShallowSizeOfExcludingThis(mallocSizeOf);
--- a/js/xpconnect/src/XPCMaps.h
+++ b/js/xpconnect/src/XPCMaps.h
@@ -273,17 +273,22 @@ private:
 /*************************/
 
 class ClassInfo2NativeSetMap
 {
 public:
     struct Entry : public PLDHashEntryHdr
     {
         nsIClassInfo* key;
-        XPCNativeSet* value;
+        XPCNativeSet* value; // strong reference
+        static const PLDHashTableOps sOps;
+
+    private:
+        static bool Match(const PLDHashEntryHdr* aEntry, const void* aKey);
+        static void Clear(PLDHashTable* aTable, PLDHashEntryHdr* aEntry);
     };
 
     static ClassInfo2NativeSetMap* newMap(int length);
 
     inline XPCNativeSet* Find(nsIClassInfo* info)
     {
         auto entry = static_cast<Entry*>(mTable.Search(info));
         return entry ? entry->value : nullptr;
@@ -293,30 +298,28 @@ public:
     {
         NS_PRECONDITION(info,"bad param");
         auto entry = static_cast<Entry*>(mTable.Add(info, mozilla::fallible));
         if (!entry)
             return nullptr;
         if (entry->key)
             return entry->value;
         entry->key = info;
-        entry->value = set;
+        NS_ADDREF(entry->value = set);
         return set;
     }
 
     inline void Remove(nsIClassInfo* info)
     {
         NS_PRECONDITION(info,"bad param");
         mTable.Remove(info);
     }
 
     inline uint32_t Count() { return mTable.EntryCount(); }
 
-    PLDHashTable::Iterator Iter() { return mTable.Iter(); }
-
     // ClassInfo2NativeSetMap holds pointers to *some* XPCNativeSets.
     // So we don't want to count those XPCNativeSets, because they are better
     // counted elsewhere (i.e. in XPCJSContext::mNativeSetMap, which holds
     // pointers to *all* XPCNativeSets).  Hence the "Shallow".
     size_t ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
 
 private:
     ClassInfo2NativeSetMap();    // no implementation
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -426,25 +426,25 @@ XPCWrappedNative::GetNewOrUsed(xpcObject
             return NS_ERROR_FAILURE;
 
         wrapper = new XPCWrappedNative(helper.forgetCanonical(), proto);
     } else {
         RefPtr<XPCNativeInterface> iface = Interface;
         if (!iface)
             iface = XPCNativeInterface::GetISupports();
 
-        AutoMarkingNativeSetPtr set(cx);
         XPCNativeSetKey key(iface);
-        set = XPCNativeSet::GetNewOrUsed(&key);
+        RefPtr<XPCNativeSet> set =
+            XPCNativeSet::GetNewOrUsed(&key);
 
         if (!set)
             return NS_ERROR_FAILURE;
 
-        wrapper =
-            new XPCWrappedNative(helper.forgetCanonical(), Scope, set);
+        wrapper = new XPCWrappedNative(helper.forgetCanonical(), Scope,
+                                       set.forget());
     }
 
     MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(parent),
                "Xray wrapper being used to parent XPCWrappedNative?");
 
     // We use an AutoMarkingPtr here because it is possible for JS gc to happen
     // after we have Init'd the wrapper but *before* we add it to the hashtable.
     // This would cause the mSet to get collected and we'd later crash. I've
@@ -561,29 +561,29 @@ XPCWrappedNative::XPCWrappedNative(alrea
 
     MOZ_ASSERT(mMaybeProto, "bad ctor param");
     MOZ_ASSERT(mSet, "bad ctor param");
 }
 
 // This ctor is used if this object will NOT have a proto.
 XPCWrappedNative::XPCWrappedNative(already_AddRefed<nsISupports>&& aIdentity,
                                    XPCWrappedNativeScope* aScope,
-                                   XPCNativeSet* aSet)
+                                   already_AddRefed<XPCNativeSet>&& aSet)
 
     : mMaybeScope(TagScope(aScope)),
       mSet(aSet),
       mScriptableInfo(nullptr)
 {
     MOZ_ASSERT(NS_IsMainThread());
 
     mIdentity = aIdentity;
     mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
 
     MOZ_ASSERT(aScope, "bad ctor param");
-    MOZ_ASSERT(aSet, "bad ctor param");
+    MOZ_ASSERT(mSet, "bad ctor param");
 }
 
 XPCWrappedNative::~XPCWrappedNative()
 {
     Destroy();
 }
 
 void
@@ -1009,26 +1009,24 @@ public:
 private:
     RootedObject mOldReflector;
     RootedObject mNewReflector;
 };
 
 bool
 XPCWrappedNative::ExtendSet(XPCNativeInterface* aInterface)
 {
-    AutoJSContext cx;
-
     if (!mSet->HasInterface(aInterface)) {
-        AutoMarkingNativeSetPtr newSet(cx);
         XPCNativeSetKey key(mSet, aInterface);
-        newSet = XPCNativeSet::GetNewOrUsed(&key);
+        RefPtr<XPCNativeSet> newSet =
+            XPCNativeSet::GetNewOrUsed(&key);
         if (!newSet)
             return false;
 
-        mSet = newSet;
+        mSet = newSet.forget();
     }
     return true;
 }
 
 XPCWrappedNativeTearOff*
 XPCWrappedNative::FindTearOff(XPCNativeInterface* aInterface,
                               bool needJSObject /* = false */,
                               nsresult* pError /* = nullptr */)
@@ -2159,17 +2157,17 @@ NS_IMETHODIMP XPCWrappedNative::DebugDum
             else
                 XPC_LOG_ALWAYS(("mMaybeProto @ %x", proto));
         } else
             XPC_LOG_ALWAYS(("Scope @ %x", GetScope()));
 
         if (depth && mSet)
             mSet->DebugDump(depth);
         else
-            XPC_LOG_ALWAYS(("mSet @ %x", mSet));
+            XPC_LOG_ALWAYS(("mSet @ %x", mSet.get()));
 
         XPC_LOG_ALWAYS(("mFlatJSObject of %x", mFlatJSObject.getPtr()));
         XPC_LOG_ALWAYS(("mIdentity of %x", mIdentity.get()));
         XPC_LOG_ALWAYS(("mScriptableInfo @ %x", mScriptableInfo));
 
         if (depth && mScriptableInfo) {
             XPC_LOG_INDENT();
             XPC_LOG_ALWAYS(("mScriptable @ %x", mScriptableInfo->GetCallback()));
--- a/js/xpconnect/src/XPCWrappedNativeInfo.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeInfo.cpp
@@ -457,69 +457,73 @@ XPCNativeSetKey::Hash() const
     }
 
     return h;
 }
 
 /***************************************************************************/
 // XPCNativeSet
 
+XPCNativeSet::~XPCNativeSet()
+{
+    // Remove |this| before we clear the interfaces to ensure that the
+    // hashtable look up is correct.
+    XPCJSContext::Get()->GetNativeSetMap()->Remove(this);
+
+    for (int i = 0; i < mInterfaceCount; i++) {
+        NS_RELEASE(mInterfaces[i]);
+    }
+}
+
 // static
-XPCNativeSet*
+already_AddRefed<XPCNativeSet>
 XPCNativeSet::GetNewOrUsed(const nsIID* iid)
 {
-    AutoJSContext cx;
-    AutoMarkingNativeSetPtr set(cx);
-
     RefPtr<XPCNativeInterface> iface =
         XPCNativeInterface::GetNewOrUsed(iid);
     if (!iface)
         return nullptr;
 
     XPCNativeSetKey key(iface);
 
     XPCJSContext* xpccx = XPCJSContext::Get();
     NativeSetMap* map = xpccx->GetNativeSetMap();
     if (!map)
         return nullptr;
 
-    set = map->Find(&key);
+    RefPtr<XPCNativeSet> set = map->Find(&key);
 
     if (set)
-        return set;
+        return set.forget();
 
     set = NewInstance({iface.forget()});
     if (!set)
         return nullptr;
 
     if (!map->AddNew(&key, set)) {
         NS_ERROR("failed to add our set!");
-        DestroyInstance(set);
         set = nullptr;
     }
 
-    return set;
+    return set.forget();
 }
 
 // static
-XPCNativeSet*
+already_AddRefed<XPCNativeSet>
 XPCNativeSet::GetNewOrUsed(nsIClassInfo* classInfo)
 {
-    AutoJSContext cx;
-    AutoMarkingNativeSetPtr set(cx);
     XPCJSContext* xpccx = XPCJSContext::Get();
-
     ClassInfo2NativeSetMap* map = xpccx->GetClassInfo2NativeSetMap();
     if (!map)
         return nullptr;
 
-    set = map->Find(classInfo);
+    RefPtr<XPCNativeSet> set = map->Find(classInfo);
 
     if (set)
-        return set;
+        return set.forget();
 
     nsIID** iidArray = nullptr;
     uint32_t iidCount = 0;
 
     if (NS_FAILED(classInfo->GetInterfaces(&iidCount, &iidArray))) {
         // Note: I'm making it OK for this call to fail so that one can add
         // nsIClassInfo to classes implemented in script without requiring this
         // method to be implemented.
@@ -562,24 +566,22 @@ XPCNativeSet::GetNewOrUsed(nsIClassInfo*
                 if (!map2)
                     goto out;
 
                 XPCNativeSetKey key(set);
 
                 XPCNativeSet* set2 = map2->Add(&key, set);
                 if (!set2) {
                     NS_ERROR("failed to add our set!");
-                    DestroyInstance(set);
                     set = nullptr;
                     goto out;
                 }
                 // It is okay to find an existing entry here because
                 // we did not look for one before we called Add().
                 if (set2 != set) {
-                    DestroyInstance(set);
                     set = set2;
                 }
             }
         } else
             set = GetNewOrUsed(&NS_GET_IID(nsISupports));
     } else
         set = GetNewOrUsed(&NS_GET_IID(nsISupports));
 
@@ -591,111 +593,107 @@ XPCNativeSet::GetNewOrUsed(nsIClassInfo*
         MOZ_ASSERT(set2, "failed to add our set!");
         MOZ_ASSERT(set2 == set, "hashtables inconsistent!");
     }
 
 out:
     if (iidArray)
         NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(iidCount, iidArray);
 
-    return set;
+    return set.forget();
 }
 
 // static
 void
 XPCNativeSet::ClearCacheEntryForClassInfo(nsIClassInfo* classInfo)
 {
     XPCJSContext* xpccx = nsXPConnect::GetContextInstance();
     ClassInfo2NativeSetMap* map = xpccx->GetClassInfo2NativeSetMap();
     if (map)
         map->Remove(classInfo);
 }
 
 // static
-XPCNativeSet*
+already_AddRefed<XPCNativeSet>
 XPCNativeSet::GetNewOrUsed(XPCNativeSetKey* key)
 {
-    AutoJSContext cx;
-    AutoMarkingNativeSetPtr set(cx);
-    XPCJSContext* xpccx = XPCJSContext::Get();
-    NativeSetMap* map = xpccx->GetNativeSetMap();
+    NativeSetMap* map = XPCJSContext::Get()->GetNativeSetMap();
     if (!map)
         return nullptr;
 
-    set = map->Find(key);
+    RefPtr<XPCNativeSet> set = map->Find(key);
 
     if (set)
-        return set;
+        return set.forget();
 
     if (key->GetBaseSet())
         set = NewInstanceMutate(key);
     else
         set = NewInstance({key->GetAddition()});
 
     if (!set)
         return nullptr;
 
     if (!map->AddNew(key, set)) {
         NS_ERROR("failed to add our set!");
-        DestroyInstance(set);
         set = nullptr;
     }
 
-    return set;
+    return set.forget();
 }
 
 // static
-XPCNativeSet*
+already_AddRefed<XPCNativeSet>
 XPCNativeSet::GetNewOrUsed(XPCNativeSet* firstSet,
                            XPCNativeSet* secondSet,
                            bool preserveFirstSetOrder)
 {
     // Figure out how many interfaces we'll need in the new set.
     uint32_t uniqueCount = firstSet->mInterfaceCount;
     for (uint32_t i = 0; i < secondSet->mInterfaceCount; ++i) {
         if (!firstSet->HasInterface(secondSet->mInterfaces[i]))
             uniqueCount++;
     }
 
     // If everything in secondSet was a duplicate, we can just use the first
     // set.
     if (uniqueCount == firstSet->mInterfaceCount)
-        return firstSet;
+        return RefPtr<XPCNativeSet>(firstSet).forget();
 
     // If the secondSet is just a superset of the first, we can use it provided
     // that the caller doesn't care about ordering.
     if (!preserveFirstSetOrder && uniqueCount == secondSet->mInterfaceCount)
-        return secondSet;
+        return RefPtr<XPCNativeSet>(secondSet).forget();
 
     // Ok, darn. Now we have to make a new set.
     //
     // It would be faster to just create the new set all at once, but that
     // would involve wrangling with some pretty hairy code - especially since
     // a lot of stuff assumes that sets are created by adding one interface to an
     // existing set. So let's just do the slow and easy thing and hope that the
     // above optimizations handle the common cases.
-    XPCNativeSet* currentSet = firstSet;
+    RefPtr<XPCNativeSet> currentSet = firstSet;
     for (uint32_t i = 0; i < secondSet->mInterfaceCount; ++i) {
         XPCNativeInterface* iface = secondSet->mInterfaces[i];
         if (!currentSet->HasInterface(iface)) {
             // Create a new augmented set, inserting this interface at the end.
             XPCNativeSetKey key(currentSet, iface);
             currentSet = XPCNativeSet::GetNewOrUsed(&key);
             if (!currentSet)
                 return nullptr;
         }
     }
 
     // We've got the union set. Hand it back to the caller.
     MOZ_ASSERT(currentSet->mInterfaceCount == uniqueCount);
-    return currentSet;
+    return currentSet.forget();
 }
 
 // static
-XPCNativeSet*
+already_AddRefed<XPCNativeSet>
 XPCNativeSet::NewInstance(nsTArray<RefPtr<XPCNativeInterface>>&& array)
 {
     if (array.Length() == 0)
         return nullptr;
 
     // We impose the invariant:
     // "All sets have exactly one nsISupports interface and it comes first."
     // This is the place where we impose that rule - even if given inputs
@@ -710,17 +708,17 @@ XPCNativeSet::NewInstance(nsTArray<RefPt
     }
 
     // Use placement new to create an object with the right amount of space
     // to hold the members array
     int size = sizeof(XPCNativeSet);
     if (slots > 1)
         size += (slots - 1) * sizeof(XPCNativeInterface*);
     void* place = new char[size];
-    XPCNativeSet* obj = new(place) XPCNativeSet();
+    RefPtr<XPCNativeSet> obj = new(place) XPCNativeSet();
 
     // Stick the nsISupports in front and skip additional nsISupport(s)
     XPCNativeInterface** outp = (XPCNativeInterface**) &obj->mInterfaces;
     uint16_t memberCount = 1;   // for the one member in nsISupports
 
     NS_ADDREF(*(outp++) = isup);
 
     for (auto key = array.begin(); key != array.end(); key++) {
@@ -728,50 +726,50 @@ XPCNativeSet::NewInstance(nsTArray<RefPt
         if (isup == cur)
             continue;
         memberCount += cur->GetMemberCount();
         *(outp++) = cur.forget().take();
     }
     obj->mMemberCount = memberCount;
     obj->mInterfaceCount = slots;
 
-    return obj;
+    return obj.forget();
 }
 
 // static
-XPCNativeSet*
+already_AddRefed<XPCNativeSet>
 XPCNativeSet::NewInstanceMutate(XPCNativeSetKey* key)
 {
     XPCNativeSet* otherSet = key->GetBaseSet();
     XPCNativeInterface* newInterface = key->GetAddition();
 
     MOZ_ASSERT(otherSet);
 
     if (!newInterface)
         return nullptr;
 
     // Use placement new to create an object with the right amount of space
     // to hold the members array
     int size = sizeof(XPCNativeSet);
     size += otherSet->mInterfaceCount * sizeof(XPCNativeInterface*);
     void* place = new char[size];
-    XPCNativeSet* obj = new(place) XPCNativeSet();
+    RefPtr<XPCNativeSet> obj = new(place) XPCNativeSet();
 
     obj->mMemberCount = otherSet->GetMemberCount() +
         newInterface->GetMemberCount();
     obj->mInterfaceCount = otherSet->mInterfaceCount + 1;
 
     XPCNativeInterface** src = otherSet->mInterfaces;
     XPCNativeInterface** dest = obj->mInterfaces;
     for (uint16_t i = 0; i < otherSet->mInterfaceCount; i++) {
         NS_ADDREF(*dest++ = *src++);
     }
     NS_ADDREF(*dest++ = newInterface);
 
-    return obj;
+    return obj.forget();
 }
 
 // static
 void
 XPCNativeSet::DestroyInstance(XPCNativeSet* inst)
 {
     inst->~XPCNativeSet();
     delete [] (char*) inst;
--- a/js/xpconnect/src/XPCWrappedNativeProto.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeProto.cpp
@@ -12,17 +12,17 @@
 using namespace mozilla;
 
 #ifdef DEBUG
 int32_t XPCWrappedNativeProto::gDEBUG_LiveProtoCount = 0;
 #endif
 
 XPCWrappedNativeProto::XPCWrappedNativeProto(XPCWrappedNativeScope* Scope,
                                              nsIClassInfo* ClassInfo,
-                                             XPCNativeSet* Set)
+                                             already_AddRefed<XPCNativeSet>&& Set)
     : mScope(Scope),
       mJSProtoObject(nullptr),
       mClassInfo(ClassInfo),
       mSet(Set),
       mScriptableInfo(nullptr)
 {
     // This native object lives as long as its associated JSObject - killed
     // by finalization of the JSObject (or explicitly if Init fails).
@@ -161,22 +161,21 @@ XPCWrappedNativeProto::GetNewOrUsed(XPCW
     AutoMarkingWrappedNativeProtoPtr proto(cx);
     ClassInfo2WrappedNativeProtoMap* map = nullptr;
 
     map = scope->GetWrappedNativeProtoMap();
     proto = map->Find(classInfo);
     if (proto)
         return proto;
 
-    AutoMarkingNativeSetPtr set(cx);
-    set = XPCNativeSet::GetNewOrUsed(classInfo);
+    RefPtr<XPCNativeSet> set = XPCNativeSet::GetNewOrUsed(classInfo);
     if (!set)
         return nullptr;
 
-    proto = new XPCWrappedNativeProto(scope, classInfo, set);
+    proto = new XPCWrappedNativeProto(scope, classInfo, set.forget());
 
     if (!proto || !proto->Init(scriptableCreateInfo, callPostCreatePrototype)) {
         delete proto.get();
         return nullptr;
     }
 
     map->Add(classInfo, proto);
 
@@ -188,17 +187,17 @@ XPCWrappedNativeProto::DebugDump(int16_t
 {
 #ifdef DEBUG
     depth-- ;
     XPC_LOG_ALWAYS(("XPCWrappedNativeProto @ %x", this));
     XPC_LOG_INDENT();
         XPC_LOG_ALWAYS(("gDEBUG_LiveProtoCount is %d", gDEBUG_LiveProtoCount));
         XPC_LOG_ALWAYS(("mScope @ %x", mScope));
         XPC_LOG_ALWAYS(("mJSProtoObject @ %x", mJSProtoObject.get()));
-        XPC_LOG_ALWAYS(("mSet @ %x", mSet));
+        XPC_LOG_ALWAYS(("mSet @ %x", mSet.get()));
         XPC_LOG_ALWAYS(("mScriptableInfo @ %x", mScriptableInfo));
         if (depth && mScriptableInfo) {
             XPC_LOG_INDENT();
             XPC_LOG_ALWAYS(("mScriptable @ %x", mScriptableInfo->GetCallback()));
             XPC_LOG_ALWAYS(("mFlags of %x", (uint32_t)mScriptableInfo->GetFlags()));
             XPC_LOG_ALWAYS(("mJSClass @ %x", mScriptableInfo->GetJSClass()));
             XPC_LOG_OUTDENT();
         }
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp
@@ -571,52 +571,16 @@ XPCWrappedNativeScope::UpdateWeakPointer
         if (cur)
             prev = cur;
         cur = next;
     }
 }
 
 // static
 void
-XPCWrappedNativeScope::MarkAllWrappedNativesAndProtos()
-{
-    for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) {
-        for (auto i = cur->mWrappedNativeMap->Iter(); !i.Done(); i.Next()) {
-            auto entry = static_cast<Native2WrappedNativeMap::Entry*>(i.Get());
-            entry->value->Mark();
-        }
-        // We need to explicitly mark all the protos too because some protos may be
-        // alive in the hashtable but not currently in use by any wrapper
-        for (auto i = cur->mWrappedNativeProtoMap->Iter(); !i.Done(); i.Next()) {
-            auto entry = static_cast<ClassInfo2WrappedNativeProtoMap::Entry*>(i.Get());
-            entry->value->Mark();
-        }
-    }
-}
-
-#ifdef DEBUG
-// static
-void
-XPCWrappedNativeScope::ASSERT_NoInterfaceSetsAreMarked()
-{
-    for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) {
-        for (auto i = cur->mWrappedNativeMap->Iter(); !i.Done(); i.Next()) {
-            auto entry = static_cast<Native2WrappedNativeMap::Entry*>(i.Get());
-            entry->value->ASSERT_SetsNotMarked();
-        }
-        for (auto i = cur->mWrappedNativeProtoMap->Iter(); !i.Done(); i.Next()) {
-            auto entry = static_cast<ClassInfo2WrappedNativeProtoMap::Entry*>(i.Get());
-            entry->value->ASSERT_SetNotMarked();
-        }
-    }
-}
-#endif
-
-// static
-void
 XPCWrappedNativeScope::SweepAllWrappedNativeTearOffs()
 {
     for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) {
         for (auto i = cur->mWrappedNativeMap->Iter(); !i.Done(); i.Next()) {
             auto entry = static_cast<Native2WrappedNativeMap::Entry*>(i.Get());
             entry->value->SweepTearOffs();
         }
     }
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -788,17 +788,17 @@ private:
 
     XPCCallContext*                 mPrevCallContext;
 
     XPCWrappedNative*               mWrapper;
     XPCWrappedNativeTearOff*        mTearOff;
 
     XPCNativeScriptableInfo*        mScriptableInfo;
 
-    XPCNativeSet*                   mSet;
+    RefPtr<XPCNativeSet>            mSet;
     RefPtr<XPCNativeInterface>      mInterface;
     XPCNativeMember*                mMember;
 
     JS::RootedId                    mName;
     bool                            mStaticMemberIsLocal;
 
     unsigned                        mArgc;
     JS::Value*                      mArgv;
@@ -924,24 +924,16 @@ public:
         if (mXrayExpandos.initialized())
             mXrayExpandos.trace(trc);
     }
 
     static void
     SuspectAllWrappers(XPCJSContext* cx, nsCycleCollectionNoteRootCallback& cb);
 
     static void
-    MarkAllWrappedNativesAndProtos();
-
-#ifdef DEBUG
-    static void
-    ASSERT_NoInterfaceSetsAreMarked();
-#endif
-
-    static void
     SweepAllWrappedNativeTearOffs();
 
     static void
     UpdateWeakPointersAfterGC(XPCJSContext* cx);
 
     static void
     KillDyingScopes();
 
@@ -1276,17 +1268,17 @@ private:
     XPCNativeMember            mMembers[1]; // always last - object sized for array
 };
 
 /***************************************************************************/
 // XPCNativeSetKey is used to key a XPCNativeSet in a NativeSetMap.
 // It represents a new XPCNativeSet we are considering constructing, without
 // requiring that the set actually be built.
 
-class XPCNativeSetKey final
+class MOZ_STACK_CLASS XPCNativeSetKey final
 {
 public:
     // This represents an existing set |baseSet|.
     explicit XPCNativeSetKey(XPCNativeSet* baseSet)
         : mBaseSet(baseSet), mAddition(nullptr)
     {
         MOZ_ASSERT(baseSet);
     }
@@ -1309,40 +1301,43 @@ public:
     XPCNativeSet* GetBaseSet() const {return mBaseSet;}
     XPCNativeInterface* GetAddition() const {return mAddition;}
 
     PLDHashNumber Hash() const;
 
     // Allow shallow copy
 
 private:
-    XPCNativeSet* mBaseSet;
-    XPCNativeInterface* mAddition;
+    RefPtr<XPCNativeSet> mBaseSet;
+    RefPtr<XPCNativeInterface> mAddition;
 };
 
 /***************************************************************************/
 // XPCNativeSet represents an ordered collection of XPCNativeInterface pointers.
 
 class XPCNativeSet final
 {
   public:
-    static XPCNativeSet* GetNewOrUsed(const nsIID* iid);
-    static XPCNativeSet* GetNewOrUsed(nsIClassInfo* classInfo);
-    static XPCNativeSet* GetNewOrUsed(XPCNativeSetKey* key);
+    NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(XPCNativeSet,
+                                            DestroyInstance(this))
+
+    static already_AddRefed<XPCNativeSet> GetNewOrUsed(const nsIID* iid);
+    static already_AddRefed<XPCNativeSet> GetNewOrUsed(nsIClassInfo* classInfo);
+    static already_AddRefed<XPCNativeSet> GetNewOrUsed(XPCNativeSetKey* key);
 
     // This generates a union set.
     //
     // If preserveFirstSetOrder is true, the elements from |firstSet| come first,
     // followed by any non-duplicate items from |secondSet|. If false, the same
     // algorithm is applied; but if we detect that |secondSet| is a superset of
     // |firstSet|, we return |secondSet| without worrying about whether the
     // ordering might differ from |firstSet|.
-    static XPCNativeSet* GetNewOrUsed(XPCNativeSet* firstSet,
-                                      XPCNativeSet* secondSet,
-                                      bool preserveFirstSetOrder);
+    static already_AddRefed<XPCNativeSet> GetNewOrUsed(XPCNativeSet* firstSet,
+                                                       XPCNativeSet* secondSet,
+                                                       bool preserveFirstSetOrder);
 
     static void ClearCacheEntryForClassInfo(nsIClassInfo* classInfo);
 
     inline bool FindMember(jsid name, XPCNativeMember** pMember,
                            uint16_t* pInterfaceIndex) const;
 
     inline bool FindMember(jsid name, XPCNativeMember** pMember,
                            RefPtr<XPCNativeInterface>* pInterface) const;
@@ -1372,60 +1367,35 @@ class XPCNativeSet final
     }
 
     XPCNativeInterface* GetInterfaceAt(uint16_t i)
         {MOZ_ASSERT(i < mInterfaceCount, "bad index"); return mInterfaces[i];}
 
     inline bool MatchesSetUpToInterface(const XPCNativeSet* other,
                                           XPCNativeInterface* iface) const;
 
-    inline void Mark();
-
-    // NOP. This is just here to make the AutoMarkingPtr code compile.
-    inline void TraceJS(JSTracer* trc) {}
-    inline void AutoTrace(JSTracer* trc) {}
-
-  public:
-    void Unmark() {
-        mMarked = 0;
-    }
-    bool IsMarked() const {
-        return !!mMarked;
-    }
-
-#ifdef DEBUG
-    inline void ASSERT_NotMarked();
-#endif
-
     void DebugDump(int16_t depth);
 
-    static void DestroyInstance(XPCNativeSet* inst);
-
     size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
 
   protected:
-    static XPCNativeSet* NewInstance(nsTArray<RefPtr<XPCNativeInterface>>&& array);
-    static XPCNativeSet* NewInstanceMutate(XPCNativeSetKey* key);
+    static already_AddRefed<XPCNativeSet> NewInstance(nsTArray<RefPtr<XPCNativeInterface>>&& array);
+    static already_AddRefed<XPCNativeSet> NewInstanceMutate(XPCNativeSetKey* key);
+
     XPCNativeSet()
-      : mMemberCount(0), mInterfaceCount(0), mMarked(0)
-    {
-        MOZ_COUNT_CTOR(XPCNativeSet);
-    }
-    ~XPCNativeSet() {
-        for (int i = 0; i < mInterfaceCount; i++) {
-            NS_RELEASE(mInterfaces[i]);
-        }
-        MOZ_COUNT_DTOR(XPCNativeSet);
-    }
+      : mMemberCount(0), mInterfaceCount(0)
+    {}
+    ~XPCNativeSet();
     void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
 
+    static void DestroyInstance(XPCNativeSet* inst);
+
   private:
     uint16_t                mMemberCount;
-    uint16_t                mInterfaceCount : 15;
-    uint16_t                mMarked : 1;
+    uint16_t                mInterfaceCount;
     // Always last - object sized for array.
     // These are strong references.
     XPCNativeInterface*     mInterfaces[1];
 };
 
 /***************************************************************************/
 // XPCNativeScriptableFlags is a wrapper class that holds the flags returned
 // from calls to nsIXPCScriptable::GetScriptableFlags(). It has convenience
@@ -1648,68 +1618,59 @@ public:
     void DebugDump(int16_t depth);
 
     void TraceSelf(JSTracer* trc) {
         if (mJSProtoObject)
             mJSProtoObject.trace(trc, "XPCWrappedNativeProto::mJSProtoObject");
     }
 
     void TraceInside(JSTracer* trc) {
-        if (trc->isMarkingTracer()) {
-            mSet->Mark();
-        }
-
         GetScope()->TraceSelf(trc);
     }
 
     void TraceJS(JSTracer* trc) {
         TraceSelf(trc);
         TraceInside(trc);
     }
 
     void WriteBarrierPre(JSContext* cx)
     {
         if (JS::IsIncrementalBarrierNeeded(cx) && mJSProtoObject)
             mJSProtoObject.writeBarrierPre(cx);
     }
 
     // NOP. This is just here to make the AutoMarkingPtr code compile.
+    void Mark() const {}
     inline void AutoTrace(JSTracer* trc) {}
 
-    void Mark() const {mSet->Mark();}
-
-#ifdef DEBUG
-    void ASSERT_SetNotMarked() const {mSet->ASSERT_NotMarked();}
-#endif
-
     ~XPCWrappedNativeProto();
 
 protected:
     // disable copy ctor and assignment
     XPCWrappedNativeProto(const XPCWrappedNativeProto& r) = delete;
     XPCWrappedNativeProto& operator= (const XPCWrappedNativeProto& r) = delete;
 
     // hide ctor
     XPCWrappedNativeProto(XPCWrappedNativeScope* Scope,
                           nsIClassInfo* ClassInfo,
-                          XPCNativeSet* Set);
+                          already_AddRefed<XPCNativeSet>&& Set);
 
     bool Init(const XPCNativeScriptableCreateInfo* scriptableCreateInfo,
               bool callPostCreatePrototype);
 
 private:
 #ifdef DEBUG
     static int32_t gDEBUG_LiveProtoCount;
 #endif
 
 private:
     XPCWrappedNativeScope*   mScope;
     JS::ObjectPtr            mJSProtoObject;
     nsCOMPtr<nsIClassInfo>   mClassInfo;
-    XPCNativeSet*            mSet;
+    RefPtr<XPCNativeSet>     mSet;
     XPCNativeScriptableInfo* mScriptableInfo;
 };
 
 /***********************************************/
 // XPCWrappedNativeTearOff represents the info needed to make calls to one
 // interface on the underlying native object of a XPCWrappedNative.
 
 class XPCWrappedNativeTearOff final
@@ -1851,17 +1812,17 @@ public:
      */
     JSObject*
     GetFlatJSObjectPreserveColor() const {return mFlatJSObject;}
 
     XPCNativeSet*
     GetSet() const {return mSet;}
 
     void
-    SetSet(XPCNativeSet* set) {mSet = set;}
+    SetSet(already_AddRefed<XPCNativeSet> set) {mSet = set;}
 
     static XPCWrappedNative* Get(JSObject* obj) {
         MOZ_ASSERT(IS_WN_REFLECTOR(obj));
         return (XPCWrappedNative*)js::GetObjectPrivate(obj);
     }
 
 private:
     inline void
@@ -1926,26 +1887,19 @@ public:
 
     inline bool HasInterfaceNoQI(const nsIID& iid);
 
     XPCWrappedNativeTearOff* FindTearOff(XPCNativeInterface* aInterface,
                                          bool needJSObject = false,
                                          nsresult* pError = nullptr);
     XPCWrappedNativeTearOff* FindTearOff(const nsIID& iid);
 
-    void Mark() const
-    {
-        mSet->Mark();
-        if (HasProto()) GetProto()->Mark();
-    }
+    void Mark() const {}
 
     inline void TraceInside(JSTracer* trc) {
-        if (trc->isMarkingTracer()) {
-            mSet->Mark();
-        }
         if (HasProto())
             GetProto()->TraceSelf(trc);
         else
             GetScope()->TraceSelf(trc);
         if (mFlatJSObject && JS_IsGlobalObject(mFlatJSObject))
         {
             xpc::TraceXPCGlobal(trc, mFlatJSObject);
         }
@@ -1964,22 +1918,16 @@ public:
     }
 
     static void Trace(JSTracer* trc, JSObject* obj);
 
     void AutoTrace(JSTracer* trc) {
         TraceSelf(trc);
     }
 
-#ifdef DEBUG
-    void ASSERT_SetsNotMarked() const
-        {mSet->ASSERT_NotMarked();
-         if (HasProto()){GetProto()->ASSERT_SetNotMarked();}}
-#endif
-
     inline void SweepTearOffs();
 
     // Returns a string that shuld be free'd using JS_smprintf_free (or null).
     char* ToString(XPCWrappedNativeTearOff* to = nullptr) const;
 
     static void GatherProtoScriptableCreateInfo(nsIClassInfo* classInfo,
                                                 XPCNativeScriptableCreateInfo& sciProto);
 
@@ -1994,17 +1942,17 @@ protected:
 
     // This ctor is used if this object will have a proto.
     XPCWrappedNative(already_AddRefed<nsISupports>&& aIdentity,
                      XPCWrappedNativeProto* aProto);
 
     // This ctor is used if this object will NOT have a proto.
     XPCWrappedNative(already_AddRefed<nsISupports>&& aIdentity,
                      XPCWrappedNativeScope* aScope,
-                     XPCNativeSet* aSet);
+                     already_AddRefed<XPCNativeSet>&& aSet);
 
     virtual ~XPCWrappedNative();
     void Destroy();
 
     void UpdateScriptableInfo(XPCNativeScriptableInfo* si);
 
 private:
     enum {
@@ -2030,17 +1978,17 @@ public:
                                                                            XPCNativeScriptableCreateInfo& sciWrapper);
 
 private:
     union
     {
         XPCWrappedNativeScope* mMaybeScope;
         XPCWrappedNativeProto* mMaybeProto;
     };
-    XPCNativeSet* mSet;
+    RefPtr<XPCNativeSet> mSet;
     JS::TenuredHeap<JSObject*> mFlatJSObject;
     XPCNativeScriptableInfo* mScriptableInfo;
     XPCWrappedNativeTearOff mFirstTearOff;
 };
 
 /***************************************************************************
 ****************************************************************************
 *
@@ -2876,17 +2824,16 @@ class TypedAutoMarkingPtr : public AutoM
         if (mPtr)
             mPtr->Mark();
     }
 
   private:
     T* mPtr;
 };
 
-typedef TypedAutoMarkingPtr<XPCNativeSet> AutoMarkingNativeSetPtr;
 typedef TypedAutoMarkingPtr<XPCWrappedNative> AutoMarkingWrappedNativePtr;
 typedef TypedAutoMarkingPtr<XPCWrappedNativeTearOff> AutoMarkingWrappedNativeTearOffPtr;
 typedef TypedAutoMarkingPtr<XPCWrappedNativeProto> AutoMarkingWrappedNativeProtoPtr;
 
 /***************************************************************************/
 namespace xpc {
 // Allocates a string that grants all access ("AllAccess")
 char*
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -308,22 +308,22 @@ WrapperFactory::PrepareForWrapping(JSCon
     // This could be a problem for chrome code that passes XPCOM objects
     // across compartments, because the effects of QI would disappear across
     // compartments.
     //
     // So whenever we pull an XPCWN across compartments in this manner, we
     // give the destination object the union of the two native sets. We try
     // to do this cleverly in the common case to avoid too much overhead.
     XPCWrappedNative* newwn = XPCWrappedNative::Get(obj);
-    XPCNativeSet* unionSet = XPCNativeSet::GetNewOrUsed(newwn->GetSet(),
-                                                        wn->GetSet(), false);
+    RefPtr<XPCNativeSet> unionSet = XPCNativeSet::GetNewOrUsed(newwn->GetSet(),
+                                                               wn->GetSet(), false);
     if (!unionSet) {
         return;
     }
-    newwn->SetSet(unionSet);
+    newwn->SetSet(unionSet.forget());
 
     retObj.set(waive ? WaiveXray(cx, obj) : obj);
 }
 
 #ifdef DEBUG
 static void
 DEBUG_CheckUnwrapSafety(HandleObject obj, const js::Wrapper* handler,
                         JSCompartment* origin, JSCompartment* target)
--- a/layout/reftests/bugs/reftest-stylo.list
+++ b/layout/reftests/bugs/reftest-stylo.list
@@ -1068,17 +1068,17 @@ skip-if((B2G&&browserIsRemote)||Mulet) =
 == 403656-1.html 403656-1.html
 == 403656-2.html 403656-2.html
 == 403656-3.html 403656-3.html
 fails skip == 403656-4.html 403656-4.html
 == 403656-5.html 403656-5.html
 #== 403657-1.html 403657-1.html
 # Fails depending on the fonts...
 == 403733-1.html 403733-1.html
-== 403962-1.xhtml 403962-1.xhtml
+skip == 403962-1.xhtml 403962-1.xhtml
 == 404030-1.html 404030-1.html
 == 404030-1-notref.html 404030-1-notref.html
 == 404030-1-notref2.html 404030-1-notref2.html
 fuzzy-if(skiaContent,2,4) == 404123-1.html 404123-1.html
 == 404123-2.html 404123-2.html
 == 404123-3.html 404123-3.html
 # may fail "randomly" on OS X, doesn't seem to be rendering usefully anyhow - bug 602469
 random-if(cocoaWidget) skip-if((B2G&&browserIsRemote)||Mulet) HTTP(..) == 404149-1.xul 404149-1.xul
--- a/layout/reftests/css-display/reftest-stylo.list
+++ b/layout/reftests/css-display/reftest-stylo.list
@@ -4,17 +4,17 @@
 
 fuzzy-if(Android,8,604) pref(layout.css.display-contents.enabled,true) == display-contents-acid.html display-contents-acid.html
 random pref(layout.css.display-contents.enabled,true) == display-contents-acid-dyn-1.html display-contents-acid-dyn-1.html
 random pref(layout.css.display-contents.enabled,true) == display-contents-acid-dyn-2.html display-contents-acid-dyn-2.html
 random pref(layout.css.display-contents.enabled,true) == display-contents-acid-dyn-3.html display-contents-acid-dyn-3.html
 pref(layout.css.display-contents.enabled,true) == display-contents-generated-content.html display-contents-generated-content.html
 pref(layout.css.display-contents.enabled,true) == display-contents-generated-content-2.html display-contents-generated-content-2.html
 pref(layout.css.display-contents.enabled,true) == display-contents-style-inheritance-1.html display-contents-style-inheritance-1.html
-pref(layout.css.display-contents.enabled,true) == display-contents-style-inheritance-1-stylechange.html display-contents-style-inheritance-1-stylechange.html
+skip pref(layout.css.display-contents.enabled,true) == display-contents-style-inheritance-1-stylechange.html display-contents-style-inheritance-1-stylechange.html
 skip pref(layout.css.display-contents.enabled,true) fuzzy-if(winWidget,12,100) == display-contents-style-inheritance-1-dom-mutations.html display-contents-style-inheritance-1-dom-mutations.html
 pref(layout.css.display-contents.enabled,true) == display-contents-tables.xhtml display-contents-tables.xhtml
 pref(layout.css.display-contents.enabled,true) == display-contents-tables-2.xhtml display-contents-tables-2.xhtml
 pref(layout.css.display-contents.enabled,true) == display-contents-tables-3.xhtml display-contents-tables-3.xhtml
 pref(layout.css.display-contents.enabled,true) == display-contents-visibility-hidden.html display-contents-visibility-hidden.html
 pref(layout.css.display-contents.enabled,true) == display-contents-visibility-hidden-2.html display-contents-visibility-hidden-2.html
 random pref(layout.css.display-contents.enabled,true) == display-contents-495385-2d.html display-contents-495385-2d.html
 skip-if(B2G||Mulet) fuzzy-if(Android,7,3935) pref(layout.css.display-contents.enabled,true) == display-contents-xbl.xhtml display-contents-xbl.xhtml
--- a/layout/reftests/css-grid/reftest-stylo.list
+++ b/layout/reftests/css-grid/reftest-stylo.list
@@ -35,20 +35,20 @@ skip == grid-abspos-items-010.html grid-
 skip == grid-abspos-items-015.html grid-abspos-items-015.html
 == grid-order-abspos-items-001.html grid-order-abspos-items-001.html
 == grid-order-placement-auto-001.html grid-order-placement-auto-001.html
 fuzzy-if(skiaContent,1,200) == grid-order-placement-definite-001.html grid-order-placement-definite-001.html
 skip-if(Android) == grid-placement-definite-implicit-001.html grid-placement-definite-implicit-001.html
 == grid-placement-definite-implicit-002.html grid-placement-definite-implicit-002.html
 skip-if(Android) fuzzy-if(winWidget,1,32) == grid-placement-auto-implicit-001.html grid-placement-auto-implicit-001.html
 == grid-placement-abspos-implicit-001.html grid-placement-abspos-implicit-001.html
-pref(layout.css.vertical-text.enabled,true) == rtl-grid-placement-definite-001.html rtl-grid-placement-definite-001.html
-pref(layout.css.vertical-text.enabled,true) == rtl-grid-placement-auto-row-sparse-001.html rtl-grid-placement-auto-row-sparse-001.html
-pref(layout.css.vertical-text.enabled,true) == vlr-grid-placement-auto-row-sparse-001.html vlr-grid-placement-auto-row-sparse-001.html
-pref(layout.css.vertical-text.enabled,true) == vrl-grid-placement-auto-row-sparse-001.html vrl-grid-placement-auto-row-sparse-001.html
+== rtl-grid-placement-definite-001.html rtl-grid-placement-definite-001.html
+== rtl-grid-placement-auto-row-sparse-001.html rtl-grid-placement-auto-row-sparse-001.html
+== vlr-grid-placement-auto-row-sparse-001.html vlr-grid-placement-auto-row-sparse-001.html
+== vrl-grid-placement-auto-row-sparse-001.html vrl-grid-placement-auto-row-sparse-001.html
 == grid-relpos-items-001.html grid-relpos-items-001.html
 == grid-item-sizing-percent-001.html grid-item-sizing-percent-001.html
 == grid-item-sizing-px-001.html grid-item-sizing-px-001.html
 == grid-item-dir-001.html grid-item-dir-001.html
 fuzzy-if(winWidget,70,130) fuzzy-if(cocoaWidget,85,180) == grid-col-max-sizing-max-content-001.html grid-col-max-sizing-max-content-001.html
 fuzzy-if(winWidget,70,130) fuzzy-if(cocoaWidget,85,180) == grid-col-max-sizing-max-content-002.html grid-col-max-sizing-max-content-002.html
 == grid-min-max-content-sizing-001.html grid-min-max-content-sizing-001.html
 == grid-min-max-content-sizing-002.html grid-min-max-content-sizing-002.html
--- a/layout/reftests/css-ruby/reftest-stylo.list
+++ b/layout/reftests/css-ruby/reftest-stylo.list
@@ -43,17 +43,17 @@ skip load nested-ruby-1.html
 == no-transform.html no-transform.html
 == relative-positioning-1.html relative-positioning-1.html
 == relative-positioning-2.html relative-positioning-2.html
 == ruby-align-1.html ruby-align-1.html
 == ruby-align-1a.html ruby-align-1a.html
 == ruby-align-2.html ruby-align-2.html
 == ruby-align-2a.html ruby-align-2a.html
 == ruby-position-horizontal.html ruby-position-horizontal.html
-pref(layout.css.vertical-text.enabled,true) == ruby-position-vertical-lr.html ruby-position-vertical-lr.html
-pref(layout.css.vertical-text.enabled,true) == ruby-position-vertical-rl.html ruby-position-vertical-rl.html
+== ruby-position-vertical-lr.html ruby-position-vertical-lr.html
+== ruby-position-vertical-rl.html ruby-position-vertical-rl.html
 == ruby-reflow-1-opaqueruby.html ruby-reflow-1-opaqueruby.html
 fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),13,1) == ruby-reflow-1-transparentruby.html ruby-reflow-1-transparentruby.html
 == ruby-span-1.html ruby-span-1.html
 == ruby-whitespace-1.html ruby-whitespace-1.html
 == ruby-whitespace-2.html ruby-whitespace-2.html
 == bug1181890.html bug1181890.html
 == bug1181890.html bug1181890.html
--- a/layout/reftests/floats/reftest-stylo.list
+++ b/layout/reftests/floats/reftest-stylo.list
@@ -54,17 +54,17 @@ fails fuzzy-if(skiaContent,1,12000) == f
 == bfc-displace-4.html bfc-displace-4.html
 == bfc-shrink-1.html bfc-shrink-1.html
 
 # Testcases that involve vertical writing mode.
 #
 # XXX The default-preferences setting here can be removed after the
 #     pref has been made true by default for all channels (bug 1138384).
 
-default-preferences pref(layout.css.vertical-text.enabled,true)
+
 
 == float-in-rtl-vlr-1a.html float-in-rtl-vlr-1a.html
 == float-in-rtl-vlr-1b.html float-in-rtl-vlr-1b.html
 == float-in-rtl-vlr-1c.html float-in-rtl-vlr-1c.html
 == float-in-rtl-vlr-1d.html float-in-rtl-vlr-1d.html
 == float-in-rtl-vlr-2a.html float-in-rtl-vlr-2a.html
 == float-in-rtl-vlr-2b.html float-in-rtl-vlr-2b.html
 == float-in-rtl-vlr-2c.html float-in-rtl-vlr-2c.html
--- a/layout/reftests/forms/input/number/reftest-stylo.list
+++ b/layout/reftests/forms/input/number/reftest-stylo.list
@@ -9,18 +9,18 @@ skip skip-if(Android||B2G||Mulet) == not
 # Initial mulet triage: parity with B2G/B2G Desktop
 # only valid on Android/B2G where type=number looks the same as type=text
 skip-if(!Android&&!B2G&&!Mulet) == number-same-as-text-unthemed.html number-same-as-text-unthemed.html
 # Initial mulet triage: parity with B2G/B2G Desktop
 
 # should look the same as type=text, except for the spin box
 skip == number-similar-to-text-unthemed.html number-similar-to-text-unthemed.html
 skip == number-similar-to-text-unthemed-rtl.html number-similar-to-text-unthemed-rtl.html
-skip pref(layout.css.vertical-text.enabled,true) == number-similar-to-text-unthemed-vertical-lr.html number-similar-to-text-unthemed-vertical-lr.html
-skip pref(layout.css.vertical-text.enabled,true) == number-similar-to-text-unthemed-vertical-rl.html number-similar-to-text-unthemed-vertical-rl.html
+skip == number-similar-to-text-unthemed-vertical-lr.html number-similar-to-text-unthemed-vertical-lr.html
+skip == number-similar-to-text-unthemed-vertical-rl.html number-similar-to-text-unthemed-vertical-rl.html
 
 # dynamic type changes:
 fuzzy-if(/^Windows\x20NT\x205\.1/.test(http.oscpu),64,4) fuzzy-if(cocoaWidget,63,4) fuzzy-if(skiaContent,2,5) == to-number-from-other-type-unthemed-1.html to-number-from-other-type-unthemed-1.html
 # skip fuzzy-if(skiaContent,2,5) == from-number-to-other-type-unthemed-1.html from-number-to-other-type-unthemed-1.html
 
 # dynamic value changes:
 # skip fuzzy-if(skiaContent,2,13) == show-value.html show-value.html
 
--- a/layout/reftests/forms/input/range/reftest-stylo.list
+++ b/layout/reftests/forms/input/range/reftest-stylo.list
@@ -32,17 +32,17 @@ skip == reset-value.html reset-value.htm
 fails-if(B2G||Mulet||Android) == moz-range-progress-1.html moz-range-progress-1.html
 # Initial mulet triage: parity with B2G/B2G Desktop
 == moz-range-progress-2.html moz-range-progress-2.html
 == moz-range-progress-3.html moz-range-progress-3.html
 
 # Tests for block and inline orientation in combination with writing-mode
 # XXX Remove default-preferences setting here after bug 1138384 makes
 #     it the default for all channels
-default-preferences pref(layout.css.vertical-text.enabled,true)
+
 == range-orient-horizontal.html range-orient-horizontal.html
 == range-orient-horizontal.html range-orient-horizontal.html
 == range-orient-block.html range-orient-block.html
 == range-orient-inline.html range-orient-inline.html
 == range-vlr.html range-vlr.html
 == range-vlr-orient-block.html range-vlr-orient-block.html
 == range-vlr-orient-inline.html range-vlr-orient-inline.html
 == range-vlr-orient-horizontal.html range-vlr-orient-horizontal.html
--- a/layout/reftests/forms/meter/reftest-stylo.list
+++ b/layout/reftests/forms/meter/reftest-stylo.list
@@ -27,17 +27,17 @@ include default-style/reftest-stylo.list
 # Tests for bugs:
 == block-invalidate.html block-invalidate.html
 == in-cells.html in-cells.html
 == max-height.html max-height.html
 
 # Tests for block and inline orientation in combination with writing-mode
 # XXX Remove default-preferences setting here after bug 1138384 makes
 #     it the default for all channels
-default-preferences pref(layout.css.vertical-text.enabled,true)
+
 == meter-orient-vertical.html meter-orient-vertical.html
 == meter-orient-horizontal.html meter-orient-horizontal.html
 == meter-orient-block.html meter-orient-block.html
 == meter-orient-inline.html meter-orient-inline.html
 == meter-vlr.html meter-vlr.html
 == meter-vlr-orient-block.html meter-vlr-orient-block.html
 == meter-vlr-orient-inline.html meter-vlr-orient-inline.html
 == meter-vlr-orient-horizontal.html meter-vlr-orient-horizontal.html
--- a/layout/reftests/forms/progress/reftest-stylo.list
+++ b/layout/reftests/forms/progress/reftest-stylo.list
@@ -26,17 +26,17 @@ skip-if(B2G||Mulet) == bar-pseudo-elemen
 # Tests for bugs:
 == block-invalidate.html block-invalidate.html
 == in-cells.html in-cells.html
 == max-height.html max-height.html
 
 # Tests for block and inline orientation in combination with writing-mode
 # XXX Remove default-preferences setting here after bug 1138384 makes
 #     it the default for all channels
-default-preferences pref(layout.css.vertical-text.enabled,true)
+
 == progress-orient-horizontal.html progress-orient-horizontal.html
 skip == progress-orient-vertical.html progress-orient-vertical.html
 # only OS X currently has direction-dependent rendering here
 == progress-orient-block.html progress-orient-block.html
 == progress-orient-inline.html progress-orient-inline.html
 == progress-vlr.html progress-vlr.html
 == progress-vlr-orient-block.html progress-vlr-orient-block.html
 == progress-vlr-orient-inline.html progress-vlr-orient-inline.html
--- a/layout/reftests/svg/text/reftest-stylo.list
+++ b/layout/reftests/svg/text/reftest-stylo.list
@@ -127,17 +127,17 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(
 == textLength-4.svg textLength-4.svg
 == textLength-5.svg textLength-5.svg
 == textLength-6.svg textLength-6.svg
 
 # text-shadow
 == text-shadow.svg text-shadow.svg
 
 # vertical text
-pref(layout.css.vertical-text.enabled,true) == vertical-01.svg vertical-01.svg
+== vertical-01.svg vertical-01.svg
 
 # tests for ignoring various properties
 == ignore-border.svg ignore-border.svg
 == ignore-display.svg ignore-display.svg
 == ignore-float.svg ignore-float.svg
 == ignore-float-first-letter.svg ignore-float-first-letter.svg
 == ignore-position.svg ignore-position.svg
 == ignore-margin.svg ignore-margin.svg
--- a/layout/reftests/text-overflow/reftest-stylo.list
+++ b/layout/reftests/text-overflow/reftest-stylo.list
@@ -39,16 +39,16 @@ skip-if(B2G||Mulet) HTTP(..) == single-v
 # Initial mulet triage: parity with B2G/B2G Desktop
 fails skip-if(B2G||Mulet) fuzzy-if(gtkWidget,10,2) HTTP(..) == atomic-under-marker.html atomic-under-marker.html
 # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(Android||B2G||Mulet) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,12352) HTTP(..) == xulscroll.html xulscroll.html
 # Initial mulet triage: parity with B2G/B2G Desktop
 HTTP(..) == combobox-zoom.html combobox-zoom.html
 
 # The vertical-text pref setting can be removed after bug 1138384 lands
-pref(layout.css.vertical-text.enabled,true) == vertical-decorations-1.html vertical-decorations-1.html
-pref(layout.css.vertical-text.enabled,true) == vertical-decorations-2.html vertical-decorations-2.html
-pref(layout.css.vertical-text.enabled,true) == vertical-decorations-1.html vertical-decorations-1.html
-pref(layout.css.vertical-text.enabled,true) == vertical-decorations-2.html vertical-decorations-2.html
-pref(layout.css.vertical-text.enabled,true) == vertical-decorations-3.html vertical-decorations-3.html
-pref(layout.css.vertical-text.enabled,true) == vertical-decorations-4.html vertical-decorations-4.html
-pref(layout.css.vertical-text.enabled,true) == vertical-decorations-3.html vertical-decorations-3.html
-pref(layout.css.vertical-text.enabled,true) == vertical-decorations-4.html vertical-decorations-4.html
+== vertical-decorations-1.html vertical-decorations-1.html
+== vertical-decorations-2.html vertical-decorations-2.html
+== vertical-decorations-1.html vertical-decorations-1.html
+== vertical-decorations-2.html vertical-decorations-2.html
+== vertical-decorations-3.html vertical-decorations-3.html
+== vertical-decorations-4.html vertical-decorations-4.html
+== vertical-decorations-3.html vertical-decorations-3.html
+== vertical-decorations-4.html vertical-decorations-4.html
--- a/layout/reftests/w3c-css/submitted/flexbox/reftest-stylo.list
+++ b/layout/reftests/w3c-css/submitted/flexbox/reftest-stylo.list
@@ -190,17 +190,17 @@ random == flexbox-mbp-horiz-002b.xhtml f
 == flexbox-whitespace-handling-002.xhtml flexbox-whitespace-handling-002.xhtml
 
 # Tests for flex containers with pseudo-elements
 == flexbox-with-pseudo-elements-001.html flexbox-with-pseudo-elements-001.html
 == flexbox-with-pseudo-elements-002.html flexbox-with-pseudo-elements-002.html
 == flexbox-with-pseudo-elements-003.html flexbox-with-pseudo-elements-003.html
 
 # Tests for combined influence of 'writing-mode' & 'direction' on flex axes
-test-pref(layout.css.vertical-text.enabled,true) == flexbox-writing-mode-001.html flexbox-writing-mode-001.html
-test-pref(layout.css.vertical-text.enabled,true) == flexbox-writing-mode-002.html flexbox-writing-mode-002.html
-test-pref(layout.css.vertical-text.enabled,true) == flexbox-writing-mode-003.html flexbox-writing-mode-003.html
-test-pref(layout.css.vertical-text.enabled,true) == flexbox-writing-mode-004.html flexbox-writing-mode-004.html
-test-pref(layout.css.vertical-text.enabled,true) == flexbox-writing-mode-005.html flexbox-writing-mode-005.html
-test-pref(layout.css.vertical-text.enabled,true) == flexbox-writing-mode-006.html flexbox-writing-mode-006.html
-test-pref(layout.css.vertical-text.enabled,true) == flexbox-writing-mode-007.html flexbox-writing-mode-007.html
-test-pref(layout.css.vertical-text.enabled,true) == flexbox-writing-mode-008.html flexbox-writing-mode-008.html
-test-pref(layout.css.vertical-text.enabled,true) == flexbox-writing-mode-009.html flexbox-writing-mode-009.html
+== flexbox-writing-mode-001.html flexbox-writing-mode-001.html
+== flexbox-writing-mode-002.html flexbox-writing-mode-002.html
+== flexbox-writing-mode-003.html flexbox-writing-mode-003.html
+== flexbox-writing-mode-004.html flexbox-writing-mode-004.html
+== flexbox-writing-mode-005.html flexbox-writing-mode-005.html
+== flexbox-writing-mode-006.html flexbox-writing-mode-006.html
+== flexbox-writing-mode-007.html flexbox-writing-mode-007.html
+== flexbox-writing-mode-008.html flexbox-writing-mode-008.html
+== flexbox-writing-mode-009.html flexbox-writing-mode-009.html
--- a/layout/reftests/w3c-css/submitted/text-decor-3/reftest-stylo.list
+++ b/layout/reftests/w3c-css/submitted/text-decor-3/reftest-stylo.list
@@ -1,10 +1,10 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
-default-preferences pref(layout.css.vertical-text.enabled,true)
+
 
 == ruby-text-decoration-01.html ruby-text-decoration-01.html
 == text-decoration-propagation-01.html text-decoration-propagation-01.html
 
 # text-emphasis-style
 == text-emphasis-style-property-001.html text-emphasis-style-property-001.html
 fuzzy-if(gtkWidget,3,4) fuzzy-if(skiaContent,87,65) == text-emphasis-style-property-002.html text-emphasis-style-property-002.html
 skip-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == text-emphasis-style-property-003.html text-emphasis-style-property-003.html
--- a/layout/reftests/writing-mode/abspos/reftest-stylo.list
+++ b/layout/reftests/writing-mode/abspos/reftest-stylo.list
@@ -1,13 +1,13 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 # This directory contains tests for position:absolute and vertical writing modes.
 # They require the vertical-text pref to be true, otherwise lots of them will fail.
 # (See bug 1079151 for the origin of these testcases by GĂ©rard Talbot.)
-default-preferences pref(layout.css.vertical-text.enabled,true)
+
 
 # All of these are fuzzy-if on skia content on OS X due to subpixel text positioning.
 fails fuzzy-if(cocoaWidget,15,5) fuzzy-if(d2d,102,164) fuzzy-if(skiaContent,255,248) == s71-abs-pos-non-replaced-vlr-003.xht s71-abs-pos-non-replaced-vlr-003.xht
 fails fuzzy-if(cocoaWidget,15,5) fuzzy-if(d2d,102,164) fuzzy-if(skiaContent,255,248) == s71-abs-pos-non-replaced-vlr-005.xht s71-abs-pos-non-replaced-vlr-005.xht
 fails fuzzy-if(cocoaWidget,15,5) fuzzy-if(d2d,102,164) fuzzy-if(skiaContent,255,248) == s71-abs-pos-non-replaced-vlr-007.xht s71-abs-pos-non-replaced-vlr-007.xht
 fails fuzzy-if(cocoaWidget,15,5) fuzzy-if(d2d,102,164) fuzzy-if(skiaContent,255,248) == s71-abs-pos-non-replaced-vlr-009.xht s71-abs-pos-non-replaced-vlr-009.xht
 fails fuzzy-if(cocoaWidget,15,5) fuzzy-if(d2d,102,164) fuzzy-if(skiaContent,255,248) == s71-abs-pos-non-replaced-vlr-011.xht s71-abs-pos-non-replaced-vlr-011.xht
 fails fuzzy-if(cocoaWidget,15,5) fuzzy-if(d2d,102,164) fuzzy-if(skiaContent,255,248) == s71-abs-pos-non-replaced-vlr-013.xht s71-abs-pos-non-replaced-vlr-013.xht
--- a/layout/reftests/writing-mode/reftest-stylo.list
+++ b/layout/reftests/writing-mode/reftest-stylo.list
@@ -1,12 +1,12 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 # This directory contains tests for vertical text and logical layout coordinates.
 # They require the vertical-text pref to be true, otherwise lots of them will fail.
-default-preferences pref(layout.css.vertical-text.enabled,true)
+
 
 HTTP(..) == 1079154-1-vertical-rl-columns.html 1079154-1-vertical-rl-columns.html
 == 1082844.html 1082844.html
 HTTP(..) == 1083748.html 1083748.html
 HTTP(..) == 1083848-1-inline-border.html 1083848-1-inline-border.html
 HTTP(..) == 1083848-2-inline-background.html 1083848-2-inline-background.html
 fails fuzzy-if(gtkWidget,255,2) fuzzy-if(winWidget||Android||B2G,4,8704) HTTP(..) == 1083848-3-inline-background-repeat.html 1083848-3-inline-background-repeat.html
 == 1083892-1.html 1083892-1.html
rename from mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/UnusedResourcesUtil.java
rename to mobile/android/base/java/org/mozilla/gecko/util/UnusedResourcesUtil.java
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -6,31 +6,34 @@
 
 DIRS += ['locales']
 
 CONFIGURE_SUBST_FILES += ['adjust_sdk_app_token']
 
 include('android-services.mozbuild')
 
 geckoview_source_dir = TOPSRCDIR + '/mobile/android/geckoview/src/main/'
+geckoview_thirdparty_source_dir = TOPSRCDIR + '/mobile/android/geckoview/src/thirdparty/'
 thirdparty_source_dir = TOPSRCDIR + '/mobile/android/thirdparty/'
 
 constants_jar = add_java_jar('constants')
-constants_jar.sources = ['java/org/mozilla/gecko/' + x for x in [
-    'adjust/AdjustHelperInterface.java',
-    'adjust/AttributionHelperListener.java',
+constants_jar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x for x in [
     'annotation/JNITarget.java',
     'annotation/ReflectionTarget.java',
     'annotation/RobocopTarget.java',
     'annotation/WebRTCJNITarget.java',
     'annotation/WrapForJNI.java',
+    'SysInfo.java',
+]]
+constants_jar.sources += ['java/org/mozilla/gecko/' + x for x in [
+    'adjust/AdjustHelperInterface.java',
+    'adjust/AttributionHelperListener.java',
     'db/BrowserContract.java',
     'LocaleManager.java',
     'Locales.java',
-    'SysInfo.java',
 ]]
 constants_jar.generated_sources = [
     'preprocessed/org/mozilla/gecko/AdjustConstants.java',
     'preprocessed/org/mozilla/gecko/AppConstants.java',
 ]
 constants_jar.extra_jars = [
     CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
     CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
@@ -284,20 +287,20 @@ gvjar.sources += [geckoview_source_dir +
     'sqlite/ByteBufferInputStream.java',
     'sqlite/MatrixBlobCursor.java',
     'sqlite/SQLiteBridge.java',
     'sqlite/SQLiteBridgeException.java',
     'TouchEventInterceptor.java',
     'widget/SwipeDismissListViewTouchListener.java',
 ]]
 
-gvjar.sources += [thirdparty_source_dir + f for f in [
-    'com/googlecode/eyesfree/braille/selfbraille/ISelfBrailleService.java',
-    'com/googlecode/eyesfree/braille/selfbraille/SelfBrailleClient.java',
-    'com/googlecode/eyesfree/braille/selfbraille/WriteData.java',
+gvjar.sources += [geckoview_thirdparty_source_dir + f for f in [
+    'java/com/googlecode/eyesfree/braille/selfbraille/ISelfBrailleService.java',
+    'java/com/googlecode/eyesfree/braille/selfbraille/SelfBrailleClient.java',
+    'java/com/googlecode/eyesfree/braille/selfbraille/WriteData.java',
 ]]
 
 gvjar.extra_jars += [
     CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
     CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
     CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
     'constants.jar',
     'gecko-R.jar',
rename from mobile/android/base/java/org/mozilla/gecko/SysInfo.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/SysInfo.java
rename from mobile/android/base/java/org/mozilla/gecko/annotation/JNITarget.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/annotation/JNITarget.java
rename from mobile/android/base/java/org/mozilla/gecko/annotation/ReflectionTarget.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/annotation/ReflectionTarget.java
rename from mobile/android/base/java/org/mozilla/gecko/annotation/RobocopTarget.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/annotation/RobocopTarget.java
rename from mobile/android/base/java/org/mozilla/gecko/annotation/WebRTCJNITarget.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/annotation/WebRTCJNITarget.java
rename from mobile/android/base/java/org/mozilla/gecko/annotation/WrapForJNI.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/annotation/WrapForJNI.java
new file mode 100644
--- /dev/null
+++ b/mobile/android/geckoview/src/thirdparty/java/com/googlecode/eyesfree/braille/selfbraille/ISelfBrailleService.java
@@ -0,0 +1,147 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * 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/. */
+
+package com.googlecode.eyesfree.braille.selfbraille;
+
+/**
+ * Interface for a client to control braille output for a part of the
+ * accessibility node tree.
+ */
+public interface ISelfBrailleService extends android.os.IInterface {
+    /** Local-side IPC implementation stub class. */
+    public static abstract class Stub extends android.os.Binder implements
+            com.googlecode.eyesfree.braille.selfbraille.ISelfBrailleService {
+        private static final java.lang.String DESCRIPTOR = "com.googlecode.eyesfree.braille.selfbraille.ISelfBrailleService";
+
+        /** Construct the stub at attach it to the interface. */
+        public Stub() {
+            this.attachInterface(this, DESCRIPTOR);
+        }
+
+        /**
+         * Cast an IBinder object into an
+         * com.googlecode.eyesfree.braille.selfbraille.ISelfBrailleService
+         * interface, generating a proxy if needed.
+         */
+        public static com.googlecode.eyesfree.braille.selfbraille.ISelfBrailleService asInterface(
+                android.os.IBinder obj) {
+            if ((obj == null)) {
+                return null;
+            }
+            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+            if (((iin != null) && (iin instanceof com.googlecode.eyesfree.braille.selfbraille.ISelfBrailleService))) {
+                return ((com.googlecode.eyesfree.braille.selfbraille.ISelfBrailleService) iin);
+            }
+            return new com.googlecode.eyesfree.braille.selfbraille.ISelfBrailleService.Stub.Proxy(
+                    obj);
+        }
+
+        @Override
+        public android.os.IBinder asBinder() {
+            return this;
+        }
+
+        @Override
+        public boolean onTransact(int code, android.os.Parcel data,
+                android.os.Parcel reply, int flags)
+                throws android.os.RemoteException {
+            switch (code) {
+            case INTERFACE_TRANSACTION: {
+                reply.writeString(DESCRIPTOR);
+                return true;
+            }
+            case TRANSACTION_write: {
+                data.enforceInterface(DESCRIPTOR);
+                android.os.IBinder _arg0;
+                _arg0 = data.readStrongBinder();
+                com.googlecode.eyesfree.braille.selfbraille.WriteData _arg1;
+                if ((0 != data.readInt())) {
+                    _arg1 = com.googlecode.eyesfree.braille.selfbraille.WriteData.CREATOR
+                            .createFromParcel(data);
+                } else {
+                    _arg1 = null;
+                }
+                this.write(_arg0, _arg1);
+                reply.writeNoException();
+                return true;
+            }
+            case TRANSACTION_disconnect: {
+                data.enforceInterface(DESCRIPTOR);
+                android.os.IBinder _arg0;
+                _arg0 = data.readStrongBinder();
+                this.disconnect(_arg0);
+                return true;
+            }
+            }
+            return super.onTransact(code, data, reply, flags);
+        }
+
+        private static class Proxy implements
+                com.googlecode.eyesfree.braille.selfbraille.ISelfBrailleService {
+            private android.os.IBinder mRemote;
+
+            Proxy(android.os.IBinder remote) {
+                mRemote = remote;
+            }
+
+            @Override
+            public android.os.IBinder asBinder() {
+                return mRemote;
+            }
+
+            public java.lang.String getInterfaceDescriptor() {
+                return DESCRIPTOR;
+            }
+
+            @Override
+            public void write(
+                    android.os.IBinder clientToken,
+                    com.googlecode.eyesfree.braille.selfbraille.WriteData writeData)
+                    throws android.os.RemoteException {
+                android.os.Parcel _data = android.os.Parcel.obtain();
+                android.os.Parcel _reply = android.os.Parcel.obtain();
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeStrongBinder(clientToken);
+                    if ((writeData != null)) {
+                        _data.writeInt(1);
+                        writeData.writeToParcel(_data, 0);
+                    } else {
+                        _data.writeInt(0);
+                    }
+                    mRemote.transact(Stub.TRANSACTION_write, _data, _reply, 0);
+                    _reply.readException();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+            }
+
+            @Override
+            public void disconnect(android.os.IBinder clientToken)
+                    throws android.os.RemoteException {
+                android.os.Parcel _data = android.os.Parcel.obtain();
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeStrongBinder(clientToken);
+                    mRemote.transact(Stub.TRANSACTION_disconnect, _data, null,
+                            android.os.IBinder.FLAG_ONEWAY);
+                } finally {
+                    _data.recycle();
+                }
+            }
+        }
+
+        static final int TRANSACTION_write = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+        static final int TRANSACTION_disconnect = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
+    }
+
+    public void write(android.os.IBinder clientToken,
+            com.googlecode.eyesfree.braille.selfbraille.WriteData writeData)
+            throws android.os.RemoteException;
+
+    public void disconnect(android.os.IBinder clientToken)
+            throws android.os.RemoteException;
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/geckoview/src/thirdparty/java/com/googlecode/eyesfree/braille/selfbraille/SelfBrailleClient.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.googlecode.eyesfree.braille.selfbraille;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * Client-side interface to the self brailling interface.
+ *
+ * Threading: Instances of this object should be created and shut down
+ * in a thread with a {@link Looper} associated with it.  Other methods may
+ * be called on any thread.
+ */
+public class SelfBrailleClient {
+    private static final String LOG_TAG =
+            SelfBrailleClient.class.getSimpleName();
+    private static final String ACTION_SELF_BRAILLE_SERVICE =
+            "com.googlecode.eyesfree.braille.service.ACTION_SELF_BRAILLE_SERVICE";
+    private static final String BRAILLE_BACK_PACKAGE =
+            "com.googlecode.eyesfree.brailleback";
+    private static final Intent mServiceIntent =
+            new Intent(ACTION_SELF_BRAILLE_SERVICE)
+            .setPackage(BRAILLE_BACK_PACKAGE);
+    /**
+     * SHA-1 hash value of the Eyes-Free release key certificate, used to sign
+     * BrailleBack.  It was generated from the keystore with:
+     * $ keytool -exportcert -keystore <keystorefile> -alias android.keystore \
+     *   > cert
+     * $ keytool -printcert -file cert
+     */
+    // The typecasts are to silence a compiler warning about loss of precision
+    private static final byte[] EYES_FREE_CERT_SHA1 = new byte[] {
+        (byte) 0x9B, (byte) 0x42, (byte) 0x4C, (byte) 0x2D,
+        (byte) 0x27, (byte) 0xAD, (byte) 0x51, (byte) 0xA4,
+        (byte) 0x2A, (byte) 0x33, (byte) 0x7E, (byte) 0x0B,
+        (byte) 0xB6, (byte) 0x99, (byte) 0x1C, (byte) 0x76,
+        (byte) 0xEC, (byte) 0xA4, (byte) 0x44, (byte) 0x61
+    };
+    /**
+     * Delay before the first rebind attempt on bind error or service
+     * disconnect.
+     */
+    private static final int REBIND_DELAY_MILLIS = 500;
+    private static final int MAX_REBIND_ATTEMPTS = 5;
+
+    private final Binder mIdentity = new Binder();
+    private final Context mContext;
+    private final boolean mAllowDebugService;
+    private final SelfBrailleHandler mHandler = new SelfBrailleHandler();
+    private boolean mShutdown = false;
+
+    /**
+     * Written in handler thread, read in any thread calling methods on the
+     * object.
+     */
+    private volatile Connection mConnection;
+    /** Protected by synchronizing on mHandler. */
+    private int mNumFailedBinds = 0;
+
+    /**
+     * Constructs an instance of this class.  {@code context} is used to bind
+     * to the self braille service.  The current thread must have a Looper
+     * associated with it.  If {@code allowDebugService} is true, this instance
+     * will connect to a BrailleBack service without requiring it to be signed
+     * by the release key used to sign BrailleBack.
+     */
+    public SelfBrailleClient(Context context, boolean allowDebugService) {
+        mContext = context;
+        mAllowDebugService = allowDebugService;
+        doBindService();
+    }
+
+    /**
+     * Shuts this instance down, deallocating any global resources it is using.
+     * This method must be called on the same thread that created this object.
+     */
+    public void shutdown() {
+        mShutdown = true;
+        doUnbindService();
+    }
+
+    public void write(WriteData writeData) {
+        writeData.validate();
+        ISelfBrailleService localService = getSelfBrailleService();
+        if (localService != null) {
+            try {
+                localService.write(mIdentity, writeData);
+            } catch (RemoteException ex) {
+                Log.e(LOG_TAG, "Self braille write failed", ex);
+            }
+        }
+    }
+
+    private void doBindService() {
+        Connection localConnection = new Connection();
+        if (!mContext.bindService(mServiceIntent, localConnection,
+                Context.BIND_AUTO_CREATE)) {
+            Log.e(LOG_TAG, "Failed to bind to service");
+            mHandler.scheduleRebind();
+            return;
+        }
+        mConnection = localConnection;
+        Log.i(LOG_TAG, "Bound to self braille service");
+    }
+
+    private void doUnbindService() {
+        if (mConnection != null) {
+            ISelfBrailleService localService = getSelfBrailleService();
+            if (localService != null) {
+                try {
+                    localService.disconnect(mIdentity);
+                } catch (RemoteException ex) {
+                    // Nothing to do.
+                }
+            }
+            mContext.unbindService(mConnection);
+            mConnection = null;
+        }
+    }
+
+    private ISelfBrailleService getSelfBrailleService() {
+        Connection localConnection = mConnection;
+        if (localConnection != null) {
+            return localConnection.mService;
+        }
+        return null;
+    }
+
+    private boolean verifyPackage() {
+        PackageManager pm = mContext.getPackageManager();
+        PackageInfo pi;
+        try {
+            pi = pm.getPackageInfo(BRAILLE_BACK_PACKAGE,
+                    PackageManager.GET_SIGNATURES);
+        } catch (PackageManager.NameNotFoundException ex) {
+            Log.w(LOG_TAG, "Can't verify package " + BRAILLE_BACK_PACKAGE,
+                    ex);
+            return false;
+        }
+        MessageDigest digest;
+        try {
+            digest = MessageDigest.getInstance("SHA-1");
+        } catch (NoSuchAlgorithmException ex) {
+            Log.e(LOG_TAG, "SHA-1 not supported", ex);
+            return false;
+        }
+        // Check if any of the certificates match our hash.
+        for (Signature signature : pi.signatures) {
+            digest.update(signature.toByteArray());
+            if (MessageDigest.isEqual(EYES_FREE_CERT_SHA1, digest.digest())) {
+                return true;
+            }
+            digest.reset();
+        }
+        if (mAllowDebugService) {
+            Log.w(LOG_TAG, String.format(
+                "*** %s connected to BrailleBack with invalid (debug?) "
+                + "signature ***",
+                mContext.getPackageName()));
+            return true;
+        }
+        return false;
+    }
+    private class Connection implements ServiceConnection {
+        // Read in application threads, written in main thread.
+        private volatile ISelfBrailleService mService;
+
+        @Override
+        public void onServiceConnected(ComponentName className,
+                IBinder binder) {
+            if (!verifyPackage()) {
+                Log.w(LOG_TAG, String.format("Service certificate mismatch "
+                                + "for %s, dropping connection",
+                                BRAILLE_BACK_PACKAGE));
+                mHandler.unbindService();
+                return;
+            }
+            Log.i(LOG_TAG, "Connected to self braille service");
+            mService = ISelfBrailleService.Stub.asInterface(binder);
+            synchronized (mHandler) {
+                mNumFailedBinds = 0;
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName className) {
+            Log.e(LOG_TAG, "Disconnected from self braille service");
+            mService = null;
+            // Retry by rebinding.
+            mHandler.scheduleRebind();
+        }
+    }
+
+    private class SelfBrailleHandler extends Handler {
+        private static final int MSG_REBIND_SERVICE = 1;
+        private static final int MSG_UNBIND_SERVICE = 2;
+
+        public void scheduleRebind() {
+            synchronized (this) {
+                if (mNumFailedBinds < MAX_REBIND_ATTEMPTS) {
+                    int delay = REBIND_DELAY_MILLIS << mNumFailedBinds;
+                    sendEmptyMessageDelayed(MSG_REBIND_SERVICE, delay);
+                    ++mNumFailedBinds;
+                }
+            }
+        }
+
+        public void unbindService() {
+            sendEmptyMessage(MSG_UNBIND_SERVICE);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_REBIND_SERVICE:
+                    handleRebindService();
+                    break;
+                case MSG_UNBIND_SERVICE:
+                    handleUnbindService();
+                    break;
+            }
+        }
+
+        private void handleRebindService() {
+            if (mShutdown) {
+                return;
+            }
+            if (mConnection != null) {
+                doUnbindService();
+            }
+            doBindService();
+        }
+
+        private void handleUnbindService() {
+            doUnbindService();
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/geckoview/src/thirdparty/java/com/googlecode/eyesfree/braille/selfbraille/WriteData.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.googlecode.eyesfree.braille.selfbraille;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+/**
+ * Represents what should be shown on the braille display for a
+ * part of the accessibility node tree.
+ */
+public class WriteData implements Parcelable {
+
+    private static final String PROP_SELECTION_START = "selectionStart";
+    private static final String PROP_SELECTION_END = "selectionEnd";
+
+    private AccessibilityNodeInfo mAccessibilityNodeInfo;
+    private CharSequence mText;
+    private Bundle mProperties = Bundle.EMPTY;
+
+    /**
+     * Returns a new {@link WriteData} instance for the given {@code view}.
+     */
+    public static WriteData forView(View view) {
+        AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain(view);
+        WriteData writeData = new WriteData();
+        writeData.mAccessibilityNodeInfo = node;
+        return writeData;
+    }
+
+    public static WriteData forInfo(AccessibilityNodeInfo info){
+        WriteData writeData = new WriteData();
+        writeData.mAccessibilityNodeInfo = info;
+        return writeData;
+    }
+
+
+    public AccessibilityNodeInfo getAccessibilityNodeInfo() {
+        return mAccessibilityNodeInfo;
+    }
+
+    /**
+     * Sets the text to be displayed when the accessibility node associated
+     * with this instance has focus.  If this method is not called (or
+     * {@code text} is {@code null}), this client relinquishes control over
+     * this node.
+     */
+    public WriteData setText(CharSequence text) {
+        mText = text;
+        return this;
+    }
+
+    public CharSequence getText() {
+        return mText;
+    }
+
+    /**
+     * Sets the start position in the text of a text selection or cursor that
+     * should be marked on the display.  A negative value (the default) means
+     * no selection will be added.
+     */
+    public WriteData setSelectionStart(int v) {
+        writableProperties().putInt(PROP_SELECTION_START, v);
+        return this;
+    }
+
+    /**
+     * @see {@link #setSelectionStart}.
+