merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 16 Mar 2017 15:35:50 +0100
changeset 398427 468dde25160493591211fe0505dd2ccdd6c9a0bb
parent 398397 3ea221e3ebbb5d604da5ff94ac122bbaf08170b5 (current diff)
parent 398426 ab96d8a9e2476dbd4de79ef5f7af77f7fb6bf3ca (diff)
child 398428 158cc22a2bd35e755a5cf075c2b2d6844033acd8
child 398446 0ddb41834601b8fd9a474777a89852fdf3c7d65c
child 398492 0423d3fbfacf89fd6d32182625272acc5d777157
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone55.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-inbound to mozilla-central a=merge
browser/modules/webrtcUI.jsm
security/nss/fuzz/tls_client_socket.cc
security/nss/fuzz/tls_client_socket.h
tools/profiler/public/ProfilerBacktrace.h
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -312,26 +312,23 @@ nsAccessibilityService::ListenersChanged
           listenerName != nsGkAtoms::onmousedown &&
           listenerName != nsGkAtoms::onmouseup) {
         continue;
       }
 
       nsIDocument* ownerDoc = node->OwnerDoc();
       DocAccessible* document = GetExistingDocAccessible(ownerDoc);
 
-      // Always recreate for onclick changes.
-      if (document) {
-        if (nsCoreUtils::HasClickListener(node)) {
-          if (!document->GetAccessible(node)) {
-            document->RecreateAccessible(node);
-          }
-        } else {
-          if (document->GetAccessible(node)) {
-            document->RecreateAccessible(node);
-          }
+      // Create an accessible for a inaccessible element having click event
+      // handler.
+      if (document && !document->HasAccessible(node) &&
+          nsCoreUtils::HasClickListener(node)) {
+        nsIContent* parentEl = node->GetFlattenedTreeParent();
+        if (parentEl) {
+          document->ContentInserted(parentEl, node, node->GetNextSibling());
         }
         break;
       }
     }
   }
   return NS_OK;
 }
 
--- a/accessible/tests/browser/e10s/browser_treeupdate_listener.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_listener.js
@@ -21,23 +21,9 @@ addAccessibleTask('<span id="parent"><sp
       content.window.dummyListener = () => {};
       content.document.getElementById('parent').addEventListener(
         'click', content.window.dummyListener);
     });
     yield onReorder;
 
     let tree = { TEXT: [] };
     testAccessibleTree(findAccessibleChildByID(accDoc, 'parent'), tree);
-
-    onReorder = waitForEvent(EVENT_REORDER, 'body');
-    // Remove an event listener from parent.
-    yield ContentTask.spawn(browser, {}, () => {
-      content.document.getElementById('parent').removeEventListener(
-        'click', content.window.dummyListener);
-      delete content.window.dummyListener;
-    });
-    yield onReorder;
-
-    is(findAccessibleChildByID(accDoc, 'parent'), null,
-      'Check that parent is not accessible.');
-    is(findAccessibleChildByID(accDoc, 'child'), null,
-      'Check that child is not accessible.');
   });
--- a/accessible/tests/mochitest/treeupdate/test_bug1175913.html
+++ b/accessible/tests/mochitest/treeupdate/test_bug1175913.html
@@ -42,28 +42,30 @@
       {
         return "Test that show event is sent when click listener is added";
       }
     }
 
     function testRemoveListener()
     {
       this.eventSeq = [
-        new invokerChecker(EVENT_HIDE, getNode("parent")),
+        new unexpectedInvokerChecker(EVENT_HIDE, getNode("parent")),
       ];
 
       this.invoke = function testRemoveListener_invoke()
       {
         getNode("parent").removeEventListener("click", dummyListener);
       }
 
       this.finalCheck = function testRemoveListener_finalCheck()
       {
-        is(getAccessible("parent", null, null, DONOTFAIL_IF_NO_ACC), null, "Check that parent is not accessible.");
-        is(getAccessible("child", null, null, DONOTFAIL_IF_NO_ACC), null, "Check that child is not accessible.");
+        ok(getAccessible("parent", null, null, DONOTFAIL_IF_NO_ACC),
+           "Parent stays accessible after click event listener is removed");
+        ok(!getAccessible("child", null, null, DONOTFAIL_IF_NO_ACC),
+           "Child stays inaccessible");
       }
 
       this.getID = function testRemoveListener_getID()
       {
         return "Test that hide event is sent when click listener is removed";
       }
     }
 
--- a/accessible/tests/mochitest/treeupdate/test_textleaf.html
+++ b/accessible/tests/mochitest/treeupdate/test_textleaf.html
@@ -38,32 +38,26 @@
       }
     }
 
     function setOnClickAttr(aID)
     {
       var node = getNode(aID);
       node.setAttribute("onclick", "alert(3);");
       var textLeaf = getAccessible(node).firstChild;
-      is(textLeaf.actionCount, 1, "Wrong action numbers!");
+      is(textLeaf.actionCount, 1, "setOnClickAttr: wrong action numbers!");
     }
 
     function removeOnClickAttr(aID)
     {
-      this.__proto__ = new textLeafUpdate(aID, false);
-
-      this.invoke = function removeOnClickAttr_invoke()
-      {
-        this.node.removeAttribute("onclick");
-      }
-
-      this.getID = function removeOnClickAttr_getID()
-      {
-        return "unmake " + prettyName(aID) + " linkable";
-      }
+      var node = getNode(aID);
+      node.removeAttribute("onclick");
+      var textLeaf = getAccessible(node).firstChild;
+      is(textLeaf.actionCount, 0,
+         "removeOnClickAttr: wrong action numbers!");
     }
 
     function setOnClickNRoleAttrs(aID)
     {
       this.__proto__ = new textLeafUpdate(aID, true);
 
       this.invoke = function setOnClickAttr_invoke()
       {
@@ -124,20 +118,21 @@
     //gA11yEventDumpToConsole = true;
 
     var gQueue = null;
 
     function doTest()
     {
       // adds onclick on element, text leaf should inherit its action
       setOnClickAttr("div");
+      // remove onclick attribute, text leaf shouldn't have any action
+      removeOnClickAttr("div");
+
       // Call rest of event tests.
       gQueue = new eventQueue();
-      // remove onclick attribute, text leaf shouldn't have any action
-      gQueue.push(new removeOnClickAttr("div"));
 
       // set onclick attribute making span accessible, it's inserted into tree
       // and adopts text leaf accessible, text leaf should have an action
       gQueue.push(new setOnClickNRoleAttrs("span"));
 
       // text data removal of text node should remove its text accessible
       gQueue.push(new removeTextData("p", ROLE_PARAGRAPH));
       gQueue.push(new removeTextData("pre", ROLE_TEXT_CONTAINER));
--- a/addon-sdk/source/test/test-ui-action-button.js
+++ b/addon-sdk/source/test/test-ui-action-button.js
@@ -303,17 +303,17 @@ exports['test button global state update
   // Tried to use `getWidgetIdsInArea` but seems undefined, not sure if it
   // was removed or it's not in the UX build yet
 
   let { node, id: widgetId } = getWidget(button.id);
 
   // check read-only properties
 
   assert.throws(() => button.id = 'another-id',
-    /^setting a property that has only a getter/,
+    /^setting getter-only property/,
     'id cannot be set at runtime');
 
   assert.equal(button.id, 'my-button-4',
     'id is unchanged');
   assert.equal(node.id, widgetId,
     'node id is unchanged');
 
   // check writable properties
--- a/addon-sdk/source/test/test-ui-sidebar.js
+++ b/addon-sdk/source/test/test-ui-sidebar.js
@@ -1045,17 +1045,17 @@ exports.testSidebarGettersAndSettersAfte
     url: url
   });
 
   sidebar.destroy();
 
   assert.equal(sidebar.id, undefined, 'sidebar after destroy has no id');
 
   assert.throws(() => sidebar.id = 'foo-tang',
-    /^setting a property that has only a getter/,
+    /^setting getter-only property/,
     'id cannot be set at runtime');
 
   assert.equal(sidebar.id, undefined, 'sidebar after destroy has no id');
 
   assert.equal(sidebar.title, undefined, 'sidebar after destroy has no title');
   sidebar.title = 'boo-tang';
   assert.equal(sidebar.title, undefined, 'sidebar after destroy has no title');
 
--- a/addon-sdk/source/test/test-ui-toggle-button.js
+++ b/addon-sdk/source/test/test-ui-toggle-button.js
@@ -297,17 +297,17 @@ exports['test button global state update
   // Tried to use `getWidgetIdsInArea` but seems undefined, not sure if it
   // was removed or it's not in the UX build yet
 
   let { node, id: widgetId } = getWidget(button.id);
 
   // check read-only properties
 
   assert.throws(() => button.id = 'another-id',
-    /^setting a property that has only a getter/,
+    /^setting getter-only property/,
     'id cannot be set at runtime');
 
   assert.equal(button.id, 'my-button-4',
     'id is unchanged');
   assert.equal(node.id, widgetId,
     'node id is unchanged');
 
   // check writable properties
--- a/browser/base/content/test/webrtc/browser.ini
+++ b/browser/base/content/test/webrtc/browser.ini
@@ -4,16 +4,18 @@ support-files =
   get_user_media_in_frame.html
   get_user_media_content_script.js
   head.js
 
 [browser_devices_get_user_media.js]
 skip-if = (os == "linux" && debug) # linux: bug 976544
 [browser_devices_get_user_media_anim.js]
 [browser_devices_get_user_media_in_frame.js]
+[browser_devices_get_user_media_multi_process.js]
+skip-if = (e10s && debug) # bug 1347625
 [browser_devices_get_user_media_screen.js]
 skip-if = (e10s && debug) || (os == "linux") || (os == "win" && !debug) # bug 1320754 for e10s debug, and bug 1320994 for linux opt, bug 1338038 for windows and linux debug
 [browser_devices_get_user_media_tear_off_tab.js]
 [browser_devices_get_user_media_unprompted_access.js]
 [browser_devices_get_user_media_unprompted_access_in_frame.js]
 [browser_devices_get_user_media_unprompted_access_tear_off_tab.js]
 skip-if = (os == "linux") || (os == "win" && bits == 64) # linux: bug 1331616, win8: bug 1334752
 [browser_webrtc_hooks.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_multi_process.js
@@ -0,0 +1,153 @@
+/* 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/. */
+
+registerCleanupFunction(function() {
+  gBrowser.removeCurrentTab();
+});
+
+var gTests = [
+
+{
+  desc: "getUserMedia audio in a first process + video in a second process",
+  run: function* checkMultiProcess() {
+    // The main purpose of this test is to ensure webrtc sharing indicators
+    // work with multiple content processes, but it makes sense to run this
+    // test without e10s too to ensure using webrtc devices in two different
+    // tabs is handled correctly.
+
+    // Request audio in the first tab.
+    let promise = promisePopupNotificationShown("webRTC-shareDevices");
+    yield promiseRequestDevice(true);
+    yield promise;
+    yield expectObserverCalled("getUserMedia:request");
+
+    checkDeviceSelectors(true);
+
+    let indicator = promiseIndicatorWindow();
+    yield promiseMessage("ok", () => {
+      PopupNotifications.panel.firstChild.button.click();
+    });
+    yield expectObserverCalled("getUserMedia:response:allow");
+    yield expectObserverCalled("recording-device-events");
+    Assert.deepEqual((yield getMediaCaptureState()), {audio: true},
+                     "expected microphone to be shared");
+
+    yield indicator;
+    yield checkSharingUI({audio: true});
+
+    ok(webrtcUI.showGlobalIndicator, "webrtcUI wants the global indicator shown");
+    ok(!webrtcUI.showCameraIndicator, "webrtcUI wants the camera indicator hidden");
+    ok(webrtcUI.showMicrophoneIndicator, "webrtcUI wants the mic indicator shown");
+    is(webrtcUI.getActiveStreams(false, true).length, 1, "1 active audio stream");
+    is(webrtcUI.getActiveStreams(true, true, true).length, 1, "1 active stream");
+
+    yield expectNoObserverCalled();
+
+    // If we have reached the max process count already, increase it to ensure
+    // our new tab can have its own content process.
+    var ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+                 .getService(Ci.nsIMessageBroadcaster);
+    ppmm.QueryInterface(Ci.nsIProcessScriptLoader);
+    let childCount = ppmm.childCount;
+    let maxContentProcess = Services.prefs.getIntPref("dom.ipc.processCount");
+    // The first check is because if we are on a branch where e10s-multi is
+    // disabled, we want to keep testing e10s with a single content process.
+    // The + 1 is because ppmm.childCount also counts the chrome process
+    // (which also runs process scripts).
+    if (maxContentProcess > 1 && childCount == maxContentProcess + 1) {
+      yield SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount",
+                                                childCount]]});
+    }
+
+    // Open a new tab with a different hostname.
+    let url = gBrowser.currentURI.spec.replace("https://example.com/",
+                                               "http://127.0.0.1:8888/");
+    let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+    tab.linkedBrowser.messageManager.loadFrameScript(CONTENT_SCRIPT_HELPER, true);
+
+    // Request video.
+    promise = promisePopupNotificationShown("webRTC-shareDevices");
+    yield promiseRequestDevice(false, true);
+    yield promise;
+    yield expectObserverCalled("getUserMedia:request");
+
+    checkDeviceSelectors(false, true);
+
+    yield promiseMessage("ok", () => {
+      PopupNotifications.panel.firstChild.button.click();
+    });
+    yield expectObserverCalled("getUserMedia:response:allow");
+    yield expectObserverCalled("recording-device-events");
+
+    yield checkSharingUI({video: true}, window, {audio: true, video: true});
+
+    ok(webrtcUI.showGlobalIndicator, "webrtcUI wants the global indicator shown");
+    ok(webrtcUI.showCameraIndicator, "webrtcUI wants the camera indicator shown");
+    ok(webrtcUI.showMicrophoneIndicator, "webrtcUI wants the mic indicator shown");
+    is(webrtcUI.getActiveStreams(false, true).length, 1, "1 active audio stream");
+    is(webrtcUI.getActiveStreams(true).length, 1, "1 active video stream");
+    is(webrtcUI.getActiveStreams(true, true, true).length, 2, "2 active streams");
+
+    info("removing the second tab");
+    yield BrowserTestUtils.removeTab(tab);
+
+    // Check that we still show the sharing indicators for the first tab's stream.
+    yield promiseWaitForCondition(() => !webrtcUI.showCameraIndicator);
+    ok(webrtcUI.showGlobalIndicator, "webrtcUI wants the global indicator shown");
+    ok(!webrtcUI.showCameraIndicator, "webrtcUI wants the camera indicator hidden");
+    ok(webrtcUI.showMicrophoneIndicator, "webrtcUI wants the mic indicator shown");
+    is(webrtcUI.getActiveStreams(false, true).length, 1, "1 active audio stream");
+    is(webrtcUI.getActiveStreams(true, true, true).length, 1, "1 active stream");
+
+    yield checkSharingUI({audio: true});
+
+    // When both tabs use the same content process, the frame script for the
+    // first tab receives observer notifications for things happening in the
+    // second tab, so let's clear the observer call counts before we cleanup
+    // in the first tab.
+    yield ignoreObserversCalled();
+
+    // Close the first tab's stream and verify that all indicators are removed.
+    yield closeStream();
+
+    ok(!webrtcUI.showGlobalIndicator, "webrtcUI wants the global indicator hidden");
+    is(webrtcUI.getActiveStreams(true, true, true).length, 0, "0 active streams");
+  }
+},
+
+];
+
+function test() {
+  waitForExplicitFinish();
+
+  let tab = gBrowser.addTab();
+  gBrowser.selectedTab = tab;
+  let browser = tab.linkedBrowser;
+
+  browser.messageManager.loadFrameScript(CONTENT_SCRIPT_HELPER, true);
+
+  browser.addEventListener("load", function() {
+    is(PopupNotifications._currentNotifications.length, 0,
+       "should start the test without any prior popup notification");
+    ok(gIdentityHandler._identityPopup.hidden,
+       "should start the test with the control center hidden");
+
+    Task.spawn(function* () {
+      yield SpecialPowers.pushPrefEnv({"set": [[PREF_PERMISSION_FAKE, true]]});
+
+      for (let testCase of gTests) {
+        info(testCase.desc);
+        yield testCase.run();
+      }
+    }).then(finish, ex => {
+     Cu.reportError(ex);
+     ok(false, "Unexpected Exception: " + ex);
+     finish();
+    });
+  }, {capture: true, once: true});
+  let rootDir = getRootDirectory(gTestPath);
+  rootDir = rootDir.replace("chrome://mochitests/content/",
+                            "https://example.com/");
+  content.location = rootDir + "get_user_media.html";
+}
--- a/browser/base/content/test/webrtc/head.js
+++ b/browser/base/content/test/webrtc/head.js
@@ -236,16 +236,28 @@ function expectNoObserverCalled(aIgnoreD
         }
       }
       resolve();
     });
     mm.sendAsyncMessage("Test:ExpectNoObserverCalled");
   });
 }
 
+function ignoreObserversCalled() {
+  return new Promise(resolve => {
+    let mm = _mm();
+    mm.addMessageListener("Test:ExpectNoObserverCalled:Reply",
+                          function listener() {
+      mm.removeMessageListener("Test:ExpectNoObserverCalled:Reply", listener);
+      resolve();
+    });
+    mm.sendAsyncMessage("Test:ExpectNoObserverCalled");
+  });
+}
+
 function promiseMessageReceived() {
   return new Promise((resolve, reject) => {
     let mm = _mm();
     mm.addMessageListener("Test:MessageReceived", function listener({data}) {
       mm.removeMessageListener("Test:MessageReceived", listener);
       resolve(data);
     });
     mm.sendAsyncMessage("Test:WaitForMessage");
@@ -434,17 +446,19 @@ function checkDeviceSelectors(aAudio, aV
 
   let screenSelector = document.getElementById("webRTC-selectWindowOrScreen");
   if (aScreen)
     ok(!screenSelector.hidden, "screen selector visible");
   else
     ok(screenSelector.hidden, "screen selector hidden");
 }
 
-function* checkSharingUI(aExpected, aWin = window) {
+// aExpected is for the current tab,
+// aExpectedGlobal is for all tabs.
+function* checkSharingUI(aExpected, aWin = window, aExpectedGlobal = null) {
   let doc = aWin.document;
   // First check the icon above the control center (i) icon.
   let identityBox = doc.getElementById("identity-box");
   ok(identityBox.hasAttribute("sharing"), "sharing attribute is set");
   let sharing = identityBox.getAttribute("sharing");
   if (aExpected.screen)
     is(sharing, "screen", "showing screen icon on the control center icon");
   else if (aExpected.video)
@@ -478,17 +492,17 @@ function* checkSharingUI(aExpected, aWin
       ok(!icon[0].classList.contains("in-use"),
          "if shown, the " + id + " icon should not have the in-use class");
       is(icon.length, 1, "should not show more than 1 " + id + " icon");
     }
   }
   aWin.gIdentityHandler._identityPopup.hidden = true;
 
   // Check the global indicators.
-  yield* assertWebRTCIndicatorStatus(aExpected);
+  yield* assertWebRTCIndicatorStatus(aExpectedGlobal || aExpected);
 }
 
 function* checkNotSharing() {
   Assert.deepEqual((yield getMediaCaptureState()), {},
                    "expected nothing to be shared");
 
   ok(!document.getElementById("identity-box").hasAttribute("sharing"),
      "no sharing indicator on the control center icon");
--- a/browser/modules/webrtcUI.jsm
+++ b/browser/modules/webrtcUI.jsm
@@ -149,16 +149,23 @@ this.webrtcUI = {
     webrtcUI.activePerms.delete(aBrowser.outerWindowID);
   },
 
   forgetStreamsFromBrowser(aBrowser) {
     this._streams = this._streams.filter(stream => stream.browser != aBrowser);
     webrtcUI.forgetActivePermissionsFromBrowser(aBrowser);
   },
 
+  forgetStreamsFromProcess(aProcessMM) {
+    // stream.processMM is null when e10s is disabled.
+    this._streams =
+      this._streams.filter(stream => stream.processMM &&
+                                     stream.processMM != aProcessMM);
+  },
+
   showSharingDoorhanger(aActiveStream) {
     let browserWindow = aActiveStream.browser.ownerGlobal;
     if (aActiveStream.tab) {
       browserWindow.gBrowser.selectedTab = aActiveStream.tab;
     } else {
       aActiveStream.browser.focus();
     }
     browserWindow.focus();
@@ -274,40 +281,50 @@ this.webrtcUI = {
         break;
       case "webrtc:StopRecording":
         stopRecording(aMessage.target, aMessage.data);
         break;
       case "webrtc:CancelRequest":
         removePrompt(aMessage.target, aMessage.data);
         break;
       case "webrtc:UpdatingIndicators":
-        webrtcUI._streams = [];
+        webrtcUI.forgetStreamsFromProcess(aMessage.target);
         break;
       case "webrtc:UpdateGlobalIndicators":
         updateIndicators(aMessage.data, aMessage.target);
         break;
       case "webrtc:UpdateBrowserIndicators":
         let id = aMessage.data.windowId;
+        aMessage.targetFrameLoader.QueryInterface(Ci.nsIFrameLoader);
+        let processMM =
+          aMessage.targetFrameLoader.messageManager.processMessageManager;
         let index;
         for (index = 0; index < webrtcUI._streams.length; ++index) {
-          if (webrtcUI._streams[index].state.windowId == id)
+          let stream = webrtcUI._streams[index];
+          if (stream.state.windowId == id && stream.processMM == processMM)
             break;
         }
         // If there's no documentURI, the update is actually a removal of the
         // stream, triggered by the recording-window-ended notification.
-        if (!aMessage.data.documentURI && index < webrtcUI._streams.length)
+        if (!aMessage.data.documentURI && index < webrtcUI._streams.length) {
           webrtcUI._streams.splice(index, 1);
-        else
-          webrtcUI._streams[index] = {browser: aMessage.target, state: aMessage.data};
+        } else {
+          webrtcUI._streams[index] = {
+            browser: aMessage.target,
+            processMM,
+            state: aMessage.data
+          };
+        }
         let tabbrowser = aMessage.target.ownerGlobal.gBrowser;
         if (tabbrowser)
           tabbrowser.setBrowserSharing(aMessage.target, aMessage.data);
         break;
       case "child-process-shutdown":
         webrtcUI.processIndicators.delete(aMessage.target);
+        webrtcUI.forgetStreamsFromProcess(aMessage.target);
         updateIndicators(null, null);
         break;
     }
   }
 };
 
 function getBrowserForWindow(aContentWindow) {
   return aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -94,56 +94,56 @@ OriginAttributes::SetFirstPartyDomain(co
   }
 
   mFirstPartyDomain = NS_ConvertUTF8toUTF16(aDomain);
 }
 
 void
 OriginAttributes::CreateSuffix(nsACString& aStr) const
 {
-  UniquePtr<URLParams> params(new URLParams());
+  URLParams params;
   nsAutoString value;
 
   //
   // Important: While serializing any string-valued attributes, perform a
   // release-mode assertion to make sure that they don't contain characters that
   // will break the quota manager when it uses the serialization for file
   // naming.
   //
 
   if (mAppId != nsIScriptSecurityManager::NO_APP_ID) {
     value.AppendInt(mAppId);
-    params->Set(NS_LITERAL_STRING("appId"), value);
+    params.Set(NS_LITERAL_STRING("appId"), value);
   }
 
   if (mInIsolatedMozBrowser) {
-    params->Set(NS_LITERAL_STRING("inBrowser"), NS_LITERAL_STRING("1"));
+    params.Set(NS_LITERAL_STRING("inBrowser"), NS_LITERAL_STRING("1"));
   }
 
   if (mUserContextId != nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID) {
     value.Truncate();
     value.AppendInt(mUserContextId);
-    params->Set(NS_LITERAL_STRING("userContextId"), value);
+    params.Set(NS_LITERAL_STRING("userContextId"), value);
   }
 
 
   if (mPrivateBrowsingId) {
     value.Truncate();
     value.AppendInt(mPrivateBrowsingId);
-    params->Set(NS_LITERAL_STRING("privateBrowsingId"), value);
+    params.Set(NS_LITERAL_STRING("privateBrowsingId"), value);
   }
 
   if (!mFirstPartyDomain.IsEmpty()) {
     MOZ_RELEASE_ASSERT(mFirstPartyDomain.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
-    params->Set(NS_LITERAL_STRING("firstPartyDomain"), mFirstPartyDomain);
+    params.Set(NS_LITERAL_STRING("firstPartyDomain"), mFirstPartyDomain);
   }
 
   aStr.Truncate();
 
-  params->Serialize(value);
+  params.Serialize(value);
   if (!value.IsEmpty()) {
     aStr.AppendLiteral("^");
     aStr.Append(NS_ConvertUTF16toUTF8(value));
   }
 
 // In debug builds, check the whole string for illegal characters too (just in case).
 #ifdef DEBUG
   nsAutoCString str;
@@ -250,21 +250,21 @@ OriginAttributes::PopulateFromSuffix(con
   if (aStr.IsEmpty()) {
     return true;
   }
 
   if (aStr[0] != '^') {
     return false;
   }
 
-  UniquePtr<URLParams> params(new URLParams());
-  params->ParseInput(Substring(aStr, 1, aStr.Length() - 1));
+  URLParams params;
+  params.ParseInput(Substring(aStr, 1, aStr.Length() - 1));
 
   PopulateFromSuffixIterator iterator(this);
-  return params->ForEach(iterator);
+  return params.ForEach(iterator);
 }
 
 bool
 OriginAttributes::PopulateFromOrigin(const nsACString& aOrigin,
                                      nsACString& aOriginNoSuffix)
 {
   // RFindChar is only available on nsCString.
   nsCString origin(aOrigin);
--- a/devtools/client/debugger/new/debugger.css
+++ b/devtools/client/debugger/new/debugger.css
@@ -197,17 +197,16 @@
   color: var(--theme-selection-color);
   cursor: pointer;
 }
 
 .landing-page .sidebar li:hover a,
 .landing-page .sidebar li:focus a {
   color: inherit;
 }
-
 :root.theme-light,
 :root .theme-light {
   --theme-search-overlays-semitransparent: rgba(221, 225, 228, 0.66);
 }
 
 * {
   box-sizing: border-box;
 }
@@ -1258,21 +1257,16 @@ menuseparator {
   font-weight: normal;
   white-space: pre-wrap;
 }
 
 .theme-dark .caption,
 .theme-light .caption {
   font-weight: normal;
 }
-/* vim:set ts=2 sw=2 sts=2 et: */
-
-/* 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/. */
 
 .search-container {
   position: absolute;
   top: 30px;
   left: 0;
   width: calc(100% - 1px);
   height: calc(100% - 31px);
   display: flex;
@@ -1355,50 +1349,51 @@ html[dir="rtl"] .arrow svg {
 html .arrow.expanded svg {
   transform: rotate(0deg);
 }
 
 .arrow.hidden {
   visibility: hidden;
 }
 .close-btn path {
-  fill: var(--theme-body-color);
+  fill: var(--theme-comment-alt);
 }
 
 .close-btn .close {
   cursor: pointer;
   width: 14px;
   height: 14px;
   padding: 2px;
   text-align: center;
   margin-top: 2px;
   line-height: 7px;
   transition: all 0.25s easeinout;
 }
 
 .close-btn .close svg {
-  width: 6px;
+  width: 8px;
 }
 
 .close-btn:hover {
   display: block;
 }
 
 .close-btn:hover .close {
   background: var(--theme-selection-background);
   border-radius: 2px;
 }
 
 .close-btn:hover .close path {
   fill: white;
 }
 
 .close-btn-big {
-  padding: 13px;
-  width: 40px;
+  padding: 11px;
+  margin-right: 7px;
+  width: 27px;
   height: 40px;
 }
 
 .close-btn-big .close {
   cursor: pointer;
   display: inline-block;
   padding: 2px;
   text-align: center;
@@ -1409,121 +1404,195 @@ html .arrow.expanded svg {
 }
 
 .close-btn-big .close svg {
   width: 9px;
   height: 9px;
 }
 
 .close-btn-big .close:hover {
-  background: var(--theme-selection-background);
   border-radius: 2px;
 }
 
-.close-btn-big .close:hover path {
-  fill: white;
-}
 .search-field {
   width: calc(100% - 1px);
-  height: 40px;
-  background-color: var(--theme-body-background);
+  height: 27px;
+  background-color: var(--theme-toolbar-background);
   border-bottom: 1px solid var(--theme-splitter-color);
+  padding-right: 10px;
   display: flex;
   flex-shrink: 0;
 }
 
+.search-field.big {
+  height: 40px;
+  font-size: 14px;
+}
+
+.search-field.big input {
+  font-size: 14px;
+}
+
 .search-field i {
   display: block;
-  padding: 13px;
-  width: 40px;
+  padding: 0;
+  width: 16px;
 }
 
 .search-field i svg {
   width: 16px;
 }
 
+.search-field.big input {
+  line-height: 40px;
+}
+
 .search-field input {
   border: none;
   line-height: 30px;
-  font-size: 14px;
-  background-color: var(--theme-body-background);
-  color: var(--theme-comment-alt);
+  background-color: var(--theme-toolbar-background);
+  color: var(--theme-body-color-inactive);
   width: calc(100% - 38px);
   flex: 1;
 }
 
 .theme-dark .search-field input {
-  color: var(--theme-comment-alt);
-}
-
-.search-field .magnifying-glass {
-  background-color: var(--theme-body-background);
+  color: var(--theme-body-color-inactive);
+}
+
+.search-field i.magnifying-glass,
+.search-field i.sad-face {
+  padding: 6px;
+  width: 24px;
+}
+
+.search-field.big i.magnifying-glass,
+.search-field.big i.sad-face {
+  padding: 14px;
+  width: 40px;
 }
 
 .search-field .magnifying-glass path,
 .search-field .magnifying-glass ellipse {
   stroke: var(--theme-splitter-color);
 }
 
+.search-field ::-webkit-input-placeholder {
+  color: var(--theme-body-color-inactive);
+}
+
 .search-field input::placeholder {
-  color: var(--theme-comment-alt);
+  color: var(--theme-body-color-inactive);
 }
 
 .search-field input:focus {
   outline-width: 0;
 }
 
 .search-field input.empty {
   color: var(--theme-highlight-orange);
 }
 
+.search-field.big .summary {
+  line-height: 40px;
+}
+
 .search-field .summary {
-  line-height: 40px;
+  line-height: 27px;
   padding-right: 10px;
   color: var(--theme-body-color-inactive);
 }
+
 .result-list {
   list-style: none;
   width: 100%;
-  max-height: calc(100% - 32px);
+  background-color: var(--theme-toolbar-background);
   margin: 0px;
   padding: 0px;
   overflow: auto;
 }
 
+.result-list.big {
+  max-height: calc(100% - 32px);
+}
+
 .result-list * {
   -moz-user-select: none;
   user-select: none;
 }
 
 .result-list li {
-  border: 2px solid var(--theme-splitter-color);
+  color: var(--theme-body-color);
   background-color: var(--theme-tab-toolbar-background);
+  padding: 4px 13px;
+  display: flex;
+  justify-content: space-between;
+}
+
+.result-list li:first-child {
+  border-top: none;
+}
+
+.result-list.big li {
   padding: 10px;
-  margin: 10px;
+  flex-direction: column;
+  border-bottom: 1px solid var(--theme-splitter-color);
 }
 
 .result-list li:hover {
   background: var(--theme-tab-toolbar-background);
   cursor: pointer;
 }
 
 .result-list li.selected {
-  border: 2px solid var(--theme-selection-background);
+  border: 1px solid var(--theme-selection-background);
+}
+
+.result-list.big li.selected {
+  padding-left: 9px;
+  padding-top: 9px;
+}
+
+.search-bar .result-list li.selected {
+  background-color: var(--theme-selection-background);
+  color: white;
 }
 
 .result-list li .title {
   line-height: 1.5em;
   word-break: break-all;
 }
 
-.result-list li .subtitle {
+.result-list li.selected .title {
+  color: white;
+}
+
+.result-list.big li.selected .title {
+  color: var(--theme-body-color);
+}
+
+.result-list.big li .subtitle {
+  word-break: break-all;
+  color: var(--theme-body-color-inactive);
+}
+
+.result-list.big li .subtitle {
   line-height: 1.5em;
-  color: grey;
-  word-break: break-all;
+}
+
+.search-bar .result-list li.selected .subtitle {
+  color: white;
+}
+
+.search-bar .result-list {
+  border-bottom: 1px solid var(--theme-splitter-color);
+}
+
+.theme-dark .result-list {
+  background-color: var(--theme-body-background);
 }
 
 .autocomplete {
   flex: 1;
   width: 100%;
 }
 
 .autocomplete .no-result-msg {
@@ -1637,66 +1706,79 @@ html[dir="rtl"] .tree .node > div {
   flex: 1;
   display: flex;
   overflow: hidden;
 }
 
 .theme-dark .sources-list .tree .node:not(.focused) svg {
   fill: var(--theme-comment);
 }
+
+.theme-dark .source-list .tree .node.focused {
+  background-color: var(--theme-tab-toolbar-background);
+}
 .toggle-button-start,
 .toggle-button-end {
   transform: translate(0, 2px);
   transition: transform 0.25s ease-in-out;
   cursor: pointer;
   padding: 4px 2px;
 }
 
 .toggle-button-start svg,
 .toggle-button-end svg {
-  width: 14px;
+  width: 16px;
   fill: var(--theme-comment);
 }
 
 .theme-dark .toggle-button-start svg,
 .theme-dark .toggle-button-end svg {
   fill: var(--theme-comment-alt);
 }
 
 .toggle-button-end {
   margin-left: auto;
+  margin-right: 5px;
+}
+
+.toggle-button-start {
+  margin-left: 5px;
 }
 
 html:not([dir="rtl"]) .toggle-button-end svg,
 html[dir="rtl"] .toggle-button-start svg {
   transform: rotate(180deg);
 }
 
 html .toggle-button-end.vertical svg {
   transform: rotate(-90deg);
 }
 
+.toggle-button-end.vertical {
+  margin-bottom: 2px;
+}
+
 .toggle-button-start.collapsed,
 .toggle-button-end.collapsed {
   transform: rotate(180deg);
 }
 
 .source-footer {
-  background: var(--theme-body-background);
+  background: var(--theme-toolbar-background);
   border-top: 1px solid var(--theme-splitter-color);
   position: absolute;
   display: flex;
   bottom: 0;
   left: 0;
   right: 1px;
   opacity: 1;
   z-index: 100;
   -moz-user-select: none;
   user-select: none;
-  height: 30px;
+  height: 27px;
   box-sizing: border-box;
 }
 
 .source-footer .commands {
   display: flex;
 }
 
 .source-footer .commands * {
@@ -1739,34 +1821,43 @@ html .toggle-button-end.vertical svg {
   color: var(--theme-body-color);
 }
 
 .coverage-on .source-footer .commands .coverage {
   color: var(--theme-highlight-blue);
   border: 1px solid var(--theme-body-color-inactive);
   border-radius: 2px;
 }
+
 .search-bar {
   display: flex;
   flex-direction: column;
   max-height: 50%;
 }
 
+.search-bar .search-field {
+  padding-left: 7px;
+}
+
+.search-bar .close-btn {
+  padding: 6px;
+}
+
 .search-bottom-bar * {
   -moz-user-select: none;
   user-select: none;
 }
 
 .search-bottom-bar {
   display: flex;
   flex-shrink: 0;
   justify-content: space-between;
   width: calc(100% - 1px);
-  height: 40px;
-  background-color: var(--theme-body-background);
+  height: 27px;
+  background-color: var(--theme-toolbar-background);
   border-bottom: 1px solid var(--theme-splitter-color);
   padding: 0 13px;
 }
 
 .search-bottom-bar button:focus {
   outline: none;
 }
 
@@ -1820,18 +1911,19 @@ html .toggle-button-end.vertical svg {
 }
 
 .search-bottom-bar .search-type-toggles {
   display: flex;
   align-items: center;
 }
 
 .search-bottom-bar .search-type-toggles .search-toggle-title {
-  color: var(--theme-comment-alt);
-  font-size: 12px;
+  color: var(--theme-body-color-inactive);
+  font-size: 11px;
+  font-weight: normal;
   margin: 0;
 }
 
 .search-bottom-bar .search-type-toggles .search-type-btn {
   margin: 0 6px;
   border: none;
   background: transparent;
   color: var(--theme-comment-alt);
@@ -1849,54 +1941,17 @@ html .toggle-button-end.vertical svg {
   color: var(--theme-selection-background);
 }
 
 .theme-dark .search-bottom-bar .search-type-toggles .search-type-btn.active {
   color: white;
 }
 
 .search-bar .result-list {
-  max-height: calc(100% - 80px);
-  border-bottom: 1px solid var(--theme-splitter-color);
-  background-color: var(--theme-body-background);
-}
-
-.search-bar .result-list li {
-  border: none;
-  color: var(--theme-body-color);
-  border-bottom: 1px solid var(--theme-splitter-color);
-  padding: 4px 13px;
-  margin: 0;
-  display: flex;
-  justify-content: space-between;
-}
-
-.search-bar .result-list li:first-child {
-  border-top: none;
-}
-
-.search-bar .result-list li:last-child {
-  border-bottom: none;
-}
-
-.search-bar .result-list li.selected {
-  background-color: var(--theme-selection-background);
-  color: white;
-}
-
-.search-bar .result-list li .subtitle {
-  font-weight: lighter;
-}
-
-.search-bar .result-list li.selected .subtitle {
-  color: white;
-}
-
-.theme-dark .result-list {
-  background-color: var(--theme-body-background);
+  max-height: 230px;
 }
 .popover {
   position: fixed;
   z-index: 4;
 }
 
 .popover-gap {
   height: 10px;
@@ -2171,23 +2226,23 @@ html[dir="rtl"] .editor-mount {
   font-size: 12px;
   padding: 0px 20px;
   color: var(--theme-highlight-blue);
 }
 
 .input-expression::-webkit-input-placeholder {
   text-align: center;
   font-style: italic;
-  color: var(--theme-body-color-inactive);
+  color: var(--theme-comment-alt);
 }
 
 .input-expression::placeholder {
   text-align: center;
   font-style: italic;
-  color: var(--theme-body-color-inactive);
+  color: var(--theme-comment-alt);
   opacity: 1;
 }
 
 .input-expression:focus {
   outline: none;
   cursor: text;
 }
 
@@ -2589,16 +2644,17 @@ html .breakpoints-list .breakpoint.pause
   flex: 0 0 30px;
   border-bottom: 1px solid var(--theme-splitter-color);
   display: flex;
   height: 30px;
   overflow: hidden;
   position: sticky;
   top: 0;
   z-index: 1;
+  background-color: var(--theme-body-background);
 }
 
 .theme-dark .command-bar {
   background-color: var(--theme-tab-toolbar-background);
 }
 
 .command-bar > button {
   -webkit-appearance: none;
@@ -2812,17 +2868,17 @@ html[dir="rtl"] .dropdown {
   height: 30px;
   display: inline-flex;
   align-items: center;
   position: relative;
   transition: all 0.25s ease;
   min-width: 40px;
   overflow: hidden;
   padding: 6px;
-  margin-inline-start: 8px;
+  margin-inline-start: 3px;
   margin-top: 2px;
 }
 
 .source-tab:hover {
   background-color: var(--theme-toolbar-background-alt);
   border-color: var(--theme-splitter-color);
   cursor: pointer;
 }
@@ -2874,14 +2930,11 @@ html[dir="rtl"] .dropdown {
 
 .source-tab:hover .close-btn {
   visibility: visible;
 }
 
 .source-tab .close-btn .close {
   padding: 0;
   margin-top: 0;
-  line-height: 0;
-  line-height: 13px;
-  display: inline-block;
-}
-
-/*# sourceMappingURL=debugger.css.map*/
+  display: inline-flex;
+  justify-content: center;
+}
--- a/devtools/client/debugger/new/debugger.js
+++ b/devtools/client/debugger/new/debugger.js
@@ -6,147 +6,147 @@
 	else {
 		var a = typeof exports === 'object' ? factory(require("devtools/client/shared/vendor/react"), require("Services"), require("devtools/client/shared/vendor/react-dom"), require("devtools/shared/flags")) : factory(root["devtools/client/shared/vendor/react"], root["Services"], root["devtools/client/shared/vendor/react-dom"], root["devtools/shared/flags"]);
 		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
 	}
 })(this, function(__WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_29__, __WEBPACK_EXTERNAL_MODULE_31__, __WEBPACK_EXTERNAL_MODULE_121__) {
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
-/******/
+
 /******/ 	// The require function
 /******/ 	function __webpack_require__(moduleId) {
-/******/
+
 /******/ 		// Check if module is in cache
 /******/ 		if(installedModules[moduleId])
 /******/ 			return installedModules[moduleId].exports;
-/******/
+
 /******/ 		// Create a new module (and put it into the cache)
 /******/ 		var module = installedModules[moduleId] = {
 /******/ 			exports: {},
 /******/ 			id: moduleId,
 /******/ 			loaded: false
 /******/ 		};
-/******/
+
 /******/ 		// Execute the module function
 /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
-/******/
+
 /******/ 		// Flag the module as loaded
 /******/ 		module.loaded = true;
-/******/
+
 /******/ 		// Return the exports of the module
 /******/ 		return module.exports;
 /******/ 	}
-/******/
-/******/
+
+
 /******/ 	// expose the modules object (__webpack_modules__)
 /******/ 	__webpack_require__.m = modules;
-/******/
+
 /******/ 	// expose the module cache
 /******/ 	__webpack_require__.c = installedModules;
-/******/
+
 /******/ 	// __webpack_public_path__
 /******/ 	__webpack_require__.p = "/assets/build";
-/******/
+
 /******/ 	// Load entry module and return exports
 /******/ 	return __webpack_require__(0);
 /******/ })
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ function(module, exports, __webpack_require__) {
 
 	module.exports = __webpack_require__(1);
 
 
 /***/ },
 /* 1 */
 /***/ function(module, exports, __webpack_require__) {
 
 	"use strict";
-	
+
 	var React = __webpack_require__(2);
-	
+
 	var _require = __webpack_require__(3),
 	    bindActionCreators = _require.bindActionCreators,
 	    combineReducers = _require.combineReducers;
-	
+
 	var ReactDOM = __webpack_require__(22);
-	
+
 	var _require2 = __webpack_require__(23),
 	    getClient = _require2.getClient,
 	    firefox = _require2.firefox;
-	
+
 	var _require3 = __webpack_require__(131),
 	    renderRoot = _require3.renderRoot,
 	    bootstrap = _require3.bootstrap,
 	    L10N = _require3.L10N,
 	    unmountRoot = _require3.unmountRoot;
-	
+
 	var _require4 = __webpack_require__(65),
 	    getValue = _require4.getValue,
 	    isFirefoxPanel = _require4.isFirefoxPanel;
-	
+
 	var configureStore = __webpack_require__(189);
-	
+
 	var _require5 = __webpack_require__(225),
 	    onConnect = _require5.onConnect,
 	    onFirefoxConnect = _require5.onFirefoxConnect;
-	
+
 	var reducers = __webpack_require__(227);
 	var selectors = __webpack_require__(242);
-	
+
 	var App = __webpack_require__(243);
-	
+
 	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__(244), store.dispatch);
-	
+
 	if (!isFirefoxPanel()) {
 	  window.L10N = L10N;
 	  window.L10N.setBundle(__webpack_require__(756));
 	}
-	
+
 	window.appStore = store;
-	
+
 	// Expose the bound actions so external things can do things like
 	// selecting a source.
 	window.actions = {
 	  selectSource: actions.selectSource,
 	  selectSourceURL: actions.selectSourceURL
 	};
-	
+
 	// Globals needed for mocha integration tests
 	window.getGlobalsForTesting = () => {
 	  return {
 	    debuggerStore: store,
 	    launchpadStore: window.launchpadStore,
 	    selectors,
 	    actions,
 	    threadClient: firefox.getThreadClient(),
 	    target: firefox.getTabTarget()
 	  };
 	};
-	
+
 	if (isFirefoxPanel()) {
 	  var sourceMap = __webpack_require__(246);
 	  var prettyPrint = __webpack_require__(256);
-	
+
 	  module.exports = {
 	    bootstrap: (_ref) => {
 	      var threadClient = _ref.threadClient,
 	          tabTarget = _ref.tabTarget,
 	          toolbox = _ref.toolbox;
-	
+
 	      firefox.setThreadClient(threadClient);
 	      firefox.setTabTarget(tabTarget);
 	      renderRoot(React, ReactDOM, App, store);
 	      firefox.initPage(actions);
 	      return onFirefoxConnect(actions, firefox);
 	    },
 	    destroy: () => {
 	      unmountRoot(ReactDOM);
@@ -168,92 +168,92 @@ return /******/ (function(modules) { // 
 
 	module.exports = __WEBPACK_EXTERNAL_MODULE_2__;
 
 /***/ },
 /* 3 */
 /***/ function(module, exports, __webpack_require__) {
 
 	'use strict';
-	
+
 	exports.__esModule = true;
 	exports.compose = exports.applyMiddleware = exports.bindActionCreators = exports.combineReducers = exports.createStore = undefined;
-	
+
 	var _createStore = __webpack_require__(4);
-	
+
 	var _createStore2 = _interopRequireDefault(_createStore);
-	
+
 	var _combineReducers = __webpack_require__(17);
-	
+
 	var _combineReducers2 = _interopRequireDefault(_combineReducers);
-	
+
 	var _bindActionCreators = __webpack_require__(19);
-	
+
 	var _bindActionCreators2 = _interopRequireDefault(_bindActionCreators);
-	
+
 	var _applyMiddleware = __webpack_require__(20);
-	
+
 	var _applyMiddleware2 = _interopRequireDefault(_applyMiddleware);
-	
+
 	var _compose = __webpack_require__(21);
-	
+
 	var _compose2 = _interopRequireDefault(_compose);
-	
+
 	var _warning = __webpack_require__(18);
-	
+
 	var _warning2 = _interopRequireDefault(_warning);
-	
+
 	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
-	
+
 	/*
 	* This is a dummy function to check if the function name has been altered by minification.
 	* If the function has been minified and NODE_ENV !== 'production', warn the user.
 	*/
 	function isCrushed() {}
-	
+
 	if (false) {
 	  (0, _warning2["default"])('You are currently using minified code outside of NODE_ENV === \'production\'. ' + 'This means that you are running a slower development build of Redux. ' + 'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' + 'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' + 'to ensure you have the correct code for your production build.');
 	}
-	
+
 	exports.createStore = _createStore2["default"];
 	exports.combineReducers = _combineReducers2["default"];
 	exports.bindActionCreators = _bindActionCreators2["default"];
 	exports.applyMiddleware = _applyMiddleware2["default"];
 	exports.compose = _compose2["default"];
 
 /***/ },
 /* 4 */
 /***/ function(module, exports, __webpack_require__) {
 
 	'use strict';
-	
+
 	exports.__esModule = true;
 	exports.ActionTypes = undefined;
 	exports["default"] = createStore;
-	
+
 	var _isPlainObject = __webpack_require__(5);
-	
+
 	var _isPlainObject2 = _interopRequireDefault(_isPlainObject);
-	
+
 	var _symbolObservable = __webpack_require__(15);
-	
+
 	var _symbolObservable2 = _interopRequireDefault(_symbolObservable);
-	
+
 	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
-	
+
 	/**
 	 * These are private action types reserved by Redux.
 	 * For any unknown actions, you must return the current state.
 	 * If the current state is undefined, you must return the initial state.
 	 * Do not reference these action types directly in your code.
 	 */
 	var ActionTypes = exports.ActionTypes = {
 	  INIT: '@@redux/INIT'
 	};
-	
+
 	/**
 	 * Creates a Redux store that holds the state tree.
 	 * The only way to change the data in the store is to call `dispatch()` on it.
 	 *
 	 * There should only be a single store in your app. To specify how different
 	 * parts of the state tree respond to actions, you may combine several reducers
 	 * into a single reducer function by using `combineReducers`.
 	 *
@@ -271,55 +271,55 @@ return /******/ (function(modules) { // 
 	 * time travel, persistence, etc. The only store enhancer that ships with Redux
 	 * is `applyMiddleware()`.
 	 *
 	 * @returns {Store} A Redux store that lets you read the state, dispatch actions
 	 * and subscribe to changes.
 	 */
 	function createStore(reducer, initialState, enhancer) {
 	  var _ref2;
-	
+
 	  if (typeof initialState === 'function' && typeof enhancer === 'undefined') {
 	    enhancer = initialState;
 	    initialState = undefined;
 	  }
-	
+
 	  if (typeof enhancer !== 'undefined') {
 	    if (typeof enhancer !== 'function') {
 	      throw new Error('Expected the enhancer to be a function.');
 	    }
-	
+
 	    return enhancer(createStore)(reducer, initialState);
 	  }
-	
+
 	  if (typeof reducer !== 'function') {
 	    throw new Error('Expected the reducer to be a function.');
 	  }
-	
+
 	  var currentReducer = reducer;
 	  var currentState = initialState;
 	  var currentListeners = [];
 	  var nextListeners = currentListeners;
 	  var isDispatching = false;
-	
+
 	  function ensureCanMutateNextListeners() {
 	    if (nextListeners === currentListeners) {
 	      nextListeners = currentListeners.slice();
 	    }
 	  }
-	
+
 	  /**
 	   * Reads the state tree managed by the store.
 	   *
 	   * @returns {any} The current state tree of your application.
 	   */
 	  function getState() {
 	    return currentState;
 	  }
-	
+
 	  /**
 	   * Adds a change listener. It will be called any time an action is dispatched,
 	   * and some part of the state tree may potentially have changed. You may then
 	   * call `getState()` to read the current state tree inside the callback.
 	   *
 	   * You may call `dispatch()` from a change listener, with the following
 	   * caveats:
 	   *
@@ -337,35 +337,35 @@ return /******/ (function(modules) { // 
 	   *
 	   * @param {Function} listener A callback to be invoked on every dispatch.
 	   * @returns {Function} A function to remove this change listener.
 	   */
 	  function subscribe(listener) {
 	    if (typeof listener !== 'function') {
 	      throw new Error('Expected listener to be a function.');
 	    }
-	
+
 	    var isSubscribed = true;
-	
+
 	    ensureCanMutateNextListeners();
 	    nextListeners.push(listener);
-	
+
 	    return function unsubscribe() {
 	      if (!isSubscribed) {
 	        return;
 	      }
-	
+
 	      isSubscribed = false;
-	
+
 	      ensureCanMutateNextListeners();
 	      var index = nextListeners.indexOf(listener);
 	      nextListeners.splice(index, 1);
 	    };
 	  }
-	
+
 	  /**
 	   * Dispatches an action. It is the only way to trigger a state change.
 	   *
 	   * The `reducer` function, used to create the store, will be called with the
 	   * current state tree and the given `action`. Its return value will
 	   * be considered the **next** state of the tree, and the change listeners
 	   * will be notified.
 	   *
@@ -385,136 +385,136 @@ return /******/ (function(modules) { // 
 	   *
 	   * Note that, if you use a custom middleware, it may wrap `dispatch()` to
 	   * return something else (for example, a Promise you can await).
 	   */
 	  function dispatch(action) {
 	    if (!(0, _isPlainObject2["default"])(action)) {
 	      throw new Error('Actions must be plain objects. ' + 'Use custom middleware for async actions.');
 	    }
-	
+
 	    if (typeof action.type === 'undefined') {
 	      throw new Error('Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?');
 	    }
-	
+
 	    if (isDispatching) {
 	      throw new Error('Reducers may not dispatch actions.');
 	    }
-	
+
 	    try {
 	      isDispatching = true;
 	      currentState = currentReducer(currentState, action);
 	    } finally {
 	      isDispatching = false;
 	    }
-	
+
 	    var listeners = currentListeners = nextListeners;
 	    for (var i = 0; i < listeners.length; i++) {
 	      listeners[i]();
 	    }
-	
+
 	    return action;
 	  }
-	
+
 	  /**
 	   * Replaces the reducer currently used by the store to calculate the state.
 	   *
 	   * You might need this if your app implements code splitting and you want to
 	   * load some of the reducers dynamically. You might also need this if you
 	   * implement a hot reloading mechanism for Redux.
 	   *
 	   * @param {Function} nextReducer The reducer for the store to use instead.
 	   * @returns {void}
 	   */
 	  function replaceReducer(nextReducer) {
 	    if (typeof nextReducer !== 'function') {
 	      throw new Error('Expected the nextReducer to be a function.');
 	    }
-	
+
 	    currentReducer = nextReducer;
 	    dispatch({ type: ActionTypes.INIT });
 	  }
-	
+
 	  /**
 	   * Interoperability point for observable/reactive libraries.
 	   * @returns {observable} A minimal observable of state changes.
 	   * For more information, see the observable proposal:
 	   * https://github.com/zenparsing/es-observable
 	   */
 	  function observable() {
 	    var _ref;
-	
+
 	    var outerSubscribe = subscribe;
 	    return _ref = {
 	      /**
 	       * The minimal observable subscription method.
 	       * @param {Object} observer Any object that can be used as an observer.
 	       * The observer object should have a `next` method.
 	       * @returns {subscription} An object with an `unsubscribe` method that can
 	       * be used to unsubscribe the observable from the store, and prevent further
 	       * emission of values from the observable.
 	       */
-	
+
 	      subscribe: function subscribe(observer) {
 	        if (typeof observer !== 'object') {
 	          throw new TypeError('Expected the observer to be an object.');
 	        }
-	
+
 	        function observeState() {
 	          if (observer.next) {
 	            observer.next(getState());
 	          }
 	        }
-	
+
 	        observeState();
 	        var unsubscribe = outerSubscribe(observeState);
 	        return { unsubscribe: unsubscribe };
 	      }
 	    }, _ref[_symbolObservable2["default"]] = function () {
 	      return this;
 	    }, _ref;
 	  }
-	
+
 	  // When a store is created, an "INIT" action is dispatched so that every
 	  // reducer returns their initial state. This effectively populates
 	  // the initial state tree.
 	  dispatch({ type: ActionTypes.INIT });
-	
+
 	  return _ref2 = {
 	    dispatch: dispatch,
 	    subscribe: subscribe,
 	    getState: getState,
 	    replaceReducer: replaceReducer
 	  }, _ref2[_symbolObservable2["default"]] = observable, _ref2;
 	}
 
 /***/ },
 /* 5 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var baseGetTag = __webpack_require__(6),
 	    getPrototype = __webpack_require__(12),
 	    isObjectLike = __webpack_require__(14);
-	
+
 	/** `Object#toString` result references. */
 	var objectTag = '[object Object]';
-	
+
 	/** Used for built-in method references. */
 	var funcProto = Function.prototype,
 	    objectProto = Object.prototype;
-	
+
 	/** Used to resolve the decompiled source of functions. */
 	var funcToString = funcProto.toString;
-	
+
 	/** Used to check objects for own properties. */
 	var hasOwnProperty = objectProto.hasOwnProperty;
-	
+
 	/** Used to infer the `Object` constructor. */
 	var objectCtorString = funcToString.call(Object);
-	
+
 	/**
 	 * Checks if `value` is a plain object, that is, an object created by the
 	 * `Object` constructor or one with a `[[Prototype]]` of `null`.
 	 *
 	 * @static
 	 * @memberOf _
 	 * @since 0.8.0
 	 * @category Lang
@@ -545,181 +545,181 @@ return /******/ (function(modules) { // 
 	  var proto = getPrototype(value);
 	  if (proto === null) {
 	    return true;
 	  }
 	  var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
 	  return typeof Ctor == 'function' && Ctor instanceof Ctor &&
 	    funcToString.call(Ctor) == objectCtorString;
 	}
-	
+
 	module.exports = isPlainObject;
 
 
 /***/ },
 /* 6 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var Symbol = __webpack_require__(7),
 	    getRawTag = __webpack_require__(10),
 	    objectToString = __webpack_require__(11);
-	
+
 	/** `Object#toString` result references. */
 	var nullTag = '[object Null]',
 	    undefinedTag = '[object Undefined]';
-	
+
 	/** Built-in value references. */
 	var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
-	
+
 	/**
 	 * The base implementation of `getTag` without fallbacks for buggy environments.
 	 *
 	 * @private
 	 * @param {*} value The value to query.
 	 * @returns {string} Returns the `toStringTag`.
 	 */
 	function baseGetTag(value) {
 	  if (value == null) {
 	    return value === undefined ? undefinedTag : nullTag;
 	  }
 	  return (symToStringTag && symToStringTag in Object(value))
 	    ? getRawTag(value)
 	    : objectToString(value);
 	}
-	
+
 	module.exports = baseGetTag;
 
 
 /***/ },
 /* 7 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var root = __webpack_require__(8);
-	
+
 	/** Built-in value references. */
 	var Symbol = root.Symbol;
-	
+
 	module.exports = Symbol;
 
 
 /***/ },
 /* 8 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var freeGlobal = __webpack_require__(9);
-	
+
 	/** Detect free variable `self`. */
 	var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
-	
+
 	/** Used as a reference to the global object. */
 	var root = freeGlobal || freeSelf || Function('return this')();
-	
+
 	module.exports = root;
 
 
 /***/ },
 /* 9 */
 /***/ function(module, exports) {
 
 	/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */
 	var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
-	
+
 	module.exports = freeGlobal;
-	
+
 	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
 
 /***/ },
 /* 10 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var Symbol = __webpack_require__(7);
-	
+
 	/** Used for built-in method references. */
 	var objectProto = Object.prototype;
-	
+
 	/** Used to check objects for own properties. */
 	var hasOwnProperty = objectProto.hasOwnProperty;
-	
+
 	/**
 	 * Used to resolve the
 	 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 	 * of values.
 	 */
 	var nativeObjectToString = objectProto.toString;
-	
+
 	/** Built-in value references. */
 	var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
-	
+
 	/**
 	 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
 	 *
 	 * @private
 	 * @param {*} value The value to query.
 	 * @returns {string} Returns the raw `toStringTag`.
 	 */
 	function getRawTag(value) {
 	  var isOwn = hasOwnProperty.call(value, symToStringTag),
 	      tag = value[symToStringTag];
-	
+
 	  try {
 	    value[symToStringTag] = undefined;
 	    var unmasked = true;
 	  } catch (e) {}
-	
+
 	  var result = nativeObjectToString.call(value);
 	  if (unmasked) {
 	    if (isOwn) {
 	      value[symToStringTag] = tag;
 	    } else {
 	      delete value[symToStringTag];
 	    }
 	  }
 	  return result;
 	}
-	
+
 	module.exports = getRawTag;
 
 
 /***/ },
 /* 11 */
 /***/ function(module, exports) {
 
 	/** Used for built-in method references. */
 	var objectProto = Object.prototype;
-	
+
 	/**
 	 * Used to resolve the
 	 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 	 * of values.
 	 */
 	var nativeObjectToString = objectProto.toString;
-	
+
 	/**
 	 * Converts `value` to a string using `Object.prototype.toString`.
 	 *
 	 * @private
 	 * @param {*} value The value to convert.
 	 * @returns {string} Returns the converted string.
 	 */
 	function objectToString(value) {
 	  return nativeObjectToString.call(value);
 	}
-	
+
 	module.exports = objectToString;
 
 
 /***/ },
 /* 12 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var overArg = __webpack_require__(13);
-	
+
 	/** Built-in value references. */
 	var getPrototype = overArg(Object.getPrototypeOf, Object);
-	
+
 	module.exports = getPrototype;
 
 
 /***/ },
 /* 13 */
 /***/ function(module, exports) {
 
 	/**
@@ -730,17 +730,17 @@ return /******/ (function(modules) { // 
 	 * @param {Function} transform The argument transform.
 	 * @returns {Function} Returns the new function.
 	 */
 	function overArg(func, transform) {
 	  return function(arg) {
 	    return func(transform(arg));
 	  };
 	}
-	
+
 	module.exports = overArg;
 
 
 /***/ },
 /* 14 */
 /***/ function(module, exports) {
 
 	/**
@@ -765,121 +765,121 @@ return /******/ (function(modules) { // 
 	 * // => false
 	 *
 	 * _.isObjectLike(null);
 	 * // => false
 	 */
 	function isObjectLike(value) {
 	  return value != null && typeof value == 'object';
 	}
-	
+
 	module.exports = isObjectLike;
 
 
 /***/ },
 /* 15 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* WEBPACK VAR INJECTION */(function(global) {/* global window */
 	'use strict';
-	
+
 	module.exports = __webpack_require__(16)(global || window || this);
-	
+
 	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
 
 /***/ },
 /* 16 */
 /***/ function(module, exports) {
 
 	'use strict';
-	
+
 	module.exports = function symbolObservablePonyfill(root) {
 		var result;
 		var Symbol = root.Symbol;
-	
+
 		if (typeof Symbol === 'function') {
 			if (Symbol.observable) {
 				result = Symbol.observable;
 			} else {
 				result = Symbol('observable');
 				Symbol.observable = result;
 			}
 		} else {
 			result = '@@observable';
 		}
-	
+
 		return result;
 	};
 
 
 /***/ },
 /* 17 */
 /***/ function(module, exports, __webpack_require__) {
 
 	'use strict';
-	
+
 	exports.__esModule = true;
 	exports["default"] = combineReducers;
-	
+
 	var _createStore = __webpack_require__(4);
-	
+
 	var _isPlainObject = __webpack_require__(5);
-	
+
 	var _isPlainObject2 = _interopRequireDefault(_isPlainObject);
-	
+
 	var _warning = __webpack_require__(18);
-	
+
 	var _warning2 = _interopRequireDefault(_warning);
-	
+
 	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
-	
+
 	function getUndefinedStateErrorMessage(key, action) {
 	  var actionType = action && action.type;
 	  var actionName = actionType && '"' + actionType.toString() + '"' || 'an action';
-	
+
 	  return 'Given action ' + actionName + ', reducer "' + key + '" returned undefined. ' + 'To ignore an action, you must explicitly return the previous state.';
 	}
-	
+
 	function getUnexpectedStateShapeWarningMessage(inputState, reducers, action) {
 	  var reducerKeys = Object.keys(reducers);
 	  var argumentName = action && action.type === _createStore.ActionTypes.INIT ? 'initialState argument passed to createStore' : 'previous state received by the reducer';
-	
+
 	  if (reducerKeys.length === 0) {
 	    return 'Store does not have a valid reducer. Make sure the argument passed ' + 'to combineReducers is an object whose values are reducers.';
 	  }
-	
+
 	  if (!(0, _isPlainObject2["default"])(inputState)) {
 	    return 'The ' + argumentName + ' has unexpected type of "' + {}.toString.call(inputState).match(/\s([a-z|A-Z]+)/)[1] + '". Expected argument to be an object with the following ' + ('keys: "' + reducerKeys.join('", "') + '"');
 	  }
-	
+
 	  var unexpectedKeys = Object.keys(inputState).filter(function (key) {
 	    return !reducers.hasOwnProperty(key);
 	  });
-	
+
 	  if (unexpectedKeys.length > 0) {
 	    return 'Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('"' + unexpectedKeys.join('", "') + '" found in ' + argumentName + '. ') + 'Expected to find one of the known reducer keys instead: ' + ('"' + reducerKeys.join('", "') + '". Unexpected keys will be ignored.');
 	  }
 	}
-	
+
 	function assertReducerSanity(reducers) {
 	  Object.keys(reducers).forEach(function (key) {
 	    var reducer = reducers[key];
 	    var initialState = reducer(undefined, { type: _createStore.ActionTypes.INIT });
-	
+
 	    if (typeof initialState === 'undefined') {
 	      throw new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined.');
 	    }
-	
+
 	    var type = '@@redux/PROBE_UNKNOWN_ACTION_' + Math.random().toString(36).substring(7).split('').join('.');
 	    if (typeof reducer(undefined, { type: type }) === 'undefined') {
 	      throw new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + _createStore.ActionTypes.INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined.');
 	    }
 	  });
 	}
-	
+
 	/**
 	 * Turns an object whose values are different reducer functions, into a single
 	 * reducer function. It will call every child reducer, and gather their results
 	 * into a single state object, whose keys correspond to the keys of the passed
 	 * reducer functions.
 	 *
 	 * @param {Object} reducers An object whose values correspond to different
 	 * reducer functions that need to be combined into one. One handy way to obtain
@@ -896,39 +896,39 @@ return /******/ (function(modules) { // 
 	  var finalReducers = {};
 	  for (var i = 0; i < reducerKeys.length; i++) {
 	    var key = reducerKeys[i];
 	    if (typeof reducers[key] === 'function') {
 	      finalReducers[key] = reducers[key];
 	    }
 	  }
 	  var finalReducerKeys = Object.keys(finalReducers);
-	
+
 	  var sanityError;
 	  try {
 	    assertReducerSanity(finalReducers);
 	  } catch (e) {
 	    sanityError = e;
 	  }
-	
+
 	  return function combination() {
 	    var state = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
 	    var action = arguments[1];
-	
+
 	    if (sanityError) {
 	      throw sanityError;
 	    }
-	
+
 	    if (false) {
 	      var warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action);
 	      if (warningMessage) {
 	        (0, _warning2["default"])(warningMessage);
 	      }
 	    }
-	
+
 	    var hasChanged = false;
 	    var nextState = {};
 	    for (var i = 0; i < finalReducerKeys.length; i++) {
 	      var key = finalReducerKeys[i];
 	      var reducer = finalReducers[key];
 	      var previousStateForKey = state[key];
 	      var nextStateForKey = reducer(previousStateForKey, action);
 	      if (typeof nextStateForKey === 'undefined') {
@@ -942,17 +942,17 @@ return /******/ (function(modules) { // 
 	  };
 	}
 
 /***/ },
 /* 18 */
 /***/ function(module, exports) {
 
 	'use strict';
-	
+
 	exports.__esModule = true;
 	exports["default"] = warning;
 	/**
 	 * Prints a warning in the console if it exists.
 	 *
 	 * @param {String} message The warning message.
 	 * @returns {void}
 	 */
@@ -972,25 +972,25 @@ return /******/ (function(modules) { // 
 	  /* eslint-enable no-empty */
 	}
 
 /***/ },
 /* 19 */
 /***/ function(module, exports) {
 
 	'use strict';
-	
+
 	exports.__esModule = true;
 	exports["default"] = bindActionCreators;
 	function bindActionCreator(actionCreator, dispatch) {
 	  return function () {
 	    return dispatch(actionCreator.apply(undefined, arguments));
 	  };
 	}
-	
+
 	/**
 	 * Turns an object whose values are action creators, into an object with the
 	 * same keys, but with every function wrapped into a `dispatch` call so they
 	 * may be invoked directly. This is just a convenience method, as you can call
 	 * `store.dispatch(MyActionCreators.doSomething())` yourself just fine.
 	 *
 	 * For convenience, you can also pass a single function as the first argument,
 	 * and get a function in return.
@@ -1006,21 +1006,21 @@ return /******/ (function(modules) { // 
 	 * every action creator wrapped into the `dispatch` call. If you passed a
 	 * function as `actionCreators`, the return value will also be a single
 	 * function.
 	 */
 	function bindActionCreators(actionCreators, dispatch) {
 	  if (typeof actionCreators === 'function') {
 	    return bindActionCreator(actionCreators, dispatch);
 	  }
-	
+
 	  if (typeof actionCreators !== 'object' || actionCreators === null) {
 	    throw new Error('bindActionCreators expected an object or a function, instead received ' + (actionCreators === null ? 'null' : typeof actionCreators) + '. ' + 'Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?');
 	  }
-	
+
 	  var keys = Object.keys(actionCreators);
 	  var boundActionCreators = {};
 	  for (var i = 0; i < keys.length; i++) {
 	    var key = keys[i];
 	    var actionCreator = actionCreators[key];
 	    if (typeof actionCreator === 'function') {
 	      boundActionCreators[key] = bindActionCreator(actionCreator, dispatch);
 	    }
@@ -1028,29 +1028,29 @@ return /******/ (function(modules) { // 
 	  return boundActionCreators;
 	}
 
 /***/ },
 /* 20 */
 /***/ function(module, exports, __webpack_require__) {
 
 	'use strict';
-	
+
 	exports.__esModule = true;
-	
+
 	var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
-	
+
 	exports["default"] = applyMiddleware;
-	
+
 	var _compose = __webpack_require__(21);
-	
+
 	var _compose2 = _interopRequireDefault(_compose);
-	
+
 	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
-	
+
 	/**
 	 * Creates a store enhancer that applies middleware to the dispatch method
 	 * of the Redux store. This is handy for a variety of tasks, such as expressing
 	 * asynchronous actions in a concise manner, or logging every action payload.
 	 *
 	 * See `redux-thunk` package as an example of the Redux middleware.
 	 *
 	 * Because middleware is potentially asynchronous, this should be the first
@@ -1061,82 +1061,82 @@ return /******/ (function(modules) { // 
 	 *
 	 * @param {...Function} middlewares The middleware chain to be applied.
 	 * @returns {Function} A store enhancer applying the middleware.
 	 */
 	function applyMiddleware() {
 	  for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) {
 	    middlewares[_key] = arguments[_key];
 	  }
-	
+
 	  return function (createStore) {
 	    return function (reducer, initialState, enhancer) {
 	      var store = createStore(reducer, initialState, enhancer);
 	      var _dispatch = store.dispatch;
 	      var chain = [];
-	
+
 	      var middlewareAPI = {
 	        getState: store.getState,
 	        dispatch: function dispatch(action) {
 	          return _dispatch(action);
 	        }
 	      };
 	      chain = middlewares.map(function (middleware) {
 	        return middleware(middlewareAPI);
 	      });
 	      _dispatch = _compose2["default"].apply(undefined, chain)(store.dispatch);
-	
+
 	      return _extends({}, store, {
 	        dispatch: _dispatch
 	      });
 	    };
 	  };
 	}
 
 /***/ },
 /* 21 */
 /***/ function(module, exports) {
 
 	"use strict";
-	
+
 	exports.__esModule = true;
 	exports["default"] = compose;
 	/**
 	 * Composes single-argument functions from right to left. The rightmost
 	 * function can take multiple arguments as it provides the signature for
 	 * the resulting composite function.
 	 *
 	 * @param {...Function} funcs The functions to compose.
 	 * @returns {Function} A function obtained by composing the argument functions
 	 * from right to left. For example, compose(f, g, h) is identical to doing
 	 * (...args) => f(g(h(...args))).
 	 */
-	
+
 	function compose() {
 	  for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) {
 	    funcs[_key] = arguments[_key];
 	  }
-	
+
 	  if (funcs.length === 0) {
 	    return function (arg) {
 	      return arg;
 	    };
 	  } else {
 	    var _ret = function () {
 	      var last = funcs[funcs.length - 1];
 	      var rest = funcs.slice(0, -1);
 	      return {
 	        v: function v() {
 	          return rest.reduceRight(function (composed, f) {
 	            return f(composed);
 	          }, last.apply(undefined, arguments));
 	        }
 	      };
 	    }();
-	
+
 	    if (typeof _ret === "object") return _ret.v;
 	  }
 	}
 
 /***/ },
 /* 22 */
 /***/ function(module, exports, __webpack_require__) {
 
@@ -1151,21 +1151,21 @@ return /******/ (function(modules) { // 
 	 * of patent rights can be found in the PATENTS file in the same directory.
 	 *
 	 */
 	// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js
 	;(function(f) {
 	  // CommonJS
 	  if (true) {
 	    module.exports = f(__webpack_require__(2));
-	
+
 	  // RequireJS
 	  } else if (typeof define === "function" && define.amd) {
 	    define(['react'], f);
-	
+
 	  // <script>
 	  } else {
 	    var g;
 	    if (typeof window !== "undefined") {
 	      g = window;
 	    } else if (typeof global !== "undefined") {
 	      g = global;
 	    } else if (typeof self !== "undefined") {
@@ -1173,290 +1173,290 @@ return /******/ (function(modules) { // 
 	    } else {
 	      // works providing we're not in "use strict";
 	      // needed for Java 8 Nashorn
 	      // see https://github.com/facebook/react/issues/3037
 	      g = this;
 	    }
 	    g.ReactDOM = f(g.React);
 	  }
-	
+
 	})(function(React) {
 	  return React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
 	});
 
 
 /***/ },
 /* 23 */
 /***/ function(module, exports, __webpack_require__) {
 
 	"use strict";
-	
+
 	var _require = __webpack_require__(24),
 	    Task = _require.Task;
-	
+
 	var firefox = __webpack_require__(25);
 	var chrome = __webpack_require__(125);
-	
+
 	var _require2 = __webpack_require__(123),
 	    createSource = _require2.createSource;
-	
+
 	var clientType = null;
 	function getClient() {
 	  if (clientType === "chrome" || clientType === "node") {
 	    return chrome.clientCommands;
 	  }
-	
+
 	  return firefox.clientCommands;
 	}
-	
+
 	function startDebugging(connTarget, actions) {
 	  if (connTarget.type === "node") {
 	    return startDebuggingNode(connTarget.param, actions);
 	  }
-	
+
 	  return startDebuggingTab(connTarget, actions);
 	}
-	
+
 	function startDebuggingNode(tabId, actions) {
 	  return Task.spawn(function* () {
 	    clientType = "node";
-	
+
 	    var tabs = yield chrome.connectNodeClient();
 	    var tab = tabs.find(t => t.id.indexOf(tabId) !== -1);
-	
+
 	    yield chrome.connectNode(tab.tab);
 	    chrome.initPage(actions, { clientType });
-	
+
 	    return { tabs, tab, client: chrome };
 	  });
 	}
-	
+
 	function startDebuggingTab(connTarget, actions) {
 	  var client = connTarget.type === "chrome" ? chrome : firefox;
 	  return Task.spawn(function* () {
 	    var tabs = yield client.connectClient();
 	    var tab = tabs.find(t => t.id.indexOf(connTarget.param) !== -1);
 	    if (tab) {
 	      yield client.connectTab(tab.tab);
-	
+
 	      clientType = connTarget.type;
 	      client.initPage(actions, { clientType });
 	    }
 	    return { tabs, tab, client };
 	  });
 	}
-	
+
 	module.exports = {
 	  getClient,
 	  startDebugging,
 	  firefox,
 	  chrome,
 	  createSource
 	};
 
 /***/ },
 /* 24 */
 /***/ function(module, exports) {
 
 	"use strict";
-	
+
 	/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 	 * You can obtain one at http://mozilla.org/MPL/2.0/. */
-	
+
 	/**
 	 * This object provides the public module functions.
 	 */
 	var Task = {
 	  // XXX: Not sure if this works in all cases...
 	  async: function (task) {
 	    return function () {
 	      return Task.spawn(task, this, arguments);
 	    };
 	  },
-	
+
 	  /**
 	   * Creates and starts a new task.
 	   * @param task A generator function
 	   * @return A promise, resolved when the task terminates
 	   */
 	  spawn: function (task, scope, args) {
 	    return new Promise(function (resolve, reject) {
 	      var iterator = task.apply(scope, args);
-	
+
 	      var callNext = lastValue => {
 	        var iteration = iterator.next(lastValue);
 	        Promise.resolve(iteration.value).then(value => {
 	          if (iteration.done) {
 	            resolve(value);
 	          } else {
 	            callNext(value);
 	          }
 	        }).catch(error => {
 	          reject(error);
 	          iterator.throw(error);
 	        });
 	      };
-	
+
 	      callNext(undefined);
 	    });
 	  }
 	};
-	
+
 	module.exports = { Task };
 
 /***/ },
 /* 25 */
 /***/ function(module, exports, __webpack_require__) {
 
 	"use strict";
-	
+
 	var connectClient = (() => {
 	  var _ref = _asyncToGenerator(function* () {
 	    var useProxy = !getValue("firefox.webSocketConnection");
 	    var firefoxHost = getValue(useProxy ? "firefox.proxyHost" : "firefox.webSocketHost");
-	
+
 	    var socket = new WebSocket(`ws://${firefoxHost}`);
 	    var transport = useProxy ? new DebuggerTransport(socket) : new WebsocketTransport(socket);
-	
+
 	    debuggerClient = new DebuggerClient(transport);
 	    if (!debuggerClient) {
 	      return [];
 	    }
-	
+
 	    try {
 	      yield debuggerClient.connect();
 	      var tabs = yield getTabs();
 	      return tabs;
 	    } catch (err) {
 	      console.log(err);
 	      return [];
 	    }
 	  });
-	
+
 	  return function connectClient() {
 	    return _ref.apply(this, arguments);
 	  };
 	})();
-	
+
 	var getTabs = (() => {
 	  var _ref2 = _asyncToGenerator(function* () {
 	    if (!debuggerClient || !debuggerClient.mainRoot) {
 	      return;
 	    }
-	
+
 	    var response = yield debuggerClient.listTabs();
 	    return createTabs(response.tabs);
 	  });
-	
+
 	  return function getTabs() {
 	    return _ref2.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) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
-	
+
 	var _require = __webpack_require__(26),
 	    DebuggerClient = _require.DebuggerClient,
 	    DebuggerTransport = _require.DebuggerTransport,
 	    TargetFactory = _require.TargetFactory,
 	    WebsocketTransport = _require.WebsocketTransport;
-	
+
 	var _require2 = __webpack_require__(65),
 	    getValue = _require2.getValue;
-	
+
 	var _require3 = __webpack_require__(122),
 	    setupCommands = _require3.setupCommands,
 	    clientCommands = _require3.clientCommands;
-	
+
 	var _require4 = __webpack_require__(124),
 	    setupEvents = _require4.setupEvents,
 	    clientEvents = _require4.clientEvents;
-	
+
 	var debuggerClient = null;
 	var threadClient = null;
 	var tabTarget = null;
-	
+
 	function getThreadClient() {
 	  return threadClient;
 	}
-	
+
 	function setThreadClient(client) {
 	  threadClient = client;
 	}
-	
+
 	function getTabTarget() {
 	  return tabTarget;
 	}
-	
+
 	function setTabTarget(target) {
 	  tabTarget = target;
 	}
-	
+
 	function lookupTabTarget(tab) {
 	  var options = { client: debuggerClient, form: tab, chrome: false };
 	  return TargetFactory.forRemoteTab(options);
 	}
-	
+
 	function createTabs(tabs) {
 	  return tabs.map(tab => {
 	    return {
 	      title: tab.title,
 	      url: tab.url,
 	      id: tab.actor,
 	      tab,
 	      clientType: "firefox"
 	    };
 	  });
 	}
-	
+
 	function connectTab(tab) {
 	  return new Promise((resolve, reject) => {
 	    window.addEventListener("beforeunload", () => {
 	      var tt = getTabTarget();
 	      if (tt !== null) {
 	        tt.destroy();
 	      }
 	    });
-	
+
 	    lookupTabTarget(tab).then(target => {
 	      tabTarget = target;
 	      target.activeTab.attachThread({}, (res, _threadClient) => {
 	        threadClient = _threadClient;
 	        threadClient.resume();
 	        resolve();
 	      });
 	    });
 	  });
 	}
-	
+
 	function initPage(actions) {
 	  tabTarget = getTabTarget();
 	  threadClient = getThreadClient();
-	
+
 	  if (!threadClient || !tabTarget) {
 	    return;
 	  }
-	
+
 	  setupCommands({ threadClient, tabTarget, debuggerClient });
-	
+
 	  if (actions) {
 	    // Listen to all the requested events.
 	    setupEvents({ threadClient, actions });
 	    Object.keys(clientEvents).forEach(eventName => {
 	      if (threadClient) {
 	        threadClient.addListener(eventName, clientEvents[eventName]);
 	      }
 	    });
 	  }
 	}
-	
+
 	module.exports = {
 	  connectClient,
 	  connectTab,
 	  clientCommands,
 	  clientEvents,
 	  getThreadClient,
 	  setThreadClient,
 	  getTabTarget,
@@ -1478,17 +1478,17 @@ return /******/ (function(modules) { // 
 	const AppConstants = __webpack_require__(44);
 	const EventEmitter = __webpack_require__(34);
 	const WebsocketTransport = __webpack_require__(59);
 	const Menu = __webpack_require__(60);
 	const MenuItem = __webpack_require__(61);
 	const Tree = __webpack_require__(62);
 	const sourceUtils = __webpack_require__(63);
 	const frame = __webpack_require__(64);
-	
+
 	module.exports = {
 	  KeyShortcuts,
 	  PrefsHelper,
 	  DebuggerClient,
 	  DebuggerTransport,
 	  TargetFactory,
 	  DevToolsUtils,
 	  AppConstants,
@@ -1504,22 +1504,22 @@ return /******/ (function(modules) { // 
 
 /***/ },
 /* 27 */
 /***/ 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 { Services: { appinfo }} = __webpack_require__(28);
 	const EventEmitter = __webpack_require__(34);
 	const isOSX = appinfo.OS === "Darwin";
 	"use strict";
-	
+
 	// 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",
 	  "F4": "DOM_VK_F4",
 	  "F5": "DOM_VK_F5",
 	  "F6": "DOM_VK_F6",
@@ -1558,17 +1558,17 @@ return /******/ (function(modules) { // 
 	  "Escape": "DOM_VK_ESCAPE",
 	  "Esc": "DOM_VK_ESCAPE",
 	  "Tab": "DOM_VK_TAB",
 	  "VolumeUp": "DOM_VK_VOLUME_UP",
 	  "VolumeDown": "DOM_VK_VOLUME_DOWN",
 	  "VolumeMute": "DOM_VK_VOLUME_MUTE",
 	  "PrintScreen": "DOM_VK_PRINTSCREEN",
 	};
-	
+
 	/**
 	 * Helper to listen for keyboard events decribed in .properties file.
 	 *
 	 * let shortcuts = new KeyShortcuts({
 	 *   window
 	 * });
 	 * shortcuts.on("Ctrl+F", event => {
 	 *   // `event` is the KeyboardEvent which relates to the key shortcuts
@@ -1582,32 +1582,32 @@ return /******/ (function(modules) { // 
 	 */
 	function KeyShortcuts({ window, target }) {
 	  this.window = window;
 	  this.target = target || window;
 	  this.keys = new Map();
 	  this.eventEmitter = new EventEmitter();
 	  this.target.addEventListener("keydown", this);
 	}
-	
+
 	/*
 	 * Parse an electron-like key string and return a normalized object which
 	 * allow efficient match on DOM key event. The normalized object matches DOM
 	 * API.
 	 *
 	 * @param DOMWindow window
 	 *        Any DOM Window object, just to fetch its `KeyboardEvent` object
 	 * @param String str
 	 *        The shortcut string to parse, following this document:
 	 *        https://github.com/electron/electron/blob/master/docs/api/accelerator.md
 	 */
 	KeyShortcuts.parseElectronKey = function(window, str) {
 	  let modifiers = str.split("+");
 	  let key = modifiers.pop();
-	
+
 	  let shortcut = {
 	    ctrl: false,
 	    meta: false,
 	    alt: false,
 	    shift: false,
 	    // Set for character keys
 	    key: undefined,
 	    // Set for non-character keys
@@ -1628,41 +1628,41 @@ return /******/ (function(modules) { // 
 	      shortcut.ctrl = true;
 	    } else if (mod === "Shift") {
 	      shortcut.shift = true;
 	    } else {
 	      console.error("Unsupported modifier:", mod, "from key:", str);
 	      return null;
 	    }
 	  }
-	
+
 	  // Plus is a special case. It's a character key and shouldn't be matched
 	  // against a keycode as it is only accessible via Shift/Capslock
 	  if (key === "Plus") {
 	    key = "+";
 	  }
-	
+
 	  if (typeof key === "string" && key.length === 1) {
 	    // Match any single character
 	    shortcut.key = key.toLowerCase();
 	  } else if (key in ElectronKeysMapping) {
 	    // Maps the others manually to DOM API DOM_VK_*
 	    key = ElectronKeysMapping[key];
 	    shortcut.keyCode = window.KeyboardEvent[key];
 	    // Used only to stringify the shortcut
 	    shortcut.keyCodeString = key;
 	    shortcut.key = key;
 	  } else {
 	    console.error("Unsupported key:", key);
 	    return null;
 	  }
-	
+
 	  return shortcut;
 	};
-	
+
 	KeyShortcuts.stringify = function(shortcut) {
 	  let list = [];
 	  if (shortcut.alt) {
 	    list.push("Alt");
 	  }
 	  if (shortcut.ctrl) {
 	    list.push("Ctrl");
 	  }
@@ -1676,23 +1676,23 @@ return /******/ (function(modules) { // 
 	  if (shortcut.key) {
 	    key = shortcut.key.toUpperCase();
 	  } else {
 	    key = shortcut.keyCodeString;
 	  }
 	  list.push(key);
 	  return list.join("+");
 	};
-	
+
 	KeyShortcuts.prototype = {
 	  destroy() {
 	    this.target.removeEventListener("keydown", this);
 	    this.keys.clear();
 	  },
-	
+
 	  doesEventMatchShortcut(event, shortcut) {
 	    if (shortcut.meta != event.metaKey) {
 	      return false;
 	    }
 	    if (shortcut.ctrl != event.ctrlKey) {
 	      return false;
 	    }
 	    if (shortcut.alt != event.altKey) {
@@ -1704,68 +1704,68 @@ return /******/ (function(modules) { // 
 	        event.key.match(/[a-zA-Z]/)) {
 	      return false;
 	    }
 	    if (shortcut.keyCode) {
 	      return event.keyCode == shortcut.keyCode;
 	    } else if (event.key in ElectronKeysMapping) {
 	      return ElectronKeysMapping[event.key] === shortcut.key;
 	    }
-	
+
 	    // get the key from the keyCode if key is not provided.
 	    let key = event.key || String.fromCharCode(event.keyCode);
-	
+
 	    // For character keys, we match if the final character is the expected one.
 	    // But for digits we also accept indirect match to please azerty keyboard,
 	    // which requires Shift to be pressed to get digits.
 	    return key.toLowerCase() == shortcut.key ||
 	      (shortcut.key.match(/^[0-9]$/) &&
 	       event.keyCode == shortcut.key.charCodeAt(0));
 	  },
-	
+
 	  handleEvent(event) {
 	    for (let [key, shortcut] of this.keys) {
 	      if (this.doesEventMatchShortcut(event, shortcut)) {
 	        this.eventEmitter.emit(key, event);
 	      }
 	    }
 	  },
-	
+
 	  on(key, listener) {
 	    if (typeof listener !== "function") {
 	      throw new Error("KeyShortcuts.on() expects a function as " +
 	                      "second argument");
 	    }
 	    if (!this.keys.has(key)) {
 	      let shortcut = KeyShortcuts.parseElectronKey(this.window, key);
 	      // The key string is wrong and we were unable to compute the key shortcut
 	      if (!shortcut) {
 	        return;
 	      }
 	      this.keys.set(key, shortcut);
 	    }
 	    this.eventEmitter.on(key, listener);
 	  },
-	
+
 	  off(key, listener) {
 	    this.eventEmitter.off(key, listener);
 	  },
 	};
 	exports.KeyShortcuts = KeyShortcuts;
 
 
 /***/ },
 /* 28 */
 /***/ function(module, exports, __webpack_require__) {
 
 	const Services = __webpack_require__(29);
 	const SplitBox = __webpack_require__(30);
 	// const SplitBoxCSS = require("./client/shared/components/splitter/SplitBox.css")
 	const sprintf = __webpack_require__(33).sprintf;
-	
+
 	module.exports = {
 	  Services,
 	  SplitBox,
 	  // SplitBoxCSS,
 	  sprintf
 	};
 
 
@@ -1778,23 +1778,23 @@ return /******/ (function(modules) { // 
 /***/ },
 /* 30 */
 /***/ function(module, exports, __webpack_require__) {
 
 	const React = __webpack_require__(2);
 	const ReactDOM = __webpack_require__(31);
 	const Draggable = React.createFactory(__webpack_require__(32));
 	const { DOM: dom, PropTypes } = React;
-	
+
 	/**
 	 * This component represents a Splitter. The splitter supports vertical
 	 * as well as horizontal mode.
 	 */
 	const SplitBox = React.createClass({
-	
+
 	  propTypes: {
 	    // Custom class name. You can use more names separated by a space.
 	    className: PropTypes.string,
 	    // Initial size of controlled panel.
 	    initialSize: PropTypes.any,
 	    // Optional initial width of controlled panel.
 	    initialWidth: PropTypes.number,
 	    // Optional initial height of controlled panel.
@@ -1815,181 +1815,181 @@ return /******/ (function(modules) { // 
 	    endPanelControl: PropTypes.bool,
 	    // Size of the splitter handle bar.
 	    splitterSize: PropTypes.number,
 	    // True if the splitter bar is vertical (default is vertical).
 	    vert: PropTypes.bool,
 	    // Optional style properties passed into the splitbox
 	    style: PropTypes.object
 	  },
-	
+
 	  displayName: "SplitBox",
-	
+
 	  getDefaultProps() {
 	    return {
 	      splitterSize: 5,
 	      vert: true,
 	      endPanelControl: false,
 	      endPanelCollapsed: false,
 	      startPanelCollapsed: false
 	    };
 	  },
-	
+
 	  /**
 	   * The state stores the current orientation (vertical or horizontal)
 	   * and the current size (width/height). All these values can change
 	   * during the component's life time.
 	   */
 	  getInitialState() {
 	    return {
 	      vert: this.props.vert,
 	      // We use integers for these properties
 	      width: parseInt(this.props.initialWidth || this.props.initialSize),
 	      height: parseInt(this.props.initialHeight || this.props.initialSize)
 	    };
 	  },
-	
+
 	  componentWillReceiveProps(nextProps) {
 	    if (this.props.vert !== nextProps.vert) {
 	      this.setState({ vert: nextProps.vert });
 	    }
 	  },
-	
+
 	  // Dragging Events
-	
+
 	  /**
 	   * Set 'resizing' cursor on entire document during splitter dragging.
 	   * This avoids cursor-flickering that happens when the mouse leaves
 	   * the splitter bar area (happens frequently).
 	   */
 	  onStartMove() {
 	    const splitBox = ReactDOM.findDOMNode(this);
 	    const doc = splitBox.ownerDocument;
 	    let defaultCursor = doc.documentElement.style.cursor;
 	    doc.documentElement.style.cursor =
 	      (this.state.vert ? "ew-resize" : "ns-resize");
-	
+
 	    splitBox.classList.add("dragging");
-	
+
 	    this.setState({
 	      defaultCursor: defaultCursor
 	    });
 	  },
-	
+
 	  onStopMove() {
 	    const splitBox = ReactDOM.findDOMNode(this);
 	    const doc = splitBox.ownerDocument;
 	    doc.documentElement.style.cursor = this.state.defaultCursor;
-	
+
 	    splitBox.classList.remove("dragging");
 	  },
-	
+
 	  /**
 	   * Adjust size of the controlled panel. Depending on the current
 	   * orientation we either remember the width or height of
 	   * the splitter box.
 	   */
 	  onMove({ movementX, movementY }) {
 	    const node = ReactDOM.findDOMNode(this);
 	    const doc = node.ownerDocument;
-	
+
 	    if (this.props.endPanelControl) {
 	      // For the end panel we need to increase the width/height when the
 	      // movement is towards the left/top.
 	      movementX = -movementX;
 	      movementY = -movementY;
 	    }
-	
+
 	    if (this.state.vert) {
 	      const isRtl = doc.dir === "rtl";
 	      if (isRtl) {
 	        // In RTL we need to reverse the movement again -- but only for vertical
 	        // splitters
 	        movementX = -movementX;
 	      }
-	
+
 	      this.setState((state, props) => ({
 	        width: state.width + movementX
 	      }));
 	    } else {
 	      this.setState((state, props) => ({
 	        height: state.height + movementY
 	      }));
 	    }
 	  },
-	
+
 	  // Rendering
 	  preparePanelStyles() {
 	    const vert = this.state.vert;
 	    const {
 	      minSize, maxSize, startPanelCollapsed, endPanelControl,
 	      endPanelCollapsed } = this.props;
 	    let leftPanelStyle, rightPanelStyle;
-	
+
 	    // Set proper size for panels depending on the current state.
 	    if (vert) {
 	      let startWidth = endPanelControl ? null : this.state.width,
 	        endWidth = endPanelControl ? this.state.width : null;
-	
+
 	      leftPanelStyle = {
 	        maxWidth: endPanelControl ? null : maxSize,
 	        minWidth: endPanelControl ? null : minSize,
 	        width: startPanelCollapsed ? 0 : startWidth
 	      };
 	      rightPanelStyle = {
 	        maxWidth: endPanelControl ? maxSize : null,
 	        minWidth: endPanelControl ? minSize : null,
 	        width: endPanelCollapsed ? 0 : endWidth
 	      };
 	    } else {
 	      let startHeight = endPanelControl ? null : this.state.height,
 	        endHeight = endPanelControl ? this.state.height : null;
-	
+
 	      leftPanelStyle = {
 	        maxHeight: endPanelControl ? null : maxSize,
 	        minHeight: endPanelControl ? null : minSize,
 	        height: endPanelCollapsed ? maxSize : startHeight
 	      };
 	      rightPanelStyle = {
 	        maxHeight: endPanelControl ? maxSize : null,
 	        minHeight: endPanelControl ? minSize : null,
 	        height: startPanelCollapsed ? maxSize : endHeight
 	      };
 	    }
-	
+
 	    return { leftPanelStyle, rightPanelStyle };
 	  },
-	
+
 	  render() {
 	    const vert = this.state.vert;
 	    const {
 	      startPanelCollapsed,
 	      startPanel,
 	      endPanel,
 	      endPanelControl,
 	      splitterSize,
 	      endPanelCollapsed
 	    } = this.props;
-	
+
 	    let style = Object.assign({}, this.props.style);
-	
+
 	    // Calculate class names list.
 	    let classNames = ["split-box"];
 	    classNames.push(vert ? "vert" : "horz");
 	    if (this.props.className) {
 	      classNames = classNames.concat(this.props.className.split(" "));
 	    }
-	
+
 	    const { leftPanelStyle, rightPanelStyle } = this.preparePanelStyles();
-	
+
 	    // Calculate splitter size
 	    let splitterStyle = {
 	      flex: `0 0 ${splitterSize}px`
 	    };
-	
+
 	    return (
 	      dom.div({
 	        className: classNames.join(" "),
 	        style: style },
 	        !startPanelCollapsed ?
 	          dom.div({
 	            className: endPanelControl ? "uncontrolled" : "controlled",
 	            style: leftPanelStyle },
@@ -2007,81 +2007,81 @@ return /******/ (function(modules) { // 
 	            className: endPanelControl ? "controlled" : "uncontrolled",
 	            style: rightPanelStyle },
 	            endPanel
 	          ) : null
 	      )
 	    );
 	  }
 	});
-	
+
 	module.exports = SplitBox;
 
 
 /***/ },
 /* 31 */
 /***/ function(module, exports) {
 
 	module.exports = __WEBPACK_EXTERNAL_MODULE_31__;
 
 /***/ },
 /* 32 */
 /***/ 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 React = __webpack_require__(2);
 	const ReactDOM = __webpack_require__(31);
 	const { DOM: dom, PropTypes } = React;
-	
+
 	const Draggable = React.createClass({
 	  displayName: "Draggable",
-	
+
 	  propTypes: {
 	    onMove: PropTypes.func.isRequired,
 	    onStart: PropTypes.func,
 	    onStop: PropTypes.func,
 	    style: PropTypes.object,
 	    className: PropTypes.string
 	  },
-	
+
 	  startDragging(ev) {
 	    ev.preventDefault();
 	    const doc = ReactDOM.findDOMNode(this).ownerDocument;
 	    doc.addEventListener("mousemove", this.onMove);
 	    doc.addEventListener("mouseup", this.onUp);
 	    this.props.onStart && this.props.onStart();
 	  },
-	
+
 	  onMove(ev) {
 	    ev.preventDefault();
 	    // We pass the whole event because we don't know which properties
 	    // the callee needs.
 	    this.props.onMove(ev);
 	  },
-	
+
 	  onUp(ev) {
 	    ev.preventDefault();
 	    const doc = ReactDOM.findDOMNode(this).ownerDocument;
 	    doc.removeEventListener("mousemove", this.onMove);
 	    doc.removeEventListener("mouseup", this.onUp);
 	    this.props.onStop && this.props.onStop();
 	  },
-	
+
 	  render() {
 	    return dom.div({
 	      style: this.props.style,
 	      className: this.props.className,
 	      onMouseDown: this.startDragging
 	    });
 	  }
 	});
-	
+
 	module.exports = Draggable;
 
 
 /***/ },
 /* 33 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/**
@@ -2106,22 +2106,22 @@ return /******/ (function(modules) { // 
 	 * ANY DIRECT, INDIRECT, INCIDENTAL, 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.
 	 *
 	 */
-	
+
 	/* globals window, exports, define */
-	
+
 	(function(window) {
 	    'use strict'
-	
+
 	    var re = {
 	        not_string: /[^s]/,
 	        not_bool: /[^t]/,
 	        not_type: /[^T]/,
 	        not_primitive: /[^v]/,
 	        number: /[diefg]/,
 	        numeric_arg: /bcdiefguxX/,
 	        json: /[j]/,
@@ -2129,25 +2129,25 @@ return /******/ (function(modules) { // 
 	        text: /^[^\x25]+/,
 	        modulo: /^\x25{2}/,
 	        placeholder: /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijosStTuvxX])/,
 	        key: /^([a-z_][a-z_\d]*)/i,
 	        key_access: /^\.([a-z_][a-z_\d]*)/i,
 	        index_access: /^\[(\d+)\]/,
 	        sign: /^[\+\-]/
 	    }
-	
+
 	    function sprintf() {
 	        var key = arguments[0], cache = sprintf.cache
 	        if (!(cache[key] && cache.hasOwnProperty(key))) {
 	            cache[key] = sprintf.parse(key)
 	        }
 	        return sprintf.format.call(null, cache[key], arguments)
 	    }
-	
+
 	    sprintf.format = function(parse_tree, argv) {
 	        var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length, is_positive = true, sign = ''
 	        for (i = 0; i < tree_length; i++) {
 	            node_type = get_type(parse_tree[i])
 	            if (node_type === 'string') {
 	                output[output.length] = parse_tree[i]
 	            }
 	            else if (node_type === 'array') {
@@ -2162,29 +2162,29 @@ return /******/ (function(modules) { // 
 	                    }
 	                }
 	                else if (match[1]) { // positional argument (explicit)
 	                    arg = argv[match[1]]
 	                }
 	                else { // positional argument (implicit)
 	                    arg = argv[cursor++]
 	                }
-	
+
 	                if (re.not_type.test(match[8]) && re.not_primitive.test(match[8]) && get_type(arg) == 'function') {
 	                    arg = arg()
 	                }
-	
+
 	                if (re.numeric_arg.test(match[8]) && (get_type(arg) != 'number' && isNaN(arg))) {
 	                    throw new TypeError(sprintf("[sprintf] expecting number but found %s", get_type(arg)))
 	                }
-	
+
 	                if (re.number.test(match[8])) {
 	                    is_positive = arg >= 0
 	                }
-	
+
 	                switch (match[8]) {
 	                    case 'b':
 	                        arg = parseInt(arg, 10).toString(2)
 	                    break
 	                    case 'c':
 	                        arg = String.fromCharCode(parseInt(arg, 10))
 	                    break
 	                    case 'd':
@@ -2248,19 +2248,19 @@ return /******/ (function(modules) { // 
 	                    pad_length = match[6] - (sign + arg).length
 	                    pad = match[6] ? (pad_length > 0 ? str_repeat(pad_character, pad_length) : '') : ''
 	                    output[output.length] = match[5] ? sign + arg + pad : (pad_character === '0' ? sign + pad + arg : pad + sign + arg)
 	                }
 	            }
 	        }
 	        return output.join('')
 	    }
-	
+
 	    sprintf.cache = {}
-	
+
 	    sprintf.parse = function(fmt) {
 	        var _fmt = fmt, match = [], parse_tree = [], arg_names = 0
 	        while (_fmt) {
 	            if ((match = re.text.exec(_fmt)) !== null) {
 	                parse_tree[parse_tree.length] = match[0]
 	            }
 	            else if ((match = re.modulo.exec(_fmt)) !== null) {
 	                parse_tree[parse_tree.length] = '%'
@@ -2298,61 +2298,61 @@ return /******/ (function(modules) { // 
 	            }
 	            else {
 	                throw new SyntaxError("[sprintf] unexpected placeholder")
 	            }
 	            _fmt = _fmt.substring(match[0].length)
 	        }
 	        return parse_tree
 	    }
-	
+
 	    var vsprintf = function(fmt, argv, _argv) {
 	        _argv = (argv || []).slice(0)
 	        _argv.splice(0, 0, fmt)
 	        return sprintf.apply(null, _argv)
 	    }
-	
+
 	    /**
 	     * helpers
 	     */
 	    function get_type(variable) {
 	        if (typeof variable === 'number') {
 	            return 'number'
 	        }
 	        else if (typeof variable === 'string') {
 	            return 'string'
 	        }
 	        else {
 	            return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase()
 	        }
 	    }
-	
+
 	    var preformattedPadding = {
 	        '0': ['', '0', '00', '000', '0000', '00000', '000000', '0000000'],
 	        ' ': ['', ' ', '  ', '   ', '    ', '     ', '      ', '       '],
 	        '_': ['', '_', '__', '___', '____', '_____', '______', '_______'],
 	    }
 	    function str_repeat(input, multiplier) {
 	        if (multiplier >= 0 && multiplier <= 7 && preformattedPadding[input]) {
 	            return preformattedPadding[input][multiplier]
 	        }
 	        return Array(multiplier + 1).join(input)
 	    }
-	
+
 	    /**
 	     * export to either browser or node.js
 	     */
 	    if (true) {
 	        exports.sprintf = sprintf
 	        exports.vsprintf = vsprintf
 	    }
 	    else {
 	        window.sprintf = sprintf
 	        window.vsprintf = vsprintf
-	
+
 	        if (typeof define === 'function' && define.amd) {
 	            define(function() {
 	                return {
 	                    sprintf: sprintf,
 	                    vsprintf: vsprintf
 	                }
 	            })
 	        }
@@ -2362,42 +2362,42 @@ return /******/ (function(modules) { // 
 
 /***/ },
 /* 34 */
 /***/ 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/. */
-	
+
 	/**
 	 * EventEmitter.
 	 */
-	
+
 	var EventEmitter = function EventEmitter() {};
 	module.exports = EventEmitter;
-	
+
 	const { Cu } = __webpack_require__(35);
 	const promise = __webpack_require__(40);
-	
+
 	/**
 	 * Decorate an object with event emitter functionality.
 	 *
 	 * @param Object aObjectToDecorate
 	 *        Bind all public methods of EventEmitter to
 	 *        the aObjectToDecorate object.
 	 */
 	EventEmitter.decorate = function EventEmitter_decorate (aObjectToDecorate) {
 	  let emitter = new EventEmitter();
 	  aObjectToDecorate.on = emitter.on.bind(emitter);
 	  aObjectToDecorate.off = emitter.off.bind(emitter);
 	  aObjectToDecorate.once = emitter.once.bind(emitter);
 	  aObjectToDecorate.emit = emitter.emit.bind(emitter);
 	};
-	
+
 	EventEmitter.prototype = {
 	  /**
 	   * Connect a listener.
 	   *
 	   * @param string aEvent
 	   *        The event name to which we're connecting.
 	   * @param function aListener
 	   *        Called when the event is fired.
@@ -2405,48 +2405,48 @@ return /******/ (function(modules) { // 
 	  on: function EventEmitter_on(aEvent, aListener) {
 	    if (!this._eventEmitterListeners)
 	      this._eventEmitterListeners = new Map();
 	    if (!this._eventEmitterListeners.has(aEvent)) {
 	      this._eventEmitterListeners.set(aEvent, []);
 	    }
 	    this._eventEmitterListeners.get(aEvent).push(aListener);
 	  },
-	
+
 	  /**
 	   * Listen for the next time an event is fired.
 	   *
 	   * @param string aEvent
 	   *        The event name to which we're connecting.
 	   * @param function aListener
 	   *        (Optional) Called when the event is fired. Will be called at most
 	   *        one time.
 	   * @return promise
 	   *        A promise which is resolved when the event next happens. The
 	   *        resolution value of the promise is the first event argument. If
 	   *        you need access to second or subsequent event arguments (it's rare
 	   *        that this is needed) then use aListener
 	   */
 	  once: function EventEmitter_once(aEvent, aListener) {
 	    let deferred = promise.defer();
-	
+
 	    let handler = (aEvent, aFirstArg, ...aRest) => {
 	      this.off(aEvent, handler);
 	      if (aListener) {
 	        aListener.apply(null, [aEvent, aFirstArg, ...aRest]);
 	      }
 	      deferred.resolve(aFirstArg);
 	    };
-	
+
 	    handler._originalListener = aListener;
 	    this.on(aEvent, handler);
-	
+
 	    return deferred.promise;
 	  },
-	
+
 	  /**
 	   * Remove a previously-registered event listener.  Works for events
 	   * registered with either on or once.
 	   *
 	   * @param string aEvent
 	   *        The event name whose listener we're disconnecting.
 	   * @param function aListener
 	   *        The listener to remove.
@@ -2456,34 +2456,34 @@ return /******/ (function(modules) { // 
 	      return;
 	    let listeners = this._eventEmitterListeners.get(aEvent);
 	    if (listeners) {
 	      this._eventEmitterListeners.set(aEvent, listeners.filter(l => {
 	        return l !== aListener && l._originalListener !== aListener;
 	      }));
 	    }
 	  },
-	
+
 	  /**
 	   * Emit an event.  All arguments to this method will
 	   * be sent to listener functions.
 	   */
 	  emit: function EventEmitter_emit(aEvent) {
 	    if (!this._eventEmitterListeners || !this._eventEmitterListeners.has(aEvent)) {
 	      return;
 	    }
-	
+
 	    let originalListeners = this._eventEmitterListeners.get(aEvent);
 	    for (let listener of this._eventEmitterListeners.get(aEvent)) {
 	      // If the object was destroyed during event emission, stop
 	      // emitting.
 	      if (!this._eventEmitterListeners) {
 	        break;
 	      }
-	
+
 	      // If listeners were removed during emission, make sure the
 	      // event handler we're going to fire wasn't removed.
 	      if (originalListeners === this._eventEmitterListeners.get(aEvent) ||
 	          this._eventEmitterListeners.get(aEvent).some(l => l === listener)) {
 	        try {
 	          listener.apply(null, arguments);
 	        }
 	        catch (ex) {
@@ -2500,32 +2500,32 @@ return /******/ (function(modules) { // 
 
 /***/ },
 /* 35 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/*
 	 * A sham for https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/chrome
 	 */
-	
+
 	var { inDOMUtils } = __webpack_require__(36);
-	
+
 	var ourServices = {
 	  inIDOMUtils: inDOMUtils,
 	  nsIClipboardHelper: {
 	    copyString: () => {}
 	  },
 	  nsIXULChromeRegistry: {
 	    isLocaleRTL: () => {return false;}
 	  },
 	  nsIDOMParser: {
-	
-	  },
-	};
-	
+
+	  },
+	};
+
 	module.exports = {
 	  Cc: name => {
 	    if(typeof console !== "undefined") {
 	      console.log('Cc sham for', name);
 	    }
 	    return {
 	      getService: (name) => ourServices[name],
 	      createInstance: (iface) => ourServices[iface],
@@ -2544,17 +2544,17 @@ return /******/ (function(modules) { // 
 	      "DISPATCH_SYNC":1
 	    },
 	    nsIDOMNode: typeof HTMLElement !== "undefined" ? HTMLElement : null,
 	    nsIFocusManager: {
 	      MOVEFOCUS_BACKWARD: 2,
 	      MOVEFOCUS_FORWARD: 1,
 	    },
 	    nsIDOMKeyEvent: {
-	
+
 	    },
 	    nsIDOMCSSRule: {"UNKNOWN_RULE":0,"STYLE_RULE":1,"CHARSET_RULE":2,"IMPORT_RULE":3,"MEDIA_RULE":4,"FONT_FACE_RULE":5,"PAGE_RULE":6,"KEYFRAMES_RULE":7,"KEYFRAME_RULE":8,"MOZ_KEYFRAMES_RULE":7,"MOZ_KEYFRAME_RULE":8,"NAMESPACE_RULE":10,"COUNTER_STYLE_RULE":11,"SUPPORTS_RULE":12,"FONT_FEATURE_VALUES_RULE":14},
 	    inIDOMUtils: "inIDOMUtils",
 	    nsIClipboardHelper: "nsIClipboardHelper",
 	    nsIXULChromeRegistry: "nsIXULChromeRegistry",
 	  },
 	  Cu: {
 	    reportError: msg => { (typeof console !== "undefined") ? console.error(msg) : dump(msg) },
@@ -2567,58 +2567,58 @@ return /******/ (function(modules) { // 
 	};
 
 
 /***/ },
 /* 36 */
 /***/ function(module, exports, __webpack_require__) {
 
 	// A sham for inDOMUtils.
-	
-	"use strict";
-	
+
+	"use strict";
+
 	var { CSSLexer } = __webpack_require__(37);
 	var { cssColors } = __webpack_require__(38);
 	var { cssProperties } = __webpack_require__(39);
-	
+
 	var cssRGBMap;
-	
+
 	// From inIDOMUtils.idl.
 	var EXCLUDE_SHORTHANDS = (1 << 0);
 	var INCLUDE_ALIASES = (1 << 1);
 	var TYPE_LENGTH = 0;
 	var TYPE_PERCENTAGE = 1;
 	var TYPE_COLOR = 2;
 	var TYPE_URL = 3;
 	var TYPE_ANGLE = 4;
 	var TYPE_FREQUENCY = 5;
 	var TYPE_TIME = 6;
 	var TYPE_GRADIENT = 7;
 	var TYPE_TIMING_FUNCTION = 8;
 	var TYPE_IMAGE_RECT = 9;
 	var TYPE_NUMBER = 10;
-	
+
 	function getCSSLexer(text) {
 	  return new CSSLexer(text);
 	}
-	
+
 	function rgbToColorName(r, g, b) {
 	  if (!cssRGBMap) {
 	    cssRGBMap = new Map();
 	    for (let name in cssColors) {
 	      cssRGBMap.set(JSON.stringify(cssColors[name]), name);
 	    }
 	  }
 	  let value = cssRGBMap.get(JSON.stringify([r, g, b]));
 	  if (!value) {
 	    throw new Error("no such color");
 	  }
 	  return value;
 	}
-	
+
 	// Taken from dom/tests/mochitest/ajax/mochikit/MochiKit/Color.js
 	function _hslValue(n1, n2, hue) {
 	  if (hue > 6.0) {
 	    hue -= 6.0;
 	  } else if (hue < 0.0) {
 	    hue += 6.0;
 	  }
 	  var val;
@@ -2628,17 +2628,17 @@ return /******/ (function(modules) { // 
 	    val = n2;
 	  } else if (hue < 4.0) {
 	    val = n1 + (n2 - n1) * (4.0 - hue);
 	  } else {
 	    val = n1;
 	  }
 	  return val;
 	}
-	
+
 	// Taken from dom/tests/mochitest/ajax/mochikit/MochiKit/Color.js
 	// and then modified.
 	function hslToRGB([hue, saturation, lightness]) {
 	  var red;
 	  var green;
 	  var blue;
 	  if (saturation === 0) {
 	    red = lightness;
@@ -2655,59 +2655,59 @@ return /******/ (function(modules) { // 
 	    var f = _hslValue;
 	    var h6 = hue * 6.0;
 	    red = f(m1, m2, h6 + 2);
 	    green = f(m1, m2, h6);
 	    blue = f(m1, m2, h6 - 2);
 	  }
 	  return [red, green, blue];
 	}
-	
+
 	function colorToRGBA(name) {
 	  name = name.trim().toLowerCase();
 	  if (name in cssColors) {
 	    return cssColors[name];
 	  }
-	
+
 	  if (name === "transparent") {
 	    return [0, 0, 0, 0];
 	  }
-	
+
 	  let lexer = getCSSLexer(name);
-	
+
 	  let getToken = function() {
 	    while (true) {
 	      let token = lexer.nextToken();
 	      if (!token || token.tokenType !== "comment" ||
 	          token.tokenType !== "whitespace") {
 	        return token;
 	      }
 	    }
 	  };
-	
+
 	  let requireComma = function(token) {
 	    if (token.tokenType !== "symbol" || token.text !== ",") {
 	      return null;
 	    }
 	    return getToken();
 	  };
-	
+
 	  let func = getToken();
 	  if (!func || func.tokenType !== "function") {
 	    return null;
 	  }
 	  let alpha = false;
 	  if (func.text === "rgb" || func.text === "hsl") {
 	    // Nothing.
 	  } else if (func.text === "rgba" || func.text === "hsla") {
 	    alpha = true;
 	  } else {
 	    return null;
 	  }
-	
+
 	  let vals = [];
 	  for (let i = 0; i < 3; ++i) {
 	    let token = getToken();
 	    if (i > 0) {
 	      token = requireComma(token);
 	    }
 	    if (token.tokenType !== "number" || !token.isInteger) {
 	      return null;
@@ -2715,146 +2715,146 @@ return /******/ (function(modules) { // 
 	    let num = token.number;
 	    if (num < 0) {
 	      num = 0;
 	    } else if (num > 255) {
 	      num = 255;
 	    }
 	    vals.push(num);
 	  }
-	
+
 	  if (func.text === "hsl" || func.text === "hsla") {
 	    vals = hslToRGB(vals);
 	  }
-	
+
 	  if (alpha) {
 	    let token = requireComma(getToken());
 	    if (token.tokenType !== "number") {
 	      return null;
 	    }
 	    let num = token.number;
 	    if (num < 0) {
 	      num = 0;
 	    } else if (num > 1) {
 	      num = 1;
 	    }
 	    vals.push(num);
 	  } else {
 	    vals.push(1);
 	  }
-	
+
 	  let parenToken = getToken();
 	  if (!parenToken || parenToken.tokenType !== "symbol" ||
 	      parenToken.text !== ")") {
 	    return null;
 	  }
 	  if (getToken() !== null) {
 	    return null;
 	  }
-	
+
 	  return vals;
 	}
-	
+
 	function isValidCSSColor(name) {
 	  return colorToRGBA(name) !== null;
 	}
-	
+
 	function isVariable(name) {
 	  return name.startsWith("--");
 	}
-	
+
 	function cssPropertyIsShorthand(name) {
 	  if (isVariable(name)) {
 	    return false;
 	  }
 	  if (!(name in cssProperties)) {
 	    throw Error("unknown property " + name);
 	  }
 	  return !!cssProperties[name].subproperties;
 	}
-	
+
 	function getSubpropertiesForCSSProperty(name) {
 	  if (isVariable(name)) {
 	    return [name];
 	  }
 	  if (!(name in cssProperties)) {
 	    throw Error("unknown property " + name);
 	  }
 	  if ("subproperties" in cssProperties[name]) {
 	    return cssProperties[name].subproperties.slice();
 	  }
 	  return [name];
 	}
-	
+
 	function getCSSValuesForProperty(name) {
 	  if (isVariable(name)) {
 	    return ["initial", "inherit", "unset"];
 	  }
 	  if (!(name in cssProperties)) {
 	    throw Error("unknown property " + name);
 	  }
 	  return cssProperties[name].values.slice();
 	}
-	
+
 	function getCSSPropertyNames(flags) {
 	  let names = Object.keys(cssProperties);
 	  if ((flags & EXCLUDE_SHORTHANDS) !== 0) {
 	    names = names.filter((name) => cssProperties[name].subproperties);
 	  }
 	  if ((flags & INCLUDE_ALIASES) === 0) {
 	    names = names.filter((name) => !cssProperties[name].alias);
 	  }
 	  return names;
 	}
-	
+
 	function cssPropertySupportsType(name, type) {
 	  if (isVariable(name)) {
 	    return false;
 	  }
 	  if (!(name in cssProperties)) {
 	    throw Error("unknown property " + name);
 	  }
 	  return (cssProperties[name].supports & (1 << type)) !== 0;
 	}
-	
+
 	function isInheritedProperty(name) {
 	  if (isVariable(name)) {
 	    return true;
 	  }
 	  if (!(name in cssProperties)) {
 	    return false;
 	  }
 	  return cssProperties[name].inherited;
 	}
-	
+
 	function cssPropertyIsValid(name, value) {
 	  if (isVariable(name)) {
 	    return true;
 	  }
 	  if (!(name in cssProperties)) {
 	    return false;
 	  }
 	  let elt = document.createElement("div");
 	  elt.style = name + ":" + value;
 	  return elt.style.length > 0;
 	}
-	
+
 	exports.inDOMUtils = {
 	  getCSSLexer,
 	  rgbToColorName,
 	  colorToRGBA,
 	  isValidCSSColor,
 	  cssPropertyIsShorthand,
 	  getSubpropertiesForCSSProperty,
 	  getCSSValuesForProperty,
 	  getCSSPropertyNames,
 	  cssPropertySupportsType,
 	  isInheritedProperty,
 	  cssPropertyIsValid,
-	
+
 	  // Constants.
 	  EXCLUDE_SHORTHANDS,
 	  INCLUDE_ALIASES,
 	  TYPE_LENGTH,
 	  TYPE_PERCENTAGE,
 	  TYPE_COLOR,
 	  TYPE_URL,
 	  TYPE_ANGLE,
@@ -2867,117 +2867,117 @@ return /******/ (function(modules) { // 
 	};
 
 
 /***/ },
 /* 37 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;"use strict";
-	
+
 	(function (root, factory) {
 	    // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
 	    // Rhino, and plain browser loading.
 	    if (true) {
 	        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [exports], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 	    } else if (typeof exports !== 'undefined') {
 	        factory(exports);
 	    } else {
 	        factory(root);
 	    }
 	}(this, function (exports) {
-	
+
 	function between(num, first, last) { return num >= first && num <= last; }
 	function digit(code) { return between(code, 0x30,0x39); }
 	function hexdigit(code) { return digit(code) || between(code, 0x41,0x46) || between(code, 0x61,0x66); }
 	function uppercaseletter(code) { return between(code, 0x41,0x5a); }
 	function lowercaseletter(code) { return between(code, 0x61,0x7a); }
 	function letter(code) { return uppercaseletter(code) || lowercaseletter(code); }
 	function nonascii(code) { return code >= 0x80; }
 	function namestartchar(code) { return letter(code) || nonascii(code) || code == 0x5f; }
 	function namechar(code) { return namestartchar(code) || digit(code) || code == 0x2d; }
 	function nonprintable(code) { return between(code, 0,8) || code == 0xb || between(code, 0xe,0x1f) || code == 0x7f; }
 	function newline(code) { return code == 0xa; }
 	function whitespace(code) { return newline(code) || code == 9 || code == 0x20; }
-	
+
 	var maximumallowedcodepoint = 0x10ffff;
-	
+
 	var InvalidCharacterError = function(message) {
 		this.message = message;
 	};
 	InvalidCharacterError.prototype = new Error;
 	InvalidCharacterError.prototype.name = 'InvalidCharacterError';
-	
+
 	function stringFromCode(code) {
 		if(code <= 0xffff) return String.fromCharCode(code);
 		// Otherwise, encode astral char as surrogate pair.
 		code -= Math.pow(2, 20);
 		var lead = Math.floor(code/Math.pow(2, 10)) + 0xd800;
 		var trail = code % Math.pow(2, 10) + 0xdc00;
 		return String.fromCharCode(lead) + String.fromCharCode(trail);
 	}
-	
+
 	function* tokenize(str, options) {
 		if (options === undefined) {
 			options = {};
 		}
 		if (options.loc === undefined) {
 			options.loc = false;
 		}
 		if (options.offsets === undefined) {
 			options.offsets = false;
 		}
 		if (options.keepComments === undefined) {
 			options.keepComments = false;
 		}
 		if (options.startOffset === undefined) {
 			options.startOffset = 0;
 		}
-	
+
 		var i = options.startOffset - 1;
 		var code;
-	
+
 		// Line number information.
 		var line = 0;
 		var column = 0;
 		// The only use of lastLineLength is in reconsume().
 		var lastLineLength = 0;
 		var incrLineno = function() {
 			line += 1;
 			lastLineLength = column;
 			column = 0;
 		};
 		var locStart = {line:line, column:column};
 		var offsetStart = i;
-	
+
 		var codepoint = function(i) {
 			if(i >= str.length) {
 				return -1;
 			}
 			return str.charCodeAt(i);
 		};
 		var next = function(num) {
 			if(num === undefined)
 				num = 1;
 			if(num > 3)
 				throw "Spec Error: no more than three codepoints of lookahead.";
-	
+
 			var rcode;
 			for (var offset = i + 1; num-- > 0; ++offset) {
 				rcode = codepoint(offset);
 				if (rcode === 0xd && codepoint(offset+1) === 0xa) {
 					++offset;
 					rcode = 0xa;
 				} else if (rcode === 0xd || rcode === 0xc) {
 					rcode = 0xa;
 				} else if (rcode === 0x0) {
 					rcode = 0xfffd;
 				}
 			}
-	
+
 			return rcode;
 		};
 		var consume = function(num) {
 			if(num === undefined)
 				num = 1;
 			while(num-- > 0) {
 				++i;
 				code = codepoint(i);
@@ -3005,17 +3005,17 @@ return /******/ (function(modules) { // 
 			return true;
 		};
 		var eof = function(codepoint) {
 			if(codepoint === undefined) codepoint = code;
 			return codepoint == -1;
 		};
 		var donothing = function() {};
 		var parseerror = function() { console.log("Parse error at index " + i + ", processing codepoint 0x" + code.toString(16) + ".");return true; };
-	
+
 		var consumeAToken = function() {
 			consume();
 			if (!options.keepComments) {
 				while(code == 0x2f && next() == 0x2a) {
 					consumeAComment();
 					consume();
 				}
 			}
@@ -3155,33 +3155,33 @@ return /******/ (function(modules) { // 
 			}
 			else if(namestartchar(code)) {
 				reconsume();
 				return consumeAnIdentlikeToken();
 			}
 			else if(eof()) return new EOFToken();
 			else return new DelimToken(code);
 		};
-	
+
 		var consumeAComment = function() {
 			consume();
 			var comment = "";
 			while(true) {
 				consume();
 				if(code == 0x2a && next() == 0x2f) {
 					consume();
 					break;
 				} else if(eof()) {
 					break;
 				}
 				comment += stringFromCode(code);
 			}
 			return new CommentToken(comment);
 		};
-	
+
 		var consumeANumericToken = function() {
 			var num = consumeANumber();
 			var token;
 			if(wouldStartAnIdentifier(next(1), next(2), next(3))) {
 				token = new DimensionToken();
 				token.value = num.value;
 				token.repr = num.repr;
 				token.type = num.type;
@@ -3198,17 +3198,17 @@ return /******/ (function(modules) { // 
 				token.repr = num.repr;
 				token.type = num.type;
 			}
 			token.number = token.value;
 			token.isInteger = token.type === "integer";
 			// FIXME hasSign
 			return token;
 		};
-	
+
 		var consumeAnIdentlikeToken = function() {
 			var str = consumeAName();
 			if(str.toLowerCase() == "url" && next() == 0x28) {
 				consume();
 				while(whitespace(next(1)) && whitespace(next(2)))
 					consume();
 				if((next() == 0x22 || next() == 0x27) ||
 				   (whitespace(next()) && (next(2) == 0x22 || next(2) == 0x27))) {
@@ -3226,17 +3226,17 @@ return /******/ (function(modules) { // 
 				}
 			} else if(next() == 0x28) {
 				consume();
 				return new FunctionToken(str);
 			} else {
 				return new IdentToken(str);
 			}
 		};
-	
+
 		var consumeAStringToken = function(endingCodePoint) {
 			if(endingCodePoint === undefined) endingCodePoint = code;
 			var string = "";
 			while(consume()) {
 				if(code == endingCodePoint || eof()) {
 					return new StringToken(string);
 				} else if(newline(code)) {
 					reconsume();
@@ -3249,17 +3249,17 @@ return /******/ (function(modules) { // 
 					} else {
 						string += stringFromCode(consumeEscape());
 					}
 				} else {
 					string += stringFromCode(code);
 				}
 			}
 		};
-	
+
 		var consumeAURLToken = function() {
 			var token = new URLToken("");
 			while(whitespace(next())) consume();
 			if(eof(next())) return token;
 			while(consume()) {
 				if(code == 0x29 || eof()) {
 					break;
 				} else if(whitespace(code)) {
@@ -3286,17 +3286,17 @@ return /******/ (function(modules) { // 
 					}
 				} else {
 					token.value += stringFromCode(code);
 				}
 			}
 			token.text = token.value;
 			return token;
 		};
-	
+
 		var consumeEscape = function() {
 			// Assume the the current character is the \
 			// and the next code point is not a newline.
 			consume();
 			if(hexdigit(code)) {
 				// Consume 1-6 hex digits
 				var digits = [code];
 				for(var total = 0; total < 5; total++) {
@@ -3312,41 +3312,41 @@ return /******/ (function(modules) { // 
 				if( value > maximumallowedcodepoint ) value = 0xfffd;
 				return value;
 			} else if(eof()) {
 				return 0xfffd;
 			} else {
 				return code;
 			}
 		};
-	
+
 		var areAValidEscape = function(c1, c2) {
 			if(c1 != 0x5c) return false;
 			if(newline(c2)) return false;
 			return true;
 		};
 		var startsWithAValidEscape = function() {
 			return areAValidEscape(code, next());
 		};
-	
+
 		var wouldStartAnIdentifier = function(c1, c2, c3) {
 			if(c1 == 0x2d) {
 				return namestartchar(c2) || c2 == 0x2d || areAValidEscape(c2, c3);
 			} else if(namestartchar(c1)) {
 				return true;
 			} else if(c1 == 0x5c) {
 				return areAValidEscape(c1, c2);
 			} else {
 				return false;
 			}
 		};
 		var startsWithAnIdentifier = function() {
 			return wouldStartAnIdentifier(code, next(1), next(2));
 		};
-	
+
 		var wouldStartANumber = function(c1, c2, c3) {
 			if(c1 == 0x2b || c1 == 0x2d) {
 				if(digit(c2)) return true;
 				if(c2 == 0x2e && digit(c3)) return true;
 				return false;
 			} else if(c1 == 0x2e) {
 				if(digit(c2)) return true;
 				return false;
@@ -3354,31 +3354,31 @@ return /******/ (function(modules) { // 
 				return true;
 			} else {
 				return false;
 			}
 		};
 		var startsWithANumber = function() {
 			return wouldStartANumber(code, next(1), next(2));
 		};
-	
+
 		var consumeAName = function() {
 			var result = "";
 			while(consume()) {
 				if(namechar(code)) {
 					result += stringFromCode(code);
 				} else if(startsWithAValidEscape()) {
 					result += stringFromCode(consumeEscape());
 				} else {
 					reconsume();
 					return result;
 				}
 			}
 		};
-	
+
 		var consumeANumber = function() {
 			var repr = [];
 			var type = "integer";
 			if(next() == 0x2b || next() == 0x2d) {
 				consume();
 				repr += stringFromCode(code);
 			}
 			while(digit(next())) {
@@ -3418,37 +3418,37 @@ return /******/ (function(modules) { // 
 				while(digit(next())) {
 					consume();
 					repr += stringFromCode(code);
 				}
 			}
 			var value = convertAStringToANumber(repr);
 			return {type:type, value:value, repr:repr};
 		};
-	
+
 		var convertAStringToANumber = function(string) {
 			// CSS's number rules are identical to JS, afaik.
 			return +string;
 		};
-	
+
 		var consumeTheRemnantsOfABadURL = function() {
 			while(consume()) {
 				if(code == 0x2d || eof()) {
 					return;
 				} else if(startsWithAValidEscape()) {
 					consumeEscape();
 					donothing();
 				} else {
 					donothing();
 				}
 			}
 		};
-	
-	
-	
+
+
+
 		var iterationCount = 0;
 		while(!eof(next())) {
 			var token = consumeAToken();
 			if (options.loc) {
 				token.loc = {};
 				token.loc.start = {line:locStart.line, column:locStart.column};
 				token.loc.end = {line:line, column:column};
 			}
@@ -3456,128 +3456,128 @@ return /******/ (function(modules) { // 
 				token.startOffset = offsetStart;
 				token.endOffset = i + 1;
 			}
 			yield token;
 			iterationCount++;
 			if(iterationCount > str.length*2) return "I'm infinite-looping!";
 		}
 	}
-	
+
 	function CSSParserToken() { throw "Abstract Base Class"; }
 	CSSParserToken.prototype.toJSON = function() {
 		return {token: this.tokenType};
 	};
 	CSSParserToken.prototype.toString = function() { return this.tokenType; };
 	CSSParserToken.prototype.toSource = function() { return ''+this; };
-	
+
 	function BadStringToken(text) {
 		this.text = text;
 		return this;
 	}
 	BadStringToken.prototype = Object.create(CSSParserToken.prototype);
 	BadStringToken.prototype.tokenType = "bad_string";
-	
+
 	function BadURLToken() { return this; }
 	BadURLToken.prototype = Object.create(CSSParserToken.prototype);
 	BadURLToken.prototype.tokenType = "bad_url";
-	
+
 	function WhitespaceToken() { return this; }
 	WhitespaceToken.prototype = Object.create(CSSParserToken.prototype);
 	WhitespaceToken.prototype.tokenType = "whitespace";
 	WhitespaceToken.prototype.toString = function() { return "WS"; };
 	WhitespaceToken.prototype.toSource = function() { return " "; };
-	
+
 	function CDOToken() { return this; }
 	CDOToken.prototype = Object.create(CSSParserToken.prototype);
 	CDOToken.prototype.tokenType = "htmlcomment";
 	CDOToken.prototype.toSource = function() { return "<!--"; };
-	
+
 	function CDCToken() { return this; }
 	CDCToken.prototype = Object.create(CSSParserToken.prototype);
 	CDCToken.prototype.tokenType = "htmlcomment";
 	CDCToken.prototype.toSource = function() { return "-->"; };
-	
+
 	function ColonToken() { return this; }
 	ColonToken.prototype = Object.create(CSSParserToken.prototype);
 	ColonToken.prototype.tokenType = "symbol";
 	ColonToken.prototype.text = ":";
-	
+
 	function SemicolonToken() { return this; }
 	SemicolonToken.prototype = Object.create(CSSParserToken.prototype);
 	SemicolonToken.prototype.tokenType = "symbol";
 	SemicolonToken.prototype.text = ";";
-	
+
 	function CommaToken() { return this; }
 	CommaToken.prototype = Object.create(CSSParserToken.prototype);
 	CommaToken.prototype.tokenType = "symbol";
 	CommaToken.prototype.text = ",";
-	
+
 	function GroupingToken() { throw "Abstract Base Class"; }
 	GroupingToken.prototype = Object.create(CSSParserToken.prototype);
-	
+
 	function OpenCurlyToken() { this.value = "{"; this.mirror = "}"; return this; }
 	OpenCurlyToken.prototype = Object.create(GroupingToken.prototype);
 	OpenCurlyToken.prototype.tokenType = "symbol";
 	OpenCurlyToken.prototype.text = "{";
-	
+
 	function CloseCurlyToken() { this.value = "}"; this.mirror = "{"; return this; }
 	CloseCurlyToken.prototype = Object.create(GroupingToken.prototype);
 	CloseCurlyToken.prototype.tokenType = "symbol";
 	CloseCurlyToken.prototype.text = "}";
-	
+
 	function OpenSquareToken() { this.value = "["; this.mirror = "]"; return this; }
 	OpenSquareToken.prototype = Object.create(GroupingToken.prototype);
 	OpenSquareToken.prototype.tokenType = "symbol";
 	OpenSquareToken.prototype.text = "[";
-	
+
 	function CloseSquareToken() { this.value = "]"; this.mirror = "["; return this; }
 	CloseSquareToken.prototype = Object.create(GroupingToken.prototype);
 	CloseSquareToken.prototype.tokenType = "symbol";
 	CloseSquareToken.prototype.text = "]";
-	
+
 	function OpenParenToken() { this.value = "("; this.mirror = ")"; return this; }
 	OpenParenToken.prototype = Object.create(GroupingToken.prototype);
 	OpenParenToken.prototype.tokenType = "symbol";
 	OpenParenToken.prototype.text = "(";
-	
+
 	function CloseParenToken() { this.value = ")"; this.mirror = "("; return this; }
 	CloseParenToken.prototype = Object.create(GroupingToken.prototype);
 	CloseParenToken.prototype.tokenType = "symbol";
 	CloseParenToken.prototype.text = ")";
-	
+
 	function IncludeMatchToken() { return this; }
 	IncludeMatchToken.prototype = Object.create(CSSParserToken.prototype);
 	IncludeMatchToken.prototype.tokenType = "includes";
-	
+
 	function DashMatchToken() { return this; }
 	DashMatchToken.prototype = Object.create(CSSParserToken.prototype);
 	DashMatchToken.prototype.tokenType = "dashmatch";
-	
+
 	function PrefixMatchToken() { return this; }
 	PrefixMatchToken.prototype = Object.create(CSSParserToken.prototype);
 	PrefixMatchToken.prototype.tokenType = "beginsmatch";
-	
+
 	function SuffixMatchToken() { return this; }
 	SuffixMatchToken.prototype = Object.create(CSSParserToken.prototype);
 	SuffixMatchToken.prototype.tokenType = "endsmatch";
-	
+
 	function SubstringMatchToken() { return this; }
 	SubstringMatchToken.prototype = Object.create(CSSParserToken.prototype);
 	SubstringMatchToken.prototype.tokenType = "containsmatch";
-	
+
 	function ColumnToken() { return this; }
 	ColumnToken.prototype = Object.create(CSSParserToken.prototype);
 	ColumnToken.prototype.tokenType = "||";
-	
+
 	function EOFToken() { return this; }
 	EOFToken.prototype = Object.create(CSSParserToken.prototype);
 	EOFToken.prototype.tokenType = "EOF";
 	EOFToken.prototype.toSource = function() { return ""; };
-	
+
 	function DelimToken(code) {
 		this.value = stringFromCode(code);
 		this.text = this.value;
 		return this;
 	}
 	DelimToken.prototype = Object.create(CSSParserToken.prototype);
 	DelimToken.prototype.tokenType = "symbol";
 	DelimToken.prototype.toString = function() { return "DELIM("+this.value+")"; };
@@ -3587,62 +3587,62 @@ return /******/ (function(modules) { // 
 		return json;
 	};
 	DelimToken.prototype.toSource = function() {
 		if(this.value == "\\")
 			return "\\\n";
 		else
 			return this.value;
 	};
-	
+
 	function StringValuedToken() { throw "Abstract Base Class"; }
 	StringValuedToken.prototype = Object.create(CSSParserToken.prototype);
 	StringValuedToken.prototype.ASCIIMatch = function(str) {
 		return this.value.toLowerCase() == str.toLowerCase();
 	};
 	StringValuedToken.prototype.toJSON = function() {
 		var json = this.constructor.prototype.constructor.prototype.toJSON.call(this);
 		json.value = this.value;
 		return json;
 	};
-	
+
 	function IdentToken(val) {
 		this.value = val;
 		this.text = val;
 	}
 	IdentToken.prototype = Object.create(StringValuedToken.prototype);
 	IdentToken.prototype.tokenType = "ident";
 	IdentToken.prototype.toString = function() { return "IDENT("+this.value+")"; };
 	IdentToken.prototype.toSource = function() {
 		return escapeIdent(this.value);
 	};
-	
+
 	function FunctionToken(val) {
 		this.value = val;
 		this.text = val;
 		this.mirror = ")";
 	}
 	FunctionToken.prototype = Object.create(StringValuedToken.prototype);
 	FunctionToken.prototype.tokenType = "function";
 	FunctionToken.prototype.toString = function() { return "FUNCTION("+this.value+")"; };
 	FunctionToken.prototype.toSource = function() {
 		return escapeIdent(this.value) + "(";
 	};
-	
+
 	function AtKeywordToken(val) {
 		this.value = val;
 		this.text = val;
 	}
 	AtKeywordToken.prototype = Object.create(StringValuedToken.prototype);
 	AtKeywordToken.prototype.tokenType = "at";
 	AtKeywordToken.prototype.toString = function() { return "AT("+this.value+")"; };
 	AtKeywordToken.prototype.toSource = function() {
 		return "@" + escapeIdent(this.value);
 	};
-	
+
 	function HashToken(val) {
 		this.value = val;
 		this.text = val;
 		this.type = "unrestricted";
 	}
 	HashToken.prototype = Object.create(StringValuedToken.prototype);
 	HashToken.prototype.tokenType = "hash";
 	HashToken.prototype.toString = function() { return "HASH("+this.value+")"; };
@@ -3654,48 +3654,48 @@ return /******/ (function(modules) { // 
 	};
 	HashToken.prototype.toSource = function() {
 		if(this.type == "id") {
 			return "#" + escapeIdent(this.value);
 		} else {
 			return "#" + escapeHash(this.value);
 		}
 	};
-	
+
 	function StringToken(val) {
 		this.value = val;
 		this.text = val;
 	}
 	StringToken.prototype = Object.create(StringValuedToken.prototype);
 	StringToken.prototype.tokenType = "string";
 	StringToken.prototype.toString = function() {
 		return '"' + escapeString(this.value) + '"';
 	};
-	
+
 	function CommentToken(val) {
 		this.value = val;
 	}
 	CommentToken.prototype = Object.create(StringValuedToken.prototype);
 	CommentToken.prototype.tokenType = "comment";
 	CommentToken.prototype.toString = function() {
 		return '/*' + this.value + '*/';
 	}
 	CommentToken.prototype.toSource = CommentToken.prototype.toString;
-	
+
 	function URLToken(val) {
 		this.value = val;
 		this.text = val;
 	}
 	URLToken.prototype = Object.create(StringValuedToken.prototype);
 	URLToken.prototype.tokenType = "url";
 	URLToken.prototype.toString = function() { return "URL("+this.value+")"; };
 	URLToken.prototype.toSource = function() {
 		return 'url("' + escapeString(this.value) + '")';
 	};
-	
+
 	function NumberToken() {
 		this.value = null;
 		this.type = "integer";
 		this.repr = "";
 	}
 	NumberToken.prototype = Object.create(CSSParserToken.prototype);
 	NumberToken.prototype.tokenType = "number";
 	NumberToken.prototype.toString = function() {
@@ -3706,32 +3706,32 @@ return /******/ (function(modules) { // 
 	NumberToken.prototype.toJSON = function() {
 		var json = this.constructor.prototype.constructor.prototype.toJSON.call(this);
 		json.value = this.value;
 		json.type = this.type;
 		json.repr = this.repr;
 		return json;
 	};
 	NumberToken.prototype.toSource = function() { return this.repr; };
-	
+
 	function PercentageToken() {
 		this.value = null;
 		this.repr = "";
 	}
 	PercentageToken.prototype = Object.create(CSSParserToken.prototype);
 	PercentageToken.prototype.tokenType = "percentage";
 	PercentageToken.prototype.toString = function() { return "PERCENTAGE("+this.value+")"; };
 	PercentageToken.prototype.toJSON = function() {
 		var json = this.constructor.prototype.constructor.prototype.toJSON.call(this);
 		json.value = this.value;
 		json.repr = this.repr;
 		return json;
 	};
 	PercentageToken.prototype.toSource = function() { return this.repr + "%"; };
-	
+
 	function DimensionToken() {
 		this.value = null;
 		this.type = "integer";
 		this.repr = "";
 		this.unit = "";
 	}
 	DimensionToken.prototype = Object.create(CSSParserToken.prototype);
 	DimensionToken.prototype.tokenType = "dimension";
@@ -3749,27 +3749,27 @@ return /******/ (function(modules) { // 
 		var unit = escapeIdent(this.unit);
 		if(unit[0].toLowerCase() == "e" && (unit[1] == "-" || between(unit.charCodeAt(1), 0x30, 0x39))) {
 			// Unit is ambiguous with scinot
 			// Remove the leading "e", replace with escape.
 			unit = "\\65 " + unit.slice(1, unit.length);
 		}
 		return source+unit;
 	};
-	
+
 	function escapeIdent(string) {
 		string = ''+string;
 		var result = '';
 		var firstcode = string.charCodeAt(0);
 		for(var i = 0; i < string.length; i++) {
 			var code = string.charCodeAt(i);
 			if(code === 0x0) {
 				throw new InvalidCharacterError('Invalid character: the input contains U+0000.');
 			}
-	
+
 			if(
 				between(code, 0x1, 0x1f) || code == 0x7f ||
 				(i === 0 && between(code, 0x30, 0x39)) ||
 				(i == 1 && between(code, 0x30, 0x39) && firstcode == 0x2d)
 			) {
 				result += '\\' + code.toString(16) + ' ';
 			} else if(
 				code >= 0x80 ||
@@ -3781,66 +3781,66 @@ return /******/ (function(modules) { // 
 			) {
 				result += string[i];
 			} else {
 				result += '\\' + string[i];
 			}
 		}
 		return result;
 	}
-	
+
 	function escapeHash(string) {
 		// Escapes the contents of "unrestricted"-type hash tokens.
 		// Won't preserve the ID-ness of "id"-type hash tokens;
 		// use escapeIdent() for that.
 		string = ''+string;
 		var result = '';
 		for(var i = 0; i < string.length; i++) {
 			var code = string.charCodeAt(i);
 			if(code === 0x0) {
 				throw new InvalidCharacterError('Invalid character: the input contains U+0000.');
 			}
-	
+
 			if(
 				code >= 0x80 ||
 				code == 0x2d ||
 				code == 0x5f ||
 				between(code, 0x30, 0x39) ||
 				between(code, 0x41, 0x5a) ||
 				between(code, 0x61, 0x7a)
 			) {
 				result += string[i];
 			} else {
 				result += '\\' + code.toString(16) + ' ';
 			}
 		}
 		return result;
 	}
-	
+
 	function escapeString(string) {
 		string = ''+string;
 		var result = '';
 		for(var i = 0; i < string.length; i++) {
 			var code = string.charCodeAt(i);
-	
+
 			if(code === 0x0) {
 				throw new InvalidCharacterError('Invalid character: the input contains U+0000.');
 			}
-	
+
 			if(between(code, 0x1, 0x1f) || code == 0x7f) {
 				result += '\\' + code.toString(16) + ' ';
 			} else if(code == 0x22 || code == 0x5c) {
 				result += '\\' + string[i];
 			} else {
 				result += string[i];
 			}
 		}
 		return result;
 	}
-	
+
 	// Exportation.
 	exports.tokenize = tokenize;
 	exports.IdentToken = IdentToken;
 	exports.FunctionToken = FunctionToken;
 	exports.AtKeywordToken = AtKeywordToken;
 	exports.HashToken = HashToken;
 	exports.StringToken = StringToken;
 	exports.BadStringToken = BadStringToken;
@@ -3866,17 +3866,17 @@ return /******/ (function(modules) { // 
 	exports.CloseParenToken = CloseParenToken;
 	exports.OpenSquareToken = OpenSquareToken;
 	exports.CloseSquareToken = CloseSquareToken;
 	exports.OpenCurlyToken = OpenCurlyToken;
 	exports.CloseCurlyToken = CloseCurlyToken;
 	exports.EOFToken = EOFToken;
 	exports.CSSParserToken = CSSParserToken;
 	exports.GroupingToken = GroupingToken;
-	
+
 	function TokenStream(tokens) {
 		// Assume that tokens is a iterator.
 		this.tokens = tokens;
 		this.token = undefined;
 		this.stored = [];
 	}
 	TokenStream.prototype.consume = function(num) {
 		if(num === undefined) num = 1;
@@ -3908,23 +3908,23 @@ return /******/ (function(modules) { // 
 				return new EOFToken();
 			this.stored.push(n.value);
 		}
 		return this.stored[0];
 	};
 	TokenStream.prototype.reconsume = function() {
 		this.stored.unshift(this.token);
 	};
-	
+
 	function parseerror(s, msg) {
 		console.log("Parse error at token " + s.i + ": " + s.token + ".\n" + msg);
 		return true;
 	}
 	function donothing(){ return true; }
-	
+
 	function consumeAListOfRules(s, topLevel) {
 		var rules = [];
 		var rule;
 		while(s.consume()) {
 			if(s.token instanceof WhitespaceToken) {
 				continue;
 			} else if(s.token instanceof EOFToken) {
 				return rules;
@@ -3936,49 +3936,49 @@ return /******/ (function(modules) { // 
 				s.reconsume();
 				if(rule = consumeAnAtRule(s)) rules.push(rule);
 			} else {
 				s.reconsume();
 				if(rule = consumeAQualifiedRule(s)) rules.push(rule);
 			}
 		}
 	}
-	
+
 	function consumeAnAtRule(s) {
 		s.consume();
 		var rule = new AtRule(s.token.value);
 		while(s.consume()) {
 			if(s.token instanceof SemicolonToken || s.token instanceof EOFToken) {
 				return rule;
 			} else if(s.token instanceof OpenCurlyToken) {
 				rule.value = consumeASimpleBlock(s);
 				return rule;
 			} else {
 				s.reconsume();
 				rule.prelude.push(consumeAComponentValue(s));
 			}
 		}
 	}
-	
+
 	function consumeAQualifiedRule(s) {
 		var rule = new QualifiedRule();
 		while(s.consume()) {
 			if(s.token instanceof EOFToken) {
 				parseerror(s, "Hit EOF when trying to parse the prelude of a qualified rule.");
 				return;
 			} else if(s.token instanceof OpenCurlyToken) {
 				rule.value = consumeASimpleBlock(s);
 				return rule;
 			} else {
 				s.reconsume();
 				rule.prelude.push(consumeAComponentValue(s));
 			}
 		}
 	}
-	
+
 	function consumeAListOfDeclarations(s) {
 		var decls = [];
 		while(s.consume()) {
 			if(s.token instanceof WhitespaceToken || s.token instanceof SemicolonToken) {
 				donothing();
 			} else if(s.token instanceof EOFToken) {
 				return decls;
 			} else if(s.token instanceof AtKeywordToken) {
@@ -3993,17 +3993,17 @@ return /******/ (function(modules) { // 
 			} else {
 				parseerror(s);
 				s.reconsume();
 				while(!(s.next() instanceof SemicolonToken || s.next() instanceof EOFToken))
 					consumeAComponentValue(s);
 			}
 		}
 	}
-	
+
 	function consumeADeclaration(s) {
 		// Assumes that the next input token will be an ident token.
 		s.consume();
 		var decl = new Declaration(s.token.value);
 		while(s.next() instanceof WhitespaceToken) s.consume();
 		if(!(s.next() instanceof ColonToken)) {
 			parseerror(s);
 			return;
@@ -4024,133 +4024,133 @@ return /******/ (function(modules) { // 
 				decl.important = true;
 				break;
 			} else {
 				break;
 			}
 		}
 		return decl;
 	}
-	
+
 	function consumeAComponentValue(s) {
 		s.consume();
 		if(s.token instanceof OpenCurlyToken || s.token instanceof OpenSquareToken || s.token instanceof OpenParenToken)
 			return consumeASimpleBlock(s);
 		if(s.token instanceof FunctionToken)
 			return consumeAFunction(s);
 		return s.token;
 	}
-	
+
 	function consumeASimpleBlock(s) {
 		var mirror = s.token.mirror;
 		var block = new SimpleBlock(s.token.value);
 		block.startToken = s.token;
 		while(s.consume()) {
 			if(s.token instanceof EOFToken || (s.token instanceof GroupingToken && s.token.value == mirror))
 				return block;
 			else {
 				s.reconsume();
 				block.value.push(consumeAComponentValue(s));
 			}
 		}
 	}
-	
+
 	function consumeAFunction(s) {
 		var func = new Func(s.token.value);
 		while(s.consume()) {
 			if(s.token instanceof EOFToken || s.token instanceof CloseParenToken)
 				return func;
 			else {
 				s.reconsume();
 				func.value.push(consumeAComponentValue(s));
 			}
 		}
 	}
-	
+
 	function normalizeInput(input) {
 		if(typeof input == "string")
 			return new TokenStream(tokenize(input));
 		if(input instanceof TokenStream)
 			return input;
 		if(typeof (input.next) == "function")
 			return new TokenStream(input);
 		if(input.length !== undefined)
 			return new TokenStream(input[Symbol.iterator]());
 		else throw SyntaxError(input);
 	}
-	
+
 	function parseAStylesheet(s) {
 		s = normalizeInput(s);
 		var sheet = new Stylesheet();
 		sheet.value = consumeAListOfRules(s, "top-level");
 		return sheet;
 	}
-	
+
 	function parseAListOfRules(s) {
 		s = normalizeInput(s);
 		return consumeAListOfRules(s);
 	}
-	
+
 	function parseARule(s) {
 		s = normalizeInput(s);
 		while(s.next() instanceof WhitespaceToken) s.consume();
 		if(s.next() instanceof EOFToken) throw SyntaxError();
 		var rule;
 		var startToken = s.next();
 		if(startToken instanceof AtKeywordToken) {
 			rule = consumeAnAtRule(s);
 		} else {
 			rule = consumeAQualifiedRule(s);
 			if(!rule) throw SyntaxError();
 		}
 		rule.startToken = startToken;
 		rule.endToken = s.token;
 		return rule;
 	}
-	
+
 	function parseADeclaration(s) {
 		s = normalizeInput(s);
 		while(s.next() instanceof WhitespaceToken) s.consume();
 		if(!(s.next() instanceof IdentToken)) throw SyntaxError();
 		var decl = consumeADeclaration(s);
 		if(decl)
 			return decl;
 		else
 			throw SyntaxError();
 	}
-	
+
 	function parseAListOfDeclarations(s) {
 		s = normalizeInput(s);
 		return consumeAListOfDeclarations(s);
 	}
-	
+
 	function parseAComponentValue(s) {
 		s = normalizeInput(s);
 		while(s.next() instanceof WhitespaceToken) s.consume();
 		if(s.next() instanceof EOFToken) throw SyntaxError();
 		var val = consumeAComponentValue(s);
 		if(!val) throw SyntaxError();
 		while(s.next() instanceof WhitespaceToken) s.consume();
 		if(s.next() instanceof EOFToken)
 			return val;
 		throw SyntaxError();
 	}
-	
+
 	function parseAListOfComponentValues(s) {
 		s = normalizeInput(s);
 		var vals = [];
 		while(true) {
 			var val = consumeAComponentValue(s);
 			if(val instanceof EOFToken)
 				return vals;
 			else
 				vals.push(val);
 		}
 	}
-	
+
 	function parseACommaSeparatedListOfComponentValues(s) {
 		s = normalizeInput(s);
 		var listOfCVLs = [];
 		while(true) {
 			var vals = [];
 			while(true) {
 				var val = consumeAComponentValue(s);
 				if(val instanceof EOFToken) {
@@ -4160,132 +4160,132 @@ return /******/ (function(modules) { // 
 					listOfCVLs.push(vals);
 					break;
 				} else {
 					vals.push(val);
 				}
 			}
 		}
 	}
-	
-	
+
+
 	function CSSParserRule() { throw "Abstract Base Class"; }
 	CSSParserRule.prototype.toString = function(indent) {
 		return JSON.stringify(this,null,indent);
 	};
 	CSSParserRule.prototype.toJSON = function() {
 		return {type:this.type, value:this.value};
 	};
-	
+
 	function Stylesheet() {
 		this.value = [];
 		return this;
 	}
 	Stylesheet.prototype = Object.create(CSSParserRule.prototype);
 	Stylesheet.prototype.type = "STYLESHEET";
-	
+
 	function AtRule(name) {
 		this.name = name;
 		this.prelude = [];
 		this.value = null;
 		return this;
 	}
 	AtRule.prototype = Object.create(CSSParserRule.prototype);
 	AtRule.prototype.type = "AT-RULE";
 	AtRule.prototype.toJSON = function() {
 		var json = this.constructor.prototype.constructor.prototype.toJSON.call(this);
 		json.name = this.name;
 		json.prelude = this.prelude;
 		return json;
 	};
-	
+
 	function QualifiedRule() {
 		this.prelude = [];
 		this.value = [];
 		return this;
 	}
 	QualifiedRule.prototype = Object.create(CSSParserRule.prototype);
 	QualifiedRule.prototype.type = "QUALIFIED-RULE";
 	QualifiedRule.prototype.toJSON = function() {
 		var json = this.constructor.prototype.constructor.prototype.toJSON.call(this);
 		json.prelude = this.prelude;
 		return json;
 	};
-	
+
 	function Declaration(name) {
 		this.name = name;
 		this.value = [];
 		this.important = false;
 		return this;
 	}
 	Declaration.prototype = Object.create(CSSParserRule.prototype);
 	Declaration.prototype.type = "DECLARATION";
 	Declaration.prototype.toJSON = function() {
 		var json = this.constructor.prototype.constructor.prototype.toJSON.call(this);
 		json.name = this.name;
 		json.important = this.important;
 		return json;
 	};
-	
+
 	function SimpleBlock(type) {
 		this.name = type;
 		this.value = [];
 		return this;
 	}
 	SimpleBlock.prototype = Object.create(CSSParserRule.prototype);
 	SimpleBlock.prototype.type = "BLOCK";
 	SimpleBlock.prototype.toJSON = function() {
 		var json = this.constructor.prototype.constructor.prototype.toJSON.call(this);
 		json.name = this.name;
 		return json;
 	};
-	
+
 	function Func(name) {
 		this.name = name;
 		this.value = [];
 		return this;
 	}
 	Func.prototype = Object.create(CSSParserRule.prototype);
 	Func.prototype.type = "FUNCTION";
 	Func.prototype.toJSON = function() {
 		var json = this.constructor.prototype.constructor.prototype.toJSON.call(this);
 		json.name = this.name;
 		return json;
 	};
-	
+
 	function CSSLexer(text) {
 		this.stream = tokenize(text, {
 			loc: true,
 			offsets: true,
 			keepComments: true
 		});
 		this.lineNumber = 0;
 		this.columnNumber = 0;
 		return this;
 	}
-	
+
 	CSSLexer.prototype.performEOFFixup = function(input, preserveBackslash) {
 		// Just lie for now.
 		return "";
 	};
-	
+
 	CSSLexer.prototype.nextToken = function() {
 		if (!this.stream) {
 			return null;
 		}
 		let v = this.stream.next();
 		if (v.done || v.value.tokenType === "EOF") {
 			this.stream = null;
 			return null;
 		}
 		this.lineNumber = v.value.loc.start.line;
 		this.columnNumber = v.value.loc.start.column;
 		return v.value;
 	};
-	
+
 	// Exportation.
 	exports.CSSParserRule = CSSParserRule;
 	exports.Stylesheet = Stylesheet;
 	exports.AtRule = AtRule;
 	exports.QualifiedRule = QualifiedRule;
 	exports.Declaration = Declaration;
 	exports.SimpleBlock = SimpleBlock;
 	exports.Func = Func;
@@ -4293,17 +4293,17 @@ return /******/ (function(modules) { // 
 	exports.parseAListOfRules = parseAListOfRules;
 	exports.parseARule = parseARule;
 	exports.parseADeclaration = parseADeclaration;
 	exports.parseAListOfDeclarations = parseAListOfDeclarations;
 	exports.parseAComponentValue = parseAComponentValue;
 	exports.parseAListOfComponentValues = parseAListOfComponentValues;
 	exports.parseACommaSeparatedListOfComponentValues = parseACommaSeparatedListOfComponentValues;
 	exports.CSSLexer = CSSLexer;
-	
+
 	}));
 
 
 /***/ },
 /* 38 */
 /***/ function(module, exports) {
 
 	// auto-generated from nsColorNameList.h
@@ -6601,67 +6601,67 @@ return /******/ (function(modules) { // 
 
 /***/ },
 /* 40 */
 /***/ function(module, exports) {
 
 	/*
 	 * A sham for https://dxr.mozilla.org/mozilla-central/source/toolkit/modules/Promise.jsm
 	 */
-	
+
 	/**
 	 * Promise.jsm is mostly the Promise web API with a `defer` method. Just drop this in here,
 	 * and use the native web API (although building with webpack/babel, it may replace this
 	 * with it's own version if we want to target environments that do not have `Promise`.
 	 */
-	
+
 	let p = typeof window != "undefined" ?  window.Promise : Promise;
 	p.defer = function defer() {
 	  var resolve, reject;
 	  var promise = new Promise(function() {
 	    resolve = arguments[0];
 	    reject = arguments[1];
 	  });
 	  return {
 	    resolve: resolve,
 	    reject: reject,
 	    promise: promise
 	  };
 	}
-	
+
 	module.exports = p;
 
 
 /***/ },
 /* 41 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* eslint-env browser */
 	/* -*- 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/. */
-	
+
 	// TODO: Get rid of this code once the marionette server loads transport.js as
 	// an SDK module (see bug 1000814)
-	
-	"use strict";
-	
+
+	"use strict";
+
 	const DevToolsUtils = __webpack_require__(42);
 	const { dumpn, dumpv } = DevToolsUtils;
 	const StreamUtils = __webpack_require__(48);
 	const { Packet, JSONPacket, BulkPacket } =
 	  __webpack_require__(49);
 	const promise = __webpack_require__(40);
 	const EventEmitter = __webpack_require__(34);
 	const utf8 = __webpack_require__(52);
-	
+
 	const PACKET_HEADER_MAX = 200;
-	
+
 	/**
 	 * An adapter that handles data transfers between the debugger client and
 	 * server. It can work with both nsIPipe and nsIServerSocket transports so
 	 * long as the properly created input and output streams are specified.
 	 * (However, for intra-process connections, LocalDebuggerTransport, below,
 	 * is more efficient than using an nsIPipe pair with DebuggerTransport.)
 	 *
 	 * @param input nsIAsyncInputStream
@@ -6711,54 +6711,54 @@ return /******/ (function(modules) { // 
 	 *   an optional nsresult or object, typically passed when the transport is
 	 *   closed due to some error in a underlying stream.
 	 *
 	 * See ./packets.js and the Remote Debugging Protocol specification for more
 	 * details on the format of these packets.
 	 */
 	function DebuggerTransport(socket) {
 	  EventEmitter.decorate(this);
-	
+
 	  this._socket = socket;
-	
+
 	  // The current incoming (possibly partial) header, which will determine which
 	  // type of Packet |_incoming| below will become.
 	  this._incomingHeader = "";
 	  // The current incoming Packet object
 	  this._incoming = null;
 	  // A queue of outgoing Packet objects
 	  this._outgoing = [];
-	
+
 	  this.hooks = null;
 	  this.active = false;
-	
+
 	  this._incomingEnabled = true;
 	  this._outgoingEnabled = true;
-	
+
 	  this.close = this.close.bind(this);
 	}
-	
+
 	DebuggerTransport.prototype = {
 	  /**
 	   * Transmit an object as a JSON packet.
 	   *
 	   * This method returns immediately, without waiting for the entire
 	   * packet to be transmitted, registering event handlers as needed to
 	   * transmit the entire packet. Packets are transmitted in the order
 	   * they are passed to this method.
 	   */
 	  send: function(object) {
 	    this.emit("send", object);
-	
+
 	    let packet = new JSONPacket(this);
 	    packet.object = object;
 	    this._outgoing.push(packet);
 	    this._flushOutgoing();
 	  },
-	
+
 	  /**
 	   * Transmit streaming data via a bulk packet.
 	   *
 	   * This method initiates the bulk send process by queuing up the header data.
 	   * The caller receives eventual access to a stream for writing.
 	   *
 	   * N.B.: Do *not* attempt to close the stream handed to you, as it will
 	   * continue to be used by this transport afterwards.  Most users should
@@ -6792,180 +6792,180 @@ return /******/ (function(modules) { // 
 	   *             @return Promise
 	   *                     The promise is resolved when copying completes or
 	   *                     rejected if any (unexpected) errors occur.
 	   *                     This object also emits "progress" events for each chunk
 	   *                     that is copied.  See stream-utils.js.
 	   */
 	  startBulkSend: function(header) {
 	    this.emit("startBulkSend", header);
-	
+
 	    let packet = new BulkPacket(this);
 	    packet.header = header;
 	    this._outgoing.push(packet);
 	    this._flushOutgoing();
 	    return packet.streamReadyForWriting;
 	  },
-	
+
 	  /**
 	   * Close the transport.
 	   * @param reason nsresult / object (optional)
 	   *        The status code or error message that corresponds to the reason for
 	   *        closing the transport (likely because a stream closed or failed).
 	   */
 	  close: function(reason) {
 	    this.emit("onClosed", reason);
-	
+
 	    this.active = false;
 	    this._socket.close();
 	    this._destroyIncoming();
 	    this._destroyAllOutgoing();
 	    if (this.hooks) {
 	      this.hooks.onClosed(reason);
 	      this.hooks = null;
 	    }
 	    if (reason) {
 	      dumpn("Transport closed: " + DevToolsUtils.safeErrorString(reason));
 	    } else {
 	      dumpn("Transport closed.");
 	    }
 	  },
-	
+
 	  /**
 	   * The currently outgoing packet (at the top of the queue).
 	   */
 	  get _currentOutgoing() {
 	    return this._outgoing[0];
 	  },
-	
+
 	  /**
 	   * Flush data to the outgoing stream.  Waits until the output stream notifies
 	   * us that it is ready to be written to (via onOutputStreamReady).
 	   */
 	  _flushOutgoing: function() {
 	    if (!this._outgoingEnabled || this._outgoing.length === 0) {
 	      return;
 	    }
-	
+
 	    // If the top of the packet queue has nothing more to send, remove it.
 	    if (this._currentOutgoing.done) {
 	      this._finishCurrentOutgoing();
 	    }
-	
+
 	    if (this._outgoing.length > 0) {
 	      setTimeout(this.onOutputStreamReady.bind(this), 0);
 	    }
 	  },
-	
+
 	  /**
 	   * Pause this transport's attempts to write to the output stream.  This is
 	   * used when we've temporarily handed off our output stream for writing bulk
 	   * data.
 	   */
 	  pauseOutgoing: function() {
 	    this._outgoingEnabled = false;
 	  },
-	
+
 	  /**
 	   * Resume this transport's attempts to write to the output stream.
 	   */
 	  resumeOutgoing: function() {
 	    this._outgoingEnabled = true;
 	    this._flushOutgoing();
 	  },
-	
+
 	  // nsIOutputStreamCallback
 	  /**
 	   * This is called when the output stream is ready for more data to be written.
 	   * The current outgoing packet will attempt to write some amount of data, but
 	   * may not complete.
 	   */
 	  onOutputStreamReady: DevToolsUtils.makeInfallible(function() {
 	    if (!this._outgoingEnabled || this._outgoing.length === 0) {
 	      return;
 	    }
-	
+
 	    try {
 	      this._currentOutgoing.write({
 	        write: data => {
 	          let count = data.length;
 	          this._socket.send(data);
 	          return count;
 	        }
 	      });
 	    } catch(e) {
 	      if (e.result != Cr.NS_BASE_STREAM_WOULD_BLOCK) {
 	        this.close(e.result);
 	        return;
 	      } else {
 	        throw e;
 	      }
 	    }
-	
+
 	    this._flushOutgoing();
 	  }, "DebuggerTransport.prototype.onOutputStreamReady"),
-	
+
 	  /**
 	   * Remove the current outgoing packet from the queue upon completion.
 	   */
 	  _finishCurrentOutgoing: function() {
 	    if (this._currentOutgoing) {
 	      this._currentOutgoing.destroy();
 	      this._outgoing.shift();
 	    }
 	  },
-	
+
 	  /**
 	   * Clear the entire outgoing queue.
 	   */
 	  _destroyAllOutgoing: function() {
 	    for (let packet of this._outgoing) {
 	      packet.destroy();
 	    }
 	    this._outgoing = [];
 	  },
-	
+
 	  /**
 	   * Initialize the input stream for reading. Once this method has been called,
 	   * we watch for packets on the input stream, and pass them to the appropriate
 	   * handlers via this.hooks.
 	   */
 	  ready: function() {
 	    this.active = true;
 	    this._waitForIncoming();
 	  },
-	
+
 	  /**
 	   * Asks the input stream to notify us (via onInputStreamReady) when it is
 	   * ready for reading.
 	   */
 	  _waitForIncoming: function() {
 	    if (this._incomingEnabled && !this._socket.onmessage) {
 	      this._socket.onmessage = this.onInputStreamReady.bind(this);
 	    }
 	  },
-	
+
 	  /**
 	   * Pause this transport's attempts to read from the input stream.  This is
 	   * used when we've temporarily handed off our input stream for reading bulk
 	   * data.
 	   */
 	  pauseIncoming: function() {
 	    this._incomingEnabled = false;
 	  },
-	
+
 	  /**
 	   * Resume this transport's attempts to read from the input stream.
 	   */
 	  resumeIncoming: function() {
 	    this._incomingEnabled = true;
 	    this._flushIncoming();
 	    this._waitForIncoming();
 	  },
-	
+
 	  // nsIInputStreamCallback
 	  /**
 	   * Called when the stream is either readable or closed.
 	   */
 	  onInputStreamReady:
 	  DevToolsUtils.makeInfallible(function(event) {
 	    let data = event.data;
 	    // TODO: ws-tcp-proxy decodes utf-8, but the transport expects to see the
@@ -6976,213 +6976,213 @@ return /******/ (function(modules) { // 
 	        return data.length;
 	      },
 	      readBytes(count) {
 	        let result = data.slice(0, count);
 	        data = data.slice(count);
 	        return result;
 	      },
 	    };
-	
+
 	    try {
 	      while (data && this._incomingEnabled &&
 	             this._processIncoming(stream, stream.available())) {}
 	      this._waitForIncoming();
 	    } catch(e) {
 	      if (e.result != Cr.NS_BASE_STREAM_WOULD_BLOCK) {
 	        this.close(e.result);
 	      } else {
 	        throw e;
 	      }
 	    }
 	  }, "DebuggerTransport.prototype.onInputStreamReady"),
-	
+
 	  /**
 	   * Process the incoming data.  Will create a new currently incoming Packet if
 	   * needed.  Tells the incoming Packet to read as much data as it can, but
 	   * reading may not complete.  The Packet signals that its data is ready for
 	   * delivery by calling one of this transport's _on*Ready methods (see
 	   * ./packets.js and the _on*Ready methods below).
 	   * @return boolean
 	   *         Whether incoming stream processing should continue for any
 	   *         remaining data.
 	   */
 	  _processIncoming: function(stream, count) {
 	    dumpv("Data available: " + count);
-	
+
 	    if (!count) {
 	      dumpv("Nothing to read, skipping");
 	      return false;
 	    }
-	
+
 	    try {
 	      if (!this._incoming) {
 	        dumpv("Creating a new packet from incoming");
-	
+
 	        if (!this._readHeader(stream)) {
 	          return false; // Not enough data to read packet type
 	        }
-	
+
 	        // Attempt to create a new Packet by trying to parse each possible
 	        // header pattern.
 	        this._incoming = Packet.fromHeader(this._incomingHeader, this);
 	        if (!this._incoming) {
 	          throw new Error("No packet types for header: " +
 	                          this._incomingHeader);
 	        }
 	      }
-	
+
 	      if (!this._incoming.done) {
 	        // We have an incomplete packet, keep reading it.
 	        dumpv("Existing packet incomplete, keep reading");
 	        this._incoming.read(stream);
 	      }
 	    } catch(e) {
 	      let msg = "Error reading incoming packet: (" + e + " - " + e.stack + ")";
 	      dumpn(msg);
-	
+
 	      // Now in an invalid state, shut down the transport.
 	      this.close();
 	      return false;
 	    }
-	
+
 	    if (!this._incoming.done) {
 	      // Still not complete, we'll wait for more data.
 	      dumpv("Packet not done, wait for more");
 	      return true;
 	    }
-	
+
 	    // Ready for next packet
 	    this._flushIncoming();
 	    return true;
 	  },
-	
+
 	  /**
 	   * Read as far as we can into the incoming data, attempting to build up a
 	   * complete packet header (which terminates with ":").  We'll only read up to
 	   * PACKET_HEADER_MAX characters.
 	   * @return boolean
 	   *         True if we now have a complete header.
 	   */
 	  _readHeader: function(stream) {
 	    let amountToRead = PACKET_HEADER_MAX - this._incomingHeader.length;
 	    this._incomingHeader +=
 	      StreamUtils.delimitedRead(stream, ":", amountToRead);
 	    if (dumpv.wantVerbose) {
 	      dumpv("Header read: " + this._incomingHeader);
 	    }
-	
+
 	    if (this._incomingHeader.endsWith(":")) {
 	      if (dumpv.wantVerbose) {
 	        dumpv("Found packet header successfully: " + this._incomingHeader);
 	      }
 	      return true;
 	    }
-	
+
 	    if (this._incomingHeader.length >= PACKET_HEADER_MAX) {
 	      throw new Error("Failed to parse packet header!");
 	    }
-	
+
 	    // Not enough data yet.
 	    return false;
 	  },
-	
+
 	  /**
 	   * If the incoming packet is done, log it as needed and clear the buffer.
 	   */
 	  _flushIncoming: function() {
 	    if (!this._incoming.done) {
 	      return;
 	    }
 	    if (dumpn.wantLogging) {
 	      dumpn("Got: " + this._incoming);
 	    }
 	    this._destroyIncoming();
 	  },
-	
+
 	  /**
 	   * Handler triggered by an incoming JSONPacket completing it's |read| method.
 	   * Delivers the packet to this.hooks.onPacket.
 	   */
 	  _onJSONObjectReady: function(object) {
 	    DevToolsUtils.executeSoon(DevToolsUtils.makeInfallible(() => {
 	      // Ensure the transport is still alive by the time this runs.
 	      if (this.active) {
 	        this.emit("onPacket", object);
 	        this.hooks.onPacket(object);
 	      }
 	    }, "DebuggerTransport instance's this.hooks.onPacket"));
 	  },
-	
+
 	  /**
 	   * Handler triggered by an incoming BulkPacket entering the |read| phase for
 	   * the stream portion of the packet.  Delivers info about the incoming
 	   * streaming data to this.hooks.onBulkPacket.  See the main comment on the
 	   * transport at the top of this file for more details.
 	   */
 	  _onBulkReadReady: function(...args) {
 	    DevToolsUtils.executeSoon(DevToolsUtils.makeInfallible(() => {
 	      // Ensure the transport is still alive by the time this runs.
 	      if (this.active) {
 	        this.emit("onBulkPacket", ...args);
 	        this.hooks.onBulkPacket(...args);
 	      }
 	    }, "DebuggerTransport instance's this.hooks.onBulkPacket"));
 	  },
-	
+
 	  /**
 	   * Remove all handlers and references related to the current incoming packet,
 	   * either because it is now complete or because the transport is closing.
 	   */
 	  _destroyIncoming: function() {
 	    if (this._incoming) {
 	      this._incoming.destroy();
 	    }
 	    this._incomingHeader = "";
 	    this._incoming = null;
 	  }
-	
-	};
-	
+
+	};
+
 	exports.DebuggerTransport = DebuggerTransport;
-	
+
 	/**
 	 * An adapter that handles data transfers between the debugger client and
 	 * server when they both run in the same process. It presents the same API as
 	 * DebuggerTransport, but instead of transmitting serialized messages across a
 	 * connection it merely calls the packet dispatcher of the other side.
 	 *
 	 * @param other LocalDebuggerTransport
 	 *        The other endpoint for this debugger connection.
 	 *
 	 * @see DebuggerTransport
 	 */
 	function LocalDebuggerTransport(other) {
 	  EventEmitter.decorate(this);
-	
+
 	  this.other = other;
 	  this.hooks = null;
-	
+
 	  /*
 	   * A packet number, shared between this and this.other. This isn't used
 	   * by the protocol at all, but it makes the packet traces a lot easier to
 	   * follow.
 	   */
 	  this._serial = this.other ? this.other._serial : { count: 0 };
 	  this.close = this.close.bind(this);
 	}
-	
+
 	LocalDebuggerTransport.prototype = {
 	  /**
 	   * Transmit a message by directly calling the onPacket handler of the other
 	   * endpoint.
 	   */
 	  send: function(packet) {
 	    this.emit("send", packet);
-	
+
 	    let serial = this._serial.count++;
 	    if (dumpn.wantLogging) {
 	      /* Check 'from' first, as 'echo' packets have both. */
 	      if (packet.from) {
 	        dumpn("Packet " + serial + " sent from " + uneval(packet.from));
 	      } else if (packet.to) {
 	        dumpn("Packet " + serial + " sent to " + uneval(packet.to));
 	      }
@@ -7197,121 +7197,121 @@ return /******/ (function(modules) { // 
 	        }
 	        if (other.hooks) {
 	          other.emit("onPacket", packet);
 	          other.hooks.onPacket(packet);
 	        }
 	      }, "LocalDebuggerTransport instance's this.other.hooks.onPacket"));
 	    }
 	  },
-	
+
 	  /**
 	   * Send a streaming bulk packet directly to the onBulkPacket handler of the
 	   * other endpoint.
 	   *
 	   * This case is much simpler than the full DebuggerTransport, since there is
 	   * no primary stream we have to worry about managing while we hand it off to
 	   * others temporarily.  Instead, we can just make a single use pipe and be
 	   * done with it.
 	   */
 	  startBulkSend: function({actor, type, length}) {
 	    this.emit("startBulkSend", {actor, type, length});
-	
+
 	    let serial = this._serial.count++;
-	
+
 	    dumpn("Sent bulk packet " + serial + " for actor " + actor);
 	    if (!this.other) {
 	      return;
 	    }
-	
+
 	    let pipe = new Pipe(true, true, 0, 0, null);
-	
+
 	    DevToolsUtils.executeSoon(DevToolsUtils.makeInfallible(() => {
 	      dumpn("Received bulk packet " + serial);
 	      if (!this.other.hooks) {
 	        return;
 	      }
-	
+
 	      // Receiver
 	      let deferred = promise.defer();
 	      let packet = {
 	        actor: actor,
 	        type: type,
 	        length: length,
 	        copyTo: (output) => {
 	          let copying =
 	            StreamUtils.copyStream(pipe.inputStream, output, length);
 	          deferred.resolve(copying);
 	          return copying;
 	        },
 	        stream: pipe.inputStream,
 	        done: deferred
 	      };
-	
+
 	      this.other.emit("onBulkPacket", packet);
 	      this.other.hooks.onBulkPacket(packet);
-	
+
 	      // Await the result of reading from the stream
 	      deferred.promise.then(() => pipe.inputStream.close(), this.close);
 	    }, "LocalDebuggerTransport instance's this.other.hooks.onBulkPacket"));
-	
+
 	    // Sender
 	    let sendDeferred = promise.defer();
-	
+
 	    // The remote transport is not capable of resolving immediately here, so we
 	    // shouldn't be able to either.
 	    DevToolsUtils.executeSoon(() => {
 	      let copyDeferred = promise.defer();
-	
+
 	      sendDeferred.resolve({
 	        copyFrom: (input) => {
 	          let copying =
 	            StreamUtils.copyStream(input, pipe.outputStream, length);
 	          copyDeferred.resolve(copying);
 	          return copying;
 	        },
 	        stream: pipe.outputStream,
 	        done: copyDeferred
 	      });
-	
+
 	      // Await the result of writing to the stream
 	      copyDeferred.promise.then(() => pipe.outputStream.close(), this.close);
 	    });
-	
+
 	    return sendDeferred.promise;
 	  },
-	
+
 	  /**
 	   * Close the transport.
 	   */
 	  close: function() {
 	    this.emit("close");
-	
+
 	    if (this.other) {
 	      // Remove the reference to the other endpoint before calling close(), to
 	      // avoid infinite recursion.
 	      let other = this.other;
 	      this.other = null;
 	      other.close();
 	    }
 	    if (this.hooks) {
 	      try {
 	        this.hooks.onClosed();
 	      } catch(ex) {
 	        console.error(ex);
 	      }
 	      this.hooks = null;
 	    }
 	  },
-	
+
 	  /**
 	   * An empty method for emulating the DebuggerTransport API.
 	   */
 	  ready: function() {},
-	
+
 	  /**
 	   * Helper function that makes an object fully immutable.
 	   */
 	  _deepFreeze: function(object) {
 	    Object.freeze(object);
 	    for (let prop in object) {
 	      // Freeze the properties that are objects, not on the prototype, and not
 	      // already frozen. Note that this might leave an unfrozen reference
@@ -7319,209 +7319,209 @@ return /******/ (function(modules) { // 
 	      // an unfrozen object.
 	      if (object.hasOwnProperty(prop) && typeof object === "object" &&
 	          !Object.isFrozen(object)) {
 	        this._deepFreeze(o[prop]);
 	      }
 	    }
 	  }
 	};
-	
+
 	exports.LocalDebuggerTransport = LocalDebuggerTransport;
-	
+
 	/**
 	 * A transport for the debugging protocol that uses nsIMessageSenders to
 	 * exchange packets with servers running in child processes.
 	 *
 	 * In the parent process, |sender| should be the nsIMessageSender for the
 	 * child process. In a child process, |sender| should be the child process
 	 * message manager, which sends packets to the parent.
 	 *
 	 * |prefix| is a string included in the message names, to distinguish
 	 * multiple servers running in the same child process.
 	 *
 	 * This transport exchanges messages named 'debug:<prefix>:packet', where
 	 * <prefix> is |prefix|, whose data is the protocol packet.
 	 */
 	function ChildDebuggerTransport(sender, prefix) {
 	  EventEmitter.decorate(this);
-	
+
 	  this._sender = sender.QueryInterface(Ci.nsIMessageSender);
 	  this._messageName = "debug:" + prefix + ":packet";
 	}
-	
+
 	/*
 	 * To avoid confusion, we use 'message' to mean something that
 	 * nsIMessageSender conveys, and 'packet' to mean a remote debugging
 	 * protocol packet.
 	 */
 	ChildDebuggerTransport.prototype = {
 	  constructor: ChildDebuggerTransport,
-	
+
 	  hooks: null,
-	
+
 	  ready: function () {
 	    this._sender.addMessageListener(this._messageName, this);
 	  },
-	
+
 	  close: function () {
 	    this._sender.removeMessageListener(this._messageName, this);
 	    this.emit("onClosed");
 	    this.hooks.onClosed();
 	  },
-	
+
 	  receiveMessage: function ({data}) {
 	    this.emit("onPacket", data);
 	    this.hooks.onPacket(data);
 	  },
-	
+
 	  send: function (packet) {
 	    this.emit("send", packet);
 	    this._sender.sendAsyncMessage(this._messageName, packet);
 	  },
-	
+
 	  startBulkSend: function() {
 	    throw new Error("Can't send bulk data to child processes.");
 	  }
 	};
-	
+
 	exports.ChildDebuggerTransport = ChildDebuggerTransport;
-	
+
 	// WorkerDebuggerTransport is defined differently depending on whether we are
 	// on the main thread or a worker thread. In the former case, we are required
 	// by the devtools loader, and isWorker will be false. Otherwise, we are
 	// required by the worker loader, and isWorker will be true.
 	//
 	// Each worker debugger supports only a single connection to the main thread.
 	// However, its theoretically possible for multiple servers to connect to the
 	// same worker. Consequently, each transport has a connection id, to allow
 	// messages from multiple connections to be multiplexed on a single channel.
-	
+
 	if (typeof WorkerGlobalScope === 'undefined') { // i.e. not in a worker
 	  (function () { // Main thread
 	    /**
 	     * A transport that uses a WorkerDebugger to send packets from the main
 	     * thread to a worker thread.
 	     */
 	    function WorkerDebuggerTransport(dbg, id) {
 	      this._dbg = dbg;
 	      this._id = id;
 	      this.onMessage = this._onMessage.bind(this);
 	    }
-	
+
 	    WorkerDebuggerTransport.prototype = {
 	      constructor: WorkerDebuggerTransport,
-	
+
 	      ready: function () {
 	        this._dbg.addListener(this);
 	      },
-	
+
 	      close: function () {
 	        this._dbg.removeListener(this);
 	        if (this.hooks) {
 	          this.hooks.onClosed();
 	        }
 	      },
-	
+
 	      send: function (packet) {
 	        this._dbg.postMessage(JSON.stringify({
 	          type: "message",
 	          id: this._id,
 	          message: packet
 	        }));
 	      },
-	
+
 	      startBulkSend: function () {
 	        throw new Error("Can't send bulk data from worker threads!");
 	      },
-	
+
 	      _onMessage: function (message) {
 	        let packet = JSON.parse(message);
 	        if (packet.type !== "message" || packet.id !== this._id) {
 	          return;
 	        }
-	
+
 	        if (this.hooks) {
 	          this.hooks.onPacket(packet.message);
 	        }
 	      }
 	    };
-	
+
 	    exports.WorkerDebuggerTransport = WorkerDebuggerTransport;
 	  }).call(this);
 	} else {
 	  (function () { // Worker thread
 	    /*
 	     * A transport that uses a WorkerDebuggerGlobalScope to send packets from a
 	     * worker thread to the main thread.
 	     */
 	    function WorkerDebuggerTransport(scope, id) {
 	      this._scope = scope;
 	      this._id = id;
 	      this._onMessage = this._onMessage.bind(this);
 	    }
-	
+
 	    WorkerDebuggerTransport.prototype = {
 	      constructor: WorkerDebuggerTransport,
-	
+
 	      ready: function () {
 	        this._scope.addEventListener("message", this._onMessage);
 	      },
-	
+
 	      close: function () {
 	        this._scope.removeEventListener("message", this._onMessage);
 	        if (this.hooks) {
 	          this.hooks.onClosed();
 	        }
 	      },
-	
+
 	      send: function (packet) {
 	        this._scope.postMessage(JSON.stringify({
 	          type: "message",
 	          id: this._id,
 	          message: packet
 	        }));
 	      },
-	
+
 	      startBulkSend: function () {
 	        throw new Error("Can't send bulk data from worker threads!");
 	      },
-	
+
 	      _onMessage: function (event) {
 	        let packet = JSON.parse(event.data);
 	        if (packet.type !== "message" || packet.id !== this._id) {
 	          return;
 	        }
-	
+
 	        if (this.hooks) {
 	          this.hooks.onPacket(packet.message);
 	        }
 	      }
 	    };
-	
+
 	    exports.WorkerDebuggerTransport = WorkerDebuggerTransport;
 	  }).call(this);
 	}
 
 
 /***/ },
 /* 42 */
 /***/ 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/. */
-	
+
 	/* General utilities used throughout devtools. */
 	var { Ci, Cu, Cc, components } = __webpack_require__(35);
 	const { Services } = __webpack_require__(28);
 	var promise = __webpack_require__(40);
-	
+
 	const { FileUtils } = __webpack_require__(43);
-	
+
 	/**
 	 * Turn the error |aError| into a string, without fail.
 	 */
 	exports.safeErrorString = function safeErrorString(aError) {
 	  try {
 	    let errorString = aError.toString();
 	    if (typeof errorString == "string") {
 	      // Attempt to attach a stack to |errorString|. If it throws an error, or
@@ -7529,49 +7529,49 @@ return /******/ (function(modules) { // 
 	      try {
 	        if (aError.stack) {
 	          let stack = aError.stack.toString();
 	          if (typeof stack == "string") {
 	            errorString += "\nStack: " + stack;
 	          }
 	        }
 	      } catch (ee) { }
-	
+
 	      // Append additional line and column number information to the output,
 	      // since it might not be part of the stringified error.
 	      if (typeof aError.lineNumber == "number" && typeof aError.columnNumber == "number") {
 	        errorString += "Line: " + aError.lineNumber + ", column: " + aError.columnNumber;
 	      }
-	
+
 	      return errorString;
 	    }
 	  } catch (ee) { }
-	
+
 	  // We failed to find a good error description, so do the next best thing.
 	  return Object.prototype.toString.call(aError);
 	};
-	
+
 	/**
 	 * Report that |aWho| threw an exception, |aException|.
 	 */
 	exports.reportException = function reportException(aWho, aException) {
 	  let msg = aWho + " threw an exception: " + exports.safeErrorString(aException);
-	
+
 	  console.log(msg);
-	
+
 	//  if (Cu && console.error) {
 	//    /*
 	//     * Note that the xpcshell test harness registers an observer for
 	//     * console messages, so when we're running tests, this will cause
 	//     * the test to quit.
 	//     */
 	//    console.error(msg);
 	//  }
 	};
-	
+
 	/**
 	 * Given a handler function that may throw, return an infallible handler
 	 * function that calls the fallible handler, and logs any exceptions it
 	 * throws.
 	 *
 	 * @param aHandler function
 	 *      A handler function, which may throw.
 	 * @param aName string
@@ -7579,63 +7579,63 @@ return /******/ (function(modules) { // 
 	 *      aHandler.name.
 	 *
 	 * (SpiderMonkey does generate good names for anonymous functions, but we
 	 * don't have a way to get at them from JavaScript at the moment.)
 	 */
 	exports.makeInfallible = function makeInfallible(aHandler, aName) {
 	  if (!aName)
 	    aName = aHandler.name;
-	
+
 	  return function(/* arguments */) {
 	    // try {
 	    return aHandler.apply(this, arguments);
 	    // } catch (ex) {
 	    //   let who = "Handler function";
 	    //   if (aName) {
 	    //     who += " " + aName;
 	    //   }
 	    //   return exports.reportException(who, ex);
 	    // }
 	  };
 	};
-	
+
 	/**
 	 * Waits for the next tick in the event loop to execute a callback.
 	 */
 	exports.executeSoon = function executeSoon(aFn) {
 	  setTimeout(aFn, 0);
 	};
-	
+
 	/**
 	 * Waits for the next tick in the event loop.
 	 *
 	 * @return Promise
 	 *         A promise that is resolved after the next tick in the event loop.
 	 */
 	exports.waitForTick = function waitForTick() {
 	  let deferred = promise.defer();
 	  exports.executeSoon(deferred.resolve);
 	  return deferred.promise;
 	};
-	
+
 	/**
 	 * Waits for the specified amount of time to pass.
 	 *
 	 * @param number aDelay
 	 *        The amount of time to wait, in milliseconds.
 	 * @return Promise
 	 *         A promise that is resolved after the specified amount of time passes.
 	 */
 	exports.waitForTime = function waitForTime(aDelay) {
 	  let deferred = promise.defer();
 	  setTimeout(deferred.resolve, aDelay);
 	  return deferred.promise;
 	};
-	
+
 	/**
 	 * Like Array.prototype.forEach, but doesn't cause jankiness when iterating over
 	 * very large arrays by yielding to the browser and continuing execution on the
 	 * next tick.
 	 *
 	 * @param Array aArray
 	 *        The array being iterated over.
 	 * @param Function aFn
@@ -7643,48 +7643,48 @@ return /******/ (function(modules) { // 
 	 *        returned by this function, iterating over the array will be paused
 	 *        until the respective promise is resolved.
 	 * @returns Promise
 	 *          A promise that is resolved once the whole array has been iterated
 	 *          over, and all promises returned by the aFn callback are resolved.
 	 */
 	exports.yieldingEach = function yieldingEach(aArray, aFn) {
 	  const deferred = promise.defer();
-	
+
 	  let i = 0;
 	  let len = aArray.length;
 	  let outstanding = [deferred.promise];
-	
+
 	  (function loop() {
 	    const start = Date.now();
-	
+
 	    while (i < len) {
 	      // Don't block the main thread for longer than 16 ms at a time. To
 	      // maintain 60fps, you have to render every frame in at least 16ms; we
 	      // aren't including time spent in non-JS here, but this is Good
 	      // Enough(tm).
 	      if (Date.now() - start > 16) {
 	        exports.executeSoon(loop);
 	        return;
 	      }
-	
+
 	      try {
 	        outstanding.push(aFn(aArray[i], i++));
 	      } catch (e) {
 	        deferred.reject(e);
 	        return;
 	      }
 	    }
-	
+
 	    deferred.resolve();
 	  }());
-	
+
 	  return promise.all(outstanding);
 	};
-	
+
 	/**
 	 * Like XPCOMUtils.defineLazyGetter, but with a |this| sensitive getter that
 	 * allows the lazy getter to be defined on a prototype and work correctly with
 	 * instances.
 	 *
 	 * @param Object aObject
 	 *        The prototype object to define the lazy getter on.
 	 * @param String aKey
@@ -7694,28 +7694,28 @@ return /******/ (function(modules) { // 
 	 *        called with the |this| value of the current instance.
 	 */
 	exports.defineLazyPrototypeGetter =
 	function defineLazyPrototypeGetter(aObject, aKey, aCallback) {
 	  Object.defineProperty(aObject, aKey, {
 	    configurable: true,
 	    get: function() {
 	      const value = aCallback.call(this);
-	
+
 	      Object.defineProperty(this, aKey, {
 	        configurable: true,
 	        writable: true,
 	        value: value
 	      });
-	
+
 	      return value;
 	    }
 	  });
 	};
-	
+
 	/**
 	 * Safely get the property value from a Debugger.Object for a given key. Walks
 	 * the prototype chain until the property is found.
 	 *
 	 * @param Debugger.Object aObject
 	 *        The Debugger.Object to get the value from.
 	 * @param String aKey
 	 *        The key to look for.
@@ -7736,17 +7736,17 @@ return /******/ (function(modules) { // 
 	      aObj = aObj.proto;
 	    } while (aObj);
 	  } catch (e) {
 	    // If anything goes wrong report the error and return undefined.
 	    exports.reportException("getProperty", e);
 	  }
 	  return undefined;
 	};
-	
+
 	/**
 	 * Determines if a descriptor has a getter which doesn't call into JavaScript.
 	 *
 	 * @param Object aDesc
 	 *        The descriptor to check for a safe getter.
 	 * @return Boolean
 	 *         Whether a safe getter was found.
 	 */
@@ -7756,17 +7756,17 @@ return /******/ (function(modules) { // 
 	  try {
 	    let fn = aDesc.get.unwrap();
 	    return fn && fn.callable && fn.class == "Function" && fn.script === undefined;
 	  } catch (e) {
 	    // Avoid exception 'Object in compartment marked as invisible to Debugger'
 	    return false;
 	  }
 	};
-	
+
 	/**
 	 * Check if it is safe to read properties and execute methods from the given JS
 	 * object. Safety is defined as being protected from unintended code execution
 	 * from content scripts (or cross-compartment code).
 	 *
 	 * See bugs 945920 and 946752 for discussion.
 	 *
 	 * @type Object aObj
@@ -7775,87 +7775,87 @@ return /******/ (function(modules) { // 
 	 *         True if it is safe to read properties from aObj, or false otherwise.
 	 */
 	exports.isSafeJSObject = function isSafeJSObject(aObj) {
 	  // If we are running on a worker thread, Cu is not available. In this case,
 	  // we always return false, just to be on the safe side.
 	  if (isWorker) {
 	    return false;
 	  }
-	
+
 	  if (Cu.getGlobalForObject(aObj) ==
 	      Cu.getGlobalForObject(exports.isSafeJSObject)) {
 	    return true; // aObj is not a cross-compartment wrapper.
 	  }
-	
+
 	  let principal = Cu.getObjectPrincipal(aObj);
 	  if (Services.scriptSecurityManager.isSystemPrincipal(principal)) {
 	    return true; // allow chrome objects
 	  }
-	
+
 	  return Cu.isXrayWrapper(aObj);
 	};
-	
+
 	exports.dumpn = function dumpn(str) {
 	  if (exports.dumpn.wantLogging) {
 	    console.log("DBG-SERVER: " + str + "\n");
 	  }
 	};
-	
+
 	// We want wantLogging to be writable. The exports object is frozen by the
 	// loader, so define it on dumpn instead.
 	exports.dumpn.wantLogging = false;
-	
+
 	/**
 	 * A verbose logger for low-level tracing.
 	 */
 	exports.dumpv = function(msg) {
 	  if (exports.dumpv.wantVerbose) {
 	    exports.dumpn(msg);
 	  }
 	};
-	
+
 	// We want wantLogging to be writable. The exports object is frozen by the
 	// loader, so define it on dumpn instead.
 	exports.dumpv.wantVerbose = false;
-	
+
 	/**
 	 * Utility function for updating an object with the properties of
 	 * other objects.
 	 *
 	 * @param aTarget Object
 	 *        The object being updated.
 	 * @param aNewAttrs Object
 	 *        The rest params are objects to update aTarget with. You
 	 *        can pass as many as you like.
 	 */
 	exports.update = function update(aTarget, ...aArgs) {
 	  for (let attrs of aArgs) {
 	    for (let key in attrs) {
 	      let desc = Object.getOwnPropertyDescriptor(attrs, key);
-	
+
 	      if (desc) {
 	        Object.defineProperty(aTarget, key, desc);
 	      }
 	    }
 	  }
-	
+
 	  return aTarget;
 	};
-	
+
 	/**
 	 * Utility function for getting the values from an object as an array
 	 *
 	 * @param aObject Object
 	 *        The object to iterate over
 	 */
 	exports.values = function values(aObject) {
 	  return Object.keys(aObject).map(k => aObject[k]);
 	};
-	
+
 	/**
 	 * Defines a getter on a specified object that will be created upon first use.
 	 *
 	 * @param aObject
 	 *        The object to define the lazy getter on.
 	 * @param aName
 	 *        The name of the getter to define on aObject.
 	 * @param aLambda
@@ -7867,50 +7867,50 @@ return /******/ (function(modules) { // 
 	    get: function() {
 	      delete aObject[aName];
 	      return aObject[aName] = aLambda.apply(aObject);
 	    },
 	    configurable: true,
 	    enumerable: true
 	  });
 	};
-	
+
 	// DEPRECATED: use DevToolsUtils.assert(condition, message) instead!
 	let haveLoggedDeprecationMessage = false;
 	exports.dbg_assert = function dbg_assert(cond, e) {
 	  if (!haveLoggedDeprecationMessage) {
 	    haveLoggedDeprecationMessage = true;
 	    const deprecationMessage = "DevToolsUtils.dbg_assert is deprecated! Use DevToolsUtils.assert instead!"
 	          + Error().stack;
 	    console.log(deprecationMessage);
 	    if (typeof console === "object" && console && console.warn) {
 	      console.warn(deprecationMessage);
 	    }
 	  }
-	
+
 	  if (!cond) {
 	    return e;
 	  }
 	};
-	
+
 	const { AppConstants } = __webpack_require__(44);
-	
+
 	/**
 	 * No operation. The empty function.
 	 */
 	exports.noop = function() { };
-	
+
 	function reallyAssert(condition, message) {
 	  if (!condition) {
 	    const err = new Error("Assertion failure: " + message);
 	    exports.reportException("DevToolsUtils.assert", err);
 	    throw err;
 	  }
 	}
-	
+
 	/**
 	 * DevToolsUtils.assert(condition, message)
 	 *
 	 * @param Boolean condition
 	 * @param String message
 	 *
 	 * Assertions are enabled when any of the following are true:
 	 *   - This is a DEBUG_JS_MODULES build
@@ -7925,17 +7925,17 @@ return /******/ (function(modules) { // 
 	 * This is an improvement over `dbg_assert`, which doesn't actually cause any
 	 * fatal behavior, and is therefore much easier to accidentally ignore.
 	 */
 	Object.defineProperty(exports, "assert", {
 	  get: () => (AppConstants.DEBUG || AppConstants.DEBUG_JS_MODULES || this.testing)
 	    ? reallyAssert
 	    : exports.noop,
 	});
-	
+
 	/**
 	 * Defines a getter on a specified object for a module.  The module will not
 	 * be imported until first use.
 	 *
 	 * @param aObject
 	 *        The object to define the lazy getter on.
 	 * @param aName
 	 *        The name of the getter to define on aObject for the module.
@@ -7950,23 +7950,23 @@ return /******/ (function(modules) { // 
 	                                                                 aSymbol)
 	{
 	  this.defineLazyGetter(aObject, aName, function XPCU_moduleLambda() {
 	    var temp = {};
 	    Cu.import(aResource, temp);
 	    return temp[aSymbol || aName];
 	  });
 	};
-	
+
 	const { NetUtil } = __webpack_require__(45);
-	
+
 	const { TextDecoder, OS } = __webpack_require__(46);
-	
+
 	const NetworkHelper = __webpack_require__(47);
-	
+
 	/**
 	 * Performs a request to load the desired URL and returns a promise.
 	 *
 	 * @param aURL String
 	 *        The URL we will request.
 	 * @param aOptions Object
 	 *        An object with the following optional properties:
 	 *        - loadFromCache: if false, will bypass the cache and
@@ -7992,138 +7992,138 @@ return /******/ (function(modules) { // 
 	  // Create a channel.
 	  let url = aURL.split(" -> ").pop();
 	  let channel;
 	  try {
 	    channel = newChannelForURL(url, aOptions);
 	  } catch (ex) {
 	    return promise.reject(ex);
 	  }
-	
+
 	  // Set the channel options.
 	  channel.loadFlags = aOptions.loadFromCache
 	    ? channel.LOAD_FROM_CACHE
 	    : channel.LOAD_BYPASS_CACHE;
-	
+
 	  if (aOptions.window) {
 	    // Respect private browsing.
 	    channel.loadGroup = aOptions.window.QueryInterface(Ci.nsIInterfaceRequestor)
 	                          .getInterface(Ci.nsIWebNavigation)
 	                          .QueryInterface(Ci.nsIDocumentLoader)
 	                          .loadGroup;
 	  }
-	
+
 	  let deferred = promise.defer();
 	  let onResponse = (stream, status, request) => {
 	    if (!components.isSuccessCode(status)) {
 	      deferred.reject(new Error(`Failed to fetch ${url}. Code ${status}.`));
 	      return;
 	    }
-	
+
 	    try {
 	      // We cannot use NetUtil to do the charset conversion as if charset
 	      // information is not available and our default guess is wrong the method
 	      // might fail and we lose the stream data. This means we can't fall back
 	      // to using the locale default encoding (bug 1181345).
-	
+
 	      // Read and decode the data according to the locale default encoding.
 	      let available = stream.available();
 	      let source = NetUtil.readInputStreamToString(stream, available);
 	      stream.close();
-	
+
 	      // If the channel or the caller has correct charset information, the
 	      // content will be decoded correctly. If we have to fall back to UTF-8 and
 	      // the guess is wrong, the conversion fails and convertToUnicode returns
 	      // the input unmodified. Essentially we try to decode the data as UTF-8
 	      // and if that fails, we use the locale specific default encoding. This is
 	      // the best we can do if the source does not provide charset info.
 	      let charset = channel.contentCharset || aOptions.charset || "UTF-8";
 	      let unicodeSource = NetworkHelper.convertToUnicode(source, charset);
-	
+
 	      deferred.resolve({
 	        content: unicodeSource,
 	        contentType: request.contentType
 	      });
 	    } catch (ex) {
 	      let uri = request.originalURI;
 	      if (ex.name === "NS_BASE_STREAM_CLOSED" && uri instanceof Ci.nsIFileURL) {
 	        // Empty files cause NS_BASE_STREAM_CLOSED exception. Use OS.File to
 	        // differentiate between empty files and other errors (bug 1170864).
 	        // This can be removed when bug 982654 is fixed.
-	
+
 	        uri.QueryInterface(Ci.nsIFileURL);
 	        let result = OS.File.read(uri.file.path).then(bytes => {
 	          // Convert the bytearray to a String.
 	          let decoder = new TextDecoder();
 	          let content = decoder.decode(bytes);
-	
+
 	          // We can't detect the contentType without opening a channel
 	          // and that failed already. This is the best we can do here.
 	          return {
 	            content,
 	            contentType: "text/plain"
 	          };
 	        });
-	
+
 	        deferred.resolve(result);
 	      } else {
 	        deferred.reject(ex);
 	      }
 	    }
 	  };
-	
+
 	  // Open the channel
 	  try {
 	    NetUtil.asyncFetch(channel, onResponse);
 	  } catch (ex) {
 	    return promise.reject(ex);
 	  }
-	
+
 	  return deferred.promise;
 	}
-	
+
 	/**
 	 * Opens a channel for given URL. Tries a bit harder than NetUtil.newChannel.
 	 *
 	 * @param {String} url - The URL to open a channel for.
 	 * @param {Object} options - The options object passed to @method fetch.
 	 * @return {nsIChannel} - The newly created channel. Throws on failure.
 	 */
 	function newChannelForURL(url, { policy }) {
 	  let channelOptions = {
 	    contentPolicyType: policy,
 	    loadUsingSystemPrincipal: true,
 	    uri: url
 	  };
-	
+
 	  try {
 	    return NetUtil.newChannel(channelOptions);
 	  } catch (e) {
 	    // In the xpcshell tests, the script url is the absolute path of the test
 	    // file, which will make a malformed URI error be thrown. Add the file
 	    // scheme to see if it helps.
 	    channelOptions.uri = "file://" + url;
-	
+
 	    return NetUtil.newChannel(channelOptions);
 	  }
 	}
-	
+
 	// Fetch is defined differently depending on whether we are on the main thread
 	// or a worker thread.
 	if (typeof WorkerGlobalScope === "undefined") { // i.e. not in a worker
 	  exports.fetch = mainThreadFetch;
 	} else {
 	  // Services is not available in worker threads, nor is there any other way
 	  // to fetch a URL. We need to enlist the help from the main thread here, by
 	  // issuing an rpc request, to fetch the URL on our behalf.
 	  exports.fetch = function(url, options) {
 	    return rpc("fetch", url, options);
 	  };
 	}
-	
+
 	/**
 	 * Returns a promise that is resolved or rejected when all promises have settled
 	 * (resolved or rejected).
 	 *
 	 * This differs from Promise.all, which will reject immediately after the first
 	 * rejection, instead of waiting for the remaining promises to settle.
 	 *
 	 * @param values
@@ -8136,81 +8136,81 @@ return /******/ (function(modules) { // 
 	 *         resolved values in the given order, or undefined if values is an
 	 *         empty array. The reject reason will be forwarded from the first
 	 *         promise in the list of given promises to be rejected.
 	 */
 	exports.settleAll = values => {
 	  if (values === null || typeof (values[Symbol.iterator]) != "function") {
 	    throw new Error("settleAll() expects an iterable.");
 	  }
-	
+
 	  let deferred = promise.defer();
-	
+
 	  values = Array.isArray(values) ? values : [...values];
 	  let countdown = values.length;
 	  let resolutionValues = new Array(countdown);
 	  let rejectionValue;
 	  let rejectionOccurred = false;
-	
+
 	  if (!countdown) {
 	    deferred.resolve(resolutionValues);
 	    return deferred.promise;
 	  }
-	
+
 	  function checkForCompletion() {
 	    if (--countdown > 0) {
 	      return;
 	    }
 	    if (!rejectionOccurred) {
 	      deferred.resolve(resolutionValues);
 	    } else {
 	      deferred.reject(rejectionValue);
 	    }
 	  }
-	
+
 	  for (let i = 0; i < values.length; i++) {
 	    let index = i;
 	    let value = values[i];
 	    let resolver = result => {
 	      resolutionValues[index] = result;
 	      checkForCompletion();
 	    };
 	    let rejecter = error => {
 	      if (!rejectionOccurred) {
 	        rejectionValue = error;
 	        rejectionOccurred = true;
 	      }
 	      checkForCompletion();
 	    };
-	
+
 	    if (value && typeof (value.then) == "function") {
 	      value.then(resolver, rejecter);
 	    } else {
 	      // Given value is not a promise, forward it as a resolution value.
 	      resolver(value);
 	    }
 	  }
-	
+
 	  return deferred.promise;
 	};
-	
+
 	/**
 	 * When the testing flag is set, various behaviors may be altered from
 	 * production mode, typically to enable easier testing or enhanced debugging.
 	 */
 	var testing = false;
 	Object.defineProperty(exports, "testing", {
 	  get: function() {
 	    return testing;
 	  },
 	  set: function(state) {
 	    testing = state;
 	  }
 	});
-	
+
 	/**
 	 * Open the file at the given path for reading.
 	 *
 	 * @param {String} filePath
 	 *
 	 * @returns Promise<nsIInputStream>
 	 */
 	exports.openFileStream = function(filePath) {
@@ -8218,42 +8218,42 @@ return /******/ (function(modules) { // 
 	    const uri = NetUtil.newURI(new FileUtils.File(filePath));
 	    NetUtil.asyncFetch(
 	      { uri, loadUsingSystemPrincipal: true },
 	      (stream, result) => {
 	        if (!components.isSuccessCode(result)) {
 	          reject(new Error(`Could not open "${filePath}": result = ${result}`));
 	          return;
 	        }
-	
+
 	        resolve(stream);
 	      }
 	    );
 	  });
 	};
-	
+
 	exports.isGenerator = function(fn) {
 	  if (typeof fn !== "function") {
 	    return false;
 	  }
 	  let proto = Object.getPrototypeOf(fn);
 	  if (!proto) {
 	    return false;
 	  }
 	  let ctor = proto.constructor;
 	  if (!ctor) {
 	    return false;
 	  }
 	  return ctor.name == "GeneratorFunction";
 	};
-	
+
 	exports.isPromise = function(p) {
 	  return p && typeof p.then === "function";
 	};
-	
+
 	/**
 	 * Return true if `thing` is a SavedFrame, false otherwise.
 	 */
 	exports.isSavedFrame = function(thing) {
 	  return Object.prototype.toString.call(thing) === "[object SavedFrame]";
 	};
 
 
@@ -8268,17 +8268,17 @@ return /******/ (function(modules) { // 
 
 /***/ },
 /* 44 */
 /***/ function(module, exports) {
 
 	/*
 	 * A sham for https://dxr.mozilla.org/mozilla-central/source/toolkit/modules/AppConstants.jsm
 	 */
-	
+
 	module.exports = { AppConstants: {} };
 
 
 /***/ },
 /* 45 */
 /***/ function(module, exports) {
 
 	/*
@@ -8327,17 +8327,17 @@ return /******/ (function(modules) { // 
 	 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 	 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 	 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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.
 	 */
-	
+
 	/*
 	 * Creator:
 	 *  Joe Hewitt
 	 * Contributors
 	 *  John J. Barton (IBM Almaden)
 	 *  Jan Odvarko (Mozilla Corp.)
 	 *  Max Stepanov (Aptana Inc.)
 	 *  Rob Campbell (Mozilla Corp.)
@@ -8347,26 +8347,26 @@ return /******/ (function(modules) { // 
 	 *  Kevin Decker
 	 *  Mike Ratcliffe (Comartis AG)
 	 *  Hernan Rodríguez Colmeiro
 	 *  Austin Andrews
 	 *  Christoph Dorn
 	 *  Steven Roussey (AppCenter Inc, Network54)
 	 *  Mihai Sucan (Mozilla Corp.)
 	 */
-	
-	"use strict";
-	
+
+	"use strict";
+
 	const {components, Cc, Ci, Cu} = __webpack_require__(35);
 	const { NetUtil } = __webpack_require__(45);
 	const DevToolsUtils = __webpack_require__(42);
-	
+
 	// The cache used in the `nsIURL` function.
 	const gNSURLStore = new Map();
-	
+
 	/**
 	 * Helper object for networking stuff.
 	 *
 	 * Most of the following functions have been taken from the Firebug source. They
 	 * have been modified to match the Firefox coding rules.
 	 */
 	var NetworkHelper = {
 	  /**
@@ -8386,17 +8386,17 @@ return /******/ (function(modules) { // 
 	    try {
 	      conv.charset = aCharset || "UTF-8";
 	      return conv.ConvertToUnicode(aText);
 	    }
 	    catch (ex) {
 	      return aText;
 	    }
 	  },
-	
+
 	  /**
 	   * Reads all available bytes from aStream and converts them to aCharset.
 	   *
 	   * @param nsIInputStream aStream
 	   * @param string aCharset
 	   * @returns string
 	   *          UTF-16 encoded string based on the content of aStream and aCharset.
 	   */
@@ -8406,115 +8406,115 @@ return /******/ (function(modules) { // 
 	    try {
 	      text = NetUtil.readInputStreamToString(aStream, aStream.available())
 	      return this.convertToUnicode(text, aCharset);
 	    }
 	    catch (err) {
 	      return text;
 	    }
 	  },
-	
+
 	   /**
 	   * Reads the posted text from aRequest.
 	   *
 	   * @param nsIHttpChannel aRequest
 	   * @param string aCharset
 	   *        The content document charset, used when reading the POSTed data.
 	   * @returns string or null
 	   *          Returns the posted string if it was possible to read from aRequest
 	   *          otherwise null.
 	   */
 	  readPostTextFromRequest: function NH_readPostTextFromRequest(aRequest, aCharset)
 	  {
 	    if (aRequest instanceof Ci.nsIUploadChannel) {
 	      let iStream = aRequest.uploadStream;
-	
+
 	      let isSeekableStream = false;
 	      if (iStream instanceof Ci.nsISeekableStream) {
 	        isSeekableStream = true;
 	      }
-	
+
 	      let prevOffset;
 	      if (isSeekableStream) {
 	        prevOffset = iStream.tell();
 	        iStream.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
 	      }
-	
+
 	      // Read data from the stream.
 	      let text = this.readAndConvertFromStream(iStream, aCharset);
-	
+
 	      // Seek locks the file, so seek to the beginning only if necko hasn't
 	      // read it yet, since necko doesn't seek to 0 before reading (at lest
 	      // not till 459384 is fixed).
 	      if (isSeekableStream && prevOffset == 0) {
 	        iStream.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
 	      }
 	      return text;
 	    }
 	    return null;
 	  },
-	
+
 	  /**
 	   * Reads the posted text from the page's cache.
 	   *
 	   * @param nsIDocShell aDocShell
 	   * @param string aCharset
 	   * @returns string or null
 	   *          Returns the posted string if it was possible to read from
 	   *          aDocShell otherwise null.
 	   */
 	  readPostTextFromPage: function NH_readPostTextFromPage(aDocShell, aCharset)
 	  {
 	    let webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation);
 	    return this.readPostTextFromPageViaWebNav(webNav, aCharset);
 	  },
-	
+
 	  /**
 	   * Reads the posted text from the page's cache, given an nsIWebNavigation
 	   * object.
 	   *
 	   * @param nsIWebNavigation aWebNav
 	   * @param string aCharset
 	   * @returns string or null
 	   *          Returns the posted string if it was possible to read from
 	   *          aWebNav, otherwise null.
 	   */
 	  readPostTextFromPageViaWebNav:
 	  function NH_readPostTextFromPageViaWebNav(aWebNav, aCharset)
 	  {
 	    if (aWebNav instanceof Ci.nsIWebPageDescriptor) {
 	      let descriptor = aWebNav.currentDescriptor;
-	
+
 	      if (descriptor instanceof Ci.nsISHEntry && descriptor.postData &&
 	          descriptor instanceof Ci.nsISeekableStream) {
 	        descriptor.seek(NS_SEEK_SET, 0);
-	
+
 	        return this.readAndConvertFromStream(descriptor, aCharset);
 	      }
 	    }
 	    return null;
 	  },
-	
+
 	  /**
 	   * Gets the web appId that is associated with aRequest.
 	   *
 	   * @param nsIHttpChannel aRequest
 	   * @returns number|null
 	   *          The appId for the given request, if available.
 	   */
 	  getAppIdForRequest: function NH_getAppIdForRequest(aRequest)
 	  {
 	    try {
 	      return this.getRequestLoadContext(aRequest).appId;
 	    } catch (ex) {
 	      // request loadContent is not always available.
 	    }
 	    return null;
 	  },
-	
+
 	  /**
 	   * Gets the topFrameElement that is associated with aRequest. This
 	   * works in single-process and multiprocess contexts. It may cross
 	   * the content/chrome boundary.
 	   *
 	   * @param nsIHttpChannel aRequest
 	   * @returns nsIDOMElement|null
 	   *          The top frame element for the given request.
@@ -8523,158 +8523,158 @@ return /******/ (function(modules) { // 
 	  {
 	    try {
 	      return this.getRequestLoadContext(aRequest).topFrameElement;
 	    } catch (ex) {
 	      // request loadContent is not always available.
 	    }
 	    return null;
 	  },
-	
+
 	  /**
 	   * Gets the nsIDOMWindow that is associated with aRequest.
 	   *
 	   * @param nsIHttpChannel aRequest
 	   * @returns nsIDOMWindow or null
 	   */
 	  getWindowForRequest: function NH_getWindowForRequest(aRequest)
 	  {
 	    try {
 	      return this.getRequestLoadContext(aRequest).associatedWindow;
 	    } catch (ex) {
 	      // TODO: bug 802246 - getWindowForRequest() throws on b2g: there is no
 	      // associatedWindow property.
 	    }
 	    return null;
 	  },
-	
+
 	  /**
 	   * Gets the nsILoadContext that is associated with aRequest.
 	   *
 	   * @param nsIHttpChannel aRequest
 	   * @returns nsILoadContext or null
 	   */
 	  getRequestLoadContext: function NH_getRequestLoadContext(aRequest)
 	  {
 	    try {
 	      return aRequest.notificationCallbacks.getInterface(Ci.nsILoadContext);
 	    } catch (ex) { }
-	
+
 	    try {
 	      return aRequest.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext);
 	    } catch (ex) { }
-	
+
 	    return null;
 	  },
-	
+
 	  /**
 	   * Determines whether the request has been made for the top level document.
 	   *
 	   * @param nsIHttpChannel aRequest
 	   * @returns Boolean True if the request represents the top level document.
 	   */
 	  isTopLevelLoad: function(aRequest)
 	  {
 	    if (aRequest instanceof Ci.nsIChannel) {
 	      let loadInfo = aRequest.loadInfo;
 	      if (loadInfo && loadInfo.parentOuterWindowID == loadInfo.outerWindowID) {
 	        return (aRequest.loadFlags & Ci.nsIChannel.LOAD_DOCUMENT_URI);
 	      }
 	    }
-	
+
 	    return false;
 	  },
-	
+
 	  /**
 	   * Loads the content of aUrl from the cache.
 	   *
 	   * @param string aUrl
 	   *        URL to load the cached content for.
 	   * @param string aCharset
 	   *        Assumed charset of the cached content. Used if there is no charset
 	   *        on the channel directly.
 	   * @param function aCallback
 	   *        Callback that is called with the loaded cached content if available
 	   *        or null if something failed while getting the cached content.
 	   */
 	  loadFromCache: function NH_loadFromCache(aUrl, aCharset, aCallback)
 	  {
 	    let channel = NetUtil.newChannel({uri: aUrl, loadUsingSystemPrincipal: true});
-	
+
 	    // Ensure that we only read from the cache and not the server.
 	    channel.loadFlags = Ci.nsIRequest.LOAD_FROM_CACHE |
 	      Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE |
 	      Ci.nsICachingChannel.LOAD_BYPASS_LOCAL_CACHE_IF_BUSY;
-	
+
 	    NetUtil.asyncFetch(
 	      channel,
 	      (aInputStream, aStatusCode, aRequest) => {
 	        if (!components.isSuccessCode(aStatusCode)) {
 	          aCallback(null);
 	          return;
 	        }
-	
+
 	        // Try to get the encoding from the channel. If there is none, then use
 	        // the passed assumed aCharset.
 	        let aChannel = aRequest.QueryInterface(Ci.nsIChannel);
 	        let contentCharset = aChannel.contentCharset || aCharset;
-	
+
 	        // Read the content of the stream using contentCharset as encoding.
 	        aCallback(this.readAndConvertFromStream(aInputStream, contentCharset));
 	      });
 	  },
-	
+
 	  /**
 	   * Parse a raw Cookie header value.
 	   *
 	   * @param string aHeader
 	   *        The raw Cookie header value.
 	   * @return array
 	   *         Array holding an object for each cookie. Each object holds the
 	   *         following properties: name and value.
 	   */
 	  parseCookieHeader: function NH_parseCookieHeader(aHeader)
 	  {
 	    let cookies = aHeader.split(";");
 	    let result = [];
-	
+
 	    cookies.forEach(function(aCookie) {
 	      let equal = aCookie.indexOf("=");
 	      let name = aCookie.substr(0, equal);
 	      let value = aCookie.substr(equal + 1);
 	      result.push({name: unescape(name.trim()),
 	                   value: unescape(value.trim())});
 	    });
-	
+
 	    return result;
 	  },
-	
+
 	  /**
 	   * Parse a raw Set-Cookie header value.
 	   *
 	   * @param string aHeader
 	   *        The raw Set-Cookie header value.
 	   * @return array
 	   *         Array holding an object for each cookie. Each object holds the
 	   *         following properties: name, value, secure (boolean), httpOnly
 	   *         (boolean), path, domain and expires (ISO date string).
 	   */
 	  parseSetCookieHeader: function NH_parseSetCookieHeader(aHeader)
 	  {
 	    let rawCookies = aHeader.split(/\r\n|\n|\r/);
 	    let cookies = [];
-	
+
 	    rawCookies.forEach(function(aCookie) {
 	      let equal = aCookie.indexOf("=");
 	      let name = unescape(aCookie.substr(0, equal).trim());
 	      let parts = aCookie.substr(equal + 1).split(";");
 	      let value = unescape(parts.shift().trim());
-	
+
 	      let cookie = {name: name, value: value};
-	
+
 	      parts.forEach(function(aPart) {
 	        let part = aPart.trim();
 	        if (part.toLowerCase() == "secure") {
 	          cookie.secure = true;
 	        }
 	        else if (part.toLowerCase() == "httponly") {
 	          cookie.httpOnly = true;
 	        }
@@ -8688,23 +8688,23 @@ return /******/ (function(modules) { // 
 	            try {
 	              pair[1] = pair[1].replace(/-/g, ' ');
 	              cookie.expires = new Date(pair[1]).toISOString();
 	            }
 	            catch (ex) { }
 	          }
 	        }
 	      });
-	
+
 	      cookies.push(cookie);
 	    });
-	
+
 	    return cookies;
 	  },
-	
+
 	  // This is a list of all the mime category maps jviereck could find in the
 	  // firebug code base.
 	  mimeCategoryMap: {
 	    "text/plain": "txt",
 	    "text/html": "html",
 	    "text/xml": "xml",
 	    "text/xsl": "txt",
 	    "text/xul": "txt",
@@ -8766,53 +8766,53 @@ return /******/ (function(modules) { // 
 	    "audio/wav": "media",
 	    "audio/x-wav": "media",
 	    "text/json": "json",
 	    "application/x-json": "json",
 	    "application/json-rpc": "json",
 	    "application/x-web-app-manifest+json": "json",
 	    "application/manifest+json": "json"
 	  },
-	
+
 	  /**
 	   * Check if the given MIME type is a text-only MIME type.
 	   *
 	   * @param string aMimeType
 	   * @return boolean
 	   */
 	  isTextMimeType: function NH_isTextMimeType(aMimeType)
 	  {
 	    if (aMimeType.indexOf("text/") == 0) {
 	      return true;
 	    }
-	
+
 	    // XML and JSON often come with custom MIME types, so in addition to the
 	    // standard "application/xml" and "application/json", we also look for
 	    // variants like "application/x-bigcorp+xml". For JSON we allow "+json" and
 	    // "-json" as suffixes.
 	    if (/^application\/\w+(?:[\.-]\w+)*(?:\+xml|[-+]json)$/.test(aMimeType)) {
 	      return true;
 	    }
-	
+
 	    let category = this.mimeCategoryMap[aMimeType] || null;
 	    switch (category) {
 	      case "txt":
 	      case "js":
 	      case "json":
 	      case "css":
 	      case "html":
 	      case "svg":
 	      case "xml":
 	        return true;
-	
+
 	      default:
 	        return false;
 	    }
 	  },
-	
+
 	  /**
 	   * Takes a securityInfo object of nsIRequest, the nsIRequest itself and
 	   * extracts security information from them.
 	   *
 	   * @param object securityInfo
 	   *        The securityInfo object of a request. If null channel is assumed
 	   *        to be insecure.
 	   * @param object httpActivity
@@ -8839,22 +8839,22 @@ return /******/ (function(modules) { // 
 	   *          If state == weak: Same as state == secure and
 	   *            - weaknessReasons: list of reasons that cause the request to be
 	   *                               considered weak. See getReasonsForWeakness.
 	   */
 	  parseSecurityInfo: function NH_parseSecurityInfo(securityInfo, httpActivity) {
 	    const info = {
 	      state: "insecure",
 	    };
-	
+
 	    // The request did not contain any security info.
 	    if (!securityInfo) {
 	      return info;
 	    }
-	
+
 	    /**
 	     * Different scenarios to consider here and how they are handled:
 	     * - request is HTTP, the connection is not secure
 	     *   => securityInfo is null
 	     *      => state === "insecure"
 	     *
 	     * - request is HTTPS, the connection is secure
 	     *   => .securityState has STATE_IS_SECURE flag
@@ -8876,27 +8876,27 @@ return /******/ (function(modules) { // 
 	     *   https://hg.mozilla.org/mozilla-central/annotate/def6ed9d1c1a/
 	     *   security/manager/ssl/nsNSSCallbacks.cpp#l1233
 	     * - request is mixed content (which makes no sense whatsoever)
 	     *   => .securityState has STATE_IS_BROKEN flag
 	     *   => .errorCode is NOT an NSS error code
 	     *   => .errorMessage is not available
 	     *      => state === "weak"
 	     */
-	
+
 	    securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
 	    securityInfo.QueryInterface(Ci.nsISSLStatusProvider);
-	
+
 	    const wpl = Ci.nsIWebProgressListener;
 	    const NSSErrorsService = Cc['@mozilla.org/nss_errors_service;1']
 	                               .getService(Ci.nsINSSErrorsService);
 	    const SSLStatus = securityInfo.SSLStatus;
 	    if (!NSSErrorsService.isNSSErrorCode(securityInfo.errorCode)) {
 	      const state = securityInfo.securityState;
-	
+
 	      let uri = null;
 	      if (httpActivity.channel && httpActivity.channel.URI) {
 	        uri = httpActivity.channel.URI;
 	      }
 	      if (uri && !uri.schemeIs("https") && !uri.schemeIs("wss")) {
 	        // it is not enough to look at the transport security info - schemes other than
 	        // https and wss are subject to downgrade/etc at the scheme level and should
 	        // always be considered insecure
@@ -8913,58 +8913,58 @@ return /******/ (function(modules) { // 
 	        // This was most likely an https request that was aborted before
 	        // validation. Return info as info.state = insecure.
 	        return info;
 	      } else {
 	        DevToolsUtils.reportException("NetworkHelper.parseSecurityInfo",
 	          "Security state " + state + " has no known STATE_IS_* flags.");
 	        return info;
 	      }
-	
+
 	      // Cipher suite.
 	      info.cipherSuite = SSLStatus.cipherName;
-	
+
 	      // Protocol version.
 	      info.protocolVersion = this.formatSecurityProtocol(SSLStatus.protocolVersion);
-	
+
 	      // Certificate.
 	      info.cert = this.parseCertificateInfo(SSLStatus.serverCert);
-	
+
 	      // HSTS and HPKP if available.
 	      if (httpActivity.hostname) {
 	        const sss = Cc("@mozilla.org/ssservice;1")
 	                      .getService(Ci.nsISiteSecurityService);
-	
-	
+
+
 	        // SiteSecurityService uses different storage if the channel is
 	        // private. Thus we must give isSecureHost correct flags or we
 	        // might get incorrect results.
 	        let flags = (httpActivity.private) ?
 	                      Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0;
-	
+
 	        let host = httpActivity.hostname;
-	
+
 	        info.hsts = sss.isSecureHost(sss.HEADER_HSTS, host, flags);
 	        info.hpkp = sss.isSecureHost(sss.HEADER_HPKP, host, flags);
 	      } else {
 	        DevToolsUtils.reportException("NetworkHelper.parseSecurityInfo",
 	          "Could not get HSTS/HPKP status as hostname is not available.");
 	        info.hsts = false;
 	        info.hpkp = false;
 	      }
-	
+
 	    } else {
 	      // The connection failed.
 	      info.state = "broken";
 	      info.errorMessage = securityInfo.errorMessage;
 	    }
-	
+
 	    return info;
 	  },
-	
+
 	  /**
 	   * Takes an nsIX509Cert and returns an object with certificate information.
 	   *
 	   * @param nsIX509Cert cert
 	   *        The certificate to extract the information from.
 	   * @return object
 	   *         An object with following format:
 	   *           {
@@ -8977,40 +8977,40 @@ return /******/ (function(modules) { // 
 	  parseCertificateInfo: function NH_parseCertifificateInfo(cert) {
 	    let info = {};
 	    if (cert) {
 	      info.subject = {
 	        commonName: cert.commonName,
 	        organization: cert.organization,
 	        organizationalUnit: cert.organizationalUnit,
 	      };
-	
+
 	      info.issuer = {
 	        commonName: cert.issuerCommonName,
 	        organization: cert.issuerOrganization,
 	        organizationUnit: cert.issuerOrganizationUnit,
 	      };
-	
+
 	      info.validity = {
 	        start: cert.validity.notBeforeLocalDay,
 	        end: cert.validity.notAfterLocalDay,
 	      };
-	
+
 	      info.fingerprint = {
 	        sha1: cert.sha1Fingerprint,
 	        sha256: cert.sha256Fingerprint,
 	      };
 	    } else {
 	      DevToolsUtils.reportException("NetworkHelper.parseCertificateInfo",
 	        "Secure connection established without certificate.");
 	    }
-	
+
 	    return info;
 	  },
-	
+
 	  /**
 	   * Takes protocolVersion of SSLStatus object and returns human readable
 	   * description.
 	   *
 	   * @param Number version
 	   *        One of nsISSLStatus version constants.
 	   * @return string
 	   *         One of TLSv1, TLSv1.1, TLSv1.2 if @param version is valid,
@@ -9025,119 +9025,119 @@ return /******/ (function(modules) { // 
 	      case Ci.nsISSLStatus.TLS_VERSION_1_2:
 	        return "TLSv1.2";
 	      default:
 	        DevToolsUtils.reportException("NetworkHelper.formatSecurityProtocol",
 	          "protocolVersion " + version + " is unknown.");
 	        return "Unknown";
 	    }
 	  },
-	
+
 	  /**
 	   * Takes the securityState bitfield and returns reasons for weak connection
 	   * as an array of strings.
 	   *
 	   * @param Number state
 	   *        nsITransportSecurityInfo.securityState.
 	   *
 	   * @return Array[String]
 	   *         List of weakness reasons. A subset of { cipher } where
 	   *         * cipher: The cipher suite is consireded to be weak (RC4).
 	   */
 	  getReasonsForWeakness: function NH_getReasonsForWeakness(state) {
 	    const wpl = Ci.nsIWebProgressListener;
-	
+
 	    // If there's non-fatal security issues the request has STATE_IS_BROKEN
 	    // flag set. See http://hg.mozilla.org/mozilla-central/file/44344099d119
 	    // /security/manager/ssl/nsNSSCallbacks.cpp#l1233
 	    let reasons = [];
-	
+
 	    if (state & wpl.STATE_IS_BROKEN) {
 	      let isCipher = state & wpl.STATE_USES_WEAK_CRYPTO;
-	
+
 	      if (isCipher) {
 	        reasons.push("cipher");
 	      }
-	
+
 	      if (!isCipher) {
 	        DevToolsUtils.reportException("NetworkHelper.getReasonsForWeakness",
 	          "STATE_IS_BROKEN without a known reason. Full state was: " + state);
 	      }
 	    }
-	
+
 	    return reasons;
 	  },
-	
+
 	  /**
 	   * Parse a url's query string into its components
 	   *
 	   * @param string aQueryString
 	   *        The query part of a url
 	   * @return array
 	   *         Array of query params {name, value}
 	   */
 	  parseQueryString: function(aQueryString) {
 	    // Make sure there's at least one param available.
 	    // Be careful here, params don't necessarily need to have values, so
 	    // no need to verify the existence of a "=".
 	    if (!aQueryString) {
 	      return;
 	    }
-	
+
 	    // Turn the params string into an array containing { name: value } tuples.
 	    let paramsArray = aQueryString.replace(/^[?&]/, "").split("&").map(e => {
 	      let param = e.split("=");
 	      return {
 	        name: param[0] ? NetworkHelper.convertToUnicode(unescape(param[0])) : "",
 	        value: param[1] ? NetworkHelper.convertToUnicode(unescape(param[1])) : ""
 	      }});
-	
+
 	    return paramsArray;
 	  },
-	
+
 	  /**
 	   * Helper for getting an nsIURL instance out of a string.
 	   */
 	  nsIURL: function(aUrl, aStore = gNSURLStore) {
 	    if (aStore.has(aUrl)) {
 	      return aStore.get(aUrl);
 	    }
-	
+
 	    var uri = Services.io.newURI(aUrl).QueryInterface(Ci.nsIURL);
 	    aStore.set(aUrl, uri);
 	    return uri;
 	  }
 	};
-	
+
 	for (let prop of Object.getOwnPropertyNames(NetworkHelper)) {
 	  exports[prop] = NetworkHelper[prop];
 	}
 
 
 /***/ },
 /* 48 */
 /***/ 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 { Ci, Cc, Cr, CC } = __webpack_require__(35);
 	const { Services } = __webpack_require__(28);
 	const { dumpv } = __webpack_require__(42);
 	const EventEmitter = __webpack_require__(34);
 	const promise = __webpack_require__(40);
-	
+
 	const IOUtil = Cc("@mozilla.org/io-util;1").getService(Ci.nsIIOUtil);
-	
+
 	const ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1",
 	          "nsIScriptableInputStream", "init");
-	
+
 	const BUFFER_SIZE = 0x8000;
-	
+
 	/**
 	 * This helper function (and its companion object) are used by bulk senders and
 	 * receivers to read and write data in and out of other streams.  Functions that
 	 * make use of this tool are passed to callers when it is time to read or write
 	 * bulk data.  It is highly recommended to use these copier functions instead of
 	 * the stream directly because the copier enforces the agreed upon length.
 	 * Since bulk mode reuses an existing stream, the sender and receiver must write
 	 * and read exactly the agreed upon amount of data, or else the entire transport
@@ -9165,107 +9165,107 @@ return /******/ (function(modules) { // 
 	 * @return Promise
 	 *         The promise is resolved when copying completes or rejected if any
 	 *         (unexpected) errors occur.
 	 */
 	function copyStream(input, output, length) {
 	  let copier = new StreamCopier(input, output, length);
 	  return copier.copy();
 	}
-	
+
 	function StreamCopier(input, output, length) {
 	  EventEmitter.decorate(this);
 	  this._id = StreamCopier._nextId++;
 	  this.input = input;
 	  // Save off the base output stream, since we know it's async as we've required
 	  this.baseAsyncOutput = output;
 	  if (IOUtil.outputStreamIsBuffered(output)) {
 	    this.output = output;
 	  } else {
 	    this.output = Cc("@mozilla.org/network/buffered-output-stream;1")
 	                  .createInstance(Ci.nsIBufferedOutputStream);
 	    this.output.init(output, BUFFER_SIZE);
 	  }
 	  this._length = length;
 	  this._amountLeft = length;
 	  this._deferred = promise.defer();
-	
+
 	  this._copy = this._copy.bind(this);
 	  this._flush = this._flush.bind(this);
 	  this._destroy = this._destroy.bind(this);
-	
+
 	  // Copy promise's then method up to this object.
 	  // Allows the copier to offer a promise interface for the simple succeed or
 	  // fail scenarios, but also emit events (due to the EventEmitter) for other
 	  // states, like progress.
 	  this.then = this._deferred.promise.then.bind(this._deferred.promise);
 	  this.then(this._destroy, this._destroy);
-	
+
 	  // Stream ready callback starts as |_copy|, but may switch to |_flush| at end
 	  // if flushing would block the output stream.
 	  this._streamReadyCallback = this._copy;
 	}
 	StreamCopier._nextId = 0;
-	
+
 	StreamCopier.prototype = {
-	
+
 	  copy: function() {
 	    // Dispatch to the next tick so that it's possible to attach a progress
 	    // event listener, even for extremely fast copies (like when testing).
 	    Services.tm.currentThread.dispatch(() => {
 	      try {
 	        this._copy();
 	      } catch (e) {
 	        this._deferred.reject(e);
 	      }
 	    }, 0);
 	    return this;
 	  },
-	
+
 	  _copy: function() {
 	    let bytesAvailable = this.input.available();
 	    let amountToCopy = Math.min(bytesAvailable, this._amountLeft);
 	    this._debug("Trying to copy: " + amountToCopy);
-	
+
 	    let bytesCopied;
 	    try {
 	      bytesCopied = this.output.writeFrom(this.input, amountToCopy);
 	    } catch (e) {
 	      if (e.result == Cr.NS_BASE_STREAM_WOULD_BLOCK) {
 	        this._debug("Base stream would block, will retry");
 	        this._debug("Waiting for output stream");
 	        this.baseAsyncOutput.asyncWait(this, 0, 0, Services.tm.currentThread);
 	        return;
 	      } else {
 	        throw e;
 	      }
 	    }
-	
+
 	    this._amountLeft -= bytesCopied;
 	    this._debug("Copied: " + bytesCopied +
 	                ", Left: " + this._amountLeft);
 	    this._emitProgress();
-	
+
 	    if (this._amountLeft === 0) {
 	      this._debug("Copy done!");
 	      this._flush();
 	      return;
 	    }
-	
+
 	    this._debug("Waiting for input stream");
 	    this.input.asyncWait(this, 0, 0, Services.tm.currentThread);
 	  },
-	
+
 	  _emitProgress: function() {
 	    this.emit("progress", {
 	      bytesSent: this._length - this._amountLeft,
 	      totalBytes: this._length
 	    });
 	  },
-	
+
 	  _flush: function() {
 	    try {
 	      this.output.flush();
 	    } catch (e) {
 	      if (e.result == Cr.NS_BASE_STREAM_WOULD_BLOCK ||
 	          e.result == Cr.NS_ERROR_FAILURE) {
 	        this._debug("Flush would block, will retry");
 	        this._streamReadyCallback = this._flush;
@@ -9273,43 +9273,43 @@ return /******/ (function(modules) { // 
 	        this.baseAsyncOutput.asyncWait(this, 0, 0, Services.tm.currentThread);
 	        return;
 	      } else {
 	        throw e;
 	      }
 	    }
 	    this._deferred.resolve();
 	  },
-	
+
 	  _destroy: function() {
 	    this._destroy = null;
 	    this._copy = null;
 	    this._flush = null;
 	    this.input = null;
 	    this.output = null;
 	  },
-	
+
 	  // nsIInputStreamCallback
 	  onInputStreamReady: function() {
 	    this._streamReadyCallback();
 	  },
-	
+
 	  // nsIOutputStreamCallback
 	  onOutputStreamReady: function() {
 	    this._streamReadyCallback();
 	  },
-	
+
 	  _debug: function(msg) {
 	    // Prefix logs with the copier ID, which makes logs much easier to
 	    // understand when several copiers are running simultaneously
 	    dumpv("Copier: " + this._id + " " + msg);
 	  }
-	
-	};
-	
+
+	};
+
 	/**
 	 * Read from a stream, one byte at a time, up to the next |delimiter|
 	 * character, but stopping if we've read |count| without finding it.  Reading
 	 * also terminates early if there are less than |count| bytes available on the
 	 * stream.  In that case, we only read as many bytes as the stream currently has
 	 * to offer.
 	 * TODO: This implementation could be removed if bug 984651 is fixed, which
 	 *       provides a native version of the same idea.
@@ -9321,59 +9321,59 @@ return /******/ (function(modules) { // 
 	 *        The max number of characters to read while searching.
 	 * @return string
 	 *         The data collected.  If the delimiter was found, this string will
 	 *         end with it.
 	 */
 	function delimitedRead(stream, delimiter, count) {
 	  dumpv("Starting delimited read for " + delimiter + " up to " +
 	        count + " bytes");
-	
+
 	  let scriptableStream;
 	  if (stream.readBytes) {
 	    scriptableStream = stream;
 	  } else {
 	    scriptableStream = new ScriptableInputStream(stream);
 	  }
-	
+
 	  let data = "";
-	
+
 	  // Don't exceed what's available on the stream
 	  count = Math.min(count, stream.available());
-	
+
 	  if (count <= 0) {
 	    return data;
 	  }
-	
+
 	  let char;
 	  while (char !== delimiter && count > 0) {
 	    char = scriptableStream.readBytes(1);
 	    count--;
 	    data += char;
 	  }
-	
+
 	  return data;
 	}
-	
+
 	module.exports = {
 	  copyStream: copyStream,
 	  delimitedRead: delimitedRead
 	};
 
 
 /***/ },
 /* 49 */
 /***/ 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";
-	
+
+	"use strict";
+
 	/**
 	 * Packets contain read / write functionality for the different packet types
 	 * supported by the debugging protocol, so that a transport can focus on
 	 * delivery and queue management without worrying too much about the specific
 	 * packet types.
 	 *
 	 * They are intended to be "one use only", so a new packet should be
 	 * instantiated for each incoming or outgoing packet.
@@ -9383,206 +9383,206 @@ return /******/ (function(modules) { // 
 	 *     Called when the input stream has data to read
 	 *   * write(stream)
 	 *     Called when the output stream is ready to write
 	 *   * get done()
 	 *     Returns true once the packet is done being read / written
 	 *   * destroy()
 	 *     Called to clean up at the end of use
 	 */
-	
+
 	const { Cc, Ci, Cu } = __webpack_require__(35);
 	const DevToolsUtils = __webpack_require__(42);
 	const { dumpn, dumpv } = DevToolsUtils;
 	const StreamUtils = __webpack_require__(48);
 	const promise = __webpack_require__(40);
-	
+
 	/*DevToolsUtils.defineLazyGetter(this, "unicodeConverter", () => {
 	  const unicodeConverter = Cc("@mozilla.org/intl/scriptableunicodeconverter")
 	                           .createInstance(Ci.nsIScriptableUnicodeConverter);
 	  unicodeConverter.charset = "UTF-8";
 	  return unicodeConverter;
 	});*/
 	const utf8 = __webpack_require__(50);
-	
+
 	// The transport's previous check ensured the header length did not exceed 20
 	// characters.  Here, we opt for the somewhat smaller, but still large limit of
 	// 1 TiB.
 	const PACKET_LENGTH_MAX = Math.pow(2, 40);
-	
+
 	/**
 	 * A generic Packet processing object (extended by two subtypes below).
 	 */
 	function Packet(transport) {
 	  this._transport = transport;
 	  this._length = 0;
 	}
-	
+
 	/**
 	 * Attempt to initialize a new Packet based on the incoming packet header we've
 	 * received so far.  We try each of the types in succession, trying JSON packets
 	 * first since they are much more common.
 	 * @param header string
 	 *        The packet header string to attempt parsing.
 	 * @param transport DebuggerTransport
 	 *        The transport instance that will own the packet.
 	 * @return Packet
 	 *         The parsed packet of the matching type, or null if no types matched.
 	 */
 	Packet.fromHeader = function(header, transport) {
 	  return JSONPacket.fromHeader(header, transport) ||
 	         BulkPacket.fromHeader(header, transport);
 	};
-	
+
 	Packet.prototype = {
-	
+
 	  get length() {
 	    return this._length;
 	  },
-	
+
 	  set length(length) {
 	    if (length > PACKET_LENGTH_MAX) {
 	      throw Error("Packet length " + length + " exceeds the max length of " +
 	                  PACKET_LENGTH_MAX);
 	    }
 	    this._length = length;
 	  },
-	
+
 	  destroy: function() {
 	    this._transport = null;
 	  }
-	
-	};
-	
+
+	};
+
 	exports.Packet = Packet;
-	
+
 	/**
 	 * With a JSON packet (the typical packet type sent via the transport), data is
 	 * transferred as a JSON packet serialized into a string, with the string length
 	 * prepended to the packet, followed by a colon ([length]:[packet]). The
 	 * contents of the JSON packet are specified in the Remote Debugging Protocol
 	 * specification.
 	 * @param transport DebuggerTransport
 	 *        The transport instance that will own the packet.
 	 */
 	function JSONPacket(transport) {
 	  Packet.call(this, transport);
 	  this._data = "";
 	  this._done = false;
 	}
-	
+
 	/**
 	 * Attempt to initialize a new JSONPacket based on the incoming packet header
 	 * we've received so far.
 	 * @param header string
 	 *        The packet header string to attempt parsing.
 	 * @param transport DebuggerTransport
 	 *        The transport instance that will own the packet.
 	 * @return JSONPacket
 	 *         The parsed packet, or null if it's not a match.
 	 */
 	JSONPacket.fromHeader = function(header, transport) {
 	  let match = this.HEADER_PATTERN.exec(header);
-	
+
 	  if (!match) {
 	    return null;
 	  }
-	
+
 	  dumpv("Header matches JSON packet");
 	  let packet = new JSONPacket(transport);
 	  packet.length = +match[1];
 	  return packet;
 	};
-	
+
 	JSONPacket.HEADER_PATTERN = /^(\d+):$/;
-	
+
 	JSONPacket.prototype = Object.create(Packet.prototype);
-	
+
 	Object.defineProperty(JSONPacket.prototype, "object", {
 	  /**
 	   * Gets the object (not the serialized string) being read or written.
 	   */
 	  get: function() { return this._object; },
-	
+
 	  /**
 	   * Sets the object to be sent when write() is called.
 	   */
 	  set: function(object) {
 	    this._object = object;
 	    let data = JSON.stringify(object);
 	    this._data = data;
 	    this.length = this._data.length;
 	  }
 	});
-	
+
 	JSONPacket.prototype.read = function(stream, scriptableStream) {
 	  dumpv("Reading JSON packet");
-	
+
 	  // Read in more packet data.
 	  this._readData(stream, scriptableStream);
-	
+
 	  if (!this.done) {
 	    // Don't have a complete packet yet.
 	    return;
 	  }
-	
+
 	  let json = this._data;
 	  try {
 	    json = utf8.decode(json);
 	    this._object = JSON.parse(json);
 	  } catch(e) {
 	    let msg = "Error parsing incoming packet: " + json + " (" + e +
 	              " - " + e.stack + ")";
 	    if (console.error) {
 	      console.error(msg);
 	    }
 	    dumpn(msg);
 	    return;
 	  }
-	
+
 	  this._transport._onJSONObjectReady(this._object);
 	}
-	
+
 	JSONPacket.prototype._readData = function(stream, scriptableStream) {
 	  if (!scriptableStream) {
 	    scriptableStream = stream;
 	  }
 	  if (dumpv.wantVerbose) {
 	    dumpv("Reading JSON data: _l: " + this.length + " dL: " +
 	          this._data.length + " sA: " + stream.available());
 	  }
 	  let bytesToRead = Math.min(this.length - this._data.length,
 	                             stream.available());
 	  this._data += scriptableStream.readBytes(bytesToRead);
 	  this._done = this._data.length === this.length;
 	}
-	
+
 	JSONPacket.prototype.write = function(stream) {
 	  dumpv("Writing JSON packet");
-	
+
 	  if (this._outgoing === undefined) {
 	    // Format the serialized packet to a buffer
 	    this._outgoing = this.length + ":" + this._data;
 	  }
-	
+
 	  let written = stream.write(this._outgoing, this._outgoing.length);
 	  this._outgoing = this._outgoing.slice(written);
 	  this._done = !this._outgoing.length;
 	}
-	
+
 	Object.defineProperty(JSONPacket.prototype, "done", {
 	  get: function() { return this._done; }
 	});
-	
+
 	JSONPacket.prototype.toString = function() {
 	  return JSON.stringify(this._object, null, 2);
 	}
-	
+
 	exports.JSONPacket = JSONPacket;
-	
+
 	/**
 	 * With a bulk packet, data is transferred by temporarily handing over the
 	 * transport's input or output stream to the application layer for writing data
 	 * directly.  This can be much faster for large data sets, and avoids various
 	 * stages of copies and data duplication inherent in the JSON packet type.  The
 	 * bulk packet looks like:
 	 *
 	 * bulk [actor] [type] [length]:[data]
@@ -9593,226 +9593,226 @@ return /******/ (function(modules) { // 
 	 * @param transport DebuggerTransport
 	 *        The transport instance that will own the packet.
 	 */
 	function BulkPacket(transport) {
 	  Packet.call(this, transport);
 	  this._done = false;
 	  this._readyForWriting = promise.defer();
 	}
-	
+
 	/**
 	 * Attempt to initialize a new BulkPacket based on the incoming packet header
 	 * we've received so far.
 	 * @param header string
 	 *        The packet header string to attempt parsing.
 	 * @param transport DebuggerTransport
 	 *        The transport instance that will own the packet.
 	 * @return BulkPacket
 	 *         The parsed packet, or null if it's not a match.
 	 */
 	BulkPacket.fromHeader = function(header, transport) {
 	  let match = this.HEADER_PATTERN.exec(header);
-	
+
 	  if (!match) {
 	    return null;
 	  }
-	
+
 	  dumpv("Header matches bulk packet");
 	  let packet = new BulkPacket(transport);
 	  packet.header = {
 	    actor: match[1],
 	    type: match[2],
 	    length: +match[3]
 	  };
 	  return packet;
 	};
-	
+
 	BulkPacket.HEADER_PATTERN = /^bulk ([^: ]+) ([^: ]+) (\d+):$/;
-	
+
 	BulkPacket.prototype = Object.create(Packet.prototype);
-	
+
 	BulkPacket.prototype.read = function(stream) {
 	  dumpv("Reading bulk packet, handing off input stream");
-	
+
 	  // Temporarily pause monitoring of the input stream
 	  this._transport.pauseIncoming();
-	
+
 	  let deferred = promise.defer();
-	
+
 	  this._transport._onBulkReadReady({
 	    actor: this.actor,
 	    type: this.type,
 	    length: this.length,
 	    copyTo: (output) => {
 	      dumpv("CT length: " + this.length);
 	      let copying = StreamUtils.copyStream(stream, output, this.length);
 	      deferred.resolve(copying);
 	      return copying;
 	    },
 	    stream: stream,
 	    done: deferred
 	  });
-	
+
 	  // Await the result of reading from the stream
 	  deferred.promise.then(() => {
 	    dumpv("onReadDone called, ending bulk mode");
 	    this._done = true;
 	    this._transport.resumeIncoming();
 	  }, this._transport.close);
-	
+
 	  // Ensure this is only done once
 	  this.read = () => {
 	    throw new Error("Tried to read() a BulkPacket's stream multiple times.");
 	  };
 	}
-	
+
 	BulkPacket.prototype.write = function(stream) {
 	  dumpv("Writing bulk packet");
-	
+
 	  if (this._outgoingHeader === undefined) {
 	    dumpv("Serializing bulk packet header");
 	    // Format the serialized packet header to a buffer
 	    this._outgoingHeader = "bulk " + this.actor + " " + this.type + " " +
 	                           this.length + ":";
 	  }
-	
+
 	  // Write the header, or whatever's left of it to write.
 	  if (this._outgoingHeader.length) {
 	    dumpv("Writing bulk packet header");
 	    let written = stream.write(this._outgoingHeader,
 	                               this._outgoingHeader.length);
 	    this._outgoingHeader = this._outgoingHeader.slice(written);
 	    return;
 	  }
-	
+
 	  dumpv("Handing off output stream");
-	
+
 	  // Temporarily pause the monitoring of the output stream
 	  this._transport.pauseOutgoing();
-	
+
 	  let deferred = promise.defer();
-	
+
 	  this._readyForWriting.resolve({
 	    copyFrom: (input) => {
 	      dumpv("CF length: " + this.length);
 	      let copying = StreamUtils.copyStream(input, stream, this.length);
 	      deferred.resolve(copying);
 	      return copying;
 	    },
 	    stream: stream,
 	    done: deferred
 	  });
-	
+
 	  // Await the result of writing to the stream
 	  deferred.promise.then(() => {
 	    dumpv("onWriteDone called, ending bulk mode");
 	    this._done = true;
 	    this._transport.resumeOutgoing();
 	  }, this._transport.close);
-	
+
 	  // Ensure this is only done once
 	  this.write = () => {
 	    throw new Error("Tried to write() a BulkPacket's stream multiple times.");
 	  };
 	}
-	
+
 	Object.defineProperty(BulkPacket.prototype, "streamReadyForWriting", {
 	  get: function() {
 	    return this._readyForWriting.promise;
 	  }
 	});
-	
+
 	Object.defineProperty(BulkPacket.prototype, "header", {
 	  get: function() {
 	    return {
 	      actor: this.actor,
 	      type: this.type,
 	      length: this.length
 	    };
 	  },
-	
+
 	  set: function(header) {
 	    this.actor = header.actor;
 	    this.type = header.type;
 	    this.length = header.length;
 	  },
 	});
-	
+
 	Object.defineProperty(BulkPacket.prototype, "done", {
 	  get: function() { return this._done; },
 	});
-	
-	
+
+
 	BulkPacket.prototype.toString = function() {
 	  return "Bulk: " + JSON.stringify(this.header, null, 2);
 	}
-	
+
 	exports.BulkPacket = BulkPacket;
-	
+
 	/**
 	 * RawPacket is used to test the transport's error handling of malformed
 	 * packets, by writing data directly onto the stream.
 	 * @param transport DebuggerTransport
 	 *        The transport instance that will own the packet.
 	 * @param data string
 	 *        The raw string to send out onto the stream.
 	 */
 	function RawPacket(transport, data) {
 	  Packet.call(this, transport);
 	  this._data = data;
 	  this.length = data.length;
 	  this._done = false;
 	}
-	
+
 	RawPacket.prototype = Object.create(Packet.prototype);
-	
+
 	RawPacket.prototype.read = function(stream) {
 	  // This hasn't yet been needed for testing.
 	  throw Error("Not implmented.");
 	}
-	
+
 	RawPacket.prototype.write = function(stream) {
 	  let written = stream.write(this._data, this._data.length);
 	  this._data = this._data.slice(written);
 	  this._done = !this._data.length;
 	}
-	
+
 	Object.defineProperty(RawPacket.prototype, "done", {
 	  get: function() { return this._done; }
 	});
-	
+
 	exports.RawPacket = RawPacket;
 
 
 /***/ },
 /* 50 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/utf8js v2.0.0 by @mathias */
 	;(function(root) {
-	
+
 		// Detect free variables `exports`
 		var freeExports = typeof exports == 'object' && exports;
-	
+
 		// Detect free variable `module`
 		var freeModule = typeof module == 'object' && module &&
 			module.exports == freeExports && module;
-	
+
 		// Detect free variable `global`, from Node.js or Browserified code,
 		// and use it as `root`
 		var freeGlobal = typeof global == 'object' && global;
 		if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
 			root = freeGlobal;
 		}
-	
+
 		/*--------------------------------------------------------------------------*/
-	
+
 		var stringFromCharCode = String.fromCharCode;
-	
+
 		// Taken from https://mths.be/punycode
 		function ucs2decode(string) {
 			var output = [];
 			var counter = 0;
 			var length = string.length;
 			var value;
 			var extra;
 			while (counter < length) {
@@ -9829,17 +9829,17 @@ return /******/ (function(modules) { // 
 						counter--;
 					}
 				} else {
 					output.push(value);
 				}
 			}
 			return output;
 		}
-	
+
 		// Taken from https://mths.be/punycode
 		function ucs2encode(array) {
 			var length = array.length;
 			var index = -1;
 			var value;
 			var output = '';
 			while (++index < length) {
 				value = array[index];
@@ -9847,31 +9847,31 @@ return /******/ (function(modules) { // 
 					value -= 0x10000;
 					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
 					value = 0xDC00 | value & 0x3FF;
 				}
 				output += stringFromCharCode(value);
 			}
 			return output;
 		}
-	
+
 		function checkScalarValue(codePoint) {
 			if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
 				throw Error(
 					'Lone surrogate U+' + codePoint.toString(16).toUpperCase() +
 					' is not a scalar value'
 				);
 			}
 		}
 		/*--------------------------------------------------------------------------*/
-	
+
 		function createByte(codePoint, shift) {
 			return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
 		}
-	
+
 		function encodeCodePoint(codePoint) {
 			if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
 				return stringFromCharCode(codePoint);
 			}
 			var symbol = '';
 			if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
 				symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
 			}
@@ -9883,134 +9883,134 @@ return /******/ (function(modules) { // 
 			else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
 				symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
 				symbol += createByte(codePoint, 12);
 				symbol += createByte(codePoint, 6);
 			}
 			symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
 			return symbol;
 		}
-	
+
 		function utf8encode(string) {
 			var codePoints = ucs2decode(string);
 			var length = codePoints.length;
 			var index = -1;
 			var codePoint;
 			var byteString = '';
 			while (++index < length) {
 				codePoint = codePoints[index];
 				byteString += encodeCodePoint(codePoint);
 			}
 			return byteString;
 		}
-	
+
 		/*--------------------------------------------------------------------------*/
-	
+
 		function readContinuationByte() {
 			if (byteIndex >= byteCount) {
 				throw Error('Invalid byte index');
 			}
-	
+
 			var continuationByte = byteArray[byteIndex] & 0xFF;
 			byteIndex++;
-	
+
 			if ((continuationByte & 0xC0) == 0x80) {
 				return continuationByte & 0x3F;
 			}
-	
+
 			// If we end up here, it’s not a continuation byte
 			throw Error('Invalid continuation byte');
 		}
-	
+
 		function decodeSymbol() {
 			var byte1;
 			var byte2;
 			var byte3;
 			var byte4;
 			var codePoint;
-	
+
 			if (byteIndex > byteCount) {
 				throw Error('Invalid byte index');
 			}
-	
+
 			if (byteIndex == byteCount) {
 				return false;
 			}
-	
+
 			// Read first byte
 			byte1 = byteArray[byteIndex] & 0xFF;
 			byteIndex++;
-	
+
 			// 1-byte sequence (no continuation bytes)
 			if ((byte1 & 0x80) == 0) {
 				return byte1;
 			}
-	
+
 			// 2-byte sequence
 			if ((byte1 & 0xE0) == 0xC0) {
 				var byte2 = readContinuationByte();
 				codePoint = ((byte1 & 0x1F) << 6) | byte2;
 				if (codePoint >= 0x80) {
 					return codePoint;
 				} else {
 					throw Error('Invalid continuation byte');
 				}
 			}
-	
+
 			// 3-byte sequence (may include unpaired surrogates)
 			if ((byte1 & 0xF0) == 0xE0) {
 				byte2 = readContinuationByte();
 				byte3 = readContinuationByte();
 				codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
 				if (codePoint >= 0x0800) {
 					checkScalarValue(codePoint);
 					return codePoint;
 				} else {
 					throw Error('Invalid continuation byte');
 				}
 			}
-	
+
 			// 4-byte sequence
 			if ((byte1 & 0xF8) == 0xF0) {
 				byte2 = readContinuationByte();
 				byte3 = readContinuationByte();
 				byte4 = readContinuationByte();
 				codePoint = ((byte1 & 0x0F) << 0x12) | (byte2 << 0x0C) |
 					(byte3 << 0x06) | byte4;
 				if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
 					return codePoint;
 				}
 			}
-	
+
 			throw Error('Invalid UTF-8 detected');
 		}
-	
+
 		var byteArray;
 		var byteCount;
 		var byteIndex;
 		function utf8decode(byteString) {
 			byteArray = ucs2decode(byteString);
 			byteCount = byteArray.length;
 			byteIndex = 0;
 			var codePoints = [];
 			var tmp;
 			while ((tmp = decodeSymbol()) !== false) {
 				codePoints.push(tmp);
 			}
 			return ucs2encode(codePoints);
 		}
-	
+
 		/*--------------------------------------------------------------------------*/
-	
+
 		var utf8 = {
 			'version': '2.0.0',
 			'encode': utf8encode,
 			'decode': utf8decode
 		};
-	
+
 		// Some AMD build optimizers, like r.js, check for specific condition patterns
 		// like the following:
 		if (
 			true
 		) {
 			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
 				return utf8;
 			}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
@@ -10022,19 +10022,19 @@ return /******/ (function(modules) { // 
 				var hasOwnProperty = object.hasOwnProperty;
 				for (var key in utf8) {
 					hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]);
 				}
 			}
 		} else { // in Rhino or a web browser
 			root.utf8 = utf8;
 		}
-	
+
 	}(this));
-	
+
 	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(51)(module), (function() { return this; }())))
 
 /***/ },
 /* 51 */
 /***/ function(module, exports) {
 
 	module.exports = function(module) {
 		if(!module.webpackPolyfill) {
@@ -10049,35 +10049,35 @@ return /******/ (function(modules) { // 
 
 
 /***/ },
 /* 52 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/utf8js v2.0.0 by @mathias */
 	;(function(root) {
-	
+
 		// Detect free variables `exports`
 		var freeExports = typeof exports == 'object' && exports;
-	
+
 		// Detect free variable `module`
 		var freeModule = typeof module == 'object' && module &&
 			module.exports == freeExports && module;
-	
+
 		// Detect free variable `global`, from Node.js or Browserified code,
 		// and use it as `root`
 		var freeGlobal = typeof global == 'object' && global;
 		if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
 			root = freeGlobal;
 		}
-	
+
 		/*--------------------------------------------------------------------------*/
-	
+
 		var stringFromCharCode = String.fromCharCode;
-	
+
 		// Taken from https://mths.be/punycode
 		function ucs2decode(string) {
 			var output = [];
 			var counter = 0;
 			var length = string.length;
 			var value;
 			var extra;
 			while (counter < length) {
@@ -10094,17 +10094,17 @@ return /******/ (function(modules) { // 
 						counter--;
 					}
 				} else {
 					output.push(value);
 				}
 			}
 			return output;
 		}
-	
+
 		// Taken from https://mths.be/punycode
 		function ucs2encode(array) {
 			var length = array.length;
 			var index = -1;
 			var value;
 			var output = '';
 			while (++index < length) {
 				value = array[index];
@@ -10112,31 +10112,31 @@ return /******/ (function(modules) { // 
 					value -= 0x10000;
 					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
 					value = 0xDC00 | value & 0x3FF;
 				}
 				output += stringFromCharCode(value);
 			}
 			return output;
 		}
-	
+
 		function checkScalarValue(codePoint) {
 			if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
 				throw Error(
 					'Lone surrogate U+' + codePoint.toString(16).toUpperCase() +
 					' is not a scalar value'
 				);
 			}
 		}
 		/*--------------------------------------------------------------------------*/
-	
+
 		function createByte(codePoint, shift) {
 			return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
 		}
-	
+
 		function encodeCodePoint(codePoint) {
 			if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
 				return stringFromCharCode(codePoint);
 			}
 			var symbol = '';
 			if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
 				symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
 			}
@@ -10148,134 +10148,134 @@ return /******/ (function(modules) { // 
 			else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
 				symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
 				symbol += createByte(codePoint, 12);
 				symbol += createByte(codePoint, 6);
 			}
 			symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
 			return symbol;
 		}
-	
+
 		function utf8encode(string) {
 			var codePoints = ucs2decode(string);
 			var length = codePoints.length;
 			var index = -1;
 			var codePoint;
 			var byteString = '';
 			while (++index < length) {
 				codePoint = codePoints[index];
 				byteString += encodeCodePoint(codePoint);
 			}
 			return byteString;
 		}
-	
+
 		/*--------------------------------------------------------------------------*/
-	
+
 		function readContinuationByte() {
 			if (byteIndex >= byteCount) {
 				throw Error('Invalid byte index');
 			}
-	
+
 			var continuationByte = byteArray[byteIndex] & 0xFF;
 			byteIndex++;
-	
+
 			if ((continuationByte & 0xC0) == 0x80) {
 				return continuationByte & 0x3F;
 			}
-	
+
 			// If we end up here, it’s not a continuation byte
 			throw Error('Invalid continuation byte');
 		}
-	
+
 		function decodeSymbol() {
 			var byte1;
 			var byte2;
 			var byte3;
 			var byte4;
 			var codePoint;
-	
+
 			if (byteIndex > byteCount) {
 				throw Error('Invalid byte index');
 			}
-	
+
 			if (byteIndex == byteCount) {
 				return false;
 			}
-	
+
 			// Read first byte
 			byte1 = byteArray[byteIndex] & 0xFF;
 			byteIndex++;
-	
+
 			// 1-byte sequence (no continuation bytes)
 			if ((byte1 & 0x80) == 0) {
 				return byte1;
 			}
-	
+
 			// 2-byte sequence
 			if ((byte1 & 0xE0) == 0xC0) {
 				var byte2 = readContinuationByte();
 				codePoint = ((byte1 & 0x1F) << 6) | byte2;
 				if (codePoint >= 0x80) {
 					return codePoint;
 				} else {
 					throw Error('Invalid continuation byte');
 				}
 			}
-	
+
 			// 3-byte sequence (may include unpaired surrogates)
 			if ((byte1 & 0xF0) == 0xE0) {
 				byte2 = readContinuationByte();
 				byte3 = readContinuationByte();
 				codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
 				if (codePoint >= 0x0800) {
 					checkScalarValue(codePoint);
 					return codePoint;
 				} else {
 					throw Error('Invalid continuation byte');
 				}
 			}
-	
+
 			// 4-byte sequence
 			if ((byte1 & 0xF8) == 0xF0) {
 				byte2 = readContinuationByte();
 				byte3 = readContinuationByte();
 				byte4 = readContinuationByte();
 				codePoint = ((byte1 & 0x0F) << 0x12) | (byte2 << 0x0C) |
 					(byte3 << 0x06) | byte4;
 				if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
 					return codePoint;
 				}
 			}
-	
+
 			throw Error('Invalid UTF-8 detected');
 		}
-	
+
 		var byteArray;
 		var byteCount;
 		var byteIndex;
 		function utf8decode(byteString) {
 			byteArray = ucs2decode(byteString);
 			byteCount = byteArray.length;
 			byteIndex = 0;
 			var codePoints = [];
 			var tmp;
 			while ((tmp = decodeSymbol()) !== false) {
 				codePoints.push(tmp);
 			}
 			return ucs2encode(codePoints);
 		}
-	
+
 		/*--------------------------------------------------------------------------*/
-	
+
 		var utf8 = {
 			'version': '2.0.0',
 			'encode': utf8encode,
 			'decode': utf8decode
 		};
-	
+
 		// Some AMD build optimizers, like r.js, check for specific condition patterns
 		// like the following:
 		if (
 			true
 		) {
 			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
 				return utf8;
 			}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
@@ -10287,46 +10287,46 @@ return /******/ (function(modules) { // 
 				var hasOwnProperty = object.hasOwnProperty;
 				for (var key in utf8) {
 					hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]);
 				}
 			}
 		} else { // in Rhino or a web browser
 			root.utf8 = utf8;
 		}
-	
+
 	}(this));
-	
+
 	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(51)(module), (function() { return this; }())))
 
 /***/ },
 /* 53 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- 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/. */
-	
+
 	const { Ci, Cu, components } = __webpack_require__(35);
 	const { Services } = __webpack_require__(28);
 	const DevToolsUtils = __webpack_require__(42);
-	
+
 	// WARNING I swapped the sync one for the async one here
 	// const promise = require("resource://devtools/shared/deprecated-sync-thenables.js", {}).Promise;
 	const promise = __webpack_require__(40);
-	
+
 	const events = __webpack_require__(54);
 	const { WebConsoleClient } = __webpack_require__(56);
 	/* const { DebuggerSocket } = require("../shared/security/socket");*/
 	/* const Authentication = require("../shared/security/auth");*/
-	
+
 	const noop = () => {};
-	
+
 	/**
 	 * TODO: Get rid of this API in favor of EventTarget (bug 1042642)
 	 *
 	 * Add simple event notification to a prototype object. Any object that has
 	 * some use for event notifications or the observer pattern in general can be
 	 * augmented with the necessary facilities by passing its prototype to this
 	 * function.
 	 *
@@ -10343,118 +10343,118 @@ return /******/ (function(modules) { // 
 	   *        Called when the event is fired. If the same listener
 	   *        is added more than once, it will be called once per
 	   *        addListener call.
 	   */
 	  aProto.addListener = function(aName, aListener) {
 	    if (typeof aListener != "function") {
 	      throw TypeError("Listeners must be functions.");
 	    }
-	
+
 	    if (!this._listeners) {
 	      this._listeners = {};
 	    }
-	
+
 	    this._getListeners(aName).push(aListener);
 	  };
-	
+
 	  /**
 	   * Add a listener to the event source for a given event. The
 	   * listener will be removed after it is called for the first time.
 	   *
 	   * @param aName string
 	   *        The event to listen for.
 	   * @param aListener function
 	   *        Called when the event is fired.
 	   */
 	  aProto.addOneTimeListener = function(aName, aListener) {
 	    let l = (...args) => {
 	      this.removeListener(aName, l);
 	      aListener.apply(null, args);
 	    };
 	    this.addListener(aName, l);
 	  };
-	
+
 	  /**
 	   * Remove a listener from the event source previously added with
 	   * addListener().
 	   *
 	   * @param aName string
 	   *        The event name used during addListener to add the listener.
 	   * @param aListener function
 	   *        The callback to remove. If addListener was called multiple
 	   *        times, all instances will be removed.
 	   */
 	  aProto.removeListener = function(aName, aListener) {
 	    if (!this._listeners || (aListener && !this._listeners[aName])) {
 	      return;
 	    }
-	
+
 	    if (!aListener) {
 	      this._listeners[aName] = [];
 	    }
 	    else {
 	      this._listeners[aName] =
 	        this._listeners[aName].filter(function(l) { return l != aListener; });
 	    }
 	  };
-	
+
 	  /**
 	   * Returns the listeners for the specified event name. If none are defined it
 	   * initializes an empty list and returns that.
 	   *
 	   * @param aName string
 	   *        The event name.
 	   */
 	  aProto._getListeners = function(aName) {
 	    if (aName in this._listeners) {
 	      return this._listeners[aName];
 	    }
 	    this._listeners[aName] = [];
 	    return this._listeners[aName];
 	  };
-	
+
 	  /**
 	   * Notify listeners of an event.
 	   *
 	   * @param aName string
 	   *        The event to fire.
 	   * @param arguments
 	   *        All arguments will be passed along to the listeners,
 	   *        including the name argument.
 	   */
 	  aProto.emit = function() {
 	    if (!this._listeners) {
 	      return;
 	    }
-	
+
 	    let name = arguments[0];
 	    let listeners = this._getListeners(name).slice(0);
-	
+
 	    for (let listener of listeners) {
 	      try {
 	        listener.apply(null, arguments);
 	      } catch (e) {
 	        // Prevent a bad listener from interfering with the others.
 	        DevToolsUtils.reportException("notify event '" + name + "'", e);
 	      }
 	    }
 	  };
 	}
-	
+
 	/**
 	 * Set of protocol messages that affect thread state, and the
 	 * state the actor is in after each message.
 	 */
 	const ThreadStateTypes = {
 	  "paused": "paused",
 	  "resumed": "attached",
 	  "detached": "detached"
 	};
-	
+
 	/**
 	 * Set of protocol messages that are sent by the server without a prior request
 	 * by the client.
 	 */
 	const UnsolicitedNotifications = {
 	  "consoleAPICall": "consoleAPICall",
 	  "eventNotification": "eventNotification",
 	  "fileActivity": "fileActivity",
@@ -10479,63 +10479,63 @@ return /******/ (function(modules) { // 
 	  "appOpen": "appOpen",
 	  "appClose": "appClose",
 	  "appInstall": "appInstall",
 	  "appUninstall": "appUninstall",
 	  "evaluationResult": "evaluationResult",
 	  "newSource": "newSource",
 	  "updatedSource": "updatedSource",
 	};
-	
+
 	/**
 	 * Set of pause types that are sent by the server and not as an immediate
 	 * response to a client request.
 	 */
 	const UnsolicitedPauses = {
 	  "resumeLimit": "resumeLimit",
 	  "debuggerStatement": "debuggerStatement",
 	  "breakpoint": "breakpoint",
 	  "DOMEvent": "DOMEvent",
 	  "watchpoint": "watchpoint",
 	  "exception": "exception"
 	};
-	
+
 	/**
 	 * Creates a client for the remote debugging protocol server. This client
 	 * provides the means to communicate with the server and exchange the messages
 	 * required by the protocol in a traditional JavaScript API.
 	 */
 	const DebuggerClient = exports.DebuggerClient = function(aTransport)
 	{
 	  this._transport = aTransport;
 	  this._transport.hooks = this;
-	
+
 	  // Map actor ID to client instance for each actor type.
 	  this._clients = new Map();
-	
+
 	  this._pendingRequests = new Map();
 	  this._activeRequests = new Map();
 	  this._eventsEnabled = true;
-	
+
 	  this.traits = {};
-	
+
 	  this.request = this.request.bind(this);
 	  this.localTransport = this._transport.onOutputStreamReady === undefined;
-	
+
 	  /*
 	   * As the first thing on the connection, expect a greeting packet from
 	   * the connection's root actor.
 	   */
 	  this.mainRoot = null;
 	  this.expectReply("root", (aPacket) => {
 	    this.mainRoot = new RootClient(this, aPacket);
 	    this.emit("connected", aPacket.applicationType, aPacket.traits);
 	  });
 	};
-	
+
 	/**
 	 * A declarative helper for defining methods that send requests to the server.
 	 *
 	 * @param aPacketSkeleton
 	 *        The form of the packet to send. Can specify fields to be filled from
 	 *        the parameters by using the |args| function.
 	 * @param telemetry
 	 *        The unique suffix of the telemetry histogram id.
@@ -10563,81 +10563,81 @@ return /******/ (function(modules) { // 
 	      let histogramId = "DEVTOOLS_DEBUGGER_RDP_"
 	        + transportType + telemetry + "_MS";
 	      histogram = Services.telemetry.getHistogramById(histogramId);
 	      startTime = +new Date();
 	    }
 	    let outgoingPacket = {
 	      to: aPacketSkeleton.to || this.actor
 	    };
-	
+
 	    let maxPosition = -1;
 	    for (let k of Object.keys(aPacketSkeleton)) {
 	      if (aPacketSkeleton[k] instanceof DebuggerClient.Argument) {
 	        let { position } = aPacketSkeleton[k];
 	        outgoingPacket[k] = aPacketSkeleton[k].getArgument(args);
 	        maxPosition = Math.max(position, maxPosition);
 	      } else {
 	        outgoingPacket[k] = aPacketSkeleton[k];
 	      }
 	    }
-	
+
 	    if (before) {
 	      outgoingPacket = before.call(this, outgoingPacket);
 	    }
-	
+
 	    return this.request(outgoingPacket, DevToolsUtils.makeInfallible((aResponse) => {
 	      if (after) {
 	        let { from } = aResponse;
 	        aResponse = after.call(this, aResponse);
 	        if (!aResponse.from) {
 	          aResponse.from = from;
 	        }
 	      }
-	
+
 	      // The callback is always the last parameter.
 	      let thisCallback = args[maxPosition + 1];
 	      if (thisCallback) {
 	        thisCallback(aResponse);
 	      }
-	
+
 	      if (histogram) {
 	        histogram.add(+new Date() - startTime);
 	      }
 	    }, "DebuggerClient.requester request callback"));
 	  }, "DebuggerClient.requester");
 	};
-	
+
 	function args(aPos) {
 	  return new DebuggerClient.Argument(aPos);
 	}
-	
+
 	DebuggerClient.Argument = function(aPosition) {
 	  this.position = aPosition;
 	};
-	
+
 	DebuggerClient.Argument.prototype.getArgument = function(aParams) {
 	  if (!(this.position in aParams)) {
 	    throw new Error("Bad index into params: " + this.position);
 	  }
 	  return aParams[this.position];
 	};
-	
+
 	// Expose these to save callers the trouble of importing DebuggerSocket
 	DebuggerClient.socketConnect = function(options) {
 	  // Defined here instead of just copying the function to allow lazy-load
 	  return DebuggerSocket.connect(options);
 	};
 	DevToolsUtils.defineLazyGetter(DebuggerClient, "Authenticators", () => {
 	  return Authentication.Authenticators;
 	});
 	DevToolsUtils.defineLazyGetter(DebuggerClient, "AuthenticationResult", () => {
 	  return Authentication.AuthenticationResult;
 	});
-	
+
 	DebuggerClient.prototype = {
 	  /**
 	   * Connect to the server and start exchanging protocol messages.
 	   *
 	   * @param aOnConnected function
 	   *        If specified, will be called when the greeting packet is
 	   *        received from the debugging server.
 	   *
@@ -10646,71 +10646,71 @@ return /******/ (function(modules) { // 
 	   *         is the application type, by default "browser", and the second
 	   *         element is the traits object (help figure out the features
 	   *         and behaviors of the server we connect to. See RootActor).
 	   */
 	  connect: function(aOnConnected) {
 	    return Promise.race([
 	      new Promise((resolve, reject) => {
 	        this.emit("connect");
-	
+
 	        // Also emit the event on the |DebuggerClient| object (not on the instance),
 	        // so it's possible to track all instances.
 	        events.emit(DebuggerClient, "connect", this);
-	
+
 	        this.addOneTimeListener("connected", (aName, aApplicationType, aTraits) => {
 	          this.traits = aTraits;
 	          if (aOnConnected) {
 	            aOnConnected(aApplicationType, aTraits);
 	          }
 	          resolve([aApplicationType, aTraits]);
 	        });
-	
+
 	        this._transport.ready();
 	      }),
 	      new Promise((resolve, reject) => {
 	        setTimeout(() => reject(new Error("Connect timeout error")), 6000);
 	      })
 	    ]);
 	  },
-	
+
 	  /**
 	   * Shut down communication with the debugging server.
 	   *
 	   * @param aOnClosed function
 	   *        If specified, will be called when the debugging connection
 	   *        has been closed.
 	   */
 	  close: function(aOnClosed) {
 	    // Disable detach event notifications, because event handlers will be in a
 	    // cleared scope by the time they run.
 	    this._eventsEnabled = false;
-	
+
 	    let cleanup = () => {
 	      this._transport.close();
 	      this._transport = null;
 	    };
-	
+
 	    // If the connection is already closed,
 	    // there is no need to detach client
 	    // as we won't be able to send any message.
 	    if (this._closed) {
 	      cleanup();
 	      if (aOnClosed) {
 	        aOnClosed();
 	      }
 	      return;
 	    }
-	
+
 	    if (aOnClosed) {
 	      this.addOneTimeListener("closed", function(aEvent) {
 	        aOnClosed();
 	      });
 	    }
-	
+
 	    // Call each client's `detach` method by calling
 	    // lastly registered ones first to give a chance
 	    // to detach child clients first.
 	    let clients = [...this._clients.values()];
 	    this._clients.clear();
 	    const detachClients = () => {
 	      let client = clients.pop();
 	      if (!client) {
@@ -10721,31 +10721,31 @@ return /******/ (function(modules) { // 
 	      if (client.detach) {
 	        client.detach(detachClients);
 	        return;
 	      }
 	      detachClients();
 	    };
 	    detachClients();
 	  },
-	
+
 	  /*
 	   * This function exists only to preserve DebuggerClient's interface;
 	   * new code should say 'client.mainRoot.listTabs()'.
 	   */
 	  listTabs: function(aOnResponse) { return this.mainRoot.listTabs(aOnResponse); },
-	
+
 	  /*
 	   * This function exists only to preserve DebuggerClient's interface;
 	   * new code should say 'client.mainRoot.listAddons()'.
 	   */
 	  listAddons: function(aOnResponse) { return this.mainRoot.listAddons(aOnResponse); },
-	
+
 	  getTab: function(aFilter) { return this.mainRoot.getTab(aFilter); },
-	
+
 	  /**
 	   * Attach to a tab actor.
 	   *
 	   * @param string aTabActor
 	   *        The actor ID for the tab to attach.
 	   * @param function aOnResponse
 	   *        Called with the response packet and a TabClient
 	   *        (which will be undefined on error).
@@ -10756,57 +10756,57 @@ return /******/ (function(modules) { // 
 	      let cachedResponse = {
 	        cacheDisabled: cachedTab.cacheDisabled,
 	        javascriptEnabled: cachedTab.javascriptEnabled,
 	        traits: cachedTab.traits,
 	      };
 	      DevToolsUtils.executeSoon(() => aOnResponse(cachedResponse, cachedTab));
 	      return promise.resolve([cachedResponse, cachedTab]);
 	    }
-	
+
 	    let packet = {
 	      to: aTabActor,
 	      type: "attach"
 	    };
 	    return this.request(packet).then(aResponse => {
 	      let tabClient;
 	      if (!aResponse.error) {
 	        tabClient = new TabClient(this, aResponse);
 	        this.registerClient(tabClient);
 	      }
 	      aOnResponse(aResponse, tabClient);
 	      return [aResponse, tabClient];
 	    });
 	  },
-	
+
 	  attachWorker: function DC_attachWorker(aWorkerActor, aOnResponse = noop) {
 	    let workerClient = this._clients.get(aWorkerActor);
 	    if (workerClient !== undefined) {
 	      let response = {
 	        from: workerClient.actor,
 	        type: "attached",
 	        url: workerClient.url
 	      };
 	      DevToolsUtils.executeSoon(() => aOnResponse(response, workerClient));
 	      return promise.resolve([response, workerClient]);
 	    }
-	
+
 	    return this.request({ to: aWorkerActor, type: "attach" }).then(aResponse => {
 	      if (aResponse.error) {
 	        aOnResponse(aResponse, null);
 	        return [aResponse, null];
 	      }
-	
+
 	      let workerClient = new WorkerClient(this, aResponse);
 	      this.registerClient(workerClient);
 	      aOnResponse(aResponse, workerClient);
 	      return [aResponse, workerClient];
 	    });
 	  },
-	
+
 	  /**
 	   * Attach to an addon actor.
 	   *
 	   * @param string aAddonActor
 	   *        The actor ID for the addon to attach.
 	   * @param function aOnResponse
 	   *        Called with the response packet and a AddonClient
 	   *        (which will be undefined on error).
@@ -10822,17 +10822,17 @@ return /******/ (function(modules) { // 
 	        addonClient = new AddonClient(this, aAddonActor);
 	        this.registerClient(addonClient);
 	        this.activeAddon = addonClient;
 	      }
 	      aOnResponse(aResponse, addonClient);
 	      return [aResponse, addonClient];
 	    });
 	  },
-	
+
 	  /**
 	   * Attach to a Web Console actor.
 	   *
 	   * @param string aConsoleActor
 	   *        The ID for the console actor to attach to.
 	   * @param array aListeners
 	   *        The console listeners you want to start.
 	   * @param function aOnResponse
@@ -10841,32 +10841,32 @@ return /******/ (function(modules) { // 
 	   */
 	  attachConsole:
 	  function(aConsoleActor, aListeners, aOnResponse = noop) {
 	    let packet = {
 	      to: aConsoleActor,
 	      type: "startListeners",
 	      listeners: aListeners,
 	    };
-	
+
 	    return this.request(packet).then(aResponse => {
 	      let consoleClient;
 	      if (!aResponse.error) {
 	        if (this._clients.has(aConsoleActor)) {
 	          consoleClient = this._clients.get(aConsoleActor);
 	        } else {
 	          consoleClient = new WebConsoleClient(this, aResponse);
 	          this.registerClient(consoleClient);
 	        }
 	      }
 	      aOnResponse(aResponse, consoleClient);
 	      return [aResponse, consoleClient];
 	    });
 	  },
-	
+
 	  /**
 	   * Attach to a global-scoped thread actor for chrome debugging.
 	   *
 	   * @param string aThreadActor
 	   *        The actor ID for the thread to attach.
 	   * @param function aOnResponse
 	   *        Called with the response packet and a ThreadClient
 	   *        (which will be undefined on error).
@@ -10875,62 +10875,62 @@ return /******/ (function(modules) { // 
 	   *        - useSourceMaps: whether to use source maps or not.
 	   */
 	  attachThread: function(aThreadActor, aOnResponse = noop, aOptions = {}) {
 	    if (this._clients.has(aThreadActor)) {
 	      let client = this._clients.get(aThreadActor);
 	      DevToolsUtils.executeSoon(() => aOnResponse({}, client));
 	      return promise.resolve([{}, client]);
 	    }
-	
+
 	    let packet = {
 	      to: aThreadActor,
 	      type: "attach",
 	      options: aOptions
 	    };
 	    return this.request(packet).then(aResponse => {
 	      if (!aResponse.error) {
 	        var threadClient = new ThreadClient(this, aThreadActor);
 	        this.registerClient(threadClient);
 	      }
 	      aOnResponse(aResponse, threadClient);
 	      return [aResponse, threadClient];
 	    });
 	  },
-	
+
 	  /**
 	   * Attach to a trace actor.
 	   *
 	   * @param string aTraceActor
 	   *        The actor ID for the tracer to attach.
 	   * @param function aOnResponse
 	   *        Called with the response packet and a TraceClient
 	   *        (which will be undefined on error).
 	   */
 	  attachTracer: function(aTraceActor, aOnResponse = noop) {
 	    if (this._clients.has(aTraceActor)) {
 	      let client = this._clients.get(aTraceActor);
 	      DevToolsUtils.executeSoon(() => aOnResponse({}, client));
 	      return promise.resolve([{}, client]);
 	    }
-	
+
 	    let packet = {
 	      to: aTraceActor,
 	      type: "attach"
 	    };
 	    return this.request(packet).then(aResponse => {
 	      if (!aResponse.error) {
 	        var traceClient = new TraceClient(this, aTraceActor);
 	        this.registerClient(traceClient);
 	      }
 	      aOnResponse(aResponse, traceClient);
 	      return [aResponse, traceClient];
 	    });
 	  },
-	
+
 	  /**
 	   * Fetch the ChromeActor for the main process or ChildProcessActor for a
 	   * a given child process ID.
 	   *
 	   * @param number aId
 	   *        The ID for the process to attach (returned by `listProcesses`).
 	   *        Connected to the main process if omitted, or is 0.
 	   */
@@ -10939,33 +10939,33 @@ return /******/ (function(modules) { // 
 	      to: "root",
 	      type: "getProcess"
 	    };
 	    if (typeof (aId) == "number") {
 	      packet.id = aId;
 	    }
 	    return this.request(packet);
 	  },
-	
+
 	  /**
 	   * Release an object actor.
 	   *
 	   * @param string aActor
 	   *        The actor ID to send the request to.
 	   * @param aOnResponse function
 	   *        If specified, will be called with the response packet when
 	   *        debugging server responds.
 	   */
 	  release: DebuggerClient.requester({
 	    to: args(0),
 	    type: "release"
 	  }, {
 	    telemetry: "RELEASE"
 	  }),
-	
+
 	  /**
 	   * Send a request to the debugging server.
 	   *
 	   * @param aRequest object
 	   *        A JSON packet to send to the debugging server.
 	   * @param aOnResponse function
 	   *        If specified, will be called with the JSON response packet when
 	   *        debugging server responds.
@@ -11021,26 +11021,26 @@ return /******/ (function(modules) { // 
 	                "'" + aRequest.to + "' " +
 	               "can't be sent as the connection is closed.";
 	      let resp = { error: "connectionClosed", message: msg };
 	      if (aOnResponse) {
 	        aOnResponse(resp);
 	      }
 	      return promise.reject(resp);
 	    }
-	
+
 	    let request = new Request(aRequest);
 	    request.format = "json";
 	    request.stack = components.stack;
 	    if (aOnResponse) {
 	      request.on("json-reply", aOnResponse);
 	    }
-	
+
 	    this._sendOrQueueRequest(request);
-	
+
 	    // Implement a Promise like API on the returned object
 	    // that resolves/rejects on request response
 	    let deferred = promise.defer();
 	    function listenerJson(resp) {
 	      request.off("json-reply", listenerJson);
 	      request.off("bulk-reply", listenerBulk);
 	      if (resp.error) {
 	        deferred.reject(resp);
@@ -11051,20 +11051,20 @@ return /******/ (function(modules) { // 
 	    function listenerBulk(resp) {
 	      request.off("json-reply", listenerJson);
 	      request.off("bulk-reply", listenerBulk);
 	      deferred.resolve(resp);
 	    }
 	    request.on("json-reply", listenerJson);
 	    request.on("bulk-reply", listenerBulk);
 	    request.then = deferred.promise.then.bind(deferred.promise);
-	
+
 	    return request;
 	  },
-	
+
 	  /**
 	   * Transmit streaming data via a bulk request.
 	   *
 	   * This method initiates the bulk send process by queuing up the header data.
 	   * The caller receives eventual access to a stream for writing.
 	   *
 	   * Since this opens up more options for how the server might respond (it could
 	   * send back either JSON or bulk data), and the returned Request object emits
@@ -11144,67 +11144,67 @@ return /******/ (function(modules) { // 
 	      throw Error("Bulk packet is missing the required 'type' field.");
 	    }
 	    if (!request.actor) {
 	      throw Error("'" + request.type + "' bulk packet has no destination.");
 	    }
 	    if (!request.length) {
 	      throw Error("'" + request.type + "' bulk packet has no length.");
 	    }
-	
+
 	    request = new Request(request);
 	    request.format = "bulk";
-	
+
 	    this._sendOrQueueRequest(request);
-	
+
 	    return request;
 	  },
-	
+
 	  /**
 	   * If a new request can be sent immediately, do so.  Otherwise, queue it.
 	   */
 	  _sendOrQueueRequest(request) {
 	    let actor = request.actor;
 	    if (!this._activeRequests.has(actor)) {
 	      this._sendRequest(request);
 	    } else {
 	      this._queueRequest(request);
 	    }
 	  },
-	
+
 	  /**
 	   * Send a request.
 	   * @throws Error if there is already an active request in flight for the same
 	   *         actor.
 	   */
 	  _sendRequest(request) {
 	    let actor = request.actor;
 	    this.expectReply(actor, request);
-	
+
 	    if (request.format === "json") {
 	      this._transport.send(request.request);
 	      return false;
 	    }
-	
+
 	    this._transport.startBulkSend(request.request).then((...args) => {
 	      request.emit("bulk-send-ready", ...args);
 	    });
 	  },
-	
+
 	  /**
 	   * Queue a request to be sent later.  Queues are only drained when an in
 	   * flight request to a given actor completes.
 	   */
 	  _queueRequest(request) {
 	    let actor = request.actor;
 	    let queue = this._pendingRequests.get(actor) || [];
 	    queue.push(request);
 	    this._pendingRequests.set(actor, queue);
 	  },
-	
+
 	  /**
 	   * Attempt the next request to a given actor (if any).
 	   */
 	  _attemptNextRequest(actor) {
 	    if (this._activeRequests.has(actor)) {
 	      return;
 	    }
 	    let queue = this._pendingRequests.get(actor);
@@ -11212,132 +11212,132 @@ return /******/ (function(modules) { // 
 	      return;
 	    }
 	    let request = queue.shift();
 	    if (queue.length === 0) {
 	      this._pendingRequests.delete(actor);
 	    }
 	    this._sendRequest(request);
 	  },
-	
+
 	  /**
 	   * Arrange to hand the next reply from |aActor| to the handler bound to
 	   * |aRequest|.
 	   *
 	   * DebuggerClient.prototype.request / startBulkRequest usually takes care of
 	   * establishing the handler for a given request, but in rare cases (well,
 	   * greetings from new root actors, is the only case at the moment) we must be
 	   * prepared for a "reply" that doesn't correspond to any request we sent.
 	   */
 	  expectReply: function(aActor, aRequest) {
 	    if (this._activeRequests.has(aActor)) {
 	      throw Error("clashing handlers for next reply from " + uneval(aActor));
 	    }
-	
+
 	    // If a handler is passed directly (as it is with the handler for the root
 	    // actor greeting), create a dummy request to bind this to.
 	    if (typeof aRequest === "function") {
 	      let handler = aRequest;
 	      aRequest = new Request();
 	      aRequest.on("json-reply", handler);
 	    }
-	
+
 	    this._activeRequests.set(aActor, aRequest);
 	  },
-	
+
 	  // Transport hooks.
-	
+
 	  /**
 	   * Called by DebuggerTransport to dispatch incoming packets as appropriate.
 	   *
 	   * @param aPacket object
 	   *        The incoming packet.
 	   */
 	  onPacket: function(aPacket) {
 	    if (!aPacket.from) {
 	      DevToolsUtils.reportException(
 	        "onPacket",
 	        new Error("Server did not specify an actor, dropping packet: " +
 	                  JSON.stringify(aPacket)));
 	      return;
 	    }
-	
+
 	    // If we have a registered Front for this actor, let it handle the packet
 	    // and skip all the rest of this unpleasantness.
 	    let front = this.getActor(aPacket.from);
 	    if (front) {
 	      front.onPacket(aPacket);
 	      return;
 	    }
-	
+
 	    if (this._clients.has(aPacket.from) && aPacket.type) {
 	      let client = this._clients.get(aPacket.from);
 	      let type = aPacket.type;
 	      if (client.events.indexOf(type) != -1) {
 	        client.emit(type, aPacket);
 	        // we ignore the rest, as the client is expected to handle this packet.
 	        return;
 	      }
 	    }
-	
+
 	    let activeRequest;
 	    // See if we have a handler function waiting for a reply from this
 	    // actor. (Don't count unsolicited notifications or pauses as
 	    // replies.)
 	    if (this._activeRequests.has(aPacket.from) &&
 	        !(aPacket.type in UnsolicitedNotifications) &&
 	        !(aPacket.type == ThreadStateTypes.paused &&
 	          aPacket.why.type in UnsolicitedPauses)) {
 	      activeRequest = this._activeRequests.get(aPacket.from);
 	      this._activeRequests.delete(aPacket.from);
 	    }
-	
+
 	    // If there is a subsequent request for the same actor, hand it off to the
 	    // transport.  Delivery of packets on the other end is always async, even
 	    // in the local transport case.
 	    this._attemptNextRequest(aPacket.from);
-	
+
 	    // Packets that indicate thread state changes get special treatment.
 	    if (aPacket.type in ThreadStateTypes &&
 	        this._clients.has(aPacket.from) &&
 	        typeof this._clients.get(aPacket.from)._onThreadState == "function") {
 	      this._clients.get(aPacket.from)._onThreadState(aPacket);
 	    }
-	
+
 	    // TODO: Bug 1151156 - Remove once Gecko 40 is on b2g-stable.
 	    if (!this.traits.noNeedToFakeResumptionOnNavigation) {
 	      // On navigation the server resumes, so the client must resume as well.
 	      // We achieve that by generating a fake resumption packet that triggers
 	      // the client's thread state change listeners.
 	      if (aPacket.type == UnsolicitedNotifications.tabNavigated &&
 	          this._clients.has(aPacket.from) &&
 	          this._clients.get(aPacket.from).thread) {
 	        let thread = this._clients.get(aPacket.from).thread;
 	        let resumption = { from: thread._actor, type: "resumed" };
 	        thread._onThreadState(resumption);
 	      }
 	    }
-	
+
 	    // Only try to notify listeners on events, not responses to requests
 	    // that lack a packet type.
 	    if (aPacket.type) {
 	      this.emit(aPacket.type, aPacket);
 	    }
-	
+
 	    if (activeRequest) {
 	      let emitReply = () => activeRequest.emit("json-reply", aPacket);
 	      if (activeRequest.stack) {
 	        Cu.callFunctionWithAsyncStack(emitReply, activeRequest.stack,
 	                                      "DevTools RDP");
 	      } else {
 	        emitReply();
 	      }
 	    }
 	  },
-	
+
 	  /**
 	   * Called by the DebuggerTransport to dispatch incoming bulk packets as
 	   * appropriate.
 	   *
 	   * @param packet object
 	   *        The incoming packet, which contains:
 	   *        * actor:  Name of actor that will receive the packet
 	   *        * type:   Name of actor's method that should be called on receipt
@@ -11360,79 +11360,79 @@ return /******/ (function(modules) { // 
 	   *          @return Promise
 	   *                  The promise is resolved when copying completes or rejected
 	   *                  if any (unexpected) errors occur.
 	   *                  This object also emits "progress" events for each chunk
 	   *                  that is copied.  See stream-utils.js.
 	   */
 	  onBulkPacket: function(packet) {
 	    let { actor, type, length } = packet;
-	
+
 	    if (!actor) {
 	      DevToolsUtils.reportException(
 	        "onBulkPacket",
 	        new Error("Server did not specify an actor, dropping bulk packet: " +
 	                  JSON.stringify(packet)));
 	      return;
 	    }
-	
+
 	    // See if we have a handler function waiting for a reply from this
 	    // actor.
 	    if (!this._activeRequests.has(actor)) {
 	      return;
 	    }
-	
+
 	    let activeRequest = this._activeRequests.get(actor);
 	    this._activeRequests.delete(actor);
-	
+
 	    // If there is a subsequent request for the same actor, hand it off to the
 	    // transport.  Delivery of packets on the other end is always async, even
 	    // in the local transport case.
 	    this._attemptNextRequest(actor);
-	
+
 	    activeRequest.emit("bulk-reply", packet);
 	  },
-	
+
 	  /**
 	   * Called by DebuggerTransport when the underlying stream is closed.
 	   *
 	   * @param aStatus nsresult
 	   *        The status code that corresponds to the reason for closing
 	   *        the stream.
 	   */
 	  onClosed: function(aStatus) {
 	    this._closed = true;
 	    this.emit("closed");
-	
+
 	    // Reject all pending and active requests
 	    let reject = function(type, request, actor) {
 	      // Server can send packets on its own and client only pass a callback
 	      // to expectReply, so that there is no request object.
 	      let msg;
 	      if (request.request) {
 	        msg = "'" + request.request.type + "' " + type + " request packet" +
 	              " to '" + actor + "' " +
 	              "can't be sent as the connection just closed.";
 	      } else {
 	        msg = "server side packet from '" + actor + "' can't be received " +
 	              "as the connection just closed.";
 	      }
 	      let packet = { error: "connectionClosed", message: msg };
 	      request.emit("json-reply", packet);
 	    };
-	
+
 	    let pendingRequests = new Map(this._pendingRequests);
 	    this._pendingRequests.clear();
 	    pendingRequests.forEach((list, actor) => {
 	      list.forEach(request => reject("pending", request, actor));
 	    });
 	    let activeRequests = new Map(this._activeRequests);
 	    this._activeRequests.clear();
 	    activeRequests.forEach(reject.bind(null, "active"));
-	
+
 	    // The |_pools| array on the client-side currently is used only by
 	    // protocol.js to store active fronts, mirroring the actor pools found in
 	    // the server.  So, read all usages of "pool" as "protocol.js front".
 	    //
 	    // In the normal case where we shutdown cleanly, the toolbox tells each tool
 	    // to close, and they each call |destroy| on any fronts they were using.
 	    // When |destroy| or |cleanup| is called on a protocol.js front, it also
 	    // removes itself from the |_pools| array.  Once the toolbox has shutdown,
@@ -11444,17 +11444,17 @@ return /******/ (function(modules) { // 
 	    // on them clear their state, reject pending requests, and remove themselves
 	    // from |_pools|.  This saves the toolbox from hanging indefinitely, in case
 	    // it waits for some server response before shutdown that will now never
 	    // arrive.
 	    for (let pool of this._pools) {
 	      pool.cleanup();
 	    }
 	  },
-	
+
 	  registerClient: function(client) {
 	    let actorID = client.actor;
 	    if (!actorID) {
 	      throw new Error("DebuggerServer.registerClient expects " +
 	                      "a client instance with an `actor` attribute.");
 	    }
 	    if (!Array.isArray(client.events)) {
 	      throw new Error("DebuggerServer.registerClient expects " +
@@ -11467,90 +11467,90 @@ return /******/ (function(modules) { // 
 	                      "have an `emit` function.");
 	    }
 	    if (this._clients.has(actorID)) {
 	      throw new Error("DebuggerServer.registerClient already registered " +
 	                      "a client for this actor.");
 	    }
 	    this._clients.set(actorID, client);
 	  },
-	
+
 	  unregisterClient: function(client) {
 	    let actorID = client.actor;
 	    if (!actorID) {
 	      throw new Error("DebuggerServer.unregisterClient expects " +
 	                      "a Client instance with a `actor` attribute.");
 	    }
 	    this._clients.delete(actorID);
 	  },
-	
+
 	  /**
 	   * Actor lifetime management, echos the server's actor pools.
 	   */
 	  __pools: null,
 	  get _pools() {
 	    if (this.__pools) {
 	      return this.__pools;
 	    }
 	    this.__pools = new Set();
 	    return this.__pools;
 	  },
-	
+
 	  addActorPool: function(pool) {
 	    this._pools.add(pool);
 	  },
 	  removeActorPool: function(pool) {
 	    this._pools.delete(pool);
 	  },
 	  getActor: function(actorID) {
 	    let pool = this.poolFor(actorID);
 	    return pool ? pool.get(actorID) : null;
 	  },
-	
+
 	  poolFor: function(actorID) {
 	    for (let pool of this._pools) {
 	      if (pool.has(actorID)) return pool;
 	    }
 	    return null;
 	  },
-	
+
 	  /**
 	   * Currently attached addon.
 	   */
 	  activeAddon: null
 	};
-	
+
 	eventSource(DebuggerClient.prototype);
-	
+
 	function Request(request) {
 	  this.request = request;
 	}
-	
+
 	Request.prototype = {
-	
+
 	  on: function(type, listener) {
 	    events.on(this, type, listener);
 	  },
-	
+
 	  off: function(type, listener) {
 	    events.off(this, type, listener);
 	  },
-	
+
 	  once: function(type, listener) {
 	    events.once(this, type, listener);
 	  },
-	
+
 	  emit: function(type, ...args) {
 	    events.emit(this, type, ...args);
 	  },
-	
+
 	  get actor() { return this.request.to || this.request.actor; }
-	
-	};
-	
+
+	};
+
 	/**
 	 * Creates a tab client for the remote debugging protocol server. This client
 	 * is a front to the tab actor created in the server side, hiding the protocol
 	 * details in a traditional JavaScript API.
 	 *
 	 * @param aClient DebuggerClient
 	 *        The debugger client parent.
 	 * @param aForm object
@@ -11562,52 +11562,52 @@ return /******/ (function(modules) { // 
 	  this._threadActor = aForm.threadActor;
 	  this.javascriptEnabled = aForm.javascriptEnabled;
 	  this.cacheDisabled = aForm.cacheDisabled;
 	  this.thread = null;
 	  this.request = this.client.request;
 	  this.traits = aForm.traits || {};
 	  this.events = ["workerListChanged"];
 	}
-	
+
 	TabClient.prototype = {
 	  get actor() { return this._actor; },
 	  get _transport() { return this.client._transport; },
-	
+
 	  /**
 	   * Attach to a thread actor.
 	   *
 	   * @param object aOptions
 	   *        Configuration options.
 	   *        - useSourceMaps: whether to use source maps or not.
 	   * @param function aOnResponse
 	   *        Called with the response packet and a ThreadClient
 	   *        (which will be undefined on error).
 	   */
 	  attachThread: function(aOptions = {}, aOnResponse = noop) {
 	    if (this.thread) {
 	      DevToolsUtils.executeSoon(() => aOnResponse({}, this.thread));
 	      return promise.resolve([{}, this.thread]);
 	    }
-	
+
 	    let packet = {
 	      to: this._threadActor,
 	      type: "attach",
 	      options: aOptions
 	    };
 	    return this.request(packet).then(aResponse => {
 	      if (!aResponse.error) {
 	        this.thread = new ThreadClient(this, this._threadActor);
 	        this.client.registerClient(this.thread);
 	      }
 	      aOnResponse(aResponse, this.thread);
 	      return [aResponse, this.thread];
 	    });
 	  },
-	
+
 	  /**
 	   * Detach the client from the tab actor.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  detach: DebuggerClient.requester({
 	    type: "detach"
@@ -11619,212 +11619,212 @@ return /******/ (function(modules) { // 
 	      return aPacket;
 	    },
 	    after: function(aResponse) {
 	      this.client.unregisterClient(this);
 	      return aResponse;
 	    },
 	    telemetry: "TABDETACH"
 	  }),
-	
+
 	  /**
 	   * Bring the window to the front.
 	   */
 	  focus: DebuggerClient.requester({
 	    type: "focus"
 	  }, {}),
-	
+
 	  /**
 	   * Reload the page in this tab.
 	   *
 	   * @param [optional] object options
 	   *        An object with a `force` property indicating whether or not
 	   *        this reload should skip the cache
 	   */
 	  reload: function(options = { force: false }) {
 	    return this._reload(options);
 	  },
 	  _reload: DebuggerClient.requester({
 	    type: "reload",
 	    options: args(0)
 	  }, {
 	    telemetry: "RELOAD"
 	  }),
-	
+
 	  /**
 	   * Navigate to another URL.
 	   *
 	   * @param string url
 	   *        The URL to navigate to.
 	   */
 	  navigateTo: DebuggerClient.requester({
 	    type: "navigateTo",
 	    url: args(0)
 	  }, {
 	    telemetry: "NAVIGATETO"
 	  }),
-	
+
 	  /**
 	   * Reconfigure the tab actor.
 	   *
 	   * @param object aOptions
 	   *        A dictionary object of the new options to use in the tab actor.
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  reconfigure: DebuggerClient.requester({
 	    type: "reconfigure",
 	    options: args(0)
 	  }, {
 	    telemetry: "RECONFIGURETAB"
 	  }),
-	
+
 	  listWorkers: DebuggerClient.requester({
 	    type: "listWorkers"
 	  }, {
 	    telemetry: "LISTWORKERS"
 	  }),
-	
+
 	  attachWorker: function(aWorkerActor, aOnResponse) {
 	    this.client.attachWorker(aWorkerActor, aOnResponse);
 	  },
-	
+
 	  /**
 	   * Resolve a location ({ url, line, column }) to its current
 	   * source mapping location.
 	   *
 	   * @param {String} arg[0].url
 	   * @param {Number} arg[0].line
 	   * @param {Number?} arg[0].column
 	   */
 	  resolveLocation: DebuggerClient.requester({
 	    type: "resolveLocation",
 	    location: args(0)
 	  }),
 	};
-	
+
 	eventSource(TabClient.prototype);
-	
+
 	function WorkerClient(aClient, aForm) {
 	  this.client = aClient;
 	  this._actor = aForm.from;
 	  this._isClosed = false;
 	  this._url = aForm.url;
-	
+
 	  this._onClose = this._onClose.bind(this);
-	
+
 	  this.addListener("close", this._onClose);
-	
+
 	  this.traits = {};
 	}
-	
+
 	WorkerClient.prototype = {
 	  get _transport() {
 	    return this.client._transport;
 	  },
-	
+
 	  get request() {
 	    return this.client.request;
 	  },
-	
+
 	  get actor() {
 	    return this._actor;
 	  },
-	
+
 	  get url() {
 	    return this._url;
 	  },
-	
+
 	  get isClosed() {
 	    return this._isClosed;
 	  },
-	
+
 	  detach: DebuggerClient.requester({ type: "detach" }, {
 	    after: function(aResponse) {
 	      if (this.thread) {
 	        this.client.unregisterClient(this.thread);
 	      }
 	      this.client.unregisterClient(this);
 	      return aResponse;
 	    },
-	
+
 	    telemetry: "WORKERDETACH"
 	  }),
-	
+
 	  attachThread: function(aOptions = {}, aOnResponse = noop) {
 	    if (this.thread) {
 	      let response = [{
 	        type: "connected",
 	        threadActor: this.thread._actor,
 	        consoleActor: this.consoleActor,
 	      }, this.thread];
 	      DevToolsUtils.executeSoon(() => aOnResponse(response));
 	      return response;
 	    }
-	
+
 	    // The connect call on server doesn't attach the thread as of version 44.
 	    return this.request({
 	      to: this._actor,
 	      type: "connect",
 	      options: aOptions,
 	    }).then(connectReponse => {
 	      if (connectReponse.error) {
 	        aOnResponse(connectReponse, null);
 	        return [connectResponse, null];
 	      }
-	
+
 	      return this.request({
 	        to: connectReponse.threadActor,
 	        type: "attach",
 	        options: aOptions
 	      }).then(attachResponse => {
 	        if (attachResponse.error) {
 	          aOnResponse(attachResponse, null);
 	        }
-	
+
 	        this.thread = new ThreadClient(this, connectReponse.threadActor);
 	        this.consoleActor = connectReponse.consoleActor;
 	        this.client.registerClient(this.thread);
-	
+
 	        aOnResponse(connectReponse, this.thread);
 	        return [connectResponse, this.thread];
 	      });
 	    });
 	  },
-	
+
 	  _onClose: function() {
 	    this.removeListener("close", this._onClose);
-	
+
 	    if (this.thread) {
 	      this.client.unregisterClient(this.thread);
 	    }
 	    this.client.unregisterClient(this);
 	    this._isClosed = true;
 	  },
-	
+
 	  reconfigure: function() {
 	    return Promise.resolve();
 	  },
-	
+
 	  events: ["close"]
 	};
-	
+
 	eventSource(WorkerClient.prototype);
-	
+
 	function AddonClient(aClient, aActor) {
 	  this._client = aClient;
 	  this._actor = aActor;
 	  this.request = this._client.request;
 	  this.events = [];
 	}
-	
+
 	AddonClient.prototype = {
 	  get actor() { return this._actor; },
 	  get _transport() { return this._client._transport; },
-	
+
 	  /**
 	   * Detach the client from the addon actor.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  detach: DebuggerClient.requester({
 	    type: "detach"
@@ -11834,17 +11834,17 @@ return /******/ (function(modules) { // 
 	        this._client.activeAddon = null;
 	      }
 	      this._client.unregisterClient(this);
 	      return aResponse;
 	    },
 	    telemetry: "ADDONDETACH"
 	  })
 	};
-	
+
 	/**
 	 * A RootClient object represents a root actor on the server. Each
 	 * DebuggerClient keeps a RootClient instance representing the root actor
 	 * for the initial connection; DebuggerClient's 'listTabs' and
 	 * 'listChildProcesses' methods forward to that root actor.
 	 *
 	 * @param aClient object
 	 *      The client connection to which this actor belongs.
@@ -11862,65 +11862,65 @@ return /******/ (function(modules) { // 
 	 */
 	function RootClient(aClient, aGreeting) {
 	  this._client = aClient;
 	  this.actor = aGreeting.from;
 	  this.applicationType = aGreeting.applicationType;
 	  this.traits = aGreeting.traits;
 	}
 	exports.RootClient = RootClient;
-	
+
 	RootClient.prototype = {
 	  constructor: RootClient,
-	
+
 	  /**
 	   * List the open tabs.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  listTabs: DebuggerClient.requester({ type: "listTabs" },
 	                                     { telemetry: "LISTTABS" }),
-	
+
 	  /**
 	   * List the installed addons.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  listAddons: DebuggerClient.requester({ type: "listAddons" },
 	                                       { telemetry: "LISTADDONS" }),
-	
+
 	  /**
 	   * List the registered workers.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  listWorkers: DebuggerClient.requester({ type: "listWorkers" },
 	                                        { telemetry: "LISTWORKERS" }),
-	
+
 	  /**
 	   * List the registered service workers.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  listServiceWorkerRegistrations: DebuggerClient.requester({ type: "listServiceWorkerRegistrations" },
 	                                                           { telemetry: "LISTSERVICEWORKERREGISTRATIONS" }),
-	
+
 	  /**
 	   * List the running processes.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  listProcesses: DebuggerClient.requester({ type: "listProcesses" },
 	                                          { telemetry: "LISTPROCESSES" }),
-	
+
 	  /**
 	   * Fetch the TabActor for the currently selected tab, or for a specific
 	   * tab given as first parameter.
 	   *
 	   * @param [optional] object aFilter
 	   *        A dictionary object with following optional attributes:
 	   *         - outerWindowID: used to match tabs in parent process
 	   *         - tabId: used to match tabs in child processes
@@ -11928,17 +11928,17 @@ return /******/ (function(modules) { // 
 	   *        If nothing is specified, returns the actor for the currently
 	   *        selected tab.
 	   */
 	  getTab: function(aFilter) {
 	    let packet = {
 	      to: this.actor,
 	      type: "getTab"
 	    };
-	
+
 	    if (aFilter) {
 	      if (typeof (aFilter.outerWindowID) == "number") {
 	        packet.outerWindowID = aFilter.outerWindowID;
 	      } else if (typeof (aFilter.tabId) == "number") {
 	        packet.tabId = aFilter.tabId;
 	      } else if ("tab" in aFilter) {
 	        let browser = aFilter.tab.linkedBrowser;
 	        if (browser.frameLoader.tabParent) {
@@ -11952,37 +11952,37 @@ return /******/ (function(modules) { // 
 	          packet.outerWindowID = windowUtils.outerWindowID;
 	        }
 	      } else {
 	        // Throw if a filter object have been passed but without
 	        // any clearly idenfified filter.
 	        throw new Error("Unsupported argument given to getTab request");
 	      }
 	    }
-	
+
 	    return this.request(packet);
 	  },
-	
+
 	  /**
 	   * Description of protocol's actors and methods.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  protocolDescription: DebuggerClient.requester({ type: "protocolDescription" },
 	                                                 { telemetry: "PROTOCOLDESCRIPTION" }),
-	
+
 	  /*
 	   * Methods constructed by DebuggerClient.requester require these forwards
 	   * on their 'this'.
 	   */
 	  get _transport() { return this._client._transport; },
 	  get request() { return this._client.request; }
 	};
-	
+
 	/**
 	 * Creates a thread client for the remote debugging protocol server. This client
 	 * is a front to the thread actor created in the server side, hiding the
 	 * protocol details in a traditional JavaScript API.
 	 *
 	 * @param aClient DebuggerClient|TabClient
 	 *        The parent of the thread (tab for tab-scoped debuggers, DebuggerClient
 	 *        for chrome debuggers).
@@ -11994,37 +11994,37 @@ return /******/ (function(modules) { // 
 	  this.client = aClient instanceof DebuggerClient ? aClient : aClient.client;
 	  this._actor = aActor;
 	  this._frameCache = [];
 	  this._scriptCache = {};
 	  this._pauseGrips = {};
 	  this._threadGrips = {};
 	  this.request = this.client.request;
 	}
-	
+
 	ThreadClient.prototype = {
 	  _state: "paused",
 	  get state() { return this._state; },
 	  get paused() { return this._state === "paused"; },
-	
+
 	  _pauseOnExceptions: false,
 	  _ignoreCaughtExceptions: false,
 	  _pauseOnDOMEvents: null,
-	
+
 	  _actor: null,
 	  get actor() { return this._actor; },
-	
+
 	  get _transport() { return this.client._transport; },
-	
+
 	  _assertPaused: function(aCommand) {
 	    if (!this.paused) {
 	      throw Error(aCommand + " command sent while not paused. Currently " + this._state);
 	    }
 	  },
-	
+
 	  /**
 	   * Resume a paused thread. If the optional aLimit parameter is present, then
 	   * the thread will also pause when that limit is reached.
 	   *
 	   * @param [optional] object aLimit
 	   *        An object with a type property set to the appropriate limit (next,
 	   *        step, or finish) per the remote debugging protocol specification.
 	   *        Use null to specify no limit.
@@ -12032,21 +12032,21 @@ return /******/ (function(modules) { // 
 	   *        Called with the response packet.
 	   */
 	  _doResume: DebuggerClient.requester({
 	    type: "resume",
 	    resumeLimit: args(0)
 	  }, {
 	    before: function(aPacket) {
 	      this._assertPaused("resume");
-	
+
 	      // Put the client in a tentative "resuming" state so we can prevent
 	      // further requests that should only be sent in the paused state.
 	      this._state = "resuming";
-	
+
 	      if (this._pauseOnExceptions) {
 	        aPacket.pauseOnExceptions = this._pauseOnExceptions;
 	      }
 	      if (this._ignoreCaughtExceptions) {
 	        aPacket.ignoreCaughtExceptions = this._ignoreCaughtExceptions;
 	      }
 	      if (this._pauseOnDOMEvents) {
 	        aPacket.pauseOnDOMEvents = this._pauseOnDOMEvents;
@@ -12057,142 +12057,142 @@ return /******/ (function(modules) { // 
 	      if (aResponse.error) {
 	        // There was an error resuming, back to paused state.
 	        this._state = "paused";
 	      }
 	      return aResponse;
 	    },
 	    telemetry: "RESUME"
 	  }),
-	
+
 	  /**
 	   * Reconfigure the thread actor.
 	   *
 	   * @param object aOptions
 	   *        A dictionary object of the new options to use in the thread actor.
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  reconfigure: DebuggerClient.requester({
 	    type: "reconfigure",
 	    options: args(0)
 	  }, {
 	    telemetry: "RECONFIGURETHREAD"
 	  }),
-	
+
 	  /**
 	   * Resume a paused thread.
 	   */
 	  resume: function(aOnResponse) {
 	    return this._doResume(null, aOnResponse);
 	  },
-	
+
 	  /**
 	   * Resume then pause without stepping.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  resumeThenPause: function(aOnResponse) {
 	    return this._doResume({ type: "break" }, aOnResponse);
 	  },
-	
+
 	  /**
 	   * Step over a function call.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  stepOver: function(aOnResponse) {
 	    return this._doResume({ type: "next" }, aOnResponse);
 	  },
-	
+
 	  /**
 	   * Step into a function call.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  stepIn: function(aOnResponse) {
 	    return this._doResume({ type: "step" }, aOnResponse);
 	  },
-	
+
 	  /**
 	   * Step out of a function call.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  stepOut: function(aOnResponse) {
 	    return this._doResume({ type: "finish" }, aOnResponse);
 	  },
-	
+
 	  /**
 	   * Immediately interrupt a running thread.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  interrupt: function(aOnResponse) {
 	    return this._doInterrupt(null, aOnResponse);
 	  },
-	
+
 	  /**
 	   * Pause execution right before the next JavaScript bytecode is executed.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  breakOnNext: function(aOnResponse) {
 	    return this._doInterrupt("onNext", aOnResponse);
 	  },
-	
+
 	  /**
 	   * Interrupt a running thread.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  _doInterrupt: DebuggerClient.requester({
 	    type: "interrupt",
 	    when: args(0)
 	  }, {
 	    telemetry: "INTERRUPT"
 	  }),
-	
+
 	  /**
 	   * Enable or disable pausing when an exception is thrown.
 	   *
 	   * @param boolean aFlag
 	   *        Enables pausing if true, disables otherwise.
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  pauseOnExceptions: function(aPauseOnExceptions,
 	                               aIgnoreCaughtExceptions,
 	                               aOnResponse = noop) {
 	    this._pauseOnExceptions = aPauseOnExceptions;
 	    this._ignoreCaughtExceptions = aIgnoreCaughtExceptions;
-	
+
 	    // Otherwise send the flag using a standard resume request.
 	    if (!this.paused) {
 	      return this.interrupt(aResponse => {
 	        if (aResponse.error) {
 	          // Can't continue if pausing failed.
 	          aOnResponse(aResponse);
 	          return aResponse;
 	        }
 	        return this.resume(aOnResponse);
 	      });
 	    }
-	
+
 	    aOnResponse();
 	    return promise.resolve();
 	  },
-	
+
 	  /**
 	   * Enable pausing when the specified DOM events are triggered. Disabling
 	   * pausing on an event can be realized by calling this method with the updated
 	   * array of events that doesn't contain it.
 	   *
 	   * @param array|string events
 	   *        An array of strings, representing the DOM event types to pause on,
 	   *        or "*" to pause on all DOM events. Pass an empty array to
@@ -12213,17 +12213,17 @@ return /******/ (function(modules) { // 
 	      // Can't continue if pausing failed.
 	      if (response.error) {
 	        onResponse(response);
 	        return response;
 	      }
 	      return this.resume(onResponse);
 	    });
 	  },
-	
+
 	  /**
 	   * Send a clientEvaluate packet to the debuggee. Response
 	   * will be a resume packet.
 	   *
 	   * @param string aFrame
 	   *        The actor ID of the frame where the evaluation should take place.
 	   * @param string aExpression
 	   *        The expression that will be evaluated in the scope of the frame
@@ -12247,97 +12247,97 @@ return /******/ (function(modules) { // 
 	      if (aResponse.error) {
 	        // There was an error resuming, back to paused state.
 	        this._state = "paused";
 	      }
 	      return aResponse;
 	    },
 	    telemetry: "CLIENTEVALUATE"
 	  }),
-	
+
 	  /**
 	   * Detach from the thread actor.
 	   *
 	   * @param function aOnResponse
 	   *        Called with the response packet.
 	   */
 	  detach: DebuggerClient.requester({
 	    type: "detach"
 	  }, {
 	    after: function(aResponse) {
 	      this.client.unregisterClient(this);
 	      this._parent.thread = null;
 	      return aResponse;
 	    },
 	    telemetry: "THREADDETACH"
 	  }),
-	
+
 	  /**
 	   * Release multiple thread-lifetime object actors. If any pause-lifetime
 	   * actors are included in the request, a |notReleasable| error will return,
 	   * but all the thread-lifetime ones will have been released.
 	   *
 	   * @param array actors
 	   *        An array with actor IDs to release.
 	   */
 	  releaseMany: DebuggerClient.requester({
 	    type: "releaseMany",
 	    actors: args(0),
 	  }, {
 	    telemetry: "RELEASEMANY"
 	  }),
-	
+
 	  /**
 	   * Promote multiple pause-lifetime object actors to thread-lifetime ones.
 	   *
 	   * @param array actors
 	   *        An array with actor IDs to promote.
 	   */
 	  threadGrips: DebuggerClient.requester({
 	    type: "threadGrips",
 	    actors: args(0)
 	  }, {
 	    telemetry: "THREADGRIPS"
 	  }),
-	
+
 	  /**
 	   * Return the event listeners defined on the page.
 	   *
 	   * @param aOnResponse Function
 	   *        Called with the thread's response.
 	   */
 	  eventListeners: DebuggerClient.requester({
 	    type: "eventListeners"
 	  }, {
 	    telemetry: "EVENTLISTENERS"
 	  }),
-	
+
 	  /**
 	   * Request the loaded sources for the current thread.
 	   *
 	   * @param aOnResponse Function
 	   *        Called with the thread's response.
 	   */
 	  getSources: DebuggerClient.requester({
 	    type: "sources"
 	  }, {
 	    telemetry: "SOURCES"
 	  }),
-	
+
 	  /**
 	   * Clear the thread's source script cache. A scriptscleared event
 	   * will be sent.
 	   */
 	  _clearScripts: function() {
 	    if (Object.keys(this._scriptCache).length > 0) {
 	      this._scriptCache = {};
 	      this.emit("scriptscleared");
 	    }
 	  },
-	
+
 	  /**
 	   * Request frames from the callstack for the current thread.
 	   *
 	   * @param aStart integer
 	   *        The number of the youngest stack frame to return (the youngest
 	   *        frame is 0).
 	   * @param aCount integer
 	   *        The maximum number of frames to return, or null to return all
@@ -12347,240 +12347,240 @@ return /******/ (function(modules) { // 
 	   */
 	  getFrames: DebuggerClient.requester({
 	    type: "frames",
 	    start: args(0),
 	    count: args(1)
 	  }, {
 	    telemetry: "FRAMES"
 	  }),
-	
+
 	  /**
 	   * An array of cached frames. Clients can observe the framesadded and
 	   * framescleared event to keep up to date on changes to this cache,
 	   * and can fill it using the fillFrames method.
 	   */
 	  get cachedFrames() { return this._frameCache; },
-	
+
 	  /**
 	   * true if there are more stack frames available on the server.
 	   */
 	  get moreFrames() {
 	    return this.paused && (!this._frameCache || this._frameCache.length == 0
 	          || !this._frameCache[this._frameCache.length - 1].oldest);
 	  },
-	
+
 	  /**
 	   * Ensure that at least aTotal stack frames have been loaded in the
 	   * ThreadClient's stack frame cache. A framesadded event will be
 	   * sent when the stack frame cache is updated.
 	   *
 	   * @param aTotal number
 	   *        The minimum number of stack frames to be included.
 	   * @param aCallback function
 	   *        Optional callback function called when frames have been loaded
 	   * @returns true if a framesadded notification should be expected.
 	   */
 	  fillFrames: function(aTotal, aCallback = noop) {
 	    this._assertPaused("fillFrames");
 	    if (this._frameCache.length >= aTotal) {
 	      return false;
 	    }
-	
+
 	    let numFrames = this._frameCache.length;
-	
+
 	    this.getFrames(numFrames, aTotal - numFrames, (aResponse) => {
 	      if (aResponse.error) {
 	        aCallback(aResponse);
 	        return;
 	      }
-	
+
 	      let threadGrips = DevToolsUtils.values(this._threadGrips);
-	
+
 	      for (let i in aResponse.frames) {
 	        let frame = aResponse.frames[i];
 	        if (!frame.where.source) {
 	          // Older servers use urls instead, so we need to resolve
 	          // them to source actors
 	          for (let grip of threadGrips) {
 	            if (grip instanceof SourceClient && grip.url === frame.url) {
 	              frame.where.source = grip._form;
 	            }
 	          }
 	        }
-	
+
 	        this._frameCache[frame.depth] = frame;
 	      }
-	
+
 	      // If we got as many frames as we asked for, there might be more
 	      // frames available.
 	      this.emit("framesadded");
-	
+
 	      aCallback(aResponse);
 	    });
-	
+
 	    return true;
 	  },
-	
+
 	  /**
 	   * Clear the thread's stack frame cache. A framescleared event
 	   * will be sent.
 	   */
 	  _clearFrames: function() {
 	    if (this._frameCache.length > 0) {
 	      this._frameCache = [];
 	      this.emit("framescleared");
 	    }
 	  },
-	
+
 	  /**
 	   * Return a ObjectClient object for the given object grip.
 	   *
 	   * @param aGrip object
 	   *        A pause-lifetime object grip returned by the protocol.
 	   */
 	  pauseGrip: function(aGrip) {
 	    if (aGrip.actor in this._pauseGrips) {
 	      return this._pauseGrips[aGrip.actor];
 	    }
-	
+
 	    let client = new ObjectClient(this.client, aGrip);
 	    this._pauseGrips[aGrip.actor] = client;
 	    return client;
 	  },
-	
+
 	  /**
 	   * Get or create a long string client, checking the grip client cache if it
 	   * already exists.
 	   *
 	   * @param aGrip Object
 	   *        The long string grip returned by the protocol.
 	   * @param aGripCacheName String
 	   *        The property name of the grip client cache to check for existing
 	   *        clients in.
 	   */
 	  _longString: function(aGrip, aGripCacheName) {
 	    if (aGrip.actor in this[aGripCacheName]) {
 	      return this[aGripCacheName][aGrip.actor];
 	    }
-	
+
 	    let client = new LongStringClient(this.client, aGrip);
 	    this[aGripCacheName][aGrip.actor] = client;
 	    return client;
 	  },
-	
+
 	  /**
 	   * Return an instance of LongStringClient for the given long string grip that
 	   * is scoped to the current pause.
 	   *
 	   * @param aGrip Object
 	   *        The long string grip returned by the protocol.
 	   */
 	  pauseLongString: function(aGrip) {
 	    return this._longString(aGrip, "_pauseGrips");
 	  },
-	
+
 	  /**
 	   * Return an instance of LongStringClient for the given long string grip that
 	   * is scoped to the thread lifetime.
 	   *
 	   * @param aGrip Object
 	   *        The long string grip returned by the protocol.
 	   */
 	  threadLongString: function(aGrip) {
 	    return this._longString(aGrip, "_threadGrips");
 	  },
-	
+
 	  /**
 	   * Clear and invalidate all the grip clients from the given cache.
 	   *
 	   * @param aGripCacheName
 	   *        The property name of the grip cache we want to clear.
 	   */
 	  _clearObjectClients: function(aGripCacheName) {
 	    for (let id in this[aGripCacheName]) {
 	      this[aGripCacheName][id].valid = false;
 	    }
 	    this[aGripCacheName] = {};
 	  },
-	
+
 	  /**
 	   * Invalidate pause-lifetime grip clients and clear the list of current grip
 	   * clients.
 	   */
 	  _clearPauseGrips: function() {
 	    this._clearObjectClients("_pauseGrips");
 	  },
-	
+
 	  /**
 	   * Invalidate thread-lifetime grip clients and clear the list of current grip
 	   * clients.
 	   */
 	  _clearThreadGrips: function() {
 	    this._clearObjectClients("_threadGrips");
 	  },
-	
+
 	  /**
 	   * Handle thread state change by doing necessary cleanup and notifying all
 	   * registered listeners.
 	   */
 	  _onThreadState: function(aPacket) {
 	    this._state = ThreadStateTypes[aPacket.type];
 	    // The debugger UI may not be initialized yet so we want to keep
 	    // the packet around so it knows what to pause state to display
 	    // when it's initialized
 	    this._lastPausePacket = aPacket.type === "resumed" ? null : aPacket;
 	    this._clearFrames();
 	    this._clearPauseGrips();
 	    aPacket.type === ThreadStateTypes.detached && this._clearThreadGrips();
 	    this.client._eventsEnabled && this.emit(aPacket.type, aPacket);
 	  },
-	
+
 	  getLastPausePacket: function() {
 	    return this._lastPausePacket;
 	  },
-	
+
 	  /**
 	   * Return an EnvironmentClient instance for the given environment actor form.
 	   */
 	  environment: function(aForm) {
 	    return new EnvironmentClient(this.client, aForm);
 	  },
-	
+
 	  /**
 	   * Return an instance of SourceClient for the given source actor form.
 	   */
 	  source: function(aForm) {
 	    if (aForm.actor in this._threadGrips) {
 	      return this._threadGrips[aForm.actor];
 	    }
-	
+
 	    return this._threadGrips[aForm.actor] = new SourceClient(this, aForm);
 	  },
-	
+
 	  /**
 	   * Request the prototype and own properties of mutlipleObjects.
 	   *
 	   * @param aOnResponse function
 	   *        Called with the request's response.
 	   * @param actors [string]
 	   *        List of actor ID of the queried objects.
 	   */
 	  getPrototypesAndProperties: DebuggerClient.requester({
 	    type: "prototypesAndProperties",
 	    actors: args(0)
 	  }, {
 	    telemetry: "PROTOTYPESANDPROPERTIES"
 	  }),
-	
+
 	  events: ["newSource"]
 	};
-	
+
 	eventSource(ThreadClient.prototype);
-	
+
 	/**
 	 * Creates a tracing profiler client for the remote debugging protocol
 	 * server. This client is a front to the trace actor created on the
 	 * server side, hiding the protocol details in a traditional
 	 * JavaScript API.
 	 *
 	 * @param aClient DebuggerClient
 	 *        The debugger client parent.
@@ -12591,36 +12591,36 @@ return /******/ (function(modules) { // 
 	  this._client = aClient;
 	  this._actor = aActor;
 	  this._activeTraces = new Set();
 	  this._waitingPackets = new Map();
 	  this._expectedPacket = 0;
 	  this.request = this._client.request;
 	  this.events = [];
 	}
-	
+
 	TraceClient.prototype = {
 	  get actor() { return this._actor; },
 	  get tracing() { return this._activeTraces.size > 0; },
-	
+
 	  get _transport() { return this._client._transport; },
-	
+
 	  /**
 	   * Detach from the trace actor.
 	   */
 	  detach: DebuggerClient.requester({
 	    type: "detach"
 	  }, {
 	    after: function(aResponse) {
 	      this._client.unregisterClient(this);
 	      return aResponse;
 	    },
 	    telemetry: "TRACERDETACH"
 	  }),
-	
+
 	  /**
 	   * Start a new trace.
 	   *
 	   * @param aTrace [string]
 	   *        An array of trace types to be recorded by the new trace.
 	   *
 	   * @param aName string
 	   *        The name of the new trace.
@@ -12632,28 +12632,28 @@ return /******/ (function(modules) { // 
 	    type: "startTrace",
 	    name: args(1),
 	    trace: args(0)
 	  }, {
 	    after: function(aResponse) {
 	      if (aResponse.error) {
 	        return aResponse;
 	      }
-	
+
 	      if (!this.tracing) {
 	        this._waitingPackets.clear();
 	        this._expectedPacket = 0;
 	      }
 	      this._activeTraces.add(aResponse.name);
-	
+
 	      return aResponse;
 	    },
 	    telemetry: "STARTTRACE"
 	  }),
-	
+
 	  /**
 	   * End a trace. If a name is provided, stop the named
 	   * trace. Otherwise, stop the most recently started trace.
 	   *
 	   * @param aName string
 	   *        The name of the trace to stop.
 	   *
 	   * @param aOnResponse function
@@ -12662,68 +12662,68 @@ return /******/ (function(modules) { // 
 	  stopTrace: DebuggerClient.requester({
 	    type: "stopTrace",
 	    name: args(0)
 	  }, {
 	    after: function(aResponse) {
 	      if (aResponse.error) {
 	        return aResponse;
 	      }
-	
+
 	      this._activeTraces.delete(aResponse.name);
-	
+
 	      return aResponse;
 	    },
 	    telemetry: "STOPTRACE"
 	  })
 	};
-	
+
 	/**
 	 * Grip clients are used to retrieve information about the relevant object.
 	 *
 	 * @param aClient DebuggerClient
 	 *        The debugger client parent.
 	 * @param aGrip object
 	 *        A pause-lifetime object grip returned by the protocol.
 	 */
 	function ObjectClient(aClient, aGrip)
 	{
 	  this._grip = aGrip;
 	  this._client = aClient;
 	  this.request = this._client.request;
 	}
 	exports.ObjectClient = ObjectClient;
-	
+
 	ObjectClient.prototype = {
 	  get actor() { return this._grip.actor; },
 	  get _transport() { return this._client._transport; },
-	
+
 	  valid: true,
-	
+
 	  get isFrozen() {
 	    return this._grip.frozen;
 	  },
 	  get isSealed() {
 	    return this._grip.sealed;
 	  },
 	  get isExtensible() {
 	    return this._grip.extensible;
 	  },
-	
+
 	  getDefinitionSite: DebuggerClient.requester({
 	    type: "definitionSite"
 	  }, {
 	    before: function(aPacket) {
 	      if (this._grip.class != "Function") {
 	        throw new Error("getDefinitionSite is only valid for function grips.");
 	      }
 	      return aPacket;
 	    }
 	  }),
-	
+
 	  /**
 	   * Request the names of a function's formal parameters.
 	   *
 	   * @param aOnResponse function
 	   *        Called with an object of the form:
 	   *        { parameterNames:[<parameterName>, ...] }
 	   *        where each <parameterName> is the name of a parameter.
 	   */
@@ -12733,40 +12733,40 @@ return /******/ (function(modules) { // 
 	    before: function(aPacket) {
 	      if (this._grip.class !== "Function") {
 	        throw new Error("getParameterNames is only valid for function grips.");
 	      }
 	      return aPacket;
 	    },
 	    telemetry: "PARAMETERNAMES"
 	  }),
-	
+
 	  /**
 	   * Request the names of the properties defined on the object and not its
 	   * prototype.
 	   *
 	   * @param aOnResponse function Called with the request's response.
 	   */
 	  getOwnPropertyNames: DebuggerClient.requester({
 	    type: "ownPropertyNames"
 	  }, {
 	    telemetry: "OWNPROPERTYNAMES"
 	  }),
-	
+
 	  /**
 	   * Request the prototype and own properties of the object.
 	   *
 	   * @param aOnResponse function Called with the request's response.
 	   */
 	  getPrototypeAndProperties: DebuggerClient.requester({
 	    type: "prototypeAndProperties"
 	  }, {
 	    telemetry: "PROTOTYPEANDPROPERTIES"
 	  }),
-	
+
 	  /**
 	   * Request a PropertyIteratorClient instance to ease listing
 	   * properties for this object.
 	   *
 	   * @param options Object
 	   *        A dictionary object with various boolean attributes:
 	   *        - ignoreSafeGetters Boolean
 	   *          If true, do not iterate over safe getters.
@@ -12789,17 +12789,17 @@ return /******/ (function(modules) { // 
 	    after: function(aResponse) {
 	      if (aResponse.iterator) {
 	        return { iterator: new PropertyIteratorClient(this._client, aResponse.iterator) };
 	      }
 	      return aResponse;
 	    },
 	    telemetry: "ENUMPROPERTIES"
 	  }),
-	
+
 	  /**
 	   * Request a PropertyIteratorClient instance to enumerate entries in a
 	   * Map/Set-like object.
 	   *
 	   * @param aOnResponse function Called with the request's response.
 	   */
 	  enumEntries: DebuggerClient.requester({
 	    type: "enumEntries"
@@ -12814,129 +12814,129 @@ return /******/ (function(modules) { // 
 	      if (response.iterator) {
 	        return {
 	          iterator: new PropertyIteratorClient(this._client, response.iterator)
 	        };
 	      }
 	      return response;
 	    }
 	  }),
-	
+
 	  /**
 	   * Request the property descriptor of the object's specified property.
 	   *
 	   * @param aName string The name of the requested property.
 	   * @param aOnResponse function Called with the request's response.
 	   */
 	  getProperty: DebuggerClient.requester({
 	    type: "property",
 	    name: args(0)
 	  }, {
 	    telemetry: "PROPERTY"
 	  }),
-	
+
 	  /**
 	   * Request the prototype of the object.
 	   *
 	   * @param aOnResponse function Called with the request's response.
 	   */
 	  getPrototype: DebuggerClient.requester({
 	    type: "prototype"
 	  }, {
 	    telemetry: "PROTOTYPE"
 	  }),
-	
+
 	  /**
 	   * Request the display string of the object.
 	   *
 	   * @param aOnResponse function Called with the request's response.
 	   */
 	  getDisplayString: DebuggerClient.requester({
 	    type: "displayString"
 	  }, {
 	    telemetry: "DISPLAYSTRING"
 	  }),
-	
+
 	  /**
 	   * Request the scope of the object.
 	   *
 	   * @param aOnResponse function Called with the request's response.
 	   */
 	  getScope: DebuggerClient.requester({
 	    type: "scope"
 	  }, {
 	    before: function(aPacket) {
 	      if (this._grip.class !== "Function") {
 	        throw new Error("scope is only valid for function grips.");
 	      }
 	      return aPacket;
 	    },
 	    telemetry: "SCOPE"
 	  }),
-	
+
 	  /**
 	   * Request the promises directly depending on the current promise.
 	   */
 	  getDependentPromises: DebuggerClient.requester({
 	    type: "dependentPromises"
 	  }, {
 	    before: function(aPacket) {
 	      if (this._grip.class !== "Promise") {
 	        throw new Error("getDependentPromises is only valid for promise " +
 	          "grips.");
 	      }
 	      return aPacket;
 	    }
 	  }),
-	
+
 	  /**
 	   * Request the stack to the promise's allocation point.
 	   */
 	  getPromiseAllocationStack: DebuggerClient.requester({
 	    type: "allocationStack"
 	  }, {
 	    before: function(aPacket) {
 	      if (this._grip.class !== "Promise") {
 	        throw new Error("getAllocationStack is only valid for promise grips.");
 	      }
 	      return aPacket;
 	    }
 	  }),
-	
+
 	  /**
 	   * Request the stack to the promise's fulfillment point.
 	   */
 	  getPromiseFulfillmentStack: DebuggerClient.requester({
 	    type: "fulfillmentStack"
 	  }, {
 	    before: function(packet) {
 	      if (this._grip.class !== "Promise") {
 	        throw new Error("getPromiseFulfillmentStack is only valid for " +
 	          "promise grips.");
 	      }
 	      return packet;
 	    }
 	  }),
-	
+
 	  /**
 	   * Request the stack to the promise's rejection point.
 	   */
 	  getPromiseRejectionStack: DebuggerClient.requester({
 	    type: "rejectionStack"
 	  }, {
 	    before: function(packet) {
 	      if (this._grip.class !== "Promise") {
 	        throw new Error("getPromiseRejectionStack is only valid for " +
 	          "promise grips.");
 	      }
 	      return packet;
 	    }
 	  })
 	};
-	
+
 	/**
 	 * A PropertyIteratorClient provides a way to access to property names and
 	 * values of an object efficiently, slice by slice.
 	 * Note that the properties can be sorted in the backend,
 	 * this is controled while creating the PropertyIteratorClient
 	 * from ObjectClient.enumProperties.
 	 *
 	 * @param aClient DebuggerClient
@@ -12945,90 +12945,90 @@ return /******/ (function(modules) { // 
 	 *        A PropertyIteratorActor grip returned by the protocol via
 	 *        TabActor.enumProperties request.
 	 */
 	function PropertyIteratorClient(aClient, aGrip) {
 	  this._grip = aGrip;
 	  this._client = aClient;
 	  this.request = this._client.request;
 	}
-	
+
 	PropertyIteratorClient.prototype = {
 	  get actor() { return this._grip.actor; },
-	
+
 	  /**
 	   * Get the total number of properties available in the iterator.
 	   */
 	  get count() { return this._grip.count; },
-	
+
 	  /**
 	   * Get one or more property names that correspond to the positions in the
 	   * indexes parameter.
 	   *
 	   * @param indexes Array
 	   *        An array of property indexes.
 	   * @param aCallback Function
 	   *        The function called when we receive the property names.
 	   */
 	  names: DebuggerClient.requester({
 	    type: "names",
 	    indexes: args(0)
 	  }, {}),
-	
+
 	  /**
 	   * Get a set of following property value(s).
 	   *
 	   * @param start Number
 	   *        The index of the first property to fetch.
 	   * @param count Number
 	   *        The number of properties to fetch.
 	   * @param aCallback Function
 	   *        The function called when we receive the property values.
 	   */
 	  slice: DebuggerClient.requester({
 	    type: "slice",
 	    start: args(0),
 	    count: args(1)
 	  }, {}),
-	
+
 	  /**
 	   * Get all the property values.
 	   *
 	   * @param aCallback Function
 	   *        The function called when we receive the property values.
 	   */
 	  all: DebuggerClient.requester({
 	    type: "all"
 	  }, {}),
 	};
-	
+
 	/**
 	 * A LongStringClient provides a way to access "very long" strings from the
 	 * debugger server.
 	 *
 	 * @param aClient DebuggerClient
 	 *        The debugger client parent.
 	 * @param aGrip Object
 	 *        A pause-lifetime long string grip returned by the protocol.
 	 */
 	function LongStringClient(aClient, aGrip) {
 	  this._grip = aGrip;
 	  this._client = aClient;
 	  this.request = this._client.request;
 	}
 	exports.LongStringClient = LongStringClient;
-	
+
 	LongStringClient.prototype = {
 	  get actor() { return this._grip.actor; },
 	  get length() { return this._grip.length; },
 	  get initial() { return this._grip.initial; },
 	  get _transport() { return this._client._transport; },
-	
+
 	  valid: true,
-	
+
 	  /**
 	   * Get the substring of this LongString from aStart to aEnd.
 	   *
 	   * @param aStart Number
 	   *        The starting index.
 	   * @param aEnd Number
 	   *        The ending index.
 	   * @param aCallback Function
@@ -13037,33 +13037,33 @@ return /******/ (function(modules) { // 
 	  substring: DebuggerClient.requester({
 	    type: "substring",
 	    start: args(0),
 	    end: args(1)
 	  }, {
 	    telemetry: "SUBSTRING"
 	  }),
 	};
-	
+
 	/**
 	 * A SourceClient provides a way to access the source text of a script.
 	 *
 	 * @param aClient ThreadClient
 	 *        The thread client parent.
 	 * @param aForm Object
 	 *        The form sent across the remote debugging protocol.
 	 */
 	function SourceClient(aClient, aForm) {
 	  this._form = aForm;
 	  this._isBlackBoxed = aForm.isBlackBoxed;
 	  this._isPrettyPrinted = aForm.isPrettyPrinted;
 	  this._activeThread = aClient;
 	  this._client = aClient.client;
 	}
-	
+
 	SourceClient.prototype = {
 	  get _transport() {
 	    return this._client._transport;
 	  },
 	  get isBlackBoxed() {
 	    return this._isBlackBoxed;
 	  },
 	  get isPrettyPrinted() {
@@ -13073,17 +13073,17 @@ return /******/ (function(modules) { // 
 	    return this._form.actor;
 	  },
 	  get request() {
 	    return this._client.request;
 	  },
 	  get url() {
 	    return this._form.url;
 	  },
-	
+
 	  /**
 	   * Black box this SourceClient's source.
 	   *
 	   * @param aCallback Function
 	   *        The callback function called when we receive the response from the server.
 	   */
 	  blackBox: DebuggerClient.requester({
 	    type: "blackbox"
@@ -13094,17 +13094,17 @@ return /******/ (function(modules) { // 
 	        this._isBlackBoxed = true;
 	        if (this._activeThread) {
 	          this._activeThread.emit("blackboxchange", this);
 	        }
 	      }
 	      return aResponse;
 	    }
 	  }),
-	
+
 	  /**
 	   * Un-black box this SourceClient's source.
 	   *
 	   * @param aCallback Function
 	   *        The callback function called when we receive the response from the server.
 	   */
 	  unblackBox: DebuggerClient.requester({
 	    type: "unblackbox"
@@ -13115,48 +13115,48 @@ return /******/ (function(modules) { // 
 	        this._isBlackBoxed = false;
 	        if (this._activeThread) {
 	          this._activeThread.emit("blackboxchange", this);
 	        }
 	      }
 	      return aResponse;
 	    }
 	  }),
-	
+
 	  /**
 	   * Get Executable Lines from a source
 	   *
 	   * @param aCallback Function
 	   *        The callback function called when we receive the response from the server.
 	   */
 	  getExecutableLines: function(cb = noop) {
 	    let packet = {
 	      to: this._form.actor,
 	      type: "getExecutableLines"
 	    };
-	
+
 	    return this._client.request(packet).then(res => {
 	      cb(res.lines);
 	      return res.lines;
 	    });
 	  },
-	
+
 	  /**
 	   * Get a long string grip for this SourceClient's source.
 	   */
 	  source: function(aCallback = noop) {
 	    let packet = {
 	      to: this._form.actor,
 	      type: "source"
 	    };
 	    return this._client.request(packet).then(aResponse => {
 	      return this._onSourceResponse(aResponse, aCallback);
 	    });
 	  },
-	
+
 	  /**
 	   * Pretty print this source's text.
 	   */
 	  prettyPrint: function(aIndent, aCallback = noop) {
 	    const packet = {
 	      to: this._form.actor,
 	      type: "prettyPrint",
 	      indent: aIndent
@@ -13165,17 +13165,17 @@ return /******/ (function(modules) { // 
 	      if (!aResponse.error) {
 	        this._isPrettyPrinted = true;
 	        this._activeThread._clearFrames();
 	        this._activeThread.emit("prettyprintchange", this);
 	      }
 	      return this._onSourceResponse(aResponse, aCallback);
 	    });
 	  },
-	
+
 	  /**
 	   * Stop pretty printing this source's text.
 	   */
 	  disablePrettyPrint: function(aCallback = noop) {
 	    const packet = {
 	      to: this._form.actor,
 	      type: "disablePrettyPrint"
 	    };
@@ -13183,45 +13183,45 @@ return /******/ (function(modules) { // 
 	      if (!aResponse.error) {
 	        this._isPrettyPrinted = false;
 	        this._activeThread._clearFrames();
 	        this._activeThread.emit("prettyprintchange", this);
 	      }
 	      return this._onSourceResponse(aResponse, aCallback);
 	    });
 	  },
-	
+
 	  _onSourceResponse: function(aResponse, aCallback) {
 	    if (aResponse.error) {
 	      aCallback(aResponse);
 	      return aResponse;
 	    }
-	
+
 	    if (typeof aResponse.source === "string") {
 	      aCallback(aResponse);
 	      return aResponse;
 	    }
-	
+
 	    let { contentType, source } = aResponse;
 	    let longString = this._activeThread.threadLongString(source);
 	    return longString.substring(0, longString.length).then(function(aResponse) {
 	      if (aResponse.error) {
 	        aCallback(aResponse);
 	        return aReponse;
 	      }
-	
+
 	      let response = {
 	        source: aResponse.substring,
 	        contentType: contentType
 	      };
 	      aCallback(response);
 	      return response;
 	    });
 	  },
-	
+
 	  /**
 	   * Request to set a breakpoint in the specified location.
 	   *
 	   * @param object aLocation
 	   *        The location and condition of the breakpoint in
 	   *        the form of { line[, column, condition] }.
 	   * @param function aOnResponse
 	   *        Called with the thread's response.
@@ -13229,32 +13229,32 @@ return /******/ (function(modules) { // 
 	  setBreakpoint: function({ line, column, condition, noSliding }, aOnResponse = noop) {
 	    // A helper function that sets the breakpoint.
 	    let doSetBreakpoint = aCallback => {
 	      let root = this._client.mainRoot;
 	      let location = {
 	        line: line,
 	        column: column
 	      };
-	
+
 	      let packet = {
 	        to: this.actor,
 	        type: "setBreakpoint",
 	        location: location,
 	        condition: condition,
 	        noSliding: noSliding
 	      };
-	
+
 	      // Backwards compatibility: send the breakpoint request to the
 	      // thread if the server doesn't support Debugger.Source actors.
 	      if (!root.traits.debuggerSourceActors) {
 	        packet.to = this._activeThread.actor;
 	        packet.location.url = this.url;
 	      }
-	
+
 	      return this._client.request(packet).then(aResponse => {
 	        // Ignoring errors, since the user may be setting a breakpoint in a
 	        // dead script that will reappear on a page reload.
 	        let bpClient;
 	        if (aResponse.actor) {
 	          bpClient = new BreakpointClient(
 	            this._client,
 	            this,
@@ -13265,39 +13265,39 @@ return /******/ (function(modules) { // 
 	        }
 	        aOnResponse(aResponse, bpClient);
 	        if (aCallback) {
 	          aCallback();
 	        }
 	        return [aResponse, bpClient];
 	      });
 	    };
-	
+
 	    // If the debuggee is paused, just set the breakpoint.
 	    if (this._activeThread.paused) {
 	      return doSetBreakpoint();
 	    }
 	    // Otherwise, force a pause in order to set the breakpoint.
 	    return this._activeThread.interrupt().then(aResponse => {
 	      if (aResponse.error) {
 	        // Can't set the breakpoint if pausing failed.
 	        aOnResponse(aResponse);
 	        return aResponse;
 	      }
-	
+
 	      const { type, why } = aResponse;
 	      const cleanUp = type == "paused" && why.type == "interrupted"
 	            ? () => this._activeThread.resume()
 	            : noop;
-	
+
 	      return doSetBreakpoint(cleanUp);
 	    });
 	  }
 	};
-	
+
 	/**
 	 * Breakpoint clients are used to remove breakpoints that are no longer used.
 	 *
 	 * @param aClient DebuggerClient
 	 *        The debugger client parent.
 	 * @param aSourceClient SourceClient
 	 *        The source where this breakpoint exists
 	 * @param aActor string
@@ -13311,91 +13311,91 @@ return /******/ (function(modules) { // 
 	function BreakpointClient(aClient, aSourceClient, aActor, aLocation, aCondition) {
 	  this._client = aClient;
 	  this._actor = aActor;
 	  this.location = aLocation;
 	  this.location.actor = aSourceClient.actor;
 	  this.location.url = aSourceClient.url;
 	  this.source = aSourceClient;
 	  this.request = this._client.request;
-	
+
 	  // The condition property should only exist if it's a truthy value
 	  if (aCondition) {
 	    this.condition = aCondition;
 	  }
 	}
-	
+
 	BreakpointClient.prototype = {
-	
+
 	  _actor: null,
 	  get actor() { return this._actor; },
 	  get _transport() { return this._client._transport; },
-	
+
 	  /**
 	   * Remove the breakpoint from the server.
 	   */
 	  remove: DebuggerClient.requester({
 	    type: "delete"
 	  }, {
 	    telemetry: "DELETE"
 	  }),
-	
+
 	  /**
 	   * Determines if this breakpoint has a condition
 	   */
 	  hasCondition: function() {
 	    let root = this._client.mainRoot;
 	    // XXX bug 990137: We will remove support for client-side handling of
 	    // conditional breakpoints
 	    if (root.traits.conditionalBreakpoints) {
 	      return "condition" in this;
 	    } else {
 	      return "conditionalExpression" in this;
 	    }
 	  },
-	
+
 	  /**
 	   * Get the condition of this breakpoint. Currently we have to
 	   * support locally emulated conditional breakpoints until the
 	   * debugger servers are updated (see bug 990137). We used a
 	   * different property when moving it server-side to ensure that we
 	   * are testing the right code.
 	   */
 	  getCondition: function() {
 	    let root = this._client.mainRoot;
 	    if (root.traits.conditionalBreakpoints) {
 	      return this.condition;
 	    } else {
 	      return this.conditionalExpression;
 	    }
 	  },
-	
+
 	  /**
 	   * Set the condition of this breakpoint
 	   */
 	  setCondition: function(gThreadClient, aCondition, noSliding) {
 	    let root = this._client.mainRoot;
 	    let deferred = promise.defer();
-	
+
 	    if (root.traits.conditionalBreakpoints) {
 	      let info = {
 	        line: this.location.line,
 	        column: this.location.column,
 	        condition: aCondition,
 	        noSliding
 	      };
-	
+
 	      // Remove the current breakpoint and add a new one with the
 	      // condition.
 	      this.remove(aResponse => {
 	        if (aResponse && aResponse.error) {
 	          deferred.reject(aResponse);
 	          return;
 	        }
-	
+
 	        this.source.setBreakpoint(info, (aResponse, aNewBreakpoint) => {
 	          if (aResponse && aResponse.error) {
 	            deferred.reject(aResponse);
 	          } else {
 	            deferred.resolve(aNewBreakpoint);
 	          }
 	        });
 	      });
@@ -13404,126 +13404,126 @@ return /******/ (function(modules) { // 
 	      if (aCondition === "") {
 	        delete this.conditionalExpression;
 	      }
 	      else {
 	        this.conditionalExpression = aCondition;
 	      }
 	      deferred.resolve(this);
 	    }
-	
+
 	    return deferred.promise;
 	  }
 	};
-	
+
 	eventSource(BreakpointClient.prototype);
-	
+
 	/**
 	 * Environment clients are used to manipulate the lexical environment actors.
 	 *
 	 * @param aClient DebuggerClient
 	 *        The debugger client parent.
 	 * @param aForm Object
 	 *        The form sent across the remote debugging protocol.
 	 */
 	function EnvironmentClient(aClient, aForm) {
 	  this._client = aClient;
 	  this._form = aForm;
 	  this.request = this._client.request;
 	}
 	exports.EnvironmentClient = EnvironmentClient;
-	
+
 	EnvironmentClient.prototype = {
-	
+
 	  get actor() {
 	    return this._form.actor;
 	  },
 	  get _transport() { return this._client._transport; },
-	
+
 	  /**
 	   * Fetches the bindings introduced by this lexical environment.
 	   */
 	  getBindings: DebuggerClient.requester({
 	    type: "bindings"
 	  }, {
 	    telemetry: "BINDINGS"
 	  }),
-	
+
 	  /**
 	   * Changes the value of the identifier whose name is name (a string) to that
 	   * represented by value (a grip).
 	   */
 	  assign: DebuggerClient.requester({
 	    type: "assign",
 	    name: args(0),
 	    value: args(1)
 	  }, {
 	    telemetry: "ASSIGN"
 	  })
 	};
-	
+
 	eventSource(EnvironmentClient.prototype);
 
 
 /***/ },
 /* 54 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* WEBPACK VAR INJECTION */(function(module) {/* 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": "unstable"
 	};
-	
+
 	const UNCAUGHT_ERROR = 'An error event was emitted for which there was no listener.';
 	const BAD_LISTENER = 'The event listener must be a function.';
-	
+
 	const { ns } = __webpack_require__(55);
-	
+
 	const event = ns();
-	
+
 	const EVENT_TYPE_PATTERN = /^on([A-Z]\w+$)/;
 	exports.EVENT_TYPE_PATTERN = EVENT_TYPE_PATTERN;
-	
+</