Bug 1668117 - [devtools] Remove devtools-modules and devtools-contextmenu packages r=nchevobbe
authorJulian Descottes <jdescottes@mozilla.com>
Fri, 02 Oct 2020 15:40:19 +0000
changeset 551364 6fcccce2d45e1aaa2a8a015f724ffa401be2676e
parent 551363 b1da49c81d0ca950d5fbdd5452e7779b614cc8e8
child 551365 ebec4e2881c9a996ef1426e04ae97ec1c8df7274
push id127820
push userjdescottes@mozilla.com
push dateFri, 02 Oct 2020 22:08:32 +0000
treeherderautoland@ba4685a82eea [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnchevobbe
bugs1668117
milestone83.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
Bug 1668117 - [devtools] Remove devtools-modules and devtools-contextmenu packages r=nchevobbe Depends on D92028 Differential Revision: https://phabricator.services.mozilla.com/D92029
devtools/client/debugger/.eslintignore
devtools/client/debugger/packages/devtools-contextmenu/README.md
devtools/client/debugger/packages/devtools-contextmenu/menu.css
devtools/client/debugger/packages/devtools-contextmenu/menu.js
devtools/client/debugger/packages/devtools-contextmenu/package.json
devtools/client/debugger/packages/devtools-contextmenu/yarn.lock
devtools/client/debugger/packages/devtools-modules/LICENSE
devtools/client/debugger/packages/devtools-modules/README.md
devtools/client/debugger/packages/devtools-modules/index.js
devtools/client/debugger/packages/devtools-modules/package.json
devtools/client/debugger/packages/devtools-modules/src/key-shortcuts.js
devtools/client/debugger/packages/devtools-modules/src/menu/index.js
devtools/client/debugger/packages/devtools-modules/src/menu/menu-item.js
devtools/client/debugger/packages/devtools-modules/src/plural-form.js
devtools/client/debugger/packages/devtools-modules/src/prefs.js
devtools/client/debugger/packages/devtools-modules/src/saveAs.js
devtools/client/debugger/packages/devtools-modules/src/tests/helpers/local-storage-mock.js
devtools/client/debugger/packages/devtools-modules/src/tests/prefs-helper.js
devtools/client/debugger/packages/devtools-modules/src/tests/services-prefs.js
devtools/client/debugger/packages/devtools-modules/src/tests/services-telemetry.js
devtools/client/debugger/packages/devtools-modules/src/tests/telemetry.js
devtools/client/debugger/packages/devtools-modules/src/tests/unicode-url.js
devtools/client/debugger/packages/devtools-modules/src/unicode-url.js
devtools/client/debugger/packages/devtools-modules/src/utils/defer.js
devtools/client/debugger/packages/devtools-modules/src/utils/event-emitter.js
devtools/client/debugger/packages/devtools-modules/src/utils/promise.js
devtools/client/debugger/packages/devtools-modules/src/utils/task.js
devtools/client/debugger/packages/devtools-modules/src/utils/telemetry.js
--- a/devtools/client/debugger/.eslintignore
+++ b/devtools/client/debugger/.eslintignore
@@ -2,13 +2,11 @@ assets/*
 src/test/examples/**
 src/test/integration/**
 src/test/unit-sources/**
 src/**/fixtures/**
 src/test/mochitest/**
 bin/
 packages/**/fixtures/**
 packages/devtools-config/**
-packages/devtools-contextmenu/**
 packages/devtools-environment/**
-packages/devtools-modules/**
 node_modules
 out
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-contextmenu/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-### DevTools ContextMenu
-
-
-The devtools contextmenu is an HTML shim, which lets us create
-fake contextmenus in HTML namespaces and real context menus in the
-firefox toolbox.
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-contextmenu/menu.css
+++ /dev/null
@@ -1,89 +0,0 @@
-/* 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/. */
-
-menu {
-  display: inline;
-  padding: 0;
-}
-
-menu > menuitem::after {
-  content: "►";
-  float: right;
-  padding-left: 5px;
-}
-
-menu > menupopup {
-  display: none;
-}
-
-menu > menuitem:hover + menupopup,
-menu > menupopup:hover {
-  display: block;
-}
-
-menupopup {
-  position: fixed;
-  z-index: 10000;
-  background: white;
-  border: 1px solid #cccccc;
-  padding: 5px 0;
-  background: #f2f2f2;
-  border-radius: 5px;
-  color: #585858;
-  box-shadow: 0 0 4px 0 rgba(190, 190, 190, 0.8);
-  min-width: 130px;
-}
-
-menuitem {
-  display: block;
-  padding: 0 20px;
-  line-height: 20px;
-  font-weight: 500;
-  font-size: 13px;
-  user-select: none;
-}
-
-menuitem:hover {
-  background: #3780fb;
-  color: white;
-  cursor: pointer;
-}
-
-menuitem[disabled=true] {
-  color: #cccccc;
-}
-
-menuitem[disabled=true]:hover {
-  background-color: transparent;
-  cursor: default;
-}
-
-menuitem[type=checkbox]::before {
-  content: "";
-  width: 10px;
-  display: inline-block;
-}
-
-menuitem[type=checkbox][checked=true]::before {
-  content: "✓";
-  left: -8px;
-  position: relative;
-}
-
-menuseparator {
-  border-bottom: 1px solid #cacdd3;
-  width: 100%;
-  height: 5px;
-  display: block;
-  margin-bottom: 5px;
-}
-
-#contextmenu-mask.show {
-  position: fixed;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  z-index: 999;
-}
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-contextmenu/menu.js
+++ /dev/null
@@ -1,148 +0,0 @@
-/* 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 Menu = require("devtools-modules/src/menu");
-const MenuItem = require("devtools-modules/src/menu/menu-item");
-
-function inToolbox() {
-  try {
-    return window.parent.document.documentURI.startsWith("about:devtools-toolbox");
-  } catch (e) {
-    // If `window` is not available, it's very likely that we are in the toolbox.
-    return true;
-  }
-}
-
-if (!inToolbox()) {
-  require("./menu.css");
-}
-
-function createPopup(doc) {
-  let popup = doc.createElement("menupopup");
-  popup.className = "landing-popup";
-  if (popup.openPopupAtScreen) {
-    return popup;
-  }
-
-  function preventDefault(e) {
-    e.preventDefault();
-    e.returnValue = false;
-  }
-
-  let mask = document.querySelector("#contextmenu-mask");
-  if (!mask) {
-    mask = doc.createElement("div");
-    mask.id = "contextmenu-mask";
-    document.body.appendChild(mask);
-  }
-
-  mask.onclick = () => popup.hidePopup();
-
-  popup.openPopupAtScreen = function (clientX, clientY) {
-    this.style.setProperty("left", `${clientX}px`);
-    this.style.setProperty("top", `${clientY}px`);
-    mask = document.querySelector("#contextmenu-mask");
-    window.onwheel = preventDefault;
-    mask.classList.add("show");
-    this.dispatchEvent(new Event("popupshown"));
-    this.popupshown;
-  };
-
-  popup.hidePopup = function () {
-    this.remove();
-    mask = document.querySelector("#contextmenu-mask");
-    mask.classList.remove("show");
-    window.onwheel = null;
-  };
-
-  return popup;
-}
-
-if (!inToolbox()) {
-  Menu.prototype.createPopup = createPopup;
-}
-
-function onShown(menu, popup) {
-  popup.childNodes.forEach((menuItemNode, i) => {
-    let item = menu.items[i];
-
-    if (!item.disabled && item.visible) {
-      menuItemNode.onclick = () => {
-        item.click();
-        popup.hidePopup();
-      };
-
-      showSubMenu(item.submenu, menuItemNode, popup);
-    }
-  });
-}
-
-function showMenu(evt, items) {
-  if (items.length === 0) {
-    return;
-  }
-
-  let menu = new Menu();
-  items
-    .filter((item) => item.visible === undefined || item.visible === true)
-    .forEach((item) => {
-      let menuItem = new MenuItem(item);
-      menuItem.submenu = createSubMenu(item.submenu);
-      menu.append(menuItem);
-    });
-
-  if (inToolbox()) {
-    menu.popup(evt.screenX, evt.screenY, window.parent.document);
-    return;
-  }
-
-  menu.on("open", (_, popup) => onShown(menu, popup));
-  menu.popup(evt.clientX, evt.clientY, document);
-}
-
-function createSubMenu(subItems) {
-  if (subItems) {
-    let subMenu = new Menu();
-    subItems.forEach((subItem) => {
-      subMenu.append(new MenuItem(subItem));
-    });
-    return subMenu;
-  }
-  return null;
-}
-
-function showSubMenu(subMenu, menuItemNode, popup) {
-  if (subMenu) {
-    let subMenuNode = menuItemNode.querySelector("menupopup");
-    let { top } = menuItemNode.getBoundingClientRect();
-    let { left, width } = popup.getBoundingClientRect();
-    subMenuNode.style.setProperty("left", `${left + width - 1}px`);
-    subMenuNode.style.setProperty("top", `${top}px`);
-
-    let subMenuItemNodes = menuItemNode
-      .querySelector("menupopup:not(.landing-popup)").childNodes;
-    subMenuItemNodes.forEach((subMenuItemNode, j) => {
-      let subMenuItem = subMenu.items.filter((item) =>
-        item.visible === undefined || item.visible === true)[j];
-      if (!subMenuItem.disabled && subMenuItem.visible) {
-        subMenuItemNode.onclick = () => {
-          subMenuItem.click();
-          popup.hidePopup();
-        };
-      }
-    });
-  }
-}
-
-function buildMenu(items) {
-  return items.map(itm => {
-    const hide = typeof itm.hidden === "function" ? itm.hidden() : itm.hidden;
-    return hide ? null : itm.item;
-  }).filter(itm => itm !== null);
-}
-
-module.exports = {
-  showMenu,
-  buildMenu
-};
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-contextmenu/package.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "name": "devtools-contextmenu",
-  "version": "1.0.14",
-  "description": "DevTools Contextmenu",
-  "main": "menu.js",
-  "scripts": {
-    "test": "# No tests available"
-  },
-  "author": "Jason Laster",
-  "license": "MPL-2.0",
-  "dependencies": {
-    "devtools-modules": "~1.1.9"
-  }
-}
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-contextmenu/yarn.lock
+++ /dev/null
@@ -1,18 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-devtools-modules@~1.1.5:
-  version "1.1.5"
-  resolved "https://registry.yarnpkg.com/devtools-modules/-/devtools-modules-1.1.5.tgz#55e71233692b4095f0277a00e6bfe3ff374d37f1"
-  dependencies:
-    devtools-services "0.0.1"
-    punycode "^2.1.0"
-
-devtools-services@0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/devtools-services/-/devtools-services-0.0.1.tgz#9042600c11d1f4d45cc6ca299588a86fac1fbdd5"
-
-punycode@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d"
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/LICENSE
+++ /dev/null
@@ -1,362 +0,0 @@
-Mozilla Public License, version 2.0
-
-1. Definitions
-
-1.1. "Contributor"
-
-     means each individual or legal entity that creates, contributes to the
-     creation of, or owns Covered Software.
-
-1.2. "Contributor Version"
-
-     means the combination of the Contributions of others (if any) used by a
-     Contributor and that particular Contributor's Contribution.
-
-1.3. "Contribution"
-
-     means Covered Software of a particular Contributor.
-
-1.4. "Covered Software"
-
-     means Source Code Form to which the initial Contributor has attached the
-     notice in Exhibit A, the Executable Form of such Source Code Form, and
-     Modifications of such Source Code Form, in each case including portions
-     thereof.
-
-1.5. "Incompatible With Secondary Licenses"
-     means
-
-     a. that the initial Contributor has attached the notice described in
-        Exhibit B to the Covered Software; or
-
-     b. that the Covered Software was made available under the terms of
-        version 1.1 or earlier of the License, but not also under the terms of
-        a Secondary License.
-
-1.6. "Executable Form"
-
-     means any form of the work other than Source Code Form.
-
-1.7. "Larger Work"
-
-     means a work that combines Covered Software with other material, in a
-     separate file or files, that is not Covered Software.
-
-1.8. "License"
-
-     means this document.
-
-1.9. "Licensable"
-
-     means having the right to grant, to the maximum extent possible, whether
-     at the time of the initial grant or subsequently, any and all of the
-     rights conveyed by this License.
-
-1.10. "Modifications"
-
-     means any of the following:
-
-     a. any file in Source Code Form that results from an addition to,
-        deletion from, or modification of the contents of Covered Software; or
-
-     b. any new file in Source Code Form that contains any Covered Software.
-
-1.11. "Patent Claims" of a Contributor
-
-      means any patent claim(s), including without limitation, method,
-      process, and apparatus claims, in any patent Licensable by such
-      Contributor that would be infringed, but for the grant of the License,
-      by the making, using, selling, offering for sale, having made, import,
-      or transfer of either its Contributions or its Contributor Version.
-
-1.12. "Secondary License"
-
-      means either the GNU General Public License, Version 2.0, the GNU Lesser
-      General Public License, Version 2.1, the GNU Affero General Public
-      License, Version 3.0, or any later versions of those licenses.
-
-1.13. "Source Code Form"
-
-      means the form of the work preferred for making modifications.
-
-1.14. "You" (or "Your")
-
-      means an individual or a legal entity exercising rights under this
-      License. For legal entities, "You" includes any entity that controls, is
-      controlled by, or is under common control with You. For purposes of this
-      definition, "control" means (a) the power, direct or indirect, to cause
-      the direction or management of such entity, whether by contract or
-      otherwise, or (b) ownership of more than fifty percent (50%) of the
-      outstanding shares or beneficial ownership of such entity.
-
-
-2. License Grants and Conditions
-
-2.1. Grants
-
-     Each Contributor hereby grants You a world-wide, royalty-free,
-     non-exclusive license:
-
-     a. under intellectual property rights (other than patent or trademark)
-        Licensable by such Contributor to use, reproduce, make available,
-        modify, display, perform, distribute, and otherwise exploit its
-        Contributions, either on an unmodified basis, with Modifications, or
-        as part of a Larger Work; and
-
-     b. under Patent Claims of such Contributor to make, use, sell, offer for
-        sale, have made, import, and otherwise transfer either its
-        Contributions or its Contributor Version.
-
-2.2. Effective Date
-
-     The licenses granted in Section 2.1 with respect to any Contribution
-     become effective for each Contribution on the date the Contributor first
-     distributes such Contribution.
-
-2.3. Limitations on Grant Scope
-
-     The licenses granted in this Section 2 are the only rights granted under
-     this License. No additional rights or licenses will be implied from the
-     distribution or licensing of Covered Software under this License.
-     Notwithstanding Section 2.1(b) above, no patent license is granted by a
-     Contributor:
-
-     a. for any code that a Contributor has removed from Covered Software; or
-
-     b. for infringements caused by: (i) Your and any other third party's
-        modifications of Covered Software, or (ii) the combination of its
-        Contributions with other software (except as part of its Contributor
-        Version); or
-
-     c. under Patent Claims infringed by Covered Software in the absence of
-        its Contributions.
-
-     This License does not grant any rights in the trademarks, service marks,
-     or logos of any Contributor (except as may be necessary to comply with
-     the notice requirements in Section 3.4).
-
-2.4. Subsequent Licenses
-
-     No Contributor makes additional grants as a result of Your choice to
-     distribute the Covered Software under a subsequent version of this
-     License (see Section 10.2) or under the terms of a Secondary License (if
-     permitted under the terms of Section 3.3).
-
-2.5. Representation
-
-     Each Contributor represents that the Contributor believes its
-     Contributions are its original creation(s) or it has sufficient rights to
-     grant the rights to its Contributions conveyed by this License.
-
-2.6. Fair Use
-
-     This License is not intended to limit any rights You have under
-     applicable copyright doctrines of fair use, fair dealing, or other
-     equivalents.
-
-2.7. Conditions
-
-     Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
-     Section 2.1.
-
-
-3. Responsibilities
-
-3.1. Distribution of Source Form
-
-     All distribution of Covered Software in Source Code Form, including any
-     Modifications that You create or to which You contribute, must be under
-     the terms of this License. You must inform recipients that the Source
-     Code Form of the Covered Software is governed by the terms of this
-     License, and how they can obtain a copy of this License. You may not
-     attempt to alter or restrict the recipients' rights in the Source Code
-     Form.
-
-3.2. Distribution of Executable Form
-
-     If You distribute Covered Software in Executable Form then:
-
-     a. such Covered Software must also be made available in Source Code Form,
-        as described in Section 3.1, and You must inform recipients of the
-        Executable Form how they can obtain a copy of such Source Code Form by
-        reasonable means in a timely manner, at a charge no more than the cost
-        of distribution to the recipient; and
-
-     b. You may distribute such Executable Form under the terms of this
-        License, or sublicense it under different terms, provided that the
-        license for the Executable Form does not attempt to limit or alter the
-        recipients' rights in the Source Code Form under this License.
-
-3.3. Distribution of a Larger Work
-
-     You may create and distribute a Larger Work under terms of Your choice,
-     provided that You also comply with the requirements of this License for
-     the Covered Software. If the Larger Work is a combination of Covered
-     Software with a work governed by one or more Secondary Licenses, and the
-     Covered Software is not Incompatible With Secondary Licenses, this
-     License permits You to additionally distribute such Covered Software
-     under the terms of such Secondary License(s), so that the recipient of
-     the Larger Work may, at their option, further distribute the Covered
-     Software under the terms of either this License or such Secondary
-     License(s).
-
-3.4. Notices
-
-     You may not remove or alter the substance of any license notices
-     (including copyright notices, patent notices, disclaimers of warranty, or
-     limitations of liability) contained within the Source Code Form of the
-     Covered Software, except that You may alter any license notices to the
-     extent required to remedy known factual inaccuracies.
-
-3.5. Application of Additional Terms
-
-     You may choose to offer, and to charge a fee for, warranty, support,
-     indemnity or liability obligations to one or more recipients of Covered
-     Software. However, You may do so only on Your own behalf, and not on
-     behalf of any Contributor. You must make it absolutely clear that any
-     such warranty, support, indemnity, or liability obligation is offered by
-     You alone, and You hereby agree to indemnify every Contributor for any
-     liability incurred by such Contributor as a result of warranty, support,
-     indemnity or liability terms You offer. You may include additional
-     disclaimers of warranty and limitations of liability specific to any
-     jurisdiction.
-
-4. Inability to Comply Due to Statute or Regulation
-
-   If it is impossible for You to comply with any of the terms of this License
-   with respect to some or all of the Covered Software due to statute,
-   judicial order, or regulation then You must: (a) comply with the terms of
-   this License to the maximum extent possible; and (b) describe the
-   limitations and the code they affect. Such description must be placed in a
-   text file included with all distributions of the Covered Software under
-   this License. Except to the extent prohibited by statute or regulation,
-   such description must be sufficiently detailed for a recipient of ordinary
-   skill to be able to understand it.
-
-5. Termination
-
-5.1. The rights granted under this License will terminate automatically if You
-     fail to comply with any of its terms. However, if You become compliant,
-     then the rights granted under this License from a particular Contributor
-     are reinstated (a) provisionally, unless and until such Contributor
-     explicitly and finally terminates Your grants, and (b) on an ongoing
-     basis, if such Contributor fails to notify You of the non-compliance by
-     some reasonable means prior to 60 days after You have come back into
-     compliance. Moreover, Your grants from a particular Contributor are
-     reinstated on an ongoing basis if such Contributor notifies You of the
-     non-compliance by some reasonable means, this is the first time You have
-     received notice of non-compliance with this License from such
-     Contributor, and You become compliant prior to 30 days after Your receipt
-     of the notice.
-
-5.2. If You initiate litigation against any entity by asserting a patent
-     infringement claim (excluding declaratory judgment actions,
-     counter-claims, and cross-claims) alleging that a Contributor Version
-     directly or indirectly infringes any patent, then the rights granted to
-     You by any and all Contributors for the Covered Software under Section
-     2.1 of this License shall terminate.
-
-5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
-     license agreements (excluding distributors and resellers) which have been
-     validly granted by You or Your distributors under this License prior to
-     termination shall survive termination.
-
-6. Disclaimer of Warranty
-
-   Covered Software is provided under this License on an "as is" basis,
-   without warranty of any kind, either expressed, implied, or statutory,
-   including, without limitation, warranties that the Covered Software is free
-   of defects, merchantable, fit for a particular purpose or non-infringing.
-   The entire risk as to the quality and performance of the Covered Software
-   is with You. Should any Covered Software prove defective in any respect,
-   You (not any Contributor) assume the cost of any necessary servicing,
-   repair, or correction. This disclaimer of warranty constitutes an essential
-   part of this License. No use of  any Covered Software is authorized under
-   this License except under this disclaimer.
-
-7. Limitation of Liability
-
-   Under no circumstances and under no legal theory, whether tort (including
-   negligence), contract, or otherwise, shall any Contributor, or anyone who
-   distributes Covered Software as permitted above, be liable to You for any
-   direct, indirect, special, incidental, or consequential damages of any
-   character including, without limitation, damages for lost profits, loss of
-   goodwill, work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses, even if such party shall have been
-   informed of the possibility of such damages. This limitation of liability
-   shall not apply to liability for death or personal injury resulting from
-   such party's negligence to the extent applicable law prohibits such
-   limitation. Some jurisdictions do not allow the exclusion or limitation of
-   incidental or consequential damages, so this exclusion and limitation may
-   not apply to You.
-
-8. Litigation
-
-   Any litigation relating to this License may be brought only in the courts
-   of a jurisdiction where the defendant maintains its principal place of
-   business and such litigation shall be governed by laws of that
-   jurisdiction, without reference to its conflict-of-law provisions. Nothing
-   in this Section shall prevent a party's ability to bring cross-claims or
-   counter-claims.
-
-9. Miscellaneous
-
-   This License represents the complete agreement concerning the subject
-   matter hereof. If any provision of this License is held to be
-   unenforceable, such provision shall be reformed only to the extent
-   necessary to make it enforceable. Any law or regulation which provides that
-   the language of a contract shall be construed against the drafter shall not
-   be used to construe this License against a Contributor.
-
-
-10. Versions of the License
-
-10.1. New Versions
-
-      Mozilla Foundation is the license steward. Except as provided in Section
-      10.3, no one other than the license steward has the right to modify or
-      publish new versions of this License. Each version will be given a
-      distinguishing version number.
-
-10.2. Effect of New Versions
-
-      You may distribute the Covered Software under the terms of the version
-      of the License under which You originally received the Covered Software,
-      or under the terms of any subsequent version published by the license
-      steward.
-
-10.3. Modified Versions
-
-      If you create software not governed by this License, and you want to
-      create a new license for such software, you may create and use a
-      modified version of this License if you rename the license and remove
-      any references to the name of the license steward (except to note that
-      such modified license differs from this License).
-
-10.4. Distributing Source Code Form that is Incompatible With Secondary
-      Licenses If You choose to distribute Source Code Form that is
-      Incompatible With Secondary Licenses under the terms of this version of
-      the License, the notice described in Exhibit B of this License must be
-      attached.
-
-Exhibit A - Source Code Form License Notice
-
-      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/.
-
-If it is not possible or desirable to put the notice in a particular file,
-then You may include the notice in a location (such as a LICENSE file in a
-relevant directory) where a recipient would be likely to look for such a
-notice.
-
-You may add additional accurate notices of copyright ownership.
-
-Exhibit B - "Incompatible With Secondary Licenses" Notice
-
-      This Source Code Form is "Incompatible
-      With Secondary Licenses", as defined by
-      the Mozilla Public License, v. 2.0.
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-## Devtools Modules
-
-[![Npm version](https://img.shields.io/npm/v/devtools-modules.svg)](https://npmjs.org/package/devtools-modules)
-
-* *KeyShortcuts* - keyboard shortcuts library
-* *Menu* - Context Menu library
-* *Services* - A de-privilidged shim for prefs and appInfo
-* *PrefsHelper* - A Prefs convenience Wrapper
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/index.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/* 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 { PrefsHelper } = require("./src/prefs");
-const KeyShortcuts = require("./src/key-shortcuts");
-const EventEmitter = require("./src/utils/event-emitter");
-const Telemetry = require("./src/utils/telemetry");
-const { getUnicodeHostname, getUnicodeUrlPath, getUnicodeUrl } =
-  require("./src/unicode-url");
-const PluralForm = require("./src/plural-form");
-const saveAs = require("./src/saveAs")
-
-module.exports = {
-  KeyShortcuts,
-  PrefsHelper,
-  EventEmitter,
-  Telemetry,
-  getUnicodeHostname,
-  getUnicodeUrlPath,
-  getUnicodeUrl,
-  PluralForm,
-  saveAs
-};
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/package.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
-  "name": "devtools-modules",
-  "version": "1.1.9",
-  "description": "DevTools Modules from M-C",
-  "main": "index.js",
-  "scripts": {
-    "license-check": "devtools-license-check",
-    "test": "jest"
-  },
-  "author": "",
-  "license": "MPL-2.0",
-  "dependencies": {
-    "punycode": "^2.1.0",
-    "devtools-services": "0.0.1"
-  },
-  "devDependencies": {
-    "jest": "^23.0.0"
-  },
-  "files": [
-    "src"
-  ],
-  "jest": {
-    "rootDir": "src",
-    "testMatch": [
-      "**/tests/**/*.js"
-    ],
-    "testPathIgnorePatterns": [
-      "<rootDir>/tests/helpers/local-storage-mock.js"
-    ],
-    "transformIgnorePatterns": [],
-    "setupFiles": [
-      "<rootDir>/tests/helpers/local-storage-mock.js"
-    ],
-    "moduleNameMapper": {},
-    "testURL": "http://localhost/"
-  }
-}
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/key-shortcuts.js
+++ /dev/null
@@ -1,243 +0,0 @@
-/* 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 { appinfo } = require("devtools-services");
-const EventEmitter = require("./utils/event-emitter");
-const isOSX = appinfo.OS === "Darwin";
-
-// List of electron keys mapped to DOM API (DOM_VK_*) key code
-const ElectronKeysMapping = {
-  "F1": "DOM_VK_F1",
-  "F2": "DOM_VK_F2",
-  "F3": "DOM_VK_F3",
-  "F4": "DOM_VK_F4",
-  "F5": "DOM_VK_F5",
-  "F6": "DOM_VK_F6",
-  "F7": "DOM_VK_F7",
-  "F8": "DOM_VK_F8",
-  "F9": "DOM_VK_F9",
-  "F10": "DOM_VK_F10",
-  "F11": "DOM_VK_F11",
-  "F12": "DOM_VK_F12",
-  "F13": "DOM_VK_F13",
-  "F14": "DOM_VK_F14",
-  "F15": "DOM_VK_F15",
-  "F16": "DOM_VK_F16",
-  "F17": "DOM_VK_F17",
-  "F18": "DOM_VK_F18",
-  "F19": "DOM_VK_F19",
-  "F20": "DOM_VK_F20",
-  "F21": "DOM_VK_F21",
-  "F22": "DOM_VK_F22",
-  "F23": "DOM_VK_F23",
-  "F24": "DOM_VK_F24",
-  "Space": "DOM_VK_SPACE",
-  "Backspace": "DOM_VK_BACK_SPACE",
-  "Delete": "DOM_VK_DELETE",
-  "Insert": "DOM_VK_INSERT",
-  "Return": "DOM_VK_RETURN",
-  "Enter": "DOM_VK_RETURN",
-  "Up": "DOM_VK_UP",
-  "Down": "DOM_VK_DOWN",
-  "Left": "DOM_VK_LEFT",
-  "Right": "DOM_VK_RIGHT",
-  "Home": "DOM_VK_HOME",
-  "End": "DOM_VK_END",
-  "PageUp": "DOM_VK_PAGE_UP",
-  "PageDown": "DOM_VK_PAGE_DOWN",
-  "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
- * });
- *
- * @param DOMWindow window
- *        The window object of the document to listen events from.
- * @param DOMElement target
- *        Optional DOM Element on which we should listen events from.
- *        If omitted, we listen for all events fired on `window`.
- */
-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
-    keyCode: undefined,
-  };
-  for (let mod of modifiers) {
-    if (mod === "Alt") {
-      shortcut.alt = true;
-    } else if (["Command", "Cmd"].includes(mod)) {
-      shortcut.meta = true;
-    } else if (["CommandOrControl", "CmdOrCtrl"].includes(mod)) {
-      if (isOSX) {
-        shortcut.meta = true;
-      } else {
-        shortcut.ctrl = true;
-      }
-    } else if (["Control", "Ctrl"].includes(mod)) {
-      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");
-  }
-  if (shortcut.meta) {
-    list.push("Cmd");
-  }
-  if (shortcut.shift) {
-    list.push("Shift");
-  }
-  let key;
-  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) {
-      return false;
-    }
-    // Shift is a special modifier, it may implicitely be required if the
-    // expected key is a special character accessible via shift.
-    if (shortcut.shift != event.shiftKey && event.key &&
-        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);
-  },
-};
-module.exports = KeyShortcuts;
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/menu/index.js
+++ /dev/null
@@ -1,247 +0,0 @@
-/* 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/. */
-
-import Services from "devtools-services";
-
-const { appinfo } = Services;
-
-const isMacOS = appinfo.OS === "Darwin";
-
-const EventEmitter = require("../utils/event-emitter");
-
-/**
- * Formats key for use in tooltips
- * For macOS we use the following unicode
- *
- * cmd ⌘ = \u2318
- * shift ⇧ – \u21E7
- * option (alt) ⌥ \u2325
- *
- * For Win/Lin this replaces CommandOrControl or CmdOrCtrl with Ctrl
- *
- * @static
- */
-function formatKeyShortcut(shortcut) {
-    if (isMacOS) {
-        return shortcut
-            .replace(/Shift\+/g, "\u21E7")
-            .replace(/Command\+|Cmd\+/g, "\u2318")
-            .replace(/CommandOrControl\+|CmdOrCtrl\+/g, "\u2318")
-            .replace(/Alt\+/g, "\u2325");
-    }
-    return shortcut
-        .replace(/CommandOrControl\+|CmdOrCtrl\+/g, `${L10N.getStr("ctrl")}+`)
-        .replace(/Shift\+/g, "Shift+");
-}
-
-function inToolbox() {
-  try {
-    return window.parent.document.documentURI.startsWith("about:devtools-toolbox");
-  } catch (e) {
-    // If `window` is not available, it's very likely that we are in the toolbox.
-    return true;
-  }
-}
-
-// Copied from m-c DevToolsUtils.
-function getTopWindow(win) {
-  return win.windowRoot ? win.windowRoot.ownerGlobal : win.top;
-}
-
-/**
- * A partial implementation of the Menu API provided by electron:
- * https://github.com/electron/electron/blob/master/docs/api/menu.md.
- *
- * Extra features:
- *  - Emits an 'open' and 'close' event when the menu is opened/closed
-
- * @param String id (non standard)
- *        Needed so tests can confirm the XUL implementation is working
- */
-function Menu({ id = null } = {}) {
-  this.menuitems = [];
-  this.id = id;
-
-  Object.defineProperty(this, "items", {
-    get() {
-      return this.menuitems;
-    }
-  });
-
-  EventEmitter.decorate(this);
-}
-
-/**
- * Add an item to the end of the Menu
- *
- * @param {MenuItem} menuItem
- */
-Menu.prototype.append = function (menuItem) {
-  this.menuitems.push(menuItem);
-};
-
-/**
- * Add an item to a specified position in the menu
- *
- * @param {int} pos
- * @param {MenuItem} menuItem
- */
-Menu.prototype.insert = function (pos, menuItem) {
-  throw Error("Not implemented");
-};
-
-/**
- * Show the Menu at a specified location on the screen
- *
- * Missing features:
- *   - browserWindow - BrowserWindow (optional) - Default is null.
- *   - positioningItem Number - (optional) OS X
- *
- * @param {int} screenX
- * @param {int} screenY
- * @param {Document} doc
- *        The document that should own the context menu.
- */
-Menu.prototype.popup = function (screenX, screenY, doc) {
-  // The context-menu will be created in the topmost window to preserve keyboard
-  // navigation. See Bug 1543940. Keep a reference on the window owning the menu to hide
-  // the popup on unload.
-  const win = doc.defaultView;
-  doc = getTopWindow(doc.defaultView).document;
-
-  let popupset = doc.querySelector("popupset");
-  if (!popupset) {
-    popupset = doc.createXULElement("popupset");
-    doc.documentElement.appendChild(popupset);
-  }
-  // See bug 1285229, on Windows, opening the same popup multiple times in a
-  // row ends up duplicating the popup. The newly inserted popup doesn't
-  // dismiss the old one. So remove any previously displayed popup before
-  // opening a new one.
-  let popup = popupset.querySelector("menupopup[menu-api=\"true\"]");
-  if (popup) {
-    popup.hidePopup();
-  }
-
-  popup = this.createPopup(doc);
-  popup.setAttribute("menu-api", "true");
-
-  if (this.id) {
-    popup.id = this.id;
-  }
-  this._createMenuItems(popup);
-
-  // The context menu will be created in the topmost chrome window. Hide it manually when
-  // the owner document is unloaded.
-  const onWindowUnload = () => popup.hidePopup();
-  win.addEventListener("unload", onWindowUnload);
-
-  // Remove the menu from the DOM once it's hidden.
-  popup.addEventListener("popuphidden", (e) => {
-    if (e.target === popup) {
-      win.removeEventListener("unload", onWindowUnload);
-      popup.remove();
-      this.emit("close", popup);
-    }
-  });
-
-  popup.addEventListener("popupshown", (e) => {
-    if (e.target === popup) {
-      this.emit("open", popup);
-    }
-  });
-
-  popupset.appendChild(popup);
-  popup.openPopupAtScreen(screenX, screenY, true);
-};
-
-Menu.prototype.createPopup = function(doc) {
-  return doc.createElement("menupopup");
-}
-
-Menu.prototype._createMenuItems = function(parent) {
-  let doc = parent.ownerDocument;
-  this.menuitems.forEach(item => {
-    if (!item.visible) {
-      return;
-    }
-
-    if (item.submenu) {
-      let menupopup = doc.createElement("menupopup");
-      item.submenu._createMenuItems(menupopup);
-
-      let menuitem = doc.createElement("menuitem");
-      menuitem.setAttribute("label", item.label);
-      if (!inToolbox()) {
-        menuitem.textContent = item.label;
-      }
-
-      let menu = doc.createElement("menu");
-      menu.appendChild(menuitem);
-      menu.appendChild(menupopup);
-      if (item.disabled) {
-        menu.setAttribute("disabled", "true");
-      }
-      if (item.accesskey) {
-        menu.setAttribute("accesskey", item.accesskey);
-      }
-      if (item.id) {
-        menu.id = item.id;
-      }
-      if (item.accelerator) {
-        menuitem.setAttribute("acceltext", formatKeyShortcut(item.accelerator));
-      }
-      parent.appendChild(menu);
-    } else if (item.type === "separator") {
-      let menusep = doc.createElement("menuseparator");
-      parent.appendChild(menusep);
-    } else {
-      let menuitem = doc.createElement("menuitem");
-      menuitem.setAttribute("label", item.label);
-
-      if (!inToolbox()) {
-        menuitem.textContent = item.label;
-      }
-
-      menuitem.addEventListener("command", () => item.click());
-
-      if (item.type === "checkbox") {
-        menuitem.setAttribute("type", "checkbox");
-      }
-      if (item.type === "radio") {
-        menuitem.setAttribute("type", "radio");
-      }
-      if (item.disabled) {
-        menuitem.setAttribute("disabled", "true");
-      }
-      if (item.checked) {
-        menuitem.setAttribute("checked", "true");
-      }
-      if (item.accesskey) {
-        menuitem.setAttribute("accesskey", item.accesskey);
-      }
-      if (item.id) {
-        menuitem.id = item.id;
-      }
-      if (item.accelerator) {
-        menuitem.setAttribute("acceltext", formatKeyShortcut(item.accelerator));
-      }
-      parent.appendChild(menuitem);
-    }
-  });
-};
-
-Menu.setApplicationMenu = () => {
-  throw Error("Not implemented");
-};
-
-Menu.sendActionToFirstResponder = () => {
-  throw Error("Not implemented");
-};
-
-Menu.buildFromTemplate = () => {
-  throw Error("Not implemented");
-};
-
-module.exports = Menu;
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/menu/menu-item.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/* 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/. */
-
-/**
- * A partial implementation of the MenuItem API provided by electron:
- * https://github.com/electron/electron/blob/master/docs/api/menu-item.md.
- *
- * Missing features:
- *   - id String - Unique within a single menu. If defined then it can be used
- *                 as a reference to this item by the position attribute.
- *   - role String - Define the action of the menu item; when specified the
- *                   click property will be ignored
- *   - sublabel String
- *   - icon NativeImage
- *   - position String - This field allows fine-grained definition of the
- *                       specific location within a given menu.
- *
- * Implemented features:
- *  @param Object options
- *    Function click
- *      Will be called with click(menuItem, browserWindow) when the menu item
- *       is clicked
- *    String type
- *      Can be normal, separator, submenu, checkbox or radio
- *    String label
- *    Boolean enabled
- *      If false, the menu item will be greyed out and unclickable.
- *    Boolean checked
- *      Should only be specified for checkbox or radio type menu items.
- *    Menu submenu
- *      Should be specified for submenu type menu items. If submenu is specified,
- *      the type: 'submenu' can be omitted. If the value is not a Menu then it
- *      will be automatically converted to one using Menu.buildFromTemplate.
- *    Boolean visible
- *      If false, the menu item will be entirely hidden.
- *    String accelerator
- *      If specified, will be used as accelerator text for MenuItem
- */
-function MenuItem({
-    accesskey = null,
-    checked = false,
-    click = () => {},
-    disabled = false,
-    label = "",
-    id = null,
-    submenu = null,
-    type = "normal",
-    visible = true,
-    accelerator = "",
-} = { }) {
-  this.accesskey = accesskey;
-  this.checked = checked;
-  this.click = click;
-  this.disabled = disabled;
-  this.id = id;
-  this.label = label;
-  this.submenu = submenu;
-  this.type = type;
-  this.visible = visible;
-  this.accelerator = accelerator;
-}
-
-module.exports = MenuItem;
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/plural-form.js
+++ /dev/null
@@ -1,160 +0,0 @@
-/* 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/. */
-
-// These are the available plural functions that give the appropriate index
-// based on the plural rule number specified. The first element is the number
-// of plural forms and the second is the function to figure out the index.
-const gFunctions = [
-  // 0: Chinese
-  [1, (n) => 0],
-  // 1: English
-  [2, (n) => n!=1?1:0],
-  // 2: French
-  [2, (n) => n>1?1:0],
-  // 3: Latvian
-  [3, (n) => n%10==1&&n%100!=11?1:n%10==0?0:2],
-  // 4: Scottish Gaelic
-  [4, (n) => n==1||n==11?0:n==2||n==12?1:n>0&&n<20?2:3],
-  // 5: Romanian
-  [3, (n) => n==1?0:n==0||n%100>0&&n%100<20?1:2],
-  // 6: Lithuanian
-  [3, (n) => n%10==1&&n%100!=11?0:n%10>=2&&(n%100<10||n%100>=20)?2:1],
-  // 7: Russian
-  [3, (n) => n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2],
-  // 8: Slovak
-  [3, (n) => n==1?0:n>=2&&n<=4?1:2],
-  // 9: Polish
-  [3, (n) => n==1?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2],
-  // 10: Slovenian
-  [4, (n) => n%100==1?0:n%100==2?1:n%100==3||n%100==4?2:3],
-  // 11: Irish Gaeilge
-  [5, (n) => n==1?0:n==2?1:n>=3&&n<=6?2:n>=7&&n<=10?3:4],
-  // 12: Arabic
-  [6, (n) => n==0?5:n==1?0:n==2?1:n%100>=3&&n%100<=10?2:n%100>=11&&n%100<=99?3:4],
-  // 13: Maltese
-  [4, (n) => n==1?0:n==0||n%100>0&&n%100<=10?1:n%100>10&&n%100<20?2:3],
-  // 14: Unused
-  [3, (n) => n%10==1?0:n%10==2?1:2],
-  // 15: Icelandic, Macedonian
-  [2, (n) => n%10==1&&n%100!=11?0:1],
-  // 16: Breton
-  [5, (n) => n%10==1&&n%100!=11&&n%100!=71&&n%100!=91?0:n%10==2&&n%100!=12&&n%100!=72&&n%100!=92?1:(n%10==3||n%10==4||n%10==9)&&n%100!=13&&n%100!=14&&n%100!=19&&n%100!=73&&n%100!=74&&n%100!=79&&n%100!=93&&n%100!=94&&n%100!=99?2:n%1000000==0&&n!=0?3:4],
-  // 17: Shuar
-  [2, (n) => n!=0?1:0],
-  // 18: Welsh
-  [6, (n) => n==0?0:n==1?1:n==2?2:n==3?3:n==6?4:5],
-  // 19: Bosnian, Croatian, Serbian
-  [3, (n) => n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2],
-];
-
-const PluralForm = {
-  /**
-   * Get the correct plural form of a word based on the number
-   *
-   * @param aNum
-   *        The number to decide which plural form to use
-   * @param aWords
-   *        A semi-colon (;) separated string of words to pick the plural form
-   * @return The appropriate plural form of the word
-   */
-  get get()
-  {
-    // This method will lazily load to avoid perf when it is first needed and
-    // creates getPluralForm function. The function it creates is based on the
-    // value of pluralRule specified in the intl stringbundle.
-    // See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-
-    // Delete the getters to be overwritten
-    delete this.numForms;
-    delete this.get;
-
-    // Make the plural form get function and set it as the default get
-    [this.get, this.numForms] = this.makeGetter(this.ruleNum);
-    return this.get;
-  },
-
-  /**
-   * Create a pair of plural form functions for the given plural rule number.
-   *
-   * @param aRuleNum
-   *        The plural rule number to create functions
-   * @return A pair: [function that gets the right plural form,
-   *                  function that returns the number of plural forms]
-   */
-  makeGetter: function(aRuleNum)
-  {
-    // Default to "all plural" if the value is out of bounds or invalid
-    if (aRuleNum < 0 || aRuleNum >= gFunctions.length || isNaN(aRuleNum)) {
-      log(["Invalid rule number: ", aRuleNum, " -- defaulting to 0"]);
-      aRuleNum = 0;
-    }
-
-    // Get the desired pluralRule function
-    let [numForms, pluralFunc] = gFunctions[aRuleNum];
-
-    // Return functions that give 1) the number of forms and 2) gets the right
-    // plural form
-    return [function(aNum, aWords) {
-      // Figure out which index to use for the semi-colon separated words
-      let index = pluralFunc(aNum ? Number(aNum) : 0);
-      let words = aWords ? aWords.split(/;/) : [""];
-
-      // Explicitly check bounds to avoid strict warnings
-      let ret = index < words.length ? words[index] : undefined;
-
-      // Check for array out of bounds or empty strings
-      if ((ret == undefined) || (ret == "")) {
-        // Display a message in the error console
-        log(["Index #", index, " of '", aWords, "' for value ", aNum,
-            " is invalid -- plural rule #", aRuleNum, ";"]);
-
-        // Default to the first entry (which might be empty, but not undefined)
-        ret = words[0];
-      }
-
-      return ret;
-    }, () => numForms];
-  },
-
-  /**
-   * Get the number of forms for the current plural rule
-   *
-   * @return The number of forms
-   */
-  get numForms()
-  {
-    // We lazily load numForms, so trigger the init logic with get()
-    this.get();
-    return this.numForms;
-  },
-
-  /**
-   * Get the plural rule number from the intl stringbundle
-   *
-   * @return The plural rule number
-   */
-  get ruleNum()
-  {
-    try {
-      return parseInt(L10N.getStr("pluralRule"), 10);
-    } catch (e) {
-    // Fallback to English if the pluralRule property is not available.
-      return 1;
-    }
-  }
-};
-
-/**
- * Private helper function to log errors to the error console and command line
- *
- * @param aMsg
- *        Error message to log or an array of strings to concat
- */
-function log(aMsg)
-{
-  let msg = "plural-form.js: " + (aMsg.join ? aMsg.join("") : aMsg);
-  console.log(msg + "\n");
-}
-
-module.exports = PluralForm;
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/prefs.js
+++ /dev/null
@@ -1,187 +0,0 @@
-/* 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 = require("devtools-services");
-const EventEmitter = require("./utils/event-emitter");
-
-/**
- * Shortcuts for lazily accessing and setting various preferences.
- * Usage:
- *   let prefs = new Prefs("root.path.to.branch", {
- *     myIntPref: ["Int", "leaf.path.to.my-int-pref"],
- *     myCharPref: ["Char", "leaf.path.to.my-char-pref"],
- *     myJsonPref: ["Json", "leaf.path.to.my-json-pref"],
- *     myFloatPref: ["Float", "leaf.path.to.my-float-pref"]
- *     ...
- *   });
- *
- * Get/set:
- *   prefs.myCharPref = "foo";
- *   let aux = prefs.myCharPref;
- *
- * Observe:
- *   prefs.registerObserver();
- *   prefs.on("pref-changed", (prefName, prefValue) => {
- *     ...
- *   });
- *
- * @param string prefsRoot
- *        The root path to the required preferences branch.
- * @param object prefsBlueprint
- *        An object containing { accessorName: [prefType, prefName, prefDefault] } keys.
- */
-function PrefsHelper(prefsRoot = "", prefsBlueprint = {}) {
-  EventEmitter.decorate(this);
-
-  let cache = new Map();
-
-  for (let accessorName in prefsBlueprint) {
-    let [prefType, prefName, prefDefault] = prefsBlueprint[accessorName];
-    map(this, cache, accessorName, prefType, prefsRoot, prefName, prefDefault);
-  }
-
-  let observer = makeObserver(this, cache, prefsRoot, prefsBlueprint);
-  this.registerObserver = () => observer.register();
-  this.unregisterObserver = () => observer.unregister();
-}
-
-/**
- * Helper method for getting a pref value.
- *
- * @param Map cache
- * @param string prefType
- * @param string prefsRoot
- * @param string prefName
- * @return any
- */
-function get(cache, prefType, prefsRoot, prefName) {
-  let cachedPref = cache.get(prefName);
-  if (cachedPref !== undefined) {
-    return cachedPref;
-  }
-  let value = Services.prefs["get" + prefType + "Pref"](
-    [prefsRoot, prefName].join(".")
-  );
-  cache.set(prefName, value);
-  return value;
-}
-
-/**
- * Helper method for setting a pref value.
- *
- * @param Map cache
- * @param string prefType
- * @param string prefsRoot
- * @param string prefName
- * @param any value
- */
-function set(cache, prefType, prefsRoot, prefName, value) {
-  Services.prefs["set" + prefType + "Pref"](
-    [prefsRoot, prefName].join("."),
-    value
-  );
-  cache.set(prefName, value);
-}
-
-/**
- * Maps a property name to a pref, defining lazy getters and setters.
- * Supported types are "Bool", "Char", "Int", "Float" (sugar around "Char"
- * type and casting), and "Json" (which is basically just sugar for "Char"
- * using the standard JSON serializer).
- *
- * @param PrefsHelper self
- * @param Map cache
- * @param string accessorName
- * @param string prefType
- * @param string prefsRoot
- * @param string prefName
- * @param string prefDefault
- * @param array serializer [optional]
- */
-function map(self, cache, accessorName, prefType, prefsRoot, prefName, prefDefault,
-             serializer = { in: e => e, out: e => e }) {
-  if (prefName in self) {
-    throw new Error(`Can't use ${prefName} because it overrides a property` +
-                    "on the instance.");
-  }
-  if (prefType == "Json") {
-    map(self, cache, accessorName, "String", prefsRoot, prefName, prefDefault, {
-      in: JSON.parse,
-      out: JSON.stringify
-    });
-    return;
-  }
-  if (prefType == "Float") {
-    map(self, cache, accessorName, "Char", prefsRoot, prefName, prefDefault, {
-      in: Number.parseFloat,
-      out: (n) => n + ""
-    });
-    return;
-  }
-
-  Object.defineProperty(self, accessorName, {
-    get: () => {
-      try {
-        return serializer.in(get(cache, prefType, prefsRoot, prefName));
-      } catch (e) {
-        if (typeof prefDefault !== 'undefined') {
-          return prefDefault;
-        }
-        throw e;
-      }
-    },
-    set: (e) => set(cache, prefType, prefsRoot, prefName, serializer.out(e))
-  });
-}
-
-/**
- * Finds the accessor for the provided pref, based on the blueprint object
- * used in the constructor.
- *
- * @param PrefsHelper self
- * @param object prefsBlueprint
- * @return string
- */
-function accessorNameForPref(somePrefName, prefsBlueprint) {
-  for (let accessorName in prefsBlueprint) {
-    let [, prefName] = prefsBlueprint[accessorName];
-    if (somePrefName == prefName) {
-      return accessorName;
-    }
-  }
-  return "";
-}
-
-/**
- * Creates a pref observer for `self`.
- *
- * @param PrefsHelper self
- * @param Map cache
- * @param string prefsRoot
- * @param object prefsBlueprint
- * @return object
- */
-function makeObserver(self, cache, prefsRoot, prefsBlueprint) {
-  return {
-    register: function() {
-      this._branch = Services.prefs.getBranch(prefsRoot + ".");
-      this._branch.addObserver("", this);
-    },
-    unregister: function() {
-      this._branch.removeObserver("", this);
-    },
-    observe: function(subject, topic, prefName) {
-      // If this particular pref isn't handled by the blueprint object,
-      // even though it's in the specified branch, ignore it.
-      let accessorName = accessorNameForPref(prefName, prefsBlueprint);
-      if (!(accessorName in self)) {
-        return;
-      }
-      cache.delete(prefName);
-      self.emit("pref-changed", accessorName, self[accessorName]);
-    }
-  };
-}
-
-exports.PrefsHelper = PrefsHelper;
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/saveAs.js
+++ /dev/null
@@ -1,5 +0,0 @@
-/* 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/. */
-
-module.exports = () => {}
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/tests/helpers/local-storage-mock.js
+++ /dev/null
@@ -1,30 +0,0 @@
-var localStorageMock = (() => {
-  let store = {};
-  return {
-    getItem: (key) => {
-      if (!store.hasOwnProperty(key)) {
-        return "";
-      }
-      return store[key];
-    },
-    setItem: (key, value) => {
-      store[key] = value.toString();
-    },
-    clear: () => {
-      store = {};
-    },
-    removeItem: (key) => {
-      delete store[key];
-    },
-    key: (index) => {
-      return Object.keys(store)[index];
-    },
-    get length() {
-      return Object.keys(store).length;
-    }
-  };
-})();
-
-Object.defineProperty(window, "localStorage", {
-  value: localStorageMock
-});
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/tests/prefs-helper.js
+++ /dev/null
@@ -1,37 +0,0 @@
-const { PrefsHelper } = require("../prefs");
-const Services = require("devtools-services");
-const pref = Services.pref;
-
-describe("prefs helper", () => {
-  beforeEach(() => {});
-
-  afterEach(() => {
-    localStorage.clear();
-  });
-
-  it("supports fallback values", () => {
-    pref("devtools.valid", "{\"valid\": true}");
-    pref("devtools.invalid", "{not valid at all]");
-    pref("devtools.nodefault", "{not valid at all]");
-    pref("devtools.validnodefault", "{\"nodefault\": true}");
-
-    const prefs = new PrefsHelper("devtools", {
-      valid: ["Json", "valid", {valid: true}],
-      invalid: ["Json", "invalid", {}],
-      nodefault: ["Json", "nodefault"],
-      validnodefault: ["Json", "validnodefault"],
-    });
-
-    // Valid Json pref should return the actual value
-    expect(prefs.valid).toEqual({valid: true});
-
-    // Invalid Json pref with a fallback shoud return the fallback value
-    expect(prefs.invalid).toEqual({});
-
-    // Invalid Json pref with no fallback should throw
-    expect(() => prefs.nodefault).toThrow();
-
-    // Valid Json pref with no fallback should return the value
-    expect(prefs.validnodefault).toEqual({nodefault: true});
-  });
-});
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/tests/services-prefs.js
+++ /dev/null
@@ -1,200 +0,0 @@
-const Services = require("devtools-services");
-const pref = Services.pref;
-
-describe("services prefs shim", () => {
-  beforeEach(() => {
-    // Add some starter prefs.
-    localStorage.setItem("Services.prefs:devtools.branch1.somebool", JSON.stringify({
-      // bool
-      type: 128,
-      defaultValue: false,
-      hasUserValue: false,
-      userValue: false
-    }));
-
-    localStorage.setItem("Services.prefs:devtools.branch1.somestring", JSON.stringify({
-      // string
-      type: 32,
-      defaultValue: "dinosaurs",
-      hasUserValue: true,
-      userValue: "elephants"
-    }));
-
-    localStorage.setItem("Services.prefs:devtools.branch2.someint", JSON.stringify({
-      // int
-      type: 64,
-      defaultValue: -16,
-      hasUserValue: false,
-      userValue: null
-    }));
-  });
-
-  afterEach(() => {
-    localStorage.clear();
-  });
-
-  it("can get and set preferences", () => {
-    expect(Services.prefs.getBoolPref("devtools.branch1.somebool")).toBe(false);
-    Services.prefs.setBoolPref("devtools.branch1.somebool", true);
-    expect(Services.prefs.getBoolPref("devtools.branch1.somebool")).toBe(true);
-
-    Services.prefs.clearUserPref("devtools.branch1.somestring");
-    expect(Services.prefs.getCharPref("devtools.branch1.somestring")).toBe("dinosaurs");
-
-    expect(Services.prefs.prefHasUserValue("devtools.branch1.somebool")).toBe(true,
-      "bool pref has user value");
-    expect(Services.prefs.prefHasUserValue("devtools.branch1.somestring")).toBe(false,
-      "string pref does not have user value");
-
-    // String prefs actually differ from Char prefs in the real implementation of
-    // Services.prefs, but for this shim, both are using the same implementation.
-    Services.prefs.setStringPref("devtools.branch1.somerealstring", "abcdef");
-    expect(Services.prefs.getStringPref("devtools.branch1.somerealstring")).toBe("abcdef");
-  });
-
-  it("can call savePrefFile without crashing", () => {
-    Services.prefs.savePrefFile(null);
-  });
-
-  it("can use branches", () => {
-    let branch0 = Services.prefs.getBranch(null);
-    let branch1 = Services.prefs.getBranch("devtools.branch1.");
-
-    branch1.setCharPref("somestring", "octopus");
-    Services.prefs.setCharPref("devtools.branch1.somestring", "octopus");
-    expect(Services.prefs.getCharPref("devtools.branch1.somestring")).toEqual("octopus");
-    expect(branch0.getCharPref("devtools.branch1.somestring")).toEqual("octopus");
-    expect(branch1.getCharPref("somestring")).toEqual("octopus");
-  });
-
-  it("throws exceptions when expected", () => {
-    expect(() => {
-      Services.prefs.setIntPref("devtools.branch1.somebool", 27);
-    }).toThrow();
-
-    expect(() => {
-      Services.prefs.setBoolPref("devtools.branch1.somebool", 27);
-    }).toThrow();
-
-    expect(() => {
-      Services.prefs.getCharPref("devtools.branch2.someint");
-    }).toThrow();
-
-    expect(() => {
-      Services.prefs.setCharPref("devtools.branch2.someint", "whatever");
-    }).toThrow();
-
-    expect(() => {
-      Services.prefs.setIntPref("devtools.branch2.someint", "whatever");
-    }).toThrow();
-
-    expect(() => {
-      Services.prefs.getBoolPref("devtools.branch1.somestring");
-    }).toThrow();
-
-    expect(() => {
-      Services.prefs.setBoolPref("devtools.branch1.somestring", true);
-    }).toThrow();
-
-    expect(() => {
-      Services.prefs.setCharPref("devtools.branch1.somestring", true);
-    }).toThrow();
-  });
-
-  it("returns correct pref types", () => {
-    expect(Services.prefs.getPrefType("devtools.branch1.somebool"))
-        .toEqual(Services.prefs.PREF_BOOL);
-    expect(Services.prefs.getPrefType("devtools.branch2.someint"))
-        .toEqual(Services.prefs.PREF_INT);
-    expect(Services.prefs.getPrefType("devtools.branch1.somestring"))
-        .toEqual(Services.prefs.PREF_STRING);
-  });
-
-  it("supports observers", () => {
-    let notifications = {};
-    let clearNotificationList = () => {
-      notifications = {};
-    };
-
-    let observer = {
-      observe: function (subject, topic, data) {
-        notifications[data] = true;
-      }
-    };
-
-    let branch0 = Services.prefs.getBranch(null);
-    let branch1 = Services.prefs.getBranch("devtools.branch1.");
-
-    branch0.addObserver("devtools.branch1", null, null);
-    branch0.addObserver("devtools.branch1.", observer);
-    branch1.addObserver("", observer);
-
-    Services.prefs.setCharPref("devtools.branch1.somestring", "elf owl");
-    expect(notifications).toEqual({
-      "devtools.branch1.somestring": true,
-      "somestring": true
-    }, "notifications sent to two listeners");
-
-    clearNotificationList();
-    Services.prefs.setIntPref("devtools.branch2.someint", 1729);
-    expect(notifications).toEqual({}, "no notifications sent");
-
-    clearNotificationList();
-    branch0.removeObserver("devtools.branch1.", observer);
-    Services.prefs.setCharPref("devtools.branch1.somestring", "tapir");
-    expect(notifications).toEqual({
-      "somestring": true
-    }, "removeObserver worked");
-
-    clearNotificationList();
-    branch0.addObserver("devtools.branch1.somestring", observer);
-    Services.prefs.setCharPref("devtools.branch1.somestring", "northern shoveler");
-    expect(notifications).toEqual({
-      "devtools.branch1.somestring": true,
-      "somestring": true
-    }, "notifications sent to two listeners");
-    branch0.removeObserver("devtools.branch1.somestring", observer);
-
-    // Make sure we update if the pref change comes from somewhere else.
-    clearNotificationList();
-    pref("devtools.branch1.someotherstring", "lazuli bunting");
-    expect(notifications).toEqual({
-      "someotherstring": true
-    }, "pref worked");
-  });
-
-  it("does not crash when setting prefs (bug 1296427)", () => {
-    // Regression test for bug 1296427.
-    pref("devtools.hud.loglimit", 1000);
-    pref("devtools.hud.loglimit.network", 1000);
-  });
-
-  it("fixes observer bug (bug 1319150)", () => {
-    // Regression test for bug 1319150.
-    let seen = false;
-    let fnObserver = () => {
-      seen = true;
-    };
-
-    let branch0 = Services.prefs.getBranch(null);
-    branch0.addObserver("devtools.branch1.somestring", fnObserver);
-    Services.prefs.setCharPref("devtools.branch1.somestring", "common merganser");
-    expect(seen).toBe(true);
-    branch0.removeObserver("devtools.branch1.somestring", fnObserver);
-  });
-
-  it("supports default value argument", () => {
-    // Check support for default values
-    let intPrefWithDefault =
-        Services.prefs.getIntPref("devtools.branch1.missing", 1);
-    expect(intPrefWithDefault).toEqual(1);
-
-    let charPrefWithDefault =
-        Services.prefs.getCharPref("devtools.branch1.missing", "test");
-    expect(charPrefWithDefault).toEqual("test");
-
-    let boolPrefWithDefault =
-        Services.prefs.getBoolPref("devtools.branch1.missing", true);
-    expect(boolPrefWithDefault).toBe(true);
-  });
-});
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/tests/services-telemetry.js
+++ /dev/null
@@ -1,41 +0,0 @@
-const Services = require("devtools-services");
-
-// const pref = Services;
-
-describe("services telemetry shim", () => {
-  beforeEach(() => {
-    telemetry.scalars = {};
-    telemetry.histograms = {};
-  });
-
-  it("getHistogramById", () => {
-    const hist = Services.telemetry.getHistogramById("foo");
-    hist.add(3);
-    expect(telemetry.histograms.foo).toEqual([3]);
-
-    hist.add(3);
-    expect(telemetry.histograms.foo).toEqual([3, 3]);
-  });
-
-  it("getKeyedHistogramById", () => {
-    const hist = Services.telemetry.getKeyedHistogramById("foo");
-    hist.add("a", 3);
-    expect(telemetry.histograms.foo.a).toEqual([3]);
-
-    hist.add("a", 3);
-    expect(telemetry.histograms.foo.a).toEqual([3, 3]);
-  });
-
-  it("scalarSet", () => {
-    Services.telemetry.scalarSet("foo", 3);
-    expect(telemetry.scalars.foo).toEqual(3);
-  });
-
-  it("scalarAdd", () => {
-    Services.telemetry.scalarAdd("foo", 3);
-    expect(telemetry.scalars.foo).toEqual(3);
-
-    Services.telemetry.scalarAdd("foo", 3);
-    expect(telemetry.scalars.foo).toEqual(6);
-  });
-});
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/tests/telemetry.js
+++ /dev/null
@@ -1,120 +0,0 @@
-const Telemetry = require("../utils/telemetry");
-const telemetry = new Telemetry();
-
-describe("telemetry shim", () => {
-  it("msSystemNow", () => {
-    expect(() => {
-      telemetry.msSystemNow;
-    }).not.toThrow();
-  });
-
-  it("start", () => {
-    expect(() => {
-      telemetry.start("foo", this);
-    }).not.toThrow();
-  });
-
-  it("startKeyed", () => {
-    expect(() => {
-      telemetry.startKeyed("foo", "bar", this);
-    }).not.toThrow();
-  });
-
-  it("finish", () => {
-    expect(() => {
-      telemetry.finish("foo", this);
-    }).not.toThrow();
-  });
-
-  it("finishKeyed", () => {
-    expect(() => {
-      telemetry.finishKeyed("foo", "bar", this);
-    }).not.toThrow();
-  });
-
-  it("getHistogramById", () => {
-    expect(() => {
-      telemetry.getHistogramById("foo").add(3);
-    }).not.toThrow();
-  });
-
-  it("getKeyedHistogramById", () => {
-    expect(() => {
-      telemetry.getKeyedHistogramById("foo").add("foo", 3);
-    }).not.toThrow();
-  });
-
-  it("scalarSet", () => {
-    expect(() => {
-      telemetry.scalarSet("foo", 3);
-    }).not.toThrow();
-  });
-
-  it("scalarAdd", () => {
-    expect(() => {
-      telemetry.scalarAdd("foo", 3);
-    }).not.toThrow();
-  });
-
-  it("keyedScalarAdd", () => {
-    expect(() => {
-      telemetry.keyedScalarAdd("foo", "bar", 3);
-    }).not.toThrow();
-  });
-
-  it("setEventRecordingEnabled", () => {
-    expect(() => {
-      telemetry.setEventRecordingEnabled("foo", true);
-    }).not.toThrow();
-  });
-
-  it("preparePendingEvent", () => {
-    expect(() => {
-      telemetry.preparePendingEvent(
-        "devtools.main", "open", "inspector", null, ["foo", "bar"]);
-    }).not.toThrow();
-  });
-
-  it("addEventProperty", () => {
-    expect(() => {
-      telemetry.addEventProperty(
-        "devtools.main", "open", "inspector", "foo", "1");
-    }).not.toThrow();
-  });
-
-  it("addEventProperties", () => {
-    expect(() => {
-      telemetry.addEventProperties("devtools.main", "open", "inspector", {
-        "foo": "1",
-        "bar": "2"
-      });
-    }).not.toThrow();
-  });
-
-  it("_sendPendingEvent", () => {
-    expect(() => {
-      telemetry._sendPendingEvent("devtools.main", "open", "inspector", null);
-    }).not.toThrow();
-  });
-
-  it("recordEvent", () => {
-    expect(() => {
-      telemetry.recordEvent("devtools.main", "open", "inspector", null, {
-        "foo": "1",
-        "bar": "2"
-      });
-    }).not.toThrow();
-  });
-
-  it("toolOpened", () => {
-    expect(() => {
-      telemetry.toolOpened("foo");
-    }).not.toThrow();
-  });
-
-  it("toolClosed", () => {
-    expect(() => {
-      telemetry.toolClosed("foo");
-    }).not.toThrow();
-  });
-});
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/tests/unicode-url.js
+++ /dev/null
@@ -1,228 +0,0 @@
-/* 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 { getUnicodeUrl, getUnicodeUrlPath, getUnicodeHostname } =
-  require("../unicode-url");
-
-describe("unicode-url", () => {
-  // List of URLs used to test Unicode URL conversion
-  const TEST_URLS = [
-    // Type:     Readable ASCII URLs
-    // Expected: All of Unicode versions should equal to the raw.
-    {
-      raw: "https://example.org",
-      expectedUnicode: "https://example.org",
-    },
-    {
-      raw: "http://example.org",
-      expectedUnicode: "http://example.org",
-    },
-    {
-      raw: "ftp://example.org",
-      expectedUnicode: "ftp://example.org",
-    },
-    {
-      raw: "https://example.org.",
-      expectedUnicode: "https://example.org.",
-    },
-    {
-      raw: "https://example.org/",
-      expectedUnicode: "https://example.org/",
-    },
-    {
-      raw: "https://example.org/test",
-      expectedUnicode: "https://example.org/test",
-    },
-    {
-      raw: "https://example.org/test.html",
-      expectedUnicode: "https://example.org/test.html",
-    },
-    {
-      raw: "https://example.org/test.html?one=1&two=2",
-      expectedUnicode: "https://example.org/test.html?one=1&two=2",
-    },
-    {
-      raw: "https://example.org/test.html#here",
-      expectedUnicode: "https://example.org/test.html#here",
-    },
-    {
-      raw: "https://example.org/test.html?one=1&two=2#here",
-      expectedUnicode: "https://example.org/test.html?one=1&two=2#here",
-    },
-    // Type:     Unreadable URLs with either Punycode domain names or URI-encoded
-    //           paths
-    // Expected: Unreadable domain names and URI-encoded paths should be converted
-    //           to readable Unicode.
-    {
-      raw: "https://xn--g6w.xn--8pv/test.html",
-      // Do not type Unicode characters directly, because this test file isn't
-      // specified with a known encoding.
-      expectedUnicode: "https://\u6e2c.\u672c/test.html",
-    },
-    {
-      raw: "https://example.org/%E6%B8%AC%E8%A9%A6.html",
-      // Do not type Unicode characters directly, because this test file isn't
-      // specified with a known encoding.
-      expectedUnicode: "https://example.org/\u6e2c\u8a66.html",
-    },
-    {
-      raw: "https://example.org/test.html?One=%E4%B8%80",
-      // Do not type Unicode characters directly, because this test file isn't
-      // specified with a known encoding.
-      expectedUnicode: "https://example.org/test.html?One=\u4e00",
-    },
-    {
-      raw: "https://example.org/test.html?%E4%B8%80=1",
-      // Do not type Unicode characters directly, because this test file isn't
-      // specified with a known encoding.
-      expectedUnicode: "https://example.org/test.html?\u4e00=1",
-    },
-    {
-      raw: "https://xn--g6w.xn--8pv/%E6%B8%AC%E8%A9%A6.html" +
-           "?%E4%B8%80=%E4%B8%80" +
-           "#%E6%AD%A4",
-      // Do not type Unicode characters directly, because this test file isn't
-      // specified with a known encoding.
-      expectedUnicode: "https://\u6e2c.\u672c/\u6e2c\u8a66.html" +
-                       "?\u4e00=\u4e00" +
-                       "#\u6b64",
-    },
-    // Type:     data: URIs
-    // Expected: All should not be converted.
-    {
-      raw: "data:text/plain;charset=UTF-8;Hello%20world",
-      expectedUnicode: "data:text/plain;charset=UTF-8;Hello%20world",
-    },
-    {
-      raw: "data:text/plain;charset=UTF-8;%E6%B8%AC%20%E8%A9%A6",
-      expectedUnicode: "data:text/plain;charset=UTF-8;%E6%B8%AC%20%E8%A9%A6",
-    },
-    {
-      raw: "data:image/png;base64,iVBORw0KGgoAAA" +
-           "ANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4" +
-           "//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU" +
-           "5ErkJggg==",
-      expectedUnicode: "data:image/png;base64,iVBORw0KGgoAAA" +
-                       "ANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4" +
-                       "//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU" +
-                       "5ErkJggg==",
-    },
-    // Type:     Malformed URLs
-    // Expected: All should not be converted.
-    {
-      raw: "://example.org/test",
-      expectedUnicode: "://example.org/test",
-    },
-    {
-      raw: "://xn--g6w.xn--8pv/%E6%B8%AC%E8%A9%A6.html" +
-           "?%E4%B8%80=%E4%B8%80",
-      expectedUnicode: "://xn--g6w.xn--8pv/%E6%B8%AC%E8%A9%A6.html" +
-                       "?%E4%B8%80=%E4%B8%80",
-    },
-    {
-      // %E8%A9 isn't a valid UTF-8 code, so this URL is malformed.
-      raw: "https://xn--g6w.xn--8pv/%E6%B8%AC%E8%A9",
-      expectedUnicode: "https://xn--g6w.xn--8pv/%E6%B8%AC%E8%A9",
-    },
-  ];
-
-  // List of hostanmes used to test Unicode hostname conversion
-  const TEST_HOSTNAMES = [
-    // Type:     Readable ASCII hostnames
-    // Expected: All of Unicode versions should equal to the raw.
-    {
-      raw: "example",
-      expectedUnicode: "example",
-    },
-    {
-      raw: "example.org",
-      expectedUnicode: "example.org",
-    },
-    // Type:     Unreadable Punycode hostnames
-    // Expected: Punycode should be converted to readable Unicode.
-    {
-      raw: "xn--g6w",
-      // Do not type Unicode characters directly, because this test file isn't
-      // specified with a known encoding.
-      expectedUnicode: "\u6e2c",
-    },
-    {
-      raw: "xn--g6w.xn--8pv",
-      // Do not type Unicode characters directly, because this test file isn't
-      // specified with a known encoding.
-      expectedUnicode: "\u6e2c.\u672c",
-    },
-  ];
-
-  // List of URL paths used to test Unicode URL path conversion
-  const TEST_URL_PATHS = [
-    // Type:     Readable ASCII URL paths
-    // Expected: All of Unicode versions should equal to the raw.
-    {
-      raw: "test",
-      expectedUnicode: "test",
-    },
-    {
-      raw: "/",
-      expectedUnicode: "/",
-    },
-    {
-      raw: "/test",
-      expectedUnicode: "/test",
-    },
-    {
-      raw: "/test.html?one=1&two=2#here",
-      expectedUnicode: "/test.html?one=1&two=2#here",
-    },
-    // Type:     Unreadable URI-encoded URL paths
-    // Expected: URL paths should be converted to readable Unicode.
-    {
-      raw: "/%E6%B8%AC%E8%A9%A6",
-      // Do not type Unicode characters directly, because this test file isn't
-      // specified with a known encoding.
-      expectedUnicode: "/\u6e2c\u8a66",
-    },
-    {
-      raw: "/%E6%B8%AC%E8%A9%A6.html",
-      // Do not type Unicode characters directly, because this test file isn't
-      // specified with a known encoding.
-      expectedUnicode: "/\u6e2c\u8a66.html",
-    },
-    {
-      raw: "/%E6%B8%AC%E8%A9%A6.html" +
-           "?%E4%B8%80=%E4%B8%80&%E4%BA%8C=%E4%BA%8C" +
-           "#%E6%AD%A4",
-      // Do not type Unicode characters directly, because this test file isn't
-      // specified with a known encoding.
-      expectedUnicode: "/\u6e2c\u8a66.html" +
-                       "?\u4e00=\u4e00&\u4e8c=\u4e8c" +
-                       "#\u6b64",
-    },
-    // Type:     Malformed URL paths
-    // Expected: All should not be converted.
-    {
-      // %E8%A9 isn't a valid UTF-8 code, so this URL is malformed.
-      raw: "/%E6%B8%AC%E8%A9",
-      expectedUnicode: "/%E6%B8%AC%E8%A9",
-    },
-  ];
-
-  it("Get Unicode URLs", () => {
-    for (let url of TEST_URLS) {
-      expect(getUnicodeUrl(url.raw)).toBe(url.expectedUnicode);
-    }
-  });
-
-  it("Get Unicode hostnames", () => {
-    for (let hostname of TEST_HOSTNAMES) {
-      expect(getUnicodeHostname(hostname.raw)).toBe(hostname.expectedUnicode);
-    }
-  });
-
-  it("Get Unicode URL paths", () => {
-    for (let urlPath of TEST_URL_PATHS) {
-      expect(getUnicodeUrlPath(urlPath.raw)).toBe(urlPath.expectedUnicode);
-    }
-  });
-});
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/unicode-url.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/* 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 file is a chrome-API-free version of the module
-// devtools/client/shared/unicode-url.js in the mozilla-central repository, so
-// that it can be used in Chrome-API-free applications, such as the Launchpad.
-// But because of this, it cannot take advantage of utilizing chrome APIs and
-// should implement the similar functionalities on its own.
-//
-// Please keep in mind that if the feature in this file has changed, don't
-// forget to also change that accordingly in
-// devtools/client/shared/unicode-url.js in the mozilla-central repository.
-
-"use strict";
-
-const punycode = require("punycode");
-
-/**
- * Gets a readble Unicode hostname from a hostname.
- *
- * If the `hostname` is a readable ASCII hostname, such as example.org, then
- * this function will simply return the original `hostname`.
- *
- * If the `hostname` is a Punycode hostname representing a Unicode domain name,
- * such as xn--g6w.xn--8pv, then this function will return the readable Unicode
- * domain name by decoding the Punycode hostname.
- *
- * @param {string}  hostname
- *                  the hostname from which the Unicode hostname will be
- *                  parsed, such as example.org, xn--g6w.xn--8pv.
- * @return {string} The Unicode hostname. It may be the same as the `hostname`
- *                  passed to this function if the `hostname` itself is
- *                  a readable ASCII hostname or a Unicode hostname.
- */
-function getUnicodeHostname(hostname) {
-  try {
-    return punycode.toUnicode(hostname);
-  } catch (err) {
-  }
-  return hostname;
-}
-
-/**
- * Gets a readble Unicode URL pathname from a URL pathname.
- *
- * If the `urlPath` is a readable ASCII URL pathname, such as /a/b/c.js, then
- * this function will simply return the original `urlPath`.
- *
- * If the `urlPath` is a URI-encoded pathname, such as %E8%A9%A6/%E6%B8%AC.js,
- * then this function will return the readable Unicode pathname.
- *
- * If the `urlPath` is a malformed URL pathname, then this function will simply
- * return the original `urlPath`.
- *
- * @param {string}  urlPath
- *                  the URL path from which the Unicode URL path will be parsed,
- *                  such as /a/b/c.js, %E8%A9%A6/%E6%B8%AC.js.
- * @return {string} The Unicode URL Path. It may be the same as the `urlPath`
- *                  passed to this function if the `urlPath` itself is a readable
- *                  ASCII url or a Unicode url.
- */
-function getUnicodeUrlPath(urlPath) {
-  try {
-    return decodeURIComponent(urlPath);
-  } catch (err) {
-  }
-  return urlPath;
-}
-
-/**
- * Gets a readable Unicode URL from a URL.
- *
- * If the `url` is a readable ASCII URL, such as http://example.org/a/b/c.js,
- * then this function will simply return the original `url`.
- *
- * If the `url` includes either an unreadable Punycode domain name or an
- * unreadable URI-encoded pathname, such as
- * http://xn--g6w.xn--8pv/%E8%A9%A6/%E6%B8%AC.js, then this function will return
- * the readable URL by decoding all its unreadable URL components to Unicode
- * characters.
- *
- * If the `url` is a malformed URL, then this function will return the original
- * `url`.
- *
- * If the `url` is a data: URI, then this function will return the original
- * `url`.
- *
- * @param {string}  url
- *                  the full URL, or a data: URI. from which the readable URL
- *                  will be parsed, such as, http://example.org/a/b/c.js,
- *                  http://xn--g6w.xn--8pv/%E8%A9%A6/%E6%B8%AC.js
- * @return {string} The readable URL. It may be the same as the `url` passed to
- *                  this function if the `url` itself is readable.
- */
-function getUnicodeUrl(url) {
-  try {
-    const { protocol, hostname } = new URL(url);
-    if (protocol === "data:") {
-      // Never convert a data: URI.
-      return url;
-    }
-    const readableHostname = getUnicodeHostname(hostname);
-    url = decodeURIComponent(url);
-    return url.replace(hostname, readableHostname);
-  } catch (err) {
-  }
-  return url;
-}
-
-module.exports = {
-  getUnicodeHostname,
-  getUnicodeUrlPath,
-  getUnicodeUrl,
-};
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/utils/defer.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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";
-
-// See bug 1273941 to understand this choice of promise.
-const Promise = require("../sham/promise");
-
-/**
- * Returns a deferred object, with a resolve and reject property.
- * https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred
- */
-module.exports = function defer() {
-  let resolve, reject;
-  let promise = new Promise(function () {
-    resolve = arguments[0];
-    reject = arguments[1];
-  });
-  return {
-    resolve: resolve,
-    reject: reject,
-    promise: promise
-  };
-};
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/utils/event-emitter.js
+++ /dev/null
@@ -1,127 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var EventEmitter = function EventEmitter() {};
-module.exports = EventEmitter;
-
-const promise = require("./promise");
-
-/**
- * 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.
-   */
-  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.
-   */
-  off: function EventEmitter_off(aEvent, aListener) {
-    if (!this._eventEmitterListeners)
-      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) {
-          // Prevent a bad listener from interfering with the others.
-          let msg = ex + ": " + ex.stack;
-          //console.error(msg);
-          console.log(msg);
-        }
-      }
-    }
-  },
-};
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/utils/promise.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/* 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/. */
-
-/*
- * 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;
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/utils/task.js
+++ /dev/null
@@ -1,515 +0,0 @@
-/* -*- 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/. */
-
-"use strict";
-
-/* eslint-disable spaced-comment */
-/* globals StopIteration */
-
-/**
- * This module implements a subset of "Task.js" <http://taskjs.org/>.
- * It is a copy of toolkit/modules/Task.jsm.  Please try not to
- * diverge the API here.
- *
- * Paraphrasing from the Task.js site, tasks make sequential, asynchronous
- * operations simple, using the power of JavaScript's "yield" operator.
- *
- * Tasks are built upon generator functions and promises, documented here:
- *
- * <https://developer.mozilla.org/en/JavaScript/Guide/Iterators_and_Generators>
- * <http://wiki.commonjs.org/wiki/Promises/A>
- *
- * The "Task.spawn" function takes a generator function and starts running it as
- * a task.  Every time the task yields a promise, it waits until the promise is
- * fulfilled.  "Task.spawn" returns a promise that is resolved when the task
- * completes successfully, or is rejected if an exception occurs.
- *
- * -----------------------------------------------------------------------------
- *
- * const {Task} = require("devtools/shared/task");
- *
- * Task.spawn(function* () {
- *
- *   // This is our task. Let's create a promise object, wait on it and capture
- *   // its resolution value.
- *   let myPromise = getPromiseResolvedOnTimeoutWithValue(1000, "Value");
- *   let result = yield myPromise;
- *
- *   // This part is executed only after the promise above is fulfilled (after
- *   // one second, in this imaginary example).  We can easily loop while
- *   // calling asynchronous functions, and wait multiple times.
- *   for (let i = 0; i < 3; i++) {
- *     result += yield getPromiseResolvedOnTimeoutWithValue(50, "!");
- *   }
- *
- *   return "Resolution result for the task: " + result;
- * }).then(function (result) {
- *
- *   // result == "Resolution result for the task: Value!!!"
- *
- *   // The result is undefined if no value was returned.
- *
- * }, function (exception) {
- *
- *   // Failure!  We can inspect or report the exception.
- *
- * });
- *
- * -----------------------------------------------------------------------------
- *
- * This module implements only the "Task.js" interfaces described above, with no
- * additional features to control the task externally, or do custom scheduling.
- * It also provides the following extensions that simplify task usage in the
- * most common cases:
- *
- * - The "Task.spawn" function also accepts an iterator returned by a generator
- *   function, in addition to a generator function.  This way, you can call into
- *   the generator function with the parameters you want, and with "this" bound
- *   to the correct value.  Also, "this" is never bound to the task object when
- *   "Task.spawn" calls the generator function.
- *
- * - In addition to a promise object, a task can yield the iterator returned by
- *   a generator function.  The iterator is turned into a task automatically.
- *   This reduces the syntax overhead of calling "Task.spawn" explicitly when
- *   you want to recurse into other task functions.
- *
- * - The "Task.spawn" function also accepts a primitive value, or a function
- *   returning a primitive value, and treats the value as the result of the
- *   task.  This makes it possible to call an externally provided function and
- *   spawn a task from it, regardless of whether it is an asynchronous generator
- *   or a synchronous function.  This comes in handy when iterating over
- *   function lists where some items have been converted to tasks and some not.
- */
-
-////////////////////////////////////////////////////////////////////////////////
-//// Globals
-
-const Promise = require("../sham/promise");
-const defer = require("./defer");
-
-// The following error types are considered programmer errors, which should be
-// reported (possibly redundantly) so as to let programmers fix their code.
-const ERRORS_TO_REPORT = ["EvalError", "RangeError", "ReferenceError",
-                          "TypeError"];
-
-/**
- * The Task currently being executed
- */
-var gCurrentTask = null;
-
-/**
- * If `true`, capture stacks whenever entering a Task and rewrite the
- * stack any exception thrown through a Task.
- */
-var gMaintainStack = false;
-
-/**
- * Iterate through the lines of a string.
- *
- * @return Iterator<string>
- */
-function* linesOf(string) {
-  let reLine = /([^\r\n])+/g;
-  let match;
-  while ((match = reLine.exec(string))) {
-    yield [match[0], match.index];
-  }
-}
-
-/**
- * Detect whether a value is a generator.
- *
- * @param aValue
- *        The value to identify.
- * @return A boolean indicating whether the value is a generator.
- */
-function isGenerator(value) {
-  return Object.prototype.toString.call(value) == "[object Generator]";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//// Task
-
-/**
- * This object provides the public module functions.
- */
-var Task = {
-  /**
-   * Creates and starts a new task.
-   *
-   * @param task
-   *        - If you specify a generator function, it is called with no
-   *          arguments to retrieve the associated iterator.  The generator
-   *          function is a task, that is can yield promise objects to wait
-   *          upon.
-   *        - If you specify the iterator returned by a generator function you
-   *          called, the generator function is also executed as a task.  This
-   *          allows you to call the function with arguments.
-   *        - If you specify a function that is not a generator, it is called
-   *          with no arguments, and its return value is used to resolve the
-   *          returned promise.
-   *        - If you specify anything else, you get a promise that is already
-   *          resolved with the specified value.
-   *
-   * @return A promise object where you can register completion callbacks to be
-   *         called when the task terminates.
-   */
-  spawn: function (task) {
-    return createAsyncFunction(task)();
-  },
-
-  /**
-   * Create and return an 'async function' that starts a new task.
-   *
-   * This is similar to 'spawn' except that it doesn't immediately start
-   * the task, it binds the task to the async function's 'this' object and
-   * arguments, and it requires the task to be a function.
-   *
-   * It simplifies the common pattern of implementing a method via a task,
-   * like this simple object with a 'greet' method that has a 'name' parameter
-   * and spawns a task to send a greeting and return its reply:
-   *
-   * let greeter = {
-   *   message: "Hello, NAME!",
-   *   greet: function(name) {
-   *     return Task.spawn((function* () {
-   *       return yield sendGreeting(this.message.replace(/NAME/, name));
-   *     }).bind(this);
-   *   })
-   * };
-   *
-   * With Task.async, the method can be declared succinctly:
-   *
-   * let greeter = {
-   *   message: "Hello, NAME!",
-   *   greet: Task.async(function* (name) {
-   *     return yield sendGreeting(this.message.replace(/NAME/, name));
-   *   })
-   * };
-   *
-   * While maintaining identical semantics:
-   *
-   * greeter.greet("Mitchell").then((reply) => { ... }); // behaves the same
-   *
-   * @param task
-   *        The task function to start.
-   *
-   * @return A function that starts the task function and returns its promise.
-   */
-  async: function (task) {
-    if (typeof (task) != "function") {
-      throw new TypeError("task argument must be a function");
-    }
-
-    return createAsyncFunction(task);
-  },
-
-  /**
-   * Constructs a special exception that, when thrown inside a legacy generator
-   * function (non-star generator), allows the associated task to be resolved
-   * with a specific value.
-   *
-   * Example: throw new Task.Result("Value");
-   */
-  Result: function (value) {
-    this.value = value;
-  }
-};
-
-function createAsyncFunction(task) {
-  let asyncFunction = function () {
-    let result = task;
-    if (task && typeof (task) == "function") {
-      if (task.isAsyncFunction) {
-        throw new TypeError(
-          "Cannot use an async function in place of a promise. " +
-          "You should either invoke the async function first " +
-          "or use 'Task.spawn' instead of 'Task.async' to start " +
-          "the Task and return its promise.");
-      }
-
-      try {
-        // Let's call into the function ourselves.
-        result = task.apply(this, arguments);
-      } catch (ex) {
-        if (ex instanceof Task.Result) {
-          return Promise.resolve(ex.value);
-        }
-        return Promise.reject(ex);
-      }
-    }
-
-    if (isGenerator(result)) {
-      // This is an iterator resulting from calling a generator function.
-      return new TaskImpl(result).deferred.promise;
-    }
-
-    // Just propagate the given value to the caller as a resolved promise.
-    return Promise.resolve(result);
-  };
-
-  asyncFunction.isAsyncFunction = true;
-
-  return asyncFunction;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//// TaskImpl
-
-/**
- * Executes the specified iterator as a task, and gives access to the promise
- * that is fulfilled when the task terminates.
- */
-function TaskImpl(iterator) {
-  if (gMaintainStack) {
-    this._stack = (new Error()).stack;
-  }
-  this.deferred = defer();
-  this._iterator = iterator;
-  this._isStarGenerator = !("send" in iterator);
-  this._run(true);
-}
-
-TaskImpl.prototype = {
-  /**
-   * Includes the promise object where task completion callbacks are registered,
-   * and methods to resolve or reject the promise at task completion.
-   */
-  deferred: null,
-
-  /**
-   * The iterator returned by the generator function associated with this task.
-   */
-  _iterator: null,
-
-  /**
-   * Whether this Task is using a star generator.
-   */
-  _isStarGenerator: false,
-
-  /**
-   * Main execution routine, that calls into the generator function.
-   *
-   * @param sendResolved
-   *        If true, indicates that we should continue into the generator
-   *        function regularly (if we were waiting on a promise, it was
-   *        resolved). If true, indicates that we should cause an exception to
-   *        be thrown into the generator function (if we were waiting on a
-   *        promise, it was rejected).
-   * @param sendValue
-   *        Resolution result or rejection exception, if any.
-   */
-  _run: function (sendResolved, sendValue) {
-    try {
-      gCurrentTask = this;
-
-      if (this._isStarGenerator) {
-        try {
-          let result = sendResolved ? this._iterator.next(sendValue)
-                                    : this._iterator.throw(sendValue);
-
-          if (result.done) {
-            // The generator function returned.
-            this.deferred.resolve(result.value);
-          } else {
-            // The generator function yielded.
-            this._handleResultValue(result.value);
-          }
-        } catch (ex) {
-          // The generator function failed with an uncaught exception.
-          this._handleException(ex);
-        }
-      } else {
-        try {
-          let yielded = sendResolved ? this._iterator.send(sendValue)
-                                     : this._iterator.throw(sendValue);
-          this._handleResultValue(yielded);
-        } catch (ex) {
-          if (ex instanceof Task.Result) {
-            // The generator function threw the special exception that
-            // allows it to return a specific value on resolution.
-            this.deferred.resolve(ex.value);
-          } else if (ex instanceof StopIteration) {
-            // The generator function terminated with no specific result.
-            this.deferred.resolve(undefined);
-          } else {
-            // The generator function failed with an uncaught exception.
-            this._handleException(ex);
-          }
-        }
-      }
-    } finally {
-      //
-      // At this stage, the Task may have finished executing, or have
-      // walked through a `yield` or passed control to a sub-Task.
-      // Regardless, if we still own `gCurrentTask`, reset it. If we
-      // have not finished execution of this Task, re-entering `_run`
-      // will set `gCurrentTask` to `this` as needed.
-      //
-      // We just need to be careful here in case we hit the following
-      // pattern:
-      //
-      //   Task.spawn(foo);
-      //   Task.spawn(bar);
-      //
-      // Here, `foo` and `bar` may be interleaved, so when we finish
-      // executing `foo`, `gCurrentTask` may actually either `foo` or
-      // `bar`. If `gCurrentTask` has already been set to `bar`, leave
-      // it be and it will be reset to `null` once `bar` is complete.
-      //
-      if (gCurrentTask == this) {
-        gCurrentTask = null;
-      }
-    }
-  },
-
-  /**
-   * Handle a value yielded by a generator.
-   *
-   * @param value
-   *        The yielded value to handle.
-   */
-  _handleResultValue: function (value) {
-    // If our task yielded an iterator resulting from calling another
-    // generator function, automatically spawn a task from it, effectively
-    // turning it into a promise that is fulfilled on task completion.
-    if (isGenerator(value)) {
-      value = Task.spawn(value);
-    }
-
-    if (value && typeof (value.then) == "function") {
-      // We have a promise object now. When fulfilled, call again into this
-      // function to continue the task, with either a resolution or rejection
-      // condition.
-      value.then(this._run.bind(this, true),
-                  this._run.bind(this, false));
-    } else {
-      // If our task yielded a value that is not a promise, just continue and
-      // pass it directly as the result of the yield statement.
-      this._run(true, value);
-    }
-  },
-
-  /**
-   * Handle an uncaught exception thrown from a generator.
-   *
-   * @param exception
-   *        The uncaught exception to handle.
-   */
-  _handleException: function (exception) {
-    gCurrentTask = this;
-
-    if (exception && typeof exception == "object" && "stack" in exception) {
-      let stack = exception.stack;
-
-      if (gMaintainStack &&
-          exception._capturedTaskStack != this._stack &&
-          typeof stack == "string") {
-        // Rewrite the stack for more readability.
-
-        let bottomStack = this._stack;
-
-        stack = Task.Debugging.generateReadableStack(stack);
-
-        exception.stack = stack;
-
-        // If exception is reinjected in the same task and rethrown,
-        // we don't want to perform the rewrite again.
-        exception._capturedTaskStack = bottomStack;
-      } else if (!stack) {
-        stack = "Not available";
-      }
-
-      if ("name" in exception &&
-          ERRORS_TO_REPORT.indexOf(exception.name) != -1) {
-        // We suspect that the exception is a programmer error, so we now
-        // display it using dump().  Note that we do not use Cu.reportError as
-        // we assume that this is a programming error, so we do not want end
-        // users to see it. Also, if the programmer handles errors correctly,
-        // they will either treat the error or log them somewhere.
-
-        dump("*************************\n");
-        dump("A coding exception was thrown and uncaught in a Task.\n\n");
-        dump("Full message: " + exception + "\n");
-        dump("Full stack: " + exception.stack + "\n");
-        dump("*************************\n");
-      }
-    }
-
-    this.deferred.reject(exception);
-  },
-
-  get callerStack() {
-    // Cut `this._stack` at the last line of the first block that
-    // contains task.js, keep the tail.
-    for (let [line, index] of linesOf(this._stack || "")) {
-      if (line.indexOf("/task.js:") == -1) {
-        return this._stack.substring(index);
-      }
-    }
-    return "";
-  }
-};
-
-Task.Debugging = {
-
-  /**
-   * Control stack rewriting.
-   *
-   * If `true`, any exception thrown from a Task will be rewritten to
-   * provide a human-readable stack trace. Otherwise, stack traces will
-   * be left unchanged.
-   *
-   * There is a (small but existing) runtime cost associated to stack
-   * rewriting, so you should probably not activate this in production
-   * code.
-   *
-   * @type {bool}
-   */
-  get maintainStack() {
-    return gMaintainStack;
-  },
-  set maintainStack(x) {
-    if (!x) {
-      gCurrentTask = null;
-    }
-    gMaintainStack = x;
-    return x;
-  },
-
-  /**
-   * Generate a human-readable stack for an error raised in
-   * a Task.
-   *
-   * @param {string} topStack The stack provided by the error.
-   * @param {string=} prefix Optionally, a prefix for each line.
-   */
-  generateReadableStack: function (topStack, prefix = "") {
-    if (!gCurrentTask) {
-      return topStack;
-    }
-
-    // Cut `topStack` at the first line that contains task.js, keep the head.
-    let lines = [];
-    for (let [line] of linesOf(topStack)) {
-      if (line.indexOf("/task.js:") != -1) {
-        break;
-      }
-      lines.push(prefix + line);
-    }
-    if (!prefix) {
-      lines.push(gCurrentTask.callerStack);
-    } else {
-      for (let [line] of linesOf(gCurrentTask.callerStack)) {
-        lines.push(prefix + line);
-      }
-    }
-
-    return lines.join("\n");
-  }
-};
-
-exports.Task = Task;
deleted file mode 100644
--- a/devtools/client/debugger/packages/devtools-modules/src/utils/telemetry.js
+++ /dev/null
@@ -1,331 +0,0 @@
-/* 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 is a stub of the DevTools telemetry module and will be replaced by the
- * full version of the file by Webpack for running inside Firefox.
- */
-
-class Telemetry {
-  /**
-   * Time since the system wide epoch. This is not a monotonic timer but
-   * can be used across process boundaries.
-   */
-  get msSystemNow() {
-    return 0;
-  }
-
-  /**
-   * Starts a timer associated with a telemetry histogram. The timer can be
-   * directly associated with a histogram, or with a pair of a histogram and
-   * an object.
-   *
-   * @param {String} histogramId
-   *        A string which must be a valid histogram name.
-   * @param {Object} obj
-   *        Optional parameter. If specified, the timer is associated with this
-   *        object, meaning that multiple timers for the same histogram may be
-   *        run concurrently, as long as they are associated with different
-   *        objects.
-   *
-   * @returns {Boolean}
-   *          True if the timer was successfully started, false otherwise. If a
-   *          timer already exists, it can't be started again, and the existing
-   *          one will be cleared in order to avoid measurements errors.
-   */
-  start(histogramId, obj) {
-    return true;
-  }
-
-  /**
-   * Starts a timer associated with a keyed telemetry histogram. The timer can
-   * be directly associated with a histogram and its key. Similarly to
-   * TelemetryStopwatch.start the histogram and its key can be associated
-   * with an object. Each key may have multiple associated objects and each
-   * object can be associated with multiple keys.
-   *
-   * @param {String} histogramId
-   *        A string which must be a valid histogram name.
-   * @param {String} key
-   *        A string which must be a valid histgram key.
-   * @param {Object} obj
-   *        Optional parameter. If specified, the timer is associated with this
-   *        object, meaning that multiple timers for the same histogram may be
-   *        run concurrently,as long as they are associated with different
-   *        objects.
-   *
-   * @returns {Boolean}
-   *          True if the timer was successfully started, false otherwise. If a
-   *          timer already exists, it can't be started again, and the existing
-   *          one will be cleared in order to avoid measurements errors.
-   */
-  startKeyed(histogramId, key, obj) {
-    return true;
-  }
-
-  /**
-   * Stops the timer associated with the given histogram (and object),
-   * calculates the time delta between start and finish, and adds the value
-   * to the histogram.
-   *
-   * @param {String} histogramId
-   *        A string which must be a valid histogram name.
-   * @param {Object} obj
-   *        Optional parameter which associates the histogram timer with the
-   *        given object.
-   * @param {Boolean} canceledOkay
-   *        Optional parameter which will suppress any warnings that normally
-   *        fire when a stopwatch is finished after being cancelled.
-   *        Defaults to false.
-   *
-   * @returns {Boolean}
-   *          True if the timer was succesfully stopped and the data was added
-   *          to the histogram, False otherwise.
-   */
-  finish(histogramId, obj, canceledOkay) {
-    return true;
-  }
-
-  /**
-   * Stops the timer associated with the given keyed histogram (and object),
-   * calculates the time delta between start and finish, and adds the value
-   * to the keyed histogram.
-   *
-   * @param {String} histogramId
-   *        A string which must be a valid histogram name.
-   * @param {String} key
-   *        A string which must be a valid histogram key.
-   * @param {Object} obj
-   *        Optional parameter which associates the histogram timer with the
-   *        given object.
-   * @param {Boolean} canceledOkay
-   *        Optional parameter which will suppress any warnings that normally
-   *        fire when a stopwatch is finished after being cancelled.
-   *        Defaults to false.
-   *
-   * @returns {Boolean}
-   *          True if the timer was succesfully stopped and the data was added
-   *          to the histogram, False otherwise.
-   */
-  finishKeyed(histogramId, key, obj, cancelledOkay) {
-    return true;
-  }
-
-  /**
-   * Log a value to a histogram.
-   *
-   * @param  {String} histogramId
-   *         Histogram in which the data is to be stored.
-   */
-  getHistogramById(histogramId) {
-    return {
-      add: () => {}
-    };
-  }
-
-  /**
-   * Get a keyed histogram.
-   *
-   * @param  {String} histogramId
-   *         Histogram in which the data is to be stored.
-   */
-  getKeyedHistogramById(histogramId) {
-    return {
-      add: () => {}
-    };
-  }
-
-  /**
-   * Log a value to a scalar.
-   *
-   * @param  {String} scalarId
-   *         Scalar in which the data is to be stored.
-   * @param  value
-   *         Value to store.
-   */
-  scalarSet(scalarId, value) {}
-
-  /**
-   * Log a value to a count scalar.
-   *
-   * @param  {String} scalarId
-   *         Scalar in which the data is to be stored.
-   * @param  value
-   *         Value to store.
-   */
-  scalarAdd(scalarId, value) {}
-
-  /**
-   * Log a value to a keyed count scalar.
-   *
-   * @param  {String} scalarId
-   *         Scalar in which the data is to be stored.
-   * @param  {String} key
-   *         The key within the  scalar.
-   * @param  value
-   *         Value to store.
-   */
-  keyedScalarAdd(scalarId, key, value) {}
-
-  /**
-   * Event telemetry is disabled by default. Use this method to enable it for
-   * a particular category.
-   *
-   * @param {Boolean} enabled
-   *        Enabled: true or false.
-   */
-  setEventRecordingEnabled(enabled) {
-    return enabled;
-  }
-
-  /**
-   * Telemetry events often need to make use of a number of properties from
-   * completely different codepaths. To make this possible we create a
-   * "pending event" along with an array of property names that we need to wait
-   * for before sending the event.
-   *
-   * As each property is received via addEventProperty() we check if all
-   * properties have been received. Once they have all been received we send the
-   * telemetry event.
-   *
-   * @param {Object} obj
-   *        The telemetry event or ping is associated with this object, meaning
-   *        that multiple events or pings for the same histogram may be run
-   *        concurrently, as long as they are associated with different objects.
-   * @param {String} method
-   *        The telemetry event method (describes the type of event that
-   *        occurred e.g. "open")
-   * @param {String} object
-   *        The telemetry event object name (the name of the object the event
-   *        occurred on) e.g. "tools" or "setting"
-   * @param {String|null} value
-   *        The telemetry event value (a user defined value, providing context
-   *        for the event) e.g. "console"
-   * @param {Array} expected
-   *        An array of the properties needed before sending the telemetry
-   *        event e.g.
-   *        [
-   *          "host",
-   *          "width"
-   *        ]
-   */
-  preparePendingEvent(obj, method, object, value, expected = []) {}
-
-  /**
-   * Adds an expected property for either a current or future pending event.
-   * This means that if preparePendingEvent() is called before or after sending
-   * the event properties they will automatically added to the event.
-   *
-   * @param {Object} obj
-   *        The telemetry event or ping is associated with this object, meaning
-   *        that multiple events or pings for the same histogram may be run
-   *        concurrently, as long as they are associated with different objects.
-   * @param {String} method
-   *        The telemetry event method (describes the type of event that
-   *        occurred e.g. "open")
-   * @param {String} object
-   *        The telemetry event object name (the name of the object the event
-   *        occurred on) e.g. "tools" or "setting"
-   * @param {String|null} value
-   *        The telemetry event value (a user defined value, providing context
-   *        for the event) e.g. "console"
-   * @param {String} pendingPropName
-   *        The pending property name
-   * @param {String} pendingPropValue
-   *        The pending property value
-   */
-  addEventProperty(obj, method, object, value, pendingPropName, pendingPropValue) {}
-
-  /**
-   * Adds expected properties for either a current or future pending event.
-   * This means that if preparePendingEvent() is called before or after sending
-   * the event properties they will automatically added to the event.
-   *
-   * @param {Object} obj
-   *        The telemetry event or ping is associated with this object, meaning
-   *        that multiple events or pings for the same histogram may be run
-   *        concurrently, as long as they are associated with different objects.
-   * @param {String} method
-   *        The telemetry event method (describes the type of event that
-   *        occurred e.g. "open")
-   * @param {String} object
-   *        The telemetry event object name (the name of the object the event
-   *        occurred on) e.g. "tools" or "setting"
-   * @param {String|null} value
-   *        The telemetry event value (a user defined value, providing context
-   *        for the event) e.g. "console"
-   * @param {String} pendingObject
-   *        An object containing key, value pairs that should be added to the
-   *        event as properties.
-   */
-  addEventProperties(obj, method, object, value, pendingObject) {}
-
-  /**
-   * A private method that is not to be used externally. This method is used to
-   * prepare a pending telemetry event for sending and then send it via
-   * recordEvent().
-   *
-   * @param {Object} obj
-   *        The telemetry event or ping is associated with this object, meaning
-   *        that multiple events or pings for the same histogram may be run
-   *        concurrently, as long as they are associated with different objects.
-   * @param {String} method
-   *        The telemetry event method (describes the type of event that
-   *        occurred e.g. "open")
-   * @param {String} object
-   *        The telemetry event object name (the name of the object the event
-   *        occurred on) e.g. "tools" or "setting"
-   * @param {String|null} value
-   *        The telemetry event value (a user defined value, providing context
-   *        for the event) e.g. "console"
-   */
-  _sendPendingEvent(obj, method, object, value) {}
-
-  /**
-   * Send a telemetry event.
-   *
-   * @param {String} method
-   *        The telemetry event method (describes the type of event that
-   *        occurred e.g. "open")
-   * @param {String} object
-   *        The telemetry event object name (the name of the object the event
-   *        occurred on) e.g. "tools" or "setting"
-   * @param {String|null} value
-   *        The telemetry event value (a user defined value, providing context
-   *        for the event) e.g. "console"
-   * @param {Object} extra
-   *        The telemetry event extra object containing the properties that will
-   *        be sent with the event e.g.
-   *        {
-   *          host: "bottom",
-   *          width: "1024"
-   *        }
-   */
-  recordEvent(method, object, value, extra) {}
-
-  /**
-   * Sends telemetry pings to indicate that a tool has been opened.
-   *
-   * @param {String} id
-   *        The ID of the tool opened.
-   * @param {String} sessionId
-   *        Toolbox session id used when we need to ensure a tool really has a
-   *        timer before calculating a delta.
-   * @param {Object} obj
-   *        The telemetry event or ping is associated with this object, meaning
-   *        that multiple events or pings for the same histogram may be run
-   *        concurrently, as long as they are associated with different objects.
-   */
-  toolOpened(id, sessionId, obj) {}
-
-  /**
-   * Sends telemetry pings to indicate that a tool has been closed.
-   *
-   * @param {String} id
-   *        The ID of the tool opened.
-   */
-  toolClosed(id, sessionId, obj) {}
-}
-
-module.exports = Telemetry;