Bug 1411920 - about:debugging to ES6 classes r?jdescottes draft
authorMichael Ratcliffe <mratcliffe@mozilla.com>
Thu, 26 Oct 2017 13:20:22 +0100
changeset 690128 f821e3f49ff47f3270838c859929add8b1899477
parent 690034 cd7217cf05a2332a8fd7b498767a07b2c31ea657
child 738502 46cd577a81dd51a5c54a135ebd70bfd3ba241caf
push id87225
push userbmo:mratcliffe@mozilla.com
push dateWed, 01 Nov 2017 18:02:39 +0000
reviewersjdescottes
bugs1411920
milestone58.0a1
Bug 1411920 - about:debugging to ES6 classes r?jdescottes MozReview-Commit-ID: Js4NQoGfgtI
devtools/client/aboutdebugging/components/Aboutdebugging.js
devtools/client/aboutdebugging/components/PanelHeader.js
devtools/client/aboutdebugging/components/PanelMenu.js
devtools/client/aboutdebugging/components/PanelMenuEntry.js
devtools/client/aboutdebugging/components/TargetList.js
devtools/client/aboutdebugging/components/addons/Controls.js
devtools/client/aboutdebugging/components/addons/InstallError.js
devtools/client/aboutdebugging/components/addons/Panel.js
devtools/client/aboutdebugging/components/addons/Target.js
devtools/client/aboutdebugging/components/tabs/Panel.js
devtools/client/aboutdebugging/components/tabs/Target.js
devtools/client/aboutdebugging/components/workers/MultiE10sWarning.js
devtools/client/aboutdebugging/components/workers/Panel.js
devtools/client/aboutdebugging/components/workers/ServiceWorkerTarget.js
devtools/client/aboutdebugging/components/workers/Target.js
--- a/devtools/client/aboutdebugging/components/Aboutdebugging.js
+++ b/devtools/client/aboutdebugging/components/Aboutdebugging.js
@@ -1,17 +1,17 @@
 /* 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/. */
 
 /* eslint-env browser */
 
 "use strict";
 
-const { createFactory, createClass, DOM: dom, PropTypes } =
+const { createFactory, Component, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 const Services = require("Services");
 
 const PanelMenu = createFactory(require("./PanelMenu"));
 
 loader.lazyGetter(this, "AddonsPanel",
   () => createFactory(require("./addons/Panel")));
 loader.lazyGetter(this, "TabsPanel",
@@ -41,51 +41,56 @@ const panels = [{
   id: "workers",
   name: Strings.GetStringFromName("workers"),
   icon: "chrome://devtools/skin/images/debugging-workers.svg",
   component: WorkersPanel
 }];
 
 const defaultPanelId = "addons";
 
-module.exports = createClass({
-  displayName: "AboutDebuggingApp",
+class AboutDebuggingApp extends Component {
+  static get propTypes() {
+    return {
+      client: PropTypes.instanceOf(DebuggerClient).isRequired,
+      telemetry: PropTypes.instanceOf(Telemetry).isRequired
+    };
+  }
 
-  propTypes: {
-    client: PropTypes.instanceOf(DebuggerClient).isRequired,
-    telemetry: PropTypes.instanceOf(Telemetry).isRequired
-  },
+  constructor(props) {
+    super(props);
 
-  getInitialState() {
-    return {
+    this.state = {
       selectedPanelId: defaultPanelId
     };
-  },
+
+    this.onHashChange = this.onHashChange.bind(this);
+    this.selectPanel = this.selectPanel.bind(this);
+  }
 
   componentDidMount() {
     window.addEventListener("hashchange", this.onHashChange);
     this.onHashChange();
     this.props.telemetry.toolOpened("aboutdebugging");
-  },
+  }
 
   componentWillUnmount() {
     window.removeEventListener("hashchange", this.onHashChange);
     this.props.telemetry.toolClosed("aboutdebugging");
     this.props.telemetry.destroy();
-  },
+  }
 
   onHashChange() {
     this.setState({
       selectedPanelId: window.location.hash.substr(1) || defaultPanelId
     });
-  },
+  }
 
   selectPanel(panelId) {
     window.location.hash = "#" + panelId;
-  },
+  }
 
   render() {
     let { client } = this.props;
     let { selectedPanelId } = this.state;
     let selectPanel = this.selectPanel;
     let selectedPanel = panels.find(p => p.id == selectedPanelId);
     let panel;
 
@@ -103,9 +108,11 @@ module.exports = createClass({
       );
     }
 
     return dom.div({ className: "app" },
       PanelMenu({ panels, selectedPanelId, selectPanel }),
       dom.div({ className: "main-content" }, panel)
     );
   }
-});
+}
+
+module.exports = AboutDebuggingApp;
--- a/devtools/client/aboutdebugging/components/PanelHeader.js
+++ b/devtools/client/aboutdebugging/components/PanelHeader.js
@@ -1,24 +1,26 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const { createClass, DOM: dom, PropTypes } =
+const { Component, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 
-module.exports = createClass({
-  displayName: "PanelHeader",
-
-  propTypes: {
-    id: PropTypes.string.isRequired,
-    name: PropTypes.string.isRequired
-  },
+class PanelHeader extends Component {
+  static get propTypes() {
+    return {
+      id: PropTypes.string.isRequired,
+      name: PropTypes.string.isRequired
+    };
+  }
 
   render() {
     let { name, id } = this.props;
 
     return dom.div({ className: "header" },
       dom.h1({ id, className: "header-name" }, name));
-  },
-});
+  }
+}
+
+module.exports = PanelHeader;
--- a/devtools/client/aboutdebugging/components/PanelMenu.js
+++ b/devtools/client/aboutdebugging/components/PanelMenu.js
@@ -1,41 +1,43 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const { createClass, createFactory, DOM: dom, PropTypes } =
+const { Component, createFactory, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 const PanelMenuEntry = createFactory(require("./PanelMenuEntry"));
 
-module.exports = createClass({
-  displayName: "PanelMenu",
-
-  propTypes: {
-    panels: PropTypes.arrayOf(PropTypes.shape({
-      id: PropTypes.string.isRequired,
-      name: PropTypes.string.isRequired,
-      icon: PropTypes.string.isRequired,
-      component: PropTypes.func.isRequired
-    })).isRequired,
-    selectPanel: PropTypes.func.isRequired,
-    selectedPanelId: PropTypes.string
-  },
+class PanelMenu extends Component {
+  static get propTypes() {
+    return {
+      panels: PropTypes.arrayOf(PropTypes.shape({
+        id: PropTypes.string.isRequired,
+        name: PropTypes.string.isRequired,
+        icon: PropTypes.string.isRequired,
+        component: PropTypes.func.isRequired
+      })).isRequired,
+      selectPanel: PropTypes.func.isRequired,
+      selectedPanelId: PropTypes.string
+    };
+  }
 
   render() {
     let { panels, selectedPanelId, selectPanel } = this.props;
     let panelLinks = panels.map(({ id, name, icon }) => {
       let selected = id == selectedPanelId;
       return PanelMenuEntry({
         id,
         name,
         icon,
         selected,
         selectPanel
       });
     });
 
     // "categories" id used for styling purposes
     return dom.div({ id: "categories", role: "tablist" }, panelLinks);
-  },
-});
+  }
+}
+
+module.exports = PanelMenu;
--- a/devtools/client/aboutdebugging/components/PanelMenuEntry.js
+++ b/devtools/client/aboutdebugging/components/PanelMenuEntry.js
@@ -1,31 +1,36 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const { createClass, DOM: dom, PropTypes } =
+const { Component, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 
-module.exports = createClass({
-  displayName: "PanelMenuEntry",
+class PanelMenuEntry extends Component {
+  static get propTypes() {
+    return {
+      icon: PropTypes.string.isRequired,
+      id: PropTypes.string.isRequired,
+      name: PropTypes.string.isRequired,
+      selected: PropTypes.bool,
+      selectPanel: PropTypes.func.isRequired
+    };
+  }
 
-  propTypes: {
-    icon: PropTypes.string.isRequired,
-    id: PropTypes.string.isRequired,
-    name: PropTypes.string.isRequired,
-    selected: PropTypes.bool,
-    selectPanel: PropTypes.func.isRequired
-  },
+  constructor(props) {
+    super(props);
+    this.onClick = this.onClick.bind(this);
+  }
 
   onClick() {
     this.props.selectPanel(this.props.id);
-  },
+  }
 
   render() {
     let { id, name, icon, selected } = this.props;
 
     // Here .category, .category-icon, .category-name classnames are used to
     // apply common styles defined.
     let className = "category" + (selected ? " selected" : "");
     return dom.button({
@@ -33,9 +38,11 @@ module.exports = createClass({
       "aria-controls": id + "-panel",
       className,
       onClick: this.onClick,
       tabIndex: "0",
       role: "tab" },
     dom.img({ className: "category-icon", src: icon, role: "presentation" }),
     dom.div({ className: "category-name" }, name));
   }
-});
+}
+
+module.exports = PanelMenuEntry;
--- a/devtools/client/aboutdebugging/components/TargetList.js
+++ b/devtools/client/aboutdebugging/components/TargetList.js
@@ -1,41 +1,41 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const { createClass, DOM: dom, PropTypes } =
+const { Component, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 const Services = require("Services");
 
 loader.lazyRequireGetter(this, "DebuggerClient",
   "devtools/shared/client/debugger-client", true);
 
 const Strings = Services.strings.createBundle(
   "chrome://devtools/locale/aboutdebugging.properties");
 
 const LocaleCompare = (a, b) => {
   return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
 };
 
-module.exports = createClass({
-  displayName: "TargetList",
-
-  propTypes: {
-    client: PropTypes.instanceOf(DebuggerClient).isRequired,
-    debugDisabled: PropTypes.bool,
-    error: PropTypes.node,
-    id: PropTypes.string.isRequired,
-    name: PropTypes.string,
-    sort: PropTypes.bool,
-    targetClass: PropTypes.func.isRequired,
-    targets: PropTypes.arrayOf(PropTypes.object).isRequired
-  },
+class TargetList extends Component {
+  static get propTypes() {
+    return {
+      client: PropTypes.instanceOf(DebuggerClient).isRequired,
+      debugDisabled: PropTypes.bool,
+      error: PropTypes.node,
+      id: PropTypes.string.isRequired,
+      name: PropTypes.string,
+      sort: PropTypes.bool,
+      targetClass: PropTypes.func.isRequired,
+      targets: PropTypes.arrayOf(PropTypes.object).isRequired
+    };
+  }
 
   render() {
     let { client, debugDisabled, error, targetClass, targets, sort } = this.props;
     if (sort) {
       targets = targets.sort(LocaleCompare);
     }
     targets = targets.map(target => {
       return targetClass({ client, target, debugDisabled });
@@ -47,10 +47,12 @@ module.exports = createClass({
     } else if (targets.length > 0) {
       content = dom.ul({ className: "target-list" }, targets);
     } else {
       content = dom.p(null, Strings.GetStringFromName("nothing"));
     }
 
     return dom.div({ id: this.props.id, className: "targets" },
       dom.h2(null, this.props.name), content);
-  },
-});
+  }
+}
+
+module.exports = TargetList;
--- a/devtools/client/aboutdebugging/components/addons/Controls.js
+++ b/devtools/client/aboutdebugging/components/addons/Controls.js
@@ -6,45 +6,52 @@
 /* globals AddonManager */
 
 "use strict";
 
 loader.lazyImporter(this, "AddonManager",
   "resource://gre/modules/AddonManager.jsm");
 
 const { Cc, Ci } = require("chrome");
-const { createFactory, createClass, DOM: dom, PropTypes } =
+const { createFactory, Component, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 const Services = require("Services");
 const AddonsInstallError = createFactory(require("./InstallError"));
 
 const Strings = Services.strings.createBundle(
   "chrome://devtools/locale/aboutdebugging.properties");
 
 const MORE_INFO_URL = "https://developer.mozilla.org/docs/Tools" +
                       "/about:debugging#Enabling_add-on_debugging";
 
-module.exports = createClass({
-  displayName: "AddonsControls",
+class AddonsControls extends Component {
+  static get propTypes() {
+    return {
+      debugDisabled: PropTypes.bool
+    };
+  }
 
-  propTypes: {
-    debugDisabled: PropTypes.bool
-  },
+  constructor(props) {
+    super(props);
 
-  getInitialState() {
-    return {
+    this.state = {
       installError: null,
     };
-  },
+
+    this.onEnableAddonDebuggingChange = this.onEnableAddonDebuggingChange.bind(this);
+    this.loadAddonFromFile = this.loadAddonFromFile.bind(this);
+    this.retryInstall = this.retryInstall.bind(this);
+    this.installAddon = this.installAddon.bind(this);
+  }
 
   onEnableAddonDebuggingChange(event) {
     let enabled = event.target.checked;
     Services.prefs.setBoolPref("devtools.chrome.enabled", enabled);
     Services.prefs.setBoolPref("devtools.debugger.remote-enabled", enabled);
-  },
+  }
 
   loadAddonFromFile() {
     this.setState({ installError: null });
     let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
     fp.init(window,
       Strings.GetStringFromName("selectAddonFromFile2"),
       Ci.nsIFilePicker.modeOpen);
     fp.open(res => {
@@ -55,33 +62,33 @@ module.exports = createClass({
       // AddonManager.installTemporaryAddon accepts either
       // addon directory or final xpi file.
       if (!file.isDirectory() && !file.leafName.endsWith(".xpi")) {
         file = file.parent;
       }
 
       this.installAddon(file);
     });
-  },
+  }
 
   retryInstall() {
     this.setState({ installError: null });
     this.installAddon(this.state.lastInstallErrorFile);
-  },
+  }
 
   installAddon(file) {
     AddonManager.installTemporaryAddon(file)
       .then(() => {
         this.setState({ lastInstallErrorFile: null });
       })
       .catch(e => {
         console.error(e);
         this.setState({ installError: e.message, lastInstallErrorFile: file });
       });
-  },
+  }
 
   render() {
     let { debugDisabled } = this.props;
 
     return dom.div({ className: "addons-top" },
       dom.div({ className: "addons-controls" },
         dom.div({ className: "addons-options toggle-container-with-text" },
           dom.input({
@@ -105,9 +112,11 @@ module.exports = createClass({
           onClick: this.loadAddonFromFile,
         }, Strings.GetStringFromName("loadTemporaryAddon"))
       ),
       AddonsInstallError({
         error: this.state.installError,
         retryInstall: this.retryInstall,
       }));
   }
-});
+}
+
+module.exports = AddonsControls;
--- a/devtools/client/aboutdebugging/components/addons/InstallError.js
+++ b/devtools/client/aboutdebugging/components/addons/InstallError.js
@@ -1,29 +1,29 @@
 /* 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/. */
 
 /* eslint-env browser */
 "use strict";
 
-const { createClass, DOM: dom, PropTypes } = require("devtools/client/shared/vendor/react");
+const { Component, DOM: dom, PropTypes } = require("devtools/client/shared/vendor/react");
 
 const Services = require("Services");
 
 const Strings = Services.strings.createBundle(
   "chrome://devtools/locale/aboutdebugging.properties");
 
-module.exports = createClass({
-  displayName: "AddonsInstallError",
-
-  propTypes: {
-    error: PropTypes.string,
-    retryInstall: PropTypes.func,
-  },
+class AddonsInstallError extends Component {
+  static get propTypes() {
+    return {
+      error: PropTypes.string,
+      retryInstall: PropTypes.func,
+    };
+  }
 
   render() {
     if (!this.props.error) {
       return null;
     }
     let text = `There was an error during installation: ${this.props.error}`;
     return dom.div(
       { className: "addons-install-error" },
@@ -31,9 +31,11 @@ module.exports = createClass({
         {},
         dom.div({ className: "warning" }),
         dom.span({}, text),
       ),
       dom.button(
         { className: "addons-install-retry", onClick: this.props.retryInstall },
         Strings.GetStringFromName("retryTemporaryInstall")));
   }
-});
+}
+
+module.exports = AddonsInstallError;
--- a/devtools/client/aboutdebugging/components/addons/Panel.js
+++ b/devtools/client/aboutdebugging/components/addons/Panel.js
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { AddonManager } = require("resource://gre/modules/AddonManager.jsm");
 const { Management } = require("resource://gre/modules/Extension.jsm");
-const { createFactory, createClass, DOM: dom, PropTypes } =
+const { createFactory, Component, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 const Services = require("Services");
 
 const AddonsControls = createFactory(require("./Controls"));
 const AddonTarget = createFactory(require("./Target"));
 const PanelHeader = createFactory(require("../PanelHeader"));
 const TargetList = createFactory(require("../TargetList"));
 
@@ -22,63 +22,72 @@ const Strings = Services.strings.createB
   "chrome://devtools/locale/aboutdebugging.properties");
 
 const ExtensionIcon = "chrome://mozapps/skin/extensions/extensionGeneric.svg";
 const CHROME_ENABLED_PREF = "devtools.chrome.enabled";
 const REMOTE_ENABLED_PREF = "devtools.debugger.remote-enabled";
 const WEB_EXT_URL = "https://developer.mozilla.org/Add-ons" +
                     "/WebExtensions/Getting_started_with_web-ext";
 
-module.exports = createClass({
-  displayName: "AddonsPanel",
+class AddonsPanel extends Component {
+  static get propTypes() {
+    return {
+      client: PropTypes.instanceOf(DebuggerClient).isRequired,
+      id: PropTypes.string.isRequired
+    };
+  }
 
-  propTypes: {
-    client: PropTypes.instanceOf(DebuggerClient).isRequired,
-    id: PropTypes.string.isRequired
-  },
+  constructor(props) {
+    super(props);
 
-  getInitialState() {
-    return {
+    this.state = {
       extensions: [],
       debugDisabled: false,
     };
-  },
+
+    this.updateDebugStatus = this.updateDebugStatus.bind(this);
+    this.updateAddonsList = this.updateAddonsList.bind(this);
+    this.onInstalled = this.onInstalled.bind(this);
+    this.onUninstalled = this.onUninstalled.bind(this);
+    this.onEnabled = this.onEnabled.bind(this);
+    this.onDisabled = this.onDisabled.bind(this);
+  }
 
   componentDidMount() {
     AddonManager.addAddonListener(this);
     // Listen to startup since that's when errors and warnings
     // get populated on the extension.
     Management.on("startup", this.updateAddonsList);
 
     Services.prefs.addObserver(CHROME_ENABLED_PREF,
       this.updateDebugStatus);
     Services.prefs.addObserver(REMOTE_ENABLED_PREF,
       this.updateDebugStatus);
 
     this.updateDebugStatus();
     this.updateAddonsList();
-  },
+  }
 
   componentWillUnmount() {
     AddonManager.removeAddonListener(this);
     Management.off("startup", this.updateAddonsList);
 
     Services.prefs.removeObserver(CHROME_ENABLED_PREF,
       this.updateDebugStatus);
     Services.prefs.removeObserver(REMOTE_ENABLED_PREF,
       this.updateDebugStatus);
-  },
+  }
 
   updateDebugStatus() {
     let debugDisabled =
       !Services.prefs.getBoolPref(CHROME_ENABLED_PREF) ||
       !Services.prefs.getBoolPref(REMOTE_ENABLED_PREF);
 
     this.setState({ debugDisabled });
-  },
+  }
 
   updateAddonsList() {
     this.props.client.listAddons()
       .then(({addons}) => {
         let extensions = addons.filter(addon => addon.debuggable).map(addon => {
           return {
             name: addon.name,
             icon: addon.iconURL || ExtensionIcon,
@@ -90,45 +99,45 @@ module.exports = createClass({
             warnings: addon.warnings,
           };
         });
 
         this.setState({ extensions });
       }, error => {
         throw new Error("Client error while listing addons: " + error);
       });
-  },
+  }
 
   /**
    * Mandatory callback as AddonManager listener.
    */
   onInstalled() {
     this.updateAddonsList();
-  },
+  }
 
   /**
    * Mandatory callback as AddonManager listener.
    */
   onUninstalled() {
     this.updateAddonsList();
-  },
+  }
 
   /**
    * Mandatory callback as AddonManager listener.
    */
   onEnabled() {
     this.updateAddonsList();
-  },
+  }
 
   /**
    * Mandatory callback as AddonManager listener.
    */
   onDisabled() {
     this.updateAddonsList();
-  },
+  }
 
   render() {
     let { client, id } = this.props;
     let { debugDisabled, extensions: targets } = this.state;
     let installedName = Strings.GetStringFromName("extensions");
     let temporaryName = Strings.GetStringFromName("temporaryExtensions");
     let targetClass = AddonTarget;
 
@@ -172,9 +181,11 @@ module.exports = createClass({
         targets: installedTargets,
         client,
         debugDisabled,
         targetClass,
         sort: true
       })
     ));
   }
-});
+}
+
+module.exports = AddonsPanel;
--- a/devtools/client/aboutdebugging/components/addons/Target.js
+++ b/devtools/client/aboutdebugging/components/addons/Target.js
@@ -1,17 +1,17 @@
 /* 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/. */
 
 /* eslint-env browser */
 
 "use strict";
 
-const { createClass, DOM: dom, PropTypes } =
+const { Component, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 const { debugAddon, isTemporaryID, parseFileUri, uninstallAddon } =
   require("../../modules/addon");
 const Services = require("Services");
 
 loader.lazyImporter(this, "BrowserToolboxProcess",
   "resource://devtools/client/framework/ToolboxProcess.jsm");
 
@@ -117,55 +117,62 @@ function infoMessages(target) {
 function warningMessages(warnings = []) {
   return warnings.map((warning) => {
     return dom.li(
       { className: "addon-target-warning-message addon-target-message" },
       warning);
   });
 }
 
-module.exports = createClass({
-  displayName: "AddonTarget",
+class AddonTarget extends Component {
+  static get propTypes() {
+    return {
+      client: PropTypes.instanceOf(DebuggerClient).isRequired,
+      debugDisabled: PropTypes.bool,
+      target: PropTypes.shape({
+        addonActor: PropTypes.string.isRequired,
+        addonID: PropTypes.string.isRequired,
+        icon: PropTypes.string,
+        name: PropTypes.string.isRequired,
+        temporarilyInstalled: PropTypes.bool,
+        url: PropTypes.string,
+        warnings: PropTypes.array,
+      }).isRequired
+    };
+  }
 
-  propTypes: {
-    client: PropTypes.instanceOf(DebuggerClient).isRequired,
-    debugDisabled: PropTypes.bool,
-    target: PropTypes.shape({
-      addonActor: PropTypes.string.isRequired,
-      addonID: PropTypes.string.isRequired,
-      icon: PropTypes.string,
-      name: PropTypes.string.isRequired,
-      temporarilyInstalled: PropTypes.bool,
-      url: PropTypes.string,
-      warnings: PropTypes.array,
-    }).isRequired
-  },
+  constructor(props) {
+    super(props);
+    this.debug = this.debug.bind(this);
+    this.uninstall = this.uninstall.bind(this);
+    this.reload = this.reload.bind(this);
+  }
 
   debug() {
     let { target } = this.props;
     debugAddon(target.addonID);
-  },
+  }
 
   uninstall() {
     let { target } = this.props;
     uninstallAddon(target.addonID);
-  },
+  }
 
   reload() {
     let { client, target } = this.props;
     // This function sometimes returns a partial promise that only
     // implements then().
     client.request({
       to: target.addonActor,
       type: "reload"
     }).then(() => {}, error => {
       throw new Error(
         "Error reloading addon " + target.addonID + ": " + error);
     });
-  },
+  }
 
   render() {
     let { target, debugDisabled } = this.props;
 
     return dom.li(
       { className: "addon-target-container", "data-addon-id": target.addonID },
       dom.div({ className: "target" },
         dom.img({
@@ -200,9 +207,11 @@ module.exports = createClass({
           ? dom.button({
             className: "uninstall-button addon-target-button",
             onClick: this.uninstall,
           }, Strings.GetStringFromName("remove"))
           : null,
       ),
     );
   }
-});
+}
+
+module.exports = AddonTarget;
--- a/devtools/client/aboutdebugging/components/tabs/Panel.js
+++ b/devtools/client/aboutdebugging/components/tabs/Panel.js
@@ -1,54 +1,58 @@
 /* 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/. */
 
 /* eslint-env browser */
 
 "use strict";
 
-const { createClass, createFactory, DOM: dom, PropTypes } =
+const { Component, createFactory, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 const Services = require("Services");
 
 const PanelHeader = createFactory(require("../PanelHeader"));
 const TargetList = createFactory(require("../TargetList"));
 const TabTarget = createFactory(require("./Target"));
 
 loader.lazyRequireGetter(this, "DebuggerClient",
   "devtools/shared/client/debugger-client", true);
 
 const Strings = Services.strings.createBundle(
   "chrome://devtools/locale/aboutdebugging.properties");
 
-module.exports = createClass({
-  displayName: "TabsPanel",
+class TabsPanel extends Component {
+  static get propTypes() {
+    return {
+      client: PropTypes.instanceOf(DebuggerClient).isRequired,
+      id: PropTypes.string.isRequired
+    };
+  }
 
-  propTypes: {
-    client: PropTypes.instanceOf(DebuggerClient).isRequired,
-    id: PropTypes.string.isRequired
-  },
+  constructor(props) {
+    super(props);
 
-  getInitialState() {
-    return {
+    this.state = {
       tabs: []
     };
-  },
+
+    this.update = this.update.bind(this);
+  }
 
   componentDidMount() {
     let { client } = this.props;
     client.addListener("tabListChanged", this.update);
     this.update();
-  },
+  }
 
   componentWillUnmount() {
     let { client } = this.props;
     client.removeListener("tabListChanged", this.update);
-  },
+  }
 
   update() {
     this.props.client.mainRoot.listTabs().then(({ tabs }) => {
       // Filter out closed tabs (represented as `null`).
       tabs = tabs.filter(tab => !!tab);
       tabs.forEach(tab => {
         // FIXME Also try to fetch low-res favicon. But we should use actor
         // support for this to get the high-res one (bug 1061654).
@@ -63,17 +67,17 @@ module.exports = createClass({
           }
           tab.icon = prePath + "/favicon.ico";
         } else {
           tab.icon = "chrome://devtools/skin/images/globe.svg";
         }
       });
       this.setState({ tabs });
     });
-  },
+  }
 
   render() {
     let { client, id } = this.props;
     let { tabs } = this.state;
 
     return dom.div({
       id: id + "-panel",
       className: "panel",
@@ -90,9 +94,11 @@ module.exports = createClass({
         id: "tabs",
         name: Strings.GetStringFromName("tabs"),
         sort: false,
         targetClass: TabTarget,
         targets: tabs
       })
     ));
   }
-});
+}
+
+module.exports = TabsPanel;
--- a/devtools/client/aboutdebugging/components/tabs/Target.js
+++ b/devtools/client/aboutdebugging/components/tabs/Target.js
@@ -1,39 +1,44 @@
 /* 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/. */
 
 /* eslint-env browser */
 
 "use strict";
 
-const { createClass, DOM: dom, PropTypes } =
+const { Component, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 const Services = require("Services");
 
 const Strings = Services.strings.createBundle(
   "chrome://devtools/locale/aboutdebugging.properties");
 
-module.exports = createClass({
-  displayName: "TabTarget",
+class TabTarget extends Component {
+  static get propTypes() {
+    return {
+      target: PropTypes.shape({
+        icon: PropTypes.string,
+        outerWindowID: PropTypes.number.isRequired,
+        title: PropTypes.string,
+        url: PropTypes.string.isRequired
+      }).isRequired
+    };
+  }
 
-  propTypes: {
-    target: PropTypes.shape({
-      icon: PropTypes.string,
-      outerWindowID: PropTypes.number.isRequired,
-      title: PropTypes.string,
-      url: PropTypes.string.isRequired
-    }).isRequired
-  },
+  constructor(props) {
+    super(props);
+    this.debug = this.debug.bind(this);
+  }
 
   debug() {
     let { target } = this.props;
     window.open("about:devtools-toolbox?type=tab&id=" + target.outerWindowID);
-  },
+  }
 
   render() {
     let { target } = this.props;
 
     return dom.div({ className: "target-container" },
       dom.img({
         className: "target-icon",
         role: "presentation",
@@ -45,9 +50,11 @@ module.exports = createClass({
           target.title || target.url)
       ),
       dom.button({
         className: "debug-button",
         onClick: this.debug,
       }, Strings.GetStringFromName("debug"))
     );
   }
-});
+}
+
+module.exports = TabTarget;
--- a/devtools/client/aboutdebugging/components/workers/MultiE10sWarning.js
+++ b/devtools/client/aboutdebugging/components/workers/MultiE10sWarning.js
@@ -3,43 +3,46 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* eslint-env browser */
 
 "use strict";
 
 loader.lazyImporter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
-const { createClass, DOM: dom } =
+const { Component, DOM: dom } =
   require("devtools/client/shared/vendor/react");
 const Services = require("Services");
 const { Ci } = require("chrome");
 
 loader.lazyImporter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 loader.lazyRequireGetter(this, "DebuggerClient",
   "devtools/shared/client/debugger-client", true);
 
 const Strings = Services.strings.createBundle("chrome://devtools/locale/aboutdebugging.properties");
 const MULTI_OPT_OUT_PREF = "dom.ipc.multiOptOut";
 
-module.exports = createClass({
-  displayName: "multiE10SWarning",
+class multiE10SWarning extends Component {
+  constructor(props) {
+    super(props);
+    this.onUpdatePreferenceClick = this.onUpdatePreferenceClick.bind(this);
+  }
 
   onUpdatePreferenceClick() {
     let message = Strings.GetStringFromName("multiProcessWarningConfirmUpdate2");
     if (window.confirm(message)) {
       // Disable multi until at least the next experiment.
       Services.prefs.setIntPref(MULTI_OPT_OUT_PREF,
                                 Services.appinfo.E10S_MULTI_EXPERIMENT);
       // Restart the browser.
       Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
     }
-  },
+  }
 
   render() {
     return dom.div(
       {
         className: "service-worker-multi-process"
       },
       dom.div(
         {},
@@ -53,10 +56,12 @@ module.exports = createClass({
       dom.button(
         {
           className: "update-button",
           onClick: this.onUpdatePreferenceClick,
         },
         Strings.GetStringFromName("multiProcessWarningUpdateLink2")
       )
     );
-  },
-});
+  }
+}
+
+module.exports = multiE10SWarning;
--- a/devtools/client/aboutdebugging/components/workers/Panel.js
+++ b/devtools/client/aboutdebugging/components/workers/Panel.js
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 /* globals window */
 "use strict";
 
 loader.lazyImporter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 const { Ci } = require("chrome");
-const { createClass, createFactory, DOM: dom, PropTypes } =
+const { Component, createFactory, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 const { getWorkerForms } = require("../../modules/worker");
 const Services = require("Services");
 
 const PanelHeader = createFactory(require("../PanelHeader"));
 const TargetList = createFactory(require("../TargetList"));
 const WorkerTarget = createFactory(require("./Target"));
 const MultiE10SWarning = createFactory(require("./MultiE10sWarning"));
@@ -29,34 +29,35 @@ const Strings = Services.strings.createB
   "chrome://devtools/locale/aboutdebugging.properties");
 
 const WorkerIcon = "chrome://devtools/skin/images/debugging-workers.svg";
 const MORE_INFO_URL = "https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging" +
                       "#Service_workers_not_compatible";
 const PROCESS_COUNT_PREF = "dom.ipc.processCount";
 const MULTI_OPTOUT_PREF = "dom.ipc.multiOptOut";
 
-module.exports = createClass({
-  displayName: "WorkersPanel",
-
-  propTypes: {
-    client: PropTypes.instanceOf(DebuggerClient).isRequired,
-    id: PropTypes.string.isRequired
-  },
+class WorkersPanel extends Component {
+  static get propTypes() {
+    return {
+      client: PropTypes.instanceOf(DebuggerClient).isRequired,
+      id: PropTypes.string.isRequired
+    };
+  }
 
-  getInitialState() {
-    return {
-      workers: {
-        service: [],
-        shared: [],
-        other: []
-      },
-      processCount: 1,
-    };
-  },
+  constructor(props) {
+    super(props);
+
+    this.updateMultiE10S = this.updateMultiE10S.bind(this);
+    this.updateWorkers = this.updateWorkers.bind(this);
+    this.getRegistrationForWorker = this.getRegistrationForWorker.bind(this);
+    this.isE10S = this.isE10S.bind(this);
+    this.renderServiceWorkersError = this.renderServiceWorkersError.bind(this);
+
+    this.state = this.initialState;
+  }
 
   componentDidMount() {
     let client = this.props.client;
     client.addListener("workerListChanged", this.updateWorkers);
     client.addListener("serviceWorkerRegistrationListChanged", this.updateWorkers);
     client.addListener("processListChanged", this.updateWorkers);
     client.addListener("registration-changed", this.updateWorkers);
 
@@ -72,38 +73,49 @@ module.exports = createClass({
     // - In all cases, we don't have to manually check which pref changed to
     //   what. The platform code in nsIXULRuntime.maxWebProcessCount does all
     //   of that for us.
     Services.prefs.addObserver(PROCESS_COUNT_PREF, this.updateMultiE10S);
     Services.prefs.addObserver(MULTI_OPTOUT_PREF, this.updateMultiE10S);
 
     this.updateMultiE10S();
     this.updateWorkers();
-  },
+  }
 
   componentWillUnmount() {
     let client = this.props.client;
     client.removeListener("processListChanged", this.updateWorkers);
     client.removeListener("serviceWorkerRegistrationListChanged", this.updateWorkers);
     client.removeListener("workerListChanged", this.updateWorkers);
     client.removeListener("registration-changed", this.updateWorkers);
 
     Services.prefs.removeObserver(PROCESS_COUNT_PREF, this.updateMultiE10S);
     Services.prefs.removeObserver(MULTI_OPTOUT_PREF, this.updateMultiE10S);
-  },
+  }
+
+  get initialState() {
+    return {
+      workers: {
+        service: [],
+        shared: [],
+        other: []
+      },
+      processCount: 1,
+    };
+  }
 
   updateMultiE10S() {
     // We watch the pref but set the state based on
     // nsIXULRuntime.maxWebProcessCount.
     let processCount = Services.appinfo.maxWebProcessCount;
     this.setState({ processCount });
-  },
+  }
 
   updateWorkers() {
-    let workers = this.getInitialState().workers;
+    let workers = this.initialState.workers;
 
     getWorkerForms(this.props.client).then(forms => {
       forms.registrations.forEach(form => {
         workers.service.push({
           icon: WorkerIcon,
           name: form.url,
           url: form.url,
           scope: form.scope,
@@ -151,30 +163,30 @@ module.exports = createClass({
       });
 
       // XXX: Filter out the service worker registrations for which we couldn't
       // find the scriptSpec.
       workers.service = workers.service.filter(reg => !!reg.url);
 
       this.setState({ workers });
     });
-  },
+  }
 
   getRegistrationForWorker(form, registrations) {
     for (let registration of registrations) {
       if (registration.scope === form.scope) {
         return registration;
       }
     }
     return null;
-  },
+  }
 
   isE10S() {
     return Services.appinfo.browserTabsRemoteAutostart;
-  },
+  }
 
   renderServiceWorkersError() {
     let isWindowPrivate = PrivateBrowsingUtils.isContentWindowPrivate(window);
     let isPrivateBrowsingMode = PrivateBrowsingUtils.permanentPrivateBrowsing;
     let isServiceWorkerDisabled = !Services.prefs
                                     .getBoolPref("dom.serviceWorkers.enabled");
 
     let isDisabled = isWindowPrivate || isPrivateBrowsingMode || isServiceWorkerDisabled;
@@ -195,17 +207,17 @@ module.exports = createClass({
       dom.a(
         {
           href: MORE_INFO_URL,
           target: "_blank"
         },
         Strings.GetStringFromName("configurationIsNotCompatible.learnMore")
       ),
     );
-  },
+  }
 
   render() {
     let { client, id } = this.props;
     let { workers, processCount } = this.state;
 
     let isE10S = Services.appinfo.browserTabsRemoteAutostart;
     let isMultiE10S = isE10S && processCount > 1;
 
@@ -250,9 +262,11 @@ module.exports = createClass({
           name: Strings.GetStringFromName("otherWorkers"),
           sort: true,
           targetClass: WorkerTarget,
           targets: workers.other
         })
       )
     );
   }
-});
+}
+
+module.exports = WorkersPanel;
--- a/devtools/client/aboutdebugging/components/workers/ServiceWorkerTarget.js
+++ b/devtools/client/aboutdebugging/components/workers/ServiceWorkerTarget.js
@@ -1,161 +1,175 @@
 /* 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/. */
 
 /* eslint-env browser */
 
 "use strict";
 
-const { createClass, DOM: dom, PropTypes } =
+const { Component, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 const { debugWorker } = require("../../modules/worker");
 const Services = require("Services");
 
 loader.lazyRequireGetter(this, "DebuggerClient",
   "devtools/shared/client/debugger-client", true);
 
 const Strings = Services.strings.createBundle(
   "chrome://devtools/locale/aboutdebugging.properties");
 
-module.exports = createClass({
-  displayName: "ServiceWorkerTarget",
+class ServiceWorkerTarget extends Component {
+  static get propTypes() {
+    return {
+      client: PropTypes.instanceOf(DebuggerClient).isRequired,
+      debugDisabled: PropTypes.bool,
+      target: PropTypes.shape({
+        active: PropTypes.bool,
+        fetch: PropTypes.bool.isRequired,
+        icon: PropTypes.string,
+        name: PropTypes.string.isRequired,
+        url: PropTypes.string,
+        scope: PropTypes.string.isRequired,
+        // registrationActor can be missing in e10s.
+        registrationActor: PropTypes.string,
+        workerActor: PropTypes.string
+      }).isRequired
+    };
+  }
 
-  propTypes: {
-    client: PropTypes.instanceOf(DebuggerClient).isRequired,
-    debugDisabled: PropTypes.bool,
-    target: PropTypes.shape({
-      active: PropTypes.bool,
-      fetch: PropTypes.bool.isRequired,
-      icon: PropTypes.string,
-      name: PropTypes.string.isRequired,
-      url: PropTypes.string,
-      scope: PropTypes.string.isRequired,
-      // registrationActor can be missing in e10s.
-      registrationActor: PropTypes.string,
-      workerActor: PropTypes.string
-    }).isRequired
-  },
+  constructor(props) {
+    super(props);
 
-  getInitialState() {
-    return {
+    this.state = {
       pushSubscription: null
     };
-  },
+
+    this.debug = this.debug.bind(this);
+    this.push = this.push.bind(this);
+    this.start = this.start.bind(this);
+    this.unregister = this.unregister.bind(this);
+    this.onPushSubscriptionModified = this.onPushSubscriptionModified.bind(this);
+    this.updatePushSubscription = this.updatePushSubscription.bind(this);
+    this.isRunning = this.isRunning.bind(this);
+    this.isActive = this.isActive.bind(this);
+    this.getServiceWorkerStatus = this.getServiceWorkerStatus.bind(this);
+    this.renderButtons = this.renderButtons.bind(this);
+    this.renderUnregisterLink = this.renderUnregisterLink.bind(this);
+  }
 
   componentDidMount() {
     let { client } = this.props;
     client.addListener("push-subscription-modified", this.onPushSubscriptionModified);
     this.updatePushSubscription();
-  },
+  }
 
   componentDidUpdate(oldProps, oldState) {
     let wasActive = oldProps.target.active;
     if (!wasActive && this.isActive()) {
       // While the service worker isn't active, any calls to `updatePushSubscription`
       // won't succeed. If we just became active, make sure we didn't miss a push
       // subscription change by updating it now.
       this.updatePushSubscription();
     }
-  },
+  }
 
   componentWillUnmount() {
     let { client } = this.props;
     client.removeListener("push-subscription-modified", this.onPushSubscriptionModified);
-  },
+  }
 
   debug() {
     if (!this.isRunning()) {
       // If the worker is not running, we can't debug it.
       return;
     }
 
     let { client, target } = this.props;
     debugWorker(client, target.workerActor);
-  },
+  }
 
   push() {
     if (!this.isActive() || !this.isRunning()) {
       // If the worker is not running, we can't push to it.
       // If the worker is not active, the registration might be unavailable and the
       // push will not succeed.
       return;
     }
 
     let { client, target } = this.props;
     client.request({
       to: target.workerActor,
       type: "push"
     });
-  },
+  }
 
   start() {
     if (!this.isActive() || this.isRunning()) {
       // If the worker is not active or if it is already running, we can't start it.
       return;
     }
 
     let { client, target } = this.props;
     client.request({
       to: target.registrationActor,
       type: "start"
     });
-  },
+  }
 
   unregister() {
     let { client, target } = this.props;
     client.request({
       to: target.registrationActor,
       type: "unregister"
     });
-  },
+  }
 
   onPushSubscriptionModified(type, data) {
     let { target } = this.props;
     if (data.from === target.registrationActor) {
       this.updatePushSubscription();
     }
-  },
+  }
 
   updatePushSubscription() {
     if (!this.props.target.registrationActor) {
       // A valid registrationActor is needed to retrieve the push subscription.
       return;
     }
 
     let { client, target } = this.props;
     client.request({
       to: target.registrationActor,
       type: "getPushSubscription"
     }, ({ subscription }) => {
       this.setState({ pushSubscription: subscription });
     });
-  },
+  }
 
   isRunning() {
     // We know the target is running if it has a worker actor.
     return !!this.props.target.workerActor;
-  },
+  }
 
   isActive() {
     return this.props.target.active;
-  },
+  }
 
   getServiceWorkerStatus() {
     if (this.isActive() && this.isRunning()) {
       return "running";
     } else if (this.isActive()) {
       return "stopped";
     }
     // We cannot get service worker registrations unless the registration is in
     // ACTIVE state. Unable to know the actual state ("installing", "waiting"), we
     // display a custom state "registering" for now. See Bug 1153292.
     return "registering";
-  },
+  }
 
   renderButtons() {
     let pushButton = dom.button({
       className: "push-button",
       onClick: this.push,
       disabled: this.props.debugDisabled
     }, Strings.GetStringFromName("push"));
 
@@ -174,29 +188,29 @@ module.exports = createClass({
     if (this.isRunning()) {
       if (this.isActive()) {
         return [pushButton, debugButton];
       }
       // Only debug button is available if the service worker is not active.
       return debugButton;
     }
     return startButton;
-  },
+  }
 
   renderUnregisterLink() {
     if (!this.isActive()) {
       // If not active, there might be no registrationActor available.
       return null;
     }
 
     return dom.a({
       onClick: this.unregister,
       className: "unregister-link",
     }, Strings.GetStringFromName("unregister"));
-  },
+  }
 
   render() {
     let { target } = this.props;
     let { pushSubscription } = this.state;
     let status = this.getServiceWorkerStatus();
 
     let fetch = target.fetch ? Strings.GetStringFromName("listeningForFetchEvents") :
       Strings.GetStringFromName("notListeningForFetchEvents");
@@ -235,9 +249,11 @@ module.exports = createClass({
             }, target.scope),
             this.renderUnregisterLink()
           )
         )
       ),
       this.renderButtons()
     );
   }
-});
+}
+
+module.exports = ServiceWorkerTarget;
--- a/devtools/client/aboutdebugging/components/workers/Target.js
+++ b/devtools/client/aboutdebugging/components/workers/Target.js
@@ -1,44 +1,49 @@
 /* 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/. */
 
 /* eslint-env browser */
 
 "use strict";
 
-const { createClass, DOM: dom, PropTypes } =
+const { Component, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 const { debugWorker } = require("../../modules/worker");
 const Services = require("Services");
 
 loader.lazyRequireGetter(this, "DebuggerClient",
   "devtools/shared/client/debugger-client", true);
 
 const Strings = Services.strings.createBundle(
   "chrome://devtools/locale/aboutdebugging.properties");
 
-module.exports = createClass({
-  displayName: "WorkerTarget",
+class WorkerTarget extends Component {
+  static get propTypes() {
+    return {
+      client: PropTypes.instanceOf(DebuggerClient).isRequired,
+      debugDisabled: PropTypes.bool,
+      target: PropTypes.shape({
+        icon: PropTypes.string,
+        name: PropTypes.string.isRequired,
+        workerActor: PropTypes.string
+      }).isRequired
+    };
+  }
 
-  propTypes: {
-    client: PropTypes.instanceOf(DebuggerClient).isRequired,
-    debugDisabled: PropTypes.bool,
-    target: PropTypes.shape({
-      icon: PropTypes.string,
-      name: PropTypes.string.isRequired,
-      workerActor: PropTypes.string
-    }).isRequired
-  },
+  constructor(props) {
+    super(props);
+    this.debug = this.debug.bind(this);
+  }
 
   debug() {
     let { client, target } = this.props;
     debugWorker(client, target.workerActor);
-  },
+  }
 
   render() {
     let { target, debugDisabled } = this.props;
 
     return dom.li({ className: "target-container" },
       dom.img({
         className: "target-icon",
         role: "presentation",
@@ -49,9 +54,11 @@ module.exports = createClass({
       ),
       dom.button({
         className: "debug-button",
         onClick: this.debug,
         disabled: debugDisabled
       }, Strings.GetStringFromName("debug"))
     );
   }
-});
+}
+
+module.exports = WorkerTarget;