Bug 1257173 - Make JSON viewer code eslint clean; r=linclark
authorJan Odvarko <odvarko@gmail.com>
Thu, 17 Mar 2016 22:26:53 -0700
changeset 289232 cdcccf027c37873120a30baff31e501df33f61f0
parent 289231 cbefc1f9f9f6417e922d361b7c4ece108aa052fc
child 289233 0e729ba9f2bf518876ce87959ae4a95827f68935
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslinclark
bugs1257173
milestone48.0a1
Bug 1257173 - Make JSON viewer code eslint clean; r=linclark MozReview-Commit-ID: LUzs6Pb4c3z
.eslintignore
devtools/client/jsonview/.eslintrc
devtools/client/jsonview/components/headers-panel.js
devtools/client/jsonview/components/headers.js
devtools/client/jsonview/components/json-panel.js
devtools/client/jsonview/components/main-tabbed-area.js
devtools/client/jsonview/components/reps/tabs.js
devtools/client/jsonview/components/reps/toolbar.js
devtools/client/jsonview/components/reps/tree-view.js
devtools/client/jsonview/components/search-box.js
devtools/client/jsonview/components/text-panel.js
devtools/client/jsonview/converter-child.js
devtools/client/jsonview/converter-observer.js
devtools/client/jsonview/converter-sniffer.js
devtools/client/jsonview/json-viewer.js
devtools/client/jsonview/main.js
devtools/client/jsonview/test/browser_jsonview_copy_headers.js
devtools/client/jsonview/test/browser_jsonview_copy_json.js
devtools/client/jsonview/test/browser_jsonview_copy_rawdata.js
devtools/client/jsonview/test/browser_jsonview_filter.js
devtools/client/jsonview/test/browser_jsonview_invalid_json.js
devtools/client/jsonview/test/browser_jsonview_valid_json.js
devtools/client/jsonview/test/doc_frame_script.js
devtools/client/jsonview/test/head.js
devtools/client/jsonview/utils.js
devtools/client/jsonview/viewer-config.js
--- a/.eslintignore
+++ b/.eslintignore
@@ -85,17 +85,17 @@ devtools/client/eyedropper/**
 devtools/client/framework/**
 # devtools/client/inspector/shared/*.js files are eslint-clean, so they aren't
 # included in the ignore list.
 devtools/client/inspector/computed/**
 devtools/client/inspector/fonts/**
 devtools/client/inspector/shared/test/**
 devtools/client/inspector/test/**
 devtools/client/inspector/*.js
-devtools/client/jsonview/**
+devtools/client/jsonview/lib/**
 devtools/client/memory/**
 devtools/client/netmonitor/test/**
 devtools/client/netmonitor/har/test/**
 devtools/client/performance/**
 devtools/client/projecteditor/**
 devtools/client/promisedebugger/**
 devtools/client/responsivedesign/**
 devtools/client/scratchpad/**
new file mode 100644
--- /dev/null
+++ b/devtools/client/jsonview/.eslintrc
@@ -0,0 +1,9 @@
+{
+  "globals": {
+    "define": true,
+    "document": true,
+    "window": true,
+    "CustomEvent": true,
+    "Locale": true
+  }
+}
--- a/devtools/client/jsonview/components/headers-panel.js
+++ b/devtools/client/jsonview/components/headers-panel.js
@@ -1,69 +1,79 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-define(function(require, exports, module) {
+"use strict";
 
-const React = require("devtools/client/shared/vendor/react");
-const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
-const { Headers } = createFactories(require("./headers"));
-const { Toolbar, ToolbarButton } = createFactories(require("./reps/toolbar"));
+define(function(require, exports, module) {
+  const React = require("devtools/client/shared/vendor/react");
+  const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
+  const { Headers } = createFactories(require("./headers"));
+  const { Toolbar, ToolbarButton } = createFactories(require("./reps/toolbar"));
 
-const DOM = React.DOM;
+  const DOM = React.DOM;
 
-/**
- * This template represents the 'Headers' panel
- * s responsible for rendering its content.
- */
-var HeadersPanel = React.createClass({
-  displayName: "HeadersPanel",
+  /**
+   * This template represents the 'Headers' panel
+   * s responsible for rendering its content.
+   */
+  let HeadersPanel = React.createClass({
+    propTypes: {
+      actions: React.PropTypes.object,
+      data: React.PropTypes.object,
+    },
+
+    displayName: "HeadersPanel",
 
-  getInitialState: function() {
-    return {
-      data: {}
-    };
-  },
+    getInitialState: function() {
+      return {
+        data: {}
+      };
+    },
 
-  render: function() {
-    var data = this.props.data;
+    render: function() {
+      let data = this.props.data;
 
-    return (
-      DOM.div({className: "headersPanelBox"},
-        HeadersToolbar({actions: this.props.actions}),
-        DOM.div({className: "panelContent"},
-          Headers({data: data})
+      return (
+        DOM.div({className: "headersPanelBox"},
+          HeadersToolbar({actions: this.props.actions}),
+          DOM.div({className: "panelContent"},
+            Headers({data: data})
+          )
         )
-      )
-    );
-  }
-});
+      );
+    }
+  });
 
-/**
- * This template is responsible for rendering a toolbar
- * within the 'Headers' panel.
- */
-var HeadersToolbar = React.createFactory(React.createClass({
-  displayName: "HeadersToolbar",
+  /**
+   * This template is responsible for rendering a toolbar
+   * within the 'Headers' panel.
+   */
+  let HeadersToolbar = React.createFactory(React.createClass({
+    propTypes: {
+      actions: React.PropTypes.object,
+    },
+
+    displayName: "HeadersToolbar",
+
+    // Commands
 
-  render: function() {
-    return (
-      Toolbar({},
-        ToolbarButton({className: "btn copy", onClick: this.onCopy},
-          Locale.$STR("jsonViewer.Copy")
-        )
-      )
-    )
-  },
+    onCopy: function(event) {
+      this.props.actions.onCopyHeaders();
+    },
 
-  // Commands
+    render: function() {
+      return (
+        Toolbar({},
+          ToolbarButton({className: "btn copy", onClick: this.onCopy},
+            Locale.$STR("jsonViewer.Copy")
+          )
+        )
+      );
+    },
+  }));
 
-  onCopy: function(event) {
-    this.props.actions.onCopyHeaders();
-  },
-}));
-
-// Exports from this module
-exports.HeadersPanel = HeadersPanel;
+  // Exports from this module
+  exports.HeadersPanel = HeadersPanel;
 });
--- a/devtools/client/jsonview/components/headers.js
+++ b/devtools/client/jsonview/components/headers.js
@@ -1,100 +1,113 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+"use strict";
+
 define(function(require, exports, module) {
+  const React = require("devtools/client/shared/vendor/react");
+
+  // Constants
+  const DOM = React.DOM;
+  const PropTypes = React.PropTypes;
 
-const React = require("devtools/client/shared/vendor/react");
-
-// Constants
-const DOM = React.DOM;
+  /**
+   * This template is responsible for rendering basic layout
+   * of the 'Headers' panel. It displays HTTP headers groups such as
+   * received or response headers.
+   */
+  let Headers = React.createClass({
+    propTypes: {
+      data: PropTypes.object,
+    },
 
-/**
- * This template is responsible for rendering basic layout
- * of the 'Headers' panel. It displays HTTP headers groups such as
- * received or response headers.
- */
-var Headers = React.createClass({
-  displayName: "Headers",
+    displayName: "Headers",
+
+    getInitialState: function() {
+      return {};
+    },
+
+    render: function() {
+      let data = this.props.data;
 
-  getInitialState: function() {
-    return {};
-  },
-
-  render: function() {
-    var data = this.props.data;
-
-    return (
-      DOM.div({className: "netInfoHeadersTable"},
-        DOM.div({className: "netHeadersGroup"},
-          DOM.div({className: "netInfoHeadersGroup"},
-            DOM.span({className: "netHeader twisty"},
-              Locale.$STR("jsonViewer.responseHeaders")
+      return (
+        DOM.div({className: "netInfoHeadersTable"},
+          DOM.div({className: "netHeadersGroup"},
+            DOM.div({className: "netInfoHeadersGroup"},
+              DOM.span({className: "netHeader twisty"},
+                Locale.$STR("jsonViewer.responseHeaders")
+              )
+            ),
+            DOM.table({cellPadding: 0, cellSpacing: 0},
+              HeaderList({headers: data.response})
             )
           ),
-          DOM.table({cellPadding: 0, cellSpacing: 0},
-            HeaderList({headers: data.response})
-          )
-        ),
-        DOM.div({className: "netHeadersGroup"},
-          DOM.div({className: "netInfoHeadersGroup"},
-            DOM.span({className: "netHeader twisty"},
-              Locale.$STR("jsonViewer.requestHeaders")
+          DOM.div({className: "netHeadersGroup"},
+            DOM.div({className: "netInfoHeadersGroup"},
+              DOM.span({className: "netHeader twisty"},
+                Locale.$STR("jsonViewer.requestHeaders")
+              )
+            ),
+            DOM.table({cellPadding: 0, cellSpacing: 0},
+              HeaderList({headers: data.request})
             )
-          ),
-          DOM.table({cellPadding: 0, cellSpacing: 0},
-            HeaderList({headers: data.request})
           )
         )
-      )
-    );
-  }
-});
-
-/**
- * This template renders headers list,
- * name + value pairs.
- */
-var HeaderList = React.createFactory(React.createClass({
-  displayName: "HeaderList",
+      );
+    }
+  });
 
-  getInitialState: function() {
-    return {
-      headers: []
-    };
-  },
+  /**
+   * This template renders headers list,
+   * name + value pairs.
+   */
+  let HeaderList = React.createFactory(React.createClass({
+    propTypes: {
+      headers: PropTypes.arrayOf(PropTypes.shape({
+        name: PropTypes.string,
+        value: PropTypes.string
+      }))
+    },
 
-  render: function() {
-    var headers = this.props.headers;
+    displayName: "HeaderList",
 
-    headers.sort(function(a, b) {
-      return a.name > b.name ? 1 : -1;
-    });
+    getInitialState: function() {
+      return {
+        headers: []
+      };
+    },
+
+    render: function() {
+      let headers = this.props.headers;
 
-    var rows = [];
-    headers.forEach(header => {
-      rows.push(
-        DOM.tr({key: header.name},
-          DOM.td({className: "netInfoParamName"},
-            DOM.span({title: header.name}, header.name)
-          ),
-          DOM.td({className: "netInfoParamValue"},
-            DOM.code({}, header.value)
+      headers.sort(function(a, b) {
+        return a.name > b.name ? 1 : -1;
+      });
+
+      let rows = [];
+      headers.forEach(header => {
+        rows.push(
+          DOM.tr({key: header.name},
+            DOM.td({className: "netInfoParamName"},
+              DOM.span({title: header.name}, header.name)
+            ),
+            DOM.td({className: "netInfoParamValue"},
+              DOM.code({}, header.value)
+            )
           )
+        );
+      });
+
+      return (
+        DOM.tbody({},
+          rows
         )
-      )
-    });
+      );
+    }
+  }));
 
-    return (
-      DOM.tbody({},
-        rows
-      )
-    )
-  }
-}));
-
-// Exports from this module
-exports.Headers = Headers;
+  // Exports from this module
+  exports.Headers = Headers;
 });
--- a/devtools/client/jsonview/components/json-panel.js
+++ b/devtools/client/jsonview/components/json-panel.js
@@ -1,108 +1,123 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-define(function(require, exports, module) {
+"use strict";
 
-const React = require("devtools/client/shared/vendor/react");
-const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
-const { TreeView } = createFactories(require("./reps/tree-view"));
-const { SearchBox } = createFactories(require("./search-box"));
-const { Toolbar, ToolbarButton } = createFactories(require("./reps/toolbar"));
-const DOM = React.DOM;
+define(function(require, exports, module) {
+  const React = require("devtools/client/shared/vendor/react");
+  const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
+  const { TreeView } = createFactories(require("./reps/tree-view"));
+  const { SearchBox } = createFactories(require("./search-box"));
+  const { Toolbar, ToolbarButton } = createFactories(require("./reps/toolbar"));
+  const DOM = React.DOM;
 
-/**
- * This template represents the 'JSON' panel. The panel is
- * responsible for rendering an expandable tree that allows simple
- * inspection of JSON structure.
- */
-var JsonPanel = React.createClass({
-  displayName: "JsonPanel",
+  /**
+   * This template represents the 'JSON' panel. The panel is
+   * responsible for rendering an expandable tree that allows simple
+   * inspection of JSON structure.
+   */
+  let JsonPanel = React.createClass({
+    propTypes: {
+      data: React.PropTypes.oneOfType([
+        React.PropTypes.string,
+        React.PropTypes.array,
+        React.PropTypes.object
+      ]),
+      searchFilter: React.PropTypes.string,
+      actions: React.PropTypes.object,
+    },
 
-  getInitialState: function() {
-    return {};
-  },
+    displayName: "JsonPanel",
+
+    getInitialState: function() {
+      return {};
+    },
 
-  componentDidMount: function() {
-    document.addEventListener("keypress", this.onKeyPress, true);
-  },
+    componentDidMount: function() {
+      document.addEventListener("keypress", this.onKeyPress, true);
+    },
+
+    componentWillUnmount: function() {
+      document.removeEventListener("keypress", this.onKeyPress, true);
+    },
 
-  componentWillUnmount: function() {
-    document.removeEventListener("keypress", this.onKeyPress, true);
-  },
+    onKeyPress: function(e) {
+      // XXX shortcut for focusing the Filter field (see Bug 1178771).
+    },
 
-  onKeyPress: function(e) {
-    // XXX shortcut for focusing the Filter field (see Bug 1178771).
-  },
+    render: function() {
+      let content;
+      let data = this.props.data;
 
-  render: function() {
-    var content;
-    var data = this.props.data;
-
-    try {
-      if (typeof data == "object") {
-        content = TreeView({
-          data: this.props.data,
-          mode: "tiny",
-          searchFilter: this.props.searchFilter
-        });
-      } else {
+      try {
+        if (typeof data == "object") {
+          content = TreeView({
+            data: this.props.data,
+            mode: "tiny",
+            searchFilter: this.props.searchFilter
+          });
+        } else {
+          content = DOM.div({className: "jsonParseError"},
+            data + ""
+          );
+        }
+      } catch (err) {
         content = DOM.div({className: "jsonParseError"},
-          data + ""
+          err + ""
         );
       }
-    } catch (err) {
-      content = DOM.div({className: "jsonParseError"},
-        err + ""
+
+      return (
+        DOM.div({className: "jsonPanelBox"},
+          JsonToolbar({actions: this.props.actions}),
+          DOM.div({className: "panelContent"},
+            content
+          )
+        )
       );
     }
+  });
 
-    return (
-      DOM.div({className: "jsonPanelBox"},
-        JsonToolbar({actions: this.props.actions}),
-        DOM.div({className: "panelContent"},
-          content
-        )
-      )
-    );
-  }
-});
+  /**
+   * This template represents a toolbar within the 'JSON' panel.
+   */
+  let JsonToolbar = React.createFactory(React.createClass({
+    propTypes: {
+      actions: React.PropTypes.object,
+    },
 
-/**
- * This template represents a toolbar within the 'JSON' panel.
- */
-var JsonToolbar = React.createFactory(React.createClass({
-  displayName: "JsonToolbar",
+    displayName: "JsonToolbar",
+
+    // Commands
+
+    onSave: function(event) {
+      this.props.actions.onSaveJson();
+    },
 
-  render: function() {
-    return (
-      Toolbar({},
-        ToolbarButton({className: "btn save", onClick: this.onSave},
-          Locale.$STR("jsonViewer.Save")
-        ),
-        ToolbarButton({className: "btn copy", onClick: this.onCopy},
-          Locale.$STR("jsonViewer.Copy")
-        ),
-        SearchBox({
-          actions: this.props.actions
-        })
-      )
-    )
-  },
+    onCopy: function(event) {
+      this.props.actions.onCopyJson();
+    },
 
-  // Commands
-
-  onSave: function(event) {
-    this.props.actions.onSaveJson();
-  },
+    render: function() {
+      return (
+        Toolbar({},
+          ToolbarButton({className: "btn save", onClick: this.onSave},
+            Locale.$STR("jsonViewer.Save")
+          ),
+          ToolbarButton({className: "btn copy", onClick: this.onCopy},
+            Locale.$STR("jsonViewer.Copy")
+          ),
+          SearchBox({
+            actions: this.props.actions
+          })
+        )
+      );
+    },
+  }));
 
-  onCopy: function(event) {
-    this.props.actions.onCopyJson();
-  },
-}));
-
-// Exports from this module
-exports.JsonPanel = JsonPanel;
+  // Exports from this module
+  exports.JsonPanel = JsonPanel;
 });
--- a/devtools/client/jsonview/components/main-tabbed-area.js
+++ b/devtools/client/jsonview/components/main-tabbed-area.js
@@ -2,67 +2,87 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 define(function(require, exports, module) {
-
-const React = require("devtools/client/shared/vendor/react");
-const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
-const { JsonPanel } = createFactories(require("./json-panel"));
-const { TextPanel } = createFactories(require("./text-panel"));
-const { HeadersPanel } = createFactories(require("./headers-panel"));
-const { Tabs, TabPanel } = createFactories(require("./reps/tabs"));
+  const React = require("devtools/client/shared/vendor/react");
+  const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
+  const { JsonPanel } = createFactories(require("./json-panel"));
+  const { TextPanel } = createFactories(require("./text-panel"));
+  const { HeadersPanel } = createFactories(require("./headers-panel"));
+  const { Tabs, TabPanel } = createFactories(require("./reps/tabs"));
 
-/**
- * This object represents the root application template
- * responsible for rendering the basic tab layout.
- */
-var MainTabbedArea = React.createClass({
-  displayName: "MainTabbedArea",
+  /**
+   * This object represents the root application template
+   * responsible for rendering the basic tab layout.
+   */
+  let MainTabbedArea = React.createClass({
+    propTypes: {
+      jsonText: React.PropTypes.string,
+      tabActive: React.PropTypes.number,
+      actions: React.PropTypes.object,
+      headers: React.PropTypes.object,
+      searchFilter: React.PropTypes.string,
+      json: React.PropTypes.oneOfType([
+        React.PropTypes.string,
+        React.PropTypes.object,
+        React.PropTypes.array
+      ])
+    },
 
-  getInitialState: function() {
-    return {
-      json: {},
-      headers: {},
-      jsonText: this.props.jsonText,
-      tabActive: this.props.tabActive
-   };
-  },
+    displayName: "MainTabbedArea",
 
-  onTabChanged: function(index) {
-    this.setState({tabActive: index});
-  },
+    getInitialState: function() {
+      return {
+        json: {},
+        headers: {},
+        jsonText: this.props.jsonText,
+        tabActive: this.props.tabActive
+      };
+    },
+
+    onTabChanged: function(index) {
+      this.setState({tabActive: index});
+    },
 
-  render: function() {
-    return (
-      Tabs({tabActive: this.state.tabActive, onAfterChange: this.onTabChanged},
-        TabPanel({className: "json", title: Locale.$STR("jsonViewer.tab.JSON")},
-          JsonPanel({
-            data: this.props.json,
-            actions: this.props.actions,
-            searchFilter: this.state.searchFilter
-          })
-        ),
-        TabPanel({className: "rawdata", title: Locale.$STR("jsonViewer.tab.RawData")},
-          TextPanel({
-            data: this.state.jsonText,
-            actions: this.props.actions
-          })
-        ),
-        TabPanel({className: "headers", title: Locale.$STR("jsonViewer.tab.Headers")},
-          HeadersPanel({
-            data: this.props.headers,
-            actions: this.props.actions,
-            searchFilter: this.props.searchFilter
-          })
+    render: function() {
+      return (
+        Tabs({
+          tabActive: this.state.tabActive,
+          onAfterChange: this.onTabChanged},
+          TabPanel({
+            className: "json",
+            title: Locale.$STR("jsonViewer.tab.JSON")},
+            JsonPanel({
+              data: this.props.json,
+              actions: this.props.actions,
+              searchFilter: this.state.searchFilter
+            })
+          ),
+          TabPanel({
+            className: "rawdata",
+            title: Locale.$STR("jsonViewer.tab.RawData")},
+            TextPanel({
+              data: this.state.jsonText,
+              actions: this.props.actions
+            })
+          ),
+          TabPanel({
+            className: "headers",
+            title: Locale.$STR("jsonViewer.tab.Headers")},
+            HeadersPanel({
+              data: this.props.headers,
+              actions: this.props.actions,
+              searchFilter: this.props.searchFilter
+            })
+          )
         )
-      )
-    )
-  }
+      );
+    }
+  });
+
+  // Exports from this module
+  exports.MainTabbedArea = MainTabbedArea;
 });
-
-// Exports from this module
-exports.MainTabbedArea = MainTabbedArea;
-});
--- a/devtools/client/jsonview/components/reps/tabs.js
+++ b/devtools/client/jsonview/components/reps/tabs.js
@@ -2,191 +2,190 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 define(function(require, exports, module) {
-
-const React = require("devtools/client/shared/vendor/react");
-const DOM = React.DOM;
+  const React = require("devtools/client/shared/vendor/react");
+  const DOM = React.DOM;
 
-/**
- * Renders simple 'tab' widget.
- *
- * Based on ReactSimpleTabs component
- * https://github.com/pedronauck/react-simpletabs
- *
- * Component markup (+CSS) example:
- *
- * <div class='tabs'>
- *  <nav class='tabs-navigation'>
- *    <ul class='tabs-menu'>
- *      <li class='tabs-menu-item is-active'>Tab #1</li>
- *      <li class='tabs-menu-item'>Tab #2</li>
- *    </ul>
- *  </nav>
- *  <article class='tab-panel'>
- *    The content of active panel here
- *  </article>
- * <div>
- */
-var Tabs = React.createClass({
-  displayName: "Tabs",
+  /**
+   * Renders simple 'tab' widget.
+   *
+   * Based on ReactSimpleTabs component
+   * https://github.com/pedronauck/react-simpletabs
+   *
+   * Component markup (+CSS) example:
+   *
+   * <div class='tabs'>
+   *  <nav class='tabs-navigation'>
+   *    <ul class='tabs-menu'>
+   *      <li class='tabs-menu-item is-active'>Tab #1</li>
+   *      <li class='tabs-menu-item'>Tab #2</li>
+   *    </ul>
+   *  </nav>
+   *  <article class='tab-panel'>
+   *    The content of active panel here
+   *  </article>
+   * <div>
+   */
+  let Tabs = React.createClass({
+    propTypes: {
+      className: React.PropTypes.oneOfType([
+        React.PropTypes.array,
+        React.PropTypes.string,
+        React.PropTypes.object
+      ]),
+      tabActive: React.PropTypes.number,
+      onMount: React.PropTypes.func,
+      onBeforeChange: React.PropTypes.func,
+      onAfterChange: React.PropTypes.func,
+      children: React.PropTypes.oneOfType([
+        React.PropTypes.array,
+        React.PropTypes.element
+      ]).isRequired
+    },
 
-  propTypes: {
-    className: React.PropTypes.oneOfType([
-      React.PropTypes.array,
-      React.PropTypes.string,
-      React.PropTypes.object
-    ]),
-    tabActive: React.PropTypes.number,
-    onMount: React.PropTypes.func,
-    onBeforeChange: React.PropTypes.func,
-    onAfterChange: React.PropTypes.func,
-    children: React.PropTypes.oneOfType([
-      React.PropTypes.array,
-      React.PropTypes.element
-    ]).isRequired
-  },
+    displayName: "Tabs",
 
-  getDefaultProps: function () {
-    return {
-      tabActive: 1
-    };
-  },
+    getDefaultProps: function() {
+      return {
+        tabActive: 1
+      };
+    },
 
-  getInitialState: function () {
-    return {
-      tabActive: this.props.tabActive
-    };
-  },
+    getInitialState: function() {
+      return {
+        tabActive: this.props.tabActive
+      };
+    },
 
-  componentDidMount: function() {
-    var index = this.state.tabActive;
-    if (this.props.onMount) {
-      this.props.onMount(index);
-    }
-  },
+    componentDidMount: function() {
+      let index = this.state.tabActive;
+      if (this.props.onMount) {
+        this.props.onMount(index);
+      }
+    },
 
-  componentWillReceiveProps: function(newProps){
-    if (newProps.tabActive) {
-      this.setState({tabActive: newProps.tabActive})
-    }
-  },
+    componentWillReceiveProps: function(newProps) {
+      if (newProps.tabActive) {
+        this.setState({tabActive: newProps.tabActive});
+      }
+    },
 
-  render: function () {
-    var classNames = ["tabs", this.props.className].join(" ");
+    setActive: function(index, e) {
+      let onAfterChange = this.props.onAfterChange;
+      let onBeforeChange = this.props.onBeforeChange;
 
-    return (
-      DOM.div({className: classNames},
-        this.getMenuItems(),
-        this.getSelectedPanel()
-      )
-    );
-  },
+      if (onBeforeChange) {
+        let cancel = onBeforeChange(index);
+        if (cancel) {
+          return;
+        }
+      }
 
-  setActive: function(index, e) {
-    var onAfterChange = this.props.onAfterChange;
-    var onBeforeChange = this.props.onBeforeChange;
+      let newState = {
+        tabActive: index
+      };
 
-    if (onBeforeChange) {
-      var cancel = onBeforeChange(index);
-      if (cancel) {
-        return;
-      }
-    }
+      this.setState(newState, () => {
+        if (onAfterChange) {
+          onAfterChange(index);
+        }
+      });
+
+      e.preventDefault();
+    },
 
-    var newState = {
-      tabActive: index
-    };
+    getMenuItems: function() {
+      if (!this.props.children) {
+        throw new Error("Tabs must contain at least one Panel");
+      }
 
-    this.setState(newState, () => {
-      if (onAfterChange) {
-        onAfterChange(index);
+      if (!Array.isArray(this.props.children)) {
+        this.props.children = [this.props.children];
       }
-    });
 
-    e.preventDefault();
-  },
-
-  getMenuItems: function () {
-    if (!this.props.children) {
-      throw new Error("Tabs must contain at least one Panel");
-    }
-
-    if (!Array.isArray(this.props.children)) {
-      this.props.children = [this.props.children];
-    }
+      let menuItems = this.props.children
+        .map(function(panel) {
+          return typeof panel === "function" ? panel() : panel;
+        }).filter(function(panel) {
+          return panel;
+        }).map(function(panel, index) {
+          let ref = ("tab-menu-" + (index + 1));
+          let title = panel.props.title;
+          let tabClassName = panel.props.className;
 
-    var menuItems = this.props.children
-      .map(function(panel) {
-        return typeof panel === "function" ? panel() : panel;
-      }).filter(function(panel) {
-        return panel;
-      }).map(function(panel, index) {
-        var ref = ("tab-menu-" + (index + 1));
-        var title = panel.props.title;
-        var tabClassName = panel.props.className;
+          let classes = [
+            "tabs-menu-item",
+            tabClassName,
+            this.state.tabActive === (index + 1) && "is-active"
+          ].join(" ");
 
-        var classes = [
-          "tabs-menu-item",
-          tabClassName,
-          this.state.tabActive === (index + 1) && "is-active"
-        ].join(" ");
+          return (
+            DOM.li({ref: ref, key: index, className: classes},
+              DOM.a({href: "#", onClick: this.setActive.bind(this, index + 1)},
+                title
+              )
+            )
+          );
+        }.bind(this));
 
-        return (
-          DOM.li({ref: ref, key: index, className: classes},
-            DOM.a({href: "#", onClick: this.setActive.bind(this, index + 1)},
-              title
-            )
+      return (
+        DOM.nav({className: "tabs-navigation"},
+          DOM.ul({className: "tabs-menu"},
+            menuItems
           )
-        );
-      }.bind(this));
+        )
+      );
+    },
 
-    return (
-      DOM.nav({className: "tabs-navigation"},
-        DOM.ul({className: "tabs-menu"},
-          menuItems
+    getSelectedPanel: function() {
+      let index = this.state.tabActive - 1;
+      let panel = this.props.children[index];
+
+      return (
+        DOM.article({ref: "tab-panel", className: "tab-panel"},
+          panel
         )
-      )
-    );
-  },
+      );
+    },
 
-  getSelectedPanel: function () {
-    var index = this.state.tabActive - 1;
-    var panel = this.props.children[index];
+    render: function() {
+      let classNames = ["tabs", this.props.className].join(" ");
 
-    return (
-      DOM.article({ref: "tab-panel", className: "tab-panel"},
-        panel
-      )
-    );
-  }
-});
+      return (
+        DOM.div({className: classNames},
+          this.getMenuItems(),
+          this.getSelectedPanel()
+        )
+      );
+    },
+  });
 
-/**
- * Renders simple tab 'panel'.
- */
-var Panel = React.createClass({
-  displayName: "Panel",
+  /**
+   * Renders simple tab 'panel'.
+   */
+  let Panel = React.createClass({
+    propTypes: {
+      title: React.PropTypes.string.isRequired,
+      children: React.PropTypes.oneOfType([
+        React.PropTypes.array,
+        React.PropTypes.element
+      ]).isRequired
+    },
 
-  propTypes: {
-    title: React.PropTypes.string.isRequired,
-    children: React.PropTypes.oneOfType([
-      React.PropTypes.array,
-      React.PropTypes.element
-    ]).isRequired
-  },
+    displayName: "Panel",
 
-  render: function () {
-    return DOM.div({},
-      this.props.children
-    );
-  }
+    render: function() {
+      return DOM.div({},
+        this.props.children
+      );
+    }
+  });
+
+  // Exports from this module
+  exports.TabPanel = Panel;
+  exports.Tabs = Tabs;
 });
-
-// Exports from this module
-exports.TabPanel = Panel;
-exports.Tabs = Tabs;
-});
--- a/devtools/client/jsonview/components/reps/toolbar.js
+++ b/devtools/client/jsonview/components/reps/toolbar.js
@@ -2,50 +2,57 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 define(function(require, exports, module) {
-
-const React = require("devtools/client/shared/vendor/react");
-const DOM = React.DOM;
+  const React = require("devtools/client/shared/vendor/react");
+  const DOM = React.DOM;
 
-/**
- * Renders a simple toolbar.
- */
-var Toolbar = React.createClass({
-  displayName: "Toolbar",
+  /**
+   * Renders a simple toolbar.
+   */
+  let Toolbar = React.createClass({
+    propTypes: {
+      children: React.PropTypes.oneOfType([
+        React.PropTypes.array,
+        React.PropTypes.element
+      ])
+    },
 
-  render: function() {
-    return (
-      DOM.div({className: "toolbar"},
-        this.props.children
-      )
-    );
-  }
-});
+    displayName: "Toolbar",
+
+    render: function() {
+      return (
+        DOM.div({className: "toolbar"},
+          this.props.children
+        )
+      );
+    }
+  });
 
-/**
- * Renders a simple toolbar button.
- */
-var ToolbarButton = React.createClass({
-  displayName: "ToolbarButton",
+  /**
+   * Renders a simple toolbar button.
+   */
+  let ToolbarButton = React.createClass({
+    propTypes: {
+      active: React.PropTypes.bool,
+      disabled: React.PropTypes.bool,
+      children: React.PropTypes.string,
+    },
 
-  propTypes: {
-    active: React.PropTypes.bool,
-    disabled: React.PropTypes.bool,
-  },
+    displayName: "ToolbarButton",
 
-  render: function() {
-    var props = Object.assign({className: "btn"}, this.props);
-    return (
-      DOM.button(props, this.props.children)
-    );
-  },
+    render: function() {
+      let props = Object.assign({className: "btn"}, this.props);
+      return (
+        DOM.button(props, this.props.children)
+      );
+    },
+  });
+
+  // Exports from this module
+  exports.Toolbar = Toolbar;
+  exports.ToolbarButton = ToolbarButton;
 });
-
-// Exports from this module
-exports.Toolbar = Toolbar;
-exports.ToolbarButton = ToolbarButton;
-});
--- a/devtools/client/jsonview/components/reps/tree-view.js
+++ b/devtools/client/jsonview/components/reps/tree-view.js
@@ -1,261 +1,267 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+"use strict";
+
 define(function(require, exports, module) {
+  // Dependencies
+  const React = require("devtools/client/shared/vendor/react");
+  const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
+  const { Rep } = createFactories(require("devtools/client/shared/components/reps/rep"));
+  const { StringRep } = require("devtools/client/shared/components/reps/string");
+  const DOM = React.DOM;
+
+  let uid = 0;
+
+  /**
+   * Renders a tree view with expandable/collapsible items.
+   */
+  let TreeView = React.createClass({
+    propTypes: {
+      searchFilter: React.PropTypes.string,
+      data: React.PropTypes.any,
+      mode: React.PropTypes.string,
+    },
+
+    displayName: "TreeView",
 
-// Dependencies
-const React = require("devtools/client/shared/vendor/react");
-const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
-const { Rep } = createFactories(require("devtools/client/shared/components/reps/rep"));
-const { StringRep } = require("devtools/client/shared/components/reps/string");
-const DOM = React.DOM;
+    getInitialState: function() {
+      return {
+        data: {},
+        searchFilter: null
+      };
+    },
+
+    // Data
 
-var uid = 0;
+    componentDidMount: function() {
+      let members = initMembers(this.props.data, 0);
+      this.setState({ // eslint-disable-line
+        data: members,
+        searchFilter:
+        this.props.searchFilter
+      });
+    },
+
+    componentWillReceiveProps: function(nextProps) {
+      let updatedState = {
+        searchFilter: nextProps.searchFilter
+      };
+
+      if (this.props.data !== nextProps.data) {
+        updatedState.data = initMembers(nextProps.data, 0);
+      }
+
+      this.setState(updatedState);
+    },
+
+    // Rendering
 
-/**
- * Renders a tree view with expandable/collapsible items.
- */
-var TreeView = React.createClass({
-  displayName: "TreeView",
+    render: function() {
+      let mode = this.props.mode;
+      let root = this.state.data;
+
+      let children = [];
+
+      if (Array.isArray(root)) {
+        for (let i = 0; i < root.length; i++) {
+          let child = root[i];
+          children.push(TreeNode({
+            key: child.key,
+            data: child,
+            mode: mode,
+            searchFilter: this.state.searchFilter || this.props.searchFilter
+          }));
+        }
+      } else {
+        children.push(React.addons.createFragment(root));
+      }
+
+      return (
+        DOM.div({className: "domTable", cellPadding: 0, cellSpacing: 0},
+          children
+        )
+      );
+    },
+  });
 
-  getInitialState: function() {
-    return {
-      data: {},
-      searchFilter: null
-    };
-  },
+  /**
+   * Represents a node within the tree.
+   */
+  let TreeNode = React.createFactory(React.createClass({
+    propTypes: {
+      searchFilter: React.PropTypes.string,
+      data: React.PropTypes.object,
+      mode: React.PropTypes.string,
+    },
+
+    displayName: "TreeNode",
 
-  // Rendering
+    getInitialState: function() {
+      return {
+        data: this.props.data,
+        searchFilter: null
+      };
+    },
 
-  render: function() {
-    var mode = this.props.mode;
-    var root = this.state.data;
+    onClick: function(e) {
+      let member = this.state.data;
+      member.open = !member.open;
 
-    var children = [];
+      this.setState({data: member});
+
+      e.stopPropagation();
+    },
 
-    if (Array.isArray(root)) {
-      for (var i=0; i<root.length; i++) {
-        var child = root[i];
-        children.push(TreeNode({
-          key: child.key,
-          data: child,
-          mode: mode,
-          searchFilter: this.state.searchFilter || this.props.searchFilter
-        }));
+    render: function() {
+      let member = this.state.data;
+      let mode = this.props.mode;
+
+      let classNames = ["memberRow"];
+      classNames.push(member.type + "Row");
+
+      if (member.hasChildren) {
+        classNames.push("hasChildren");
+      }
+
+      if (member.open) {
+        classNames.push("opened");
+      }
+
+      if (!member.children) {
+        // Cropped strings are expandable, but they don't have children.
+        let isString = typeof (member.value) == "string";
+        if (member.hasChildren && !isString) {
+          member.children = initMembers(member.value);
+        } else {
+          member.children = [];
+        }
       }
-    } else {
-      children.push(React.addons.createFragment(root));
-    }
+
+      let children = [];
+      if (member.open && member.children.length) {
+        for (let i in member.children) {
+          let child = member.children[i];
+          children.push(TreeNode({
+            key: child.key,
+            data: child,
+            mode: mode,
+            searchFilter: this.state.searchFilter || this.props.searchFilter
+          }));
+        }
+      }
+
+      let filter = this.props.searchFilter || "";
+      let name = member.name || "";
+      let value = member.value || "";
+
+      // Filtering is case-insensitive
+      filter = filter.toLowerCase();
+      name = name.toLowerCase();
+
+      if (filter && (name.indexOf(filter) < 0)) {
+        // Cache the stringify result, so the filtering is fast
+        // the next time.
+        if (!member.valueString) {
+          member.valueString = JSON.stringify(value).toLowerCase();
+        }
+
+        if (member.valueString && member.valueString.indexOf(filter) < 0) {
+          classNames.push("hidden");
+        }
+      }
 
-    return (
-      DOM.div({className: "domTable", cellPadding: 0, cellSpacing: 0},
-        children
-      )
-    );
-  },
+      return (
+        DOM.div({className: classNames.join(" ")},
+          DOM.span({className: "memberLabelCell", onClick: this.onClick},
+            DOM.span({className: "memberIcon"}),
+            DOM.span({className: "memberLabel " + member.type + "Label"},
+              member.name)
+          ),
+          DOM.span({className: "memberValueCell"},
+            DOM.span({},
+              Rep({
+                object: member.value,
+                mode: this.props.mode,
+                member: member
+              })
+            )
+          ),
+          DOM.div({className: "memberChildren"},
+            children
+          )
+        )
+      );
+    },
+  }));
 
-  // Data
+  // Helpers
 
-  componentDidMount: function() {
-    var members = initMembers(this.props.data, 0);
-    this.setState({data: members, searchFilter: this.props.searchFilter});
-  },
+  function initMembers(parent) {
+    let members = getMembers(parent);
+    return members;
+  }
+
+  function getMembers(object) {
+    let members = [];
+    getObjectProperties(object, function(prop, value) {
+      let valueType = typeof (value);
+      let hasChildren = (valueType === "object" && hasProperties(value));
+
+      // Cropped strings are expandable, so the user can see the
+      // entire original value.
+      if (StringRep.isCropped(value)) {
+        hasChildren = true;
+      }
 
-  componentWillReceiveProps: function(nextProps) {
-    var updatedState = {
-      searchFilter: nextProps.searchFilter
+      let type = getType(value);
+      let member = createMember(type, prop, value, hasChildren);
+      members.push(member);
+    });
+
+    return members;
+  }
+
+  function createMember(type, name, value, hasChildren) {
+    let member = {
+      name: name,
+      type: type,
+      rowClass: "memberRow-" + type,
+      hasChildren: hasChildren,
+      value: value,
+      open: false,
+      key: uid++
     };
 
-    if (this.props.data !== nextProps.data) {
-      updatedState.data = initMembers(nextProps.data, 0);
-    }
-
-    this.setState(updatedState);
+    return member;
   }
-});
-
-/**
- * Represents a node within the tree.
- */
-var TreeNode = React.createFactory(React.createClass({
-  displayName: "TreeNode",
-
-  getInitialState: function() {
-    return { data: {}, searchFilter: null };
-  },
-
-  componentDidMount: function() {
-    this.setState({data: this.props.data});
-  },
 
-  render: function() {
-    var member = this.state.data;
-    var mode = this.props.mode;
-
-    var classNames = ["memberRow"];
-    classNames.push(member.type + "Row");
-
-    if (member.hasChildren) {
-      classNames.push("hasChildren");
-    }
-
-    if (member.open) {
-      classNames.push("opened");
-    }
-
-    if (!member.children) {
-      // Cropped strings are expandable, but they don't have children.
-      var isString = typeof(member.value) == "string";
-      if (member.hasChildren && !isString) {
-        member.children = initMembers(member.value);
-      } else {
-        member.children = [];
+  function getObjectProperties(obj, callback) {
+    for (let p in obj) {
+      try {
+        callback.call(this, p, obj[p]);
+      } catch (e) {
+        // Ignore
       }
     }
+  }
 
-    var children = [];
-    if (member.open && member.children.length) {
-      for (var i in member.children) {
-        var child = member.children[i];
-        children.push(TreeNode({
-          key: child.key,
-          data: child,
-          mode: mode,
-          searchFilter: this.state.searchFilter || this.props.searchFilter
-        }));
-      };
+  function hasProperties(obj) {
+    if (typeof (obj) == "string") {
+      return false;
     }
 
-    var filter = this.props.searchFilter || "";
-    var name = member.name || "";
-    var value = member.value || "";
-
-    // Filtering is case-insensitive
-    filter = filter.toLowerCase();
-    name = name.toLowerCase();
-
-    if (filter && (name.indexOf(filter) < 0)) {
-      // Cache the stringify result, so the filtering is fast
-      // the next time.
-      if (!member.valueString) {
-        member.valueString = JSON.stringify(value).toLowerCase();
-      }
-
-      if (member.valueString && member.valueString.indexOf(filter) < 0) {
-        classNames.push("hidden");
-      }
-    }
-
-    return (
-      DOM.div({className: classNames.join(" ")},
-        DOM.span({className: "memberLabelCell", onClick: this.onClick},
-          DOM.span({className: "memberIcon"}),
-          DOM.span({className: "memberLabel " + member.type + "Label"},
-            member.name)
-        ),
-        DOM.span({className: "memberValueCell"},
-          DOM.span({},
-            Rep({
-              object: member.value,
-              mode: this.props.mode,
-              member: member
-            })
-          )
-        ),
-        DOM.div({className: "memberChildren"},
-          children
-        )
-      )
-    )
-  },
-
-  onClick: function(e) {
-    var member = this.state.data;
-    member.open = !member.open;
-
-    this.setState({data: member});
-
-    e.stopPropagation();
-  },
-}));
-
-// Helpers
-
-function initMembers(parent) {
-  var members = getMembers(parent);
-  return members;
-}
-
-function getMembers(object) {
-  var members = [];
-  getObjectProperties(object, function(prop, value) {
-    var valueType = typeof(value);
-    var hasChildren = (valueType === "object" && hasProperties(value));
-
-    // Cropped strings are expandable, so the user can see the
-    // entire original value.
-    if (StringRep.isCropped(value)) {
-      hasChildren = true;
-    }
-
-    var type = getType(value);
-    var member = createMember(type, prop, value, hasChildren);
-    members.push(member);
-  });
-
-  return members;
-}
-
-function createMember(type, name, value, hasChildren) {
-  var member = {
-    name: name,
-    type: type,
-    rowClass: "memberRow-" + type,
-    open: "",
-    hasChildren: hasChildren,
-    value: value,
-    open: false,
-    key: uid++
-  };
-
-  return member;
-}
-
-function getObjectProperties(obj, callback) {
-  for (var p in obj) {
-    try {
-      callback.call(this, p, obj[p]);
-    }
-    catch (e) {
-      console.error(e)
-    }
-  }
-}
-
-function hasProperties(obj) {
-  if (typeof(obj) == "string") {
-    return false;
+    return Object.keys(obj).length > 1;
   }
 
-  try {
-    for (var name in obj) {
-      return true;
-    }
-  }
-  catch (exc) {
+  function getType(object) {
+    // A type provider (or a decorator) should be used here.
+    return "dom";
   }
 
-  return false;
-}
-
-function getType(object) {
-  // A type provider (or a decorator) should be used here.
-  return "dom";
-}
-
-// Exports from this module
-exports.TreeView = TreeView;
+  // Exports from this module
+  exports.TreeView = TreeView;
 });
--- a/devtools/client/jsonview/components/search-box.js
+++ b/devtools/client/jsonview/components/search-box.js
@@ -2,51 +2,54 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 define(function(require, exports, module) {
+  const React = require("devtools/client/shared/vendor/react");
 
-const React = require("devtools/client/shared/vendor/react");
+  const DOM = React.DOM;
 
-const DOM = React.DOM;
+  // For smooth incremental searching (in case the user is typing quickly).
+  const searchDelay = 250;
 
-// For smooth incremental searching (in case the user is typing quickly).
-const searchDelay = 250;
+  /**
+   * This object represents a search box located at the
+   * top right corner of the application.
+   */
+  let SearchBox = React.createClass({
+    propTypes: {
+      actions: React.PropTypes.object,
+    },
 
-/**
- * This object represents a search box located at the
- * top right corner of the application.
- */
-var SearchBox = React.createClass({
-  displayName: "SearchBox",
+    displayName: "SearchBox",
+
+    onSearch: function(event) {
+      let searchBox = event.target;
+      let win = searchBox.ownerDocument.defaultView;
 
-  render: function() {
-    return (
-      DOM.input({className: "searchBox",
-        placeholder: Locale.$STR("jsonViewer.filterJSON"),
-        onChange: this.onSearch})
-    )
-  },
+      if (this.searchTimeout) {
+        win.clearTimeout(this.searchTimeout);
+      }
 
-  onSearch: function(event) {
-    var searchBox = event.target;
-    var win = searchBox.ownerDocument.defaultView;
+      let callback = this.doSearch.bind(this, searchBox);
+      this.searchTimeout = win.setTimeout(callback, searchDelay);
+    },
+
+    doSearch: function(searchBox) {
+      this.props.actions.onSearch(searchBox.value);
+    },
 
-    if (this.searchTimeout) {
-      win.clearTimeout(this.searchTimeout);
-    }
-
-    var callback = this.doSearch.bind(this, searchBox);
-    this.searchTimeout = win.setTimeout(callback, searchDelay);
-  },
+    render: function() {
+      return (
+        DOM.input({className: "searchBox",
+          placeholder: Locale.$STR("jsonViewer.filterJSON"),
+          onChange: this.onSearch})
+      );
+    },
+  });
 
-  doSearch: function(searchBox) {
-    this.props.actions.onSearch(searchBox.value);
-  }
+  // Exports from this module
+  exports.SearchBox = SearchBox;
 });
-
-// Exports from this module
-exports.SearchBox = SearchBox;
-});
--- a/devtools/client/jsonview/components/text-panel.js
+++ b/devtools/client/jsonview/components/text-panel.js
@@ -1,79 +1,95 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-define(function(require, exports, module) {
+"use strict";
 
-const React = require("devtools/client/shared/vendor/react");
-const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
-const { Toolbar, ToolbarButton } = createFactories(require("./reps/toolbar"));
-const DOM = React.DOM;
+define(function(require, exports, module) {
+  const React = require("devtools/client/shared/vendor/react");
+  const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
+  const { Toolbar, ToolbarButton } = createFactories(require("./reps/toolbar"));
+  const DOM = React.DOM;
 
-/**
- * This template represents the 'Raw Data' panel displaying
- * JSON as a text received from the server.
- */
-var TextPanel = React.createClass({
-  displayName: "TextPanel",
+  /**
+   * This template represents the 'Raw Data' panel displaying
+   * JSON as a text received from the server.
+   */
+  let TextPanel = React.createClass({
+    propTypes: {
+      actions: React.PropTypes.object,
+      data: React.PropTypes.string
+    },
+
+    displayName: "TextPanel",
 
-  getInitialState: function() {
-    return {};
-  },
+    getInitialState: function() {
+      return {};
+    },
 
-  render: function() {
-    return (
-      DOM.div({className: "textPanelBox"},
-        TextToolbar({actions: this.props.actions}),
-        DOM.div({className: "panelContent"},
-          DOM.pre({className: "data"},
-            this.props.data
+    render: function() {
+      return (
+        DOM.div({className: "textPanelBox"},
+          TextToolbar({actions: this.props.actions}),
+          DOM.div({className: "panelContent"},
+            DOM.pre({className: "data"},
+              this.props.data
+            )
           )
         )
-      )
-    );
-  }
-});
+      );
+    }
+  });
 
-/**
- * This object represents a toolbar displayed within the
- * 'Raw Data' panel.
- */
-var TextToolbar = React.createFactory(React.createClass({
-  displayName: "TextToolbar",
+  /**
+   * This object represents a toolbar displayed within the
+   * 'Raw Data' panel.
+   */
+  let TextToolbar = React.createFactory(React.createClass({
+    propTypes: {
+      actions: React.PropTypes.object,
+    },
+
+    displayName: "TextToolbar",
+
+    // Commands
+
+    onPrettify: function(event) {
+      this.props.actions.onPrettify();
+    },
+
+    onSave: function(event) {
+      this.props.actions.onSaveJson();
+    },
 
-  render: function() {
-    return (
-      Toolbar({},
-        ToolbarButton({className: "btn prettyprint",onClick: this.onPrettify},
-          Locale.$STR("jsonViewer.PrettyPrint")
-        ),
-        ToolbarButton({className: "btn save", onClick: this.onSave},
-          Locale.$STR("jsonViewer.Save")
-        ),
-        ToolbarButton({className: "btn copy", onClick: this.onCopy},
-          Locale.$STR("jsonViewer.Copy")
-        )
-      )
-    )
-  },
+    onCopy: function(event) {
+      this.props.actions.onCopyJson();
+    },
 
-  // Commands
-
-  onPrettify: function(event) {
-    this.props.actions.onPrettify();
-  },
+    render: function() {
+      return (
+        Toolbar({},
+          ToolbarButton({
+            className: "btn prettyprint",
+            onClick: this.onPrettify},
+            Locale.$STR("jsonViewer.PrettyPrint")
+          ),
+          ToolbarButton({
+            className: "btn save",
+            onClick: this.onSave},
+            Locale.$STR("jsonViewer.Save")
+          ),
+          ToolbarButton({
+            className: "btn copy",
+            onClick: this.onCopy},
+            Locale.$STR("jsonViewer.Copy")
+          )
+        )
+      );
+    },
+  }));
 
-  onSave: function(event) {
-    this.props.actions.onSaveJson();
-  },
-
-  onCopy: function(event) {
-    this.props.actions.onCopyJson();
-  },
-}));
-
-// Exports from this module
-exports.TextPanel = TextPanel;
+  // Exports from this module
+  exports.TextPanel = TextPanel;
 });
--- a/devtools/client/jsonview/converter-child.js
+++ b/devtools/client/jsonview/converter-child.js
@@ -14,119 +14,122 @@ const xpcom = require("sdk/platform/xpco
 const Events = require("sdk/dom/events");
 const Clipboard = require("sdk/clipboard");
 
 loader.lazyRequireGetter(this, "NetworkHelper",
                                "devtools/shared/webconsole/network-helper");
 loader.lazyRequireGetter(this, "JsonViewUtils",
                                "devtools/client/jsonview/utils");
 
-
 const childProcessMessageManager =
-  Cc["@mozilla.org/childprocessmessagemanager;1"].
-    getService(Ci.nsISyncMessageSender);
+  Cc["@mozilla.org/childprocessmessagemanager;1"]
+    .getService(Ci.nsISyncMessageSender);
 
 // Amount of space that will be allocated for the stream's backing-store.
 // Must be power of 2. Used to copy the data stream in onStopRequest.
 const SEGMENT_SIZE = Math.pow(2, 17);
 
 const JSON_VIEW_MIME_TYPE = "application/vnd.mozilla.json.view";
-const CONTRACT_ID = "@mozilla.org/streamconv;1?from=" + JSON_VIEW_MIME_TYPE + "&to=*/*";
+const CONTRACT_ID = "@mozilla.org/streamconv;1?from=" +
+  JSON_VIEW_MIME_TYPE + "&to=*/*";
 const CLASS_ID = "{d8c9acee-dec5-11e4-8c75-1681e6b88ec1}";
 
 // Localization
-var jsonViewStrings = Services.strings.createBundle(
+let jsonViewStrings = Services.strings.createBundle(
   "chrome://devtools/locale/jsonview.properties");
 
 /**
  * This object detects 'application/vnd.mozilla.json.view' content type
  * and converts it into a JSON Viewer application that allows simple
  * JSON inspection.
  *
  * Inspired by JSON View: https://github.com/bhollis/jsonview/
  */
-var Converter = Class({
+let Converter = Class({
   extends: Unknown,
 
   interfaces: [
     "nsIStreamConverter",
     "nsIStreamListener",
     "nsIRequestObserver"
   ],
 
   get wrappedJSObject() {
     return this;
   },
 
   /**
    * This component works as such:
    * 1. asyncConvertData captures the listener
-   * 2. onStartRequest fires, initializes stuff, modifies the listener to match our output type
+   * 2. onStartRequest fires, initializes stuff, modifies the listener
+   *    to match our output type
    * 3. onDataAvailable transcodes the data into a UTF-8 string
-   * 4. onStopRequest gets the collected data and converts it, spits it to the listener
-   * 5. convert does nothing, it's just the synchronous version of asyncConvertData
+   * 4. onStopRequest gets the collected data and converts it,
+   *    spits it to the listener
+   * 5. convert does nothing, it's just the synchronous version
+   *    of asyncConvertData
    */
-  convert: function(aFromStream, aFromType, aToType, aCtxt) {
-    return aFromStream;
+  convert: function(fromStream, fromType, toType, ctx) {
+    return fromStream;
   },
 
-  asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
-    this.listener = aListener;
+  asyncConvertData: function(fromType, toType, listener, ctx) {
+    this.listener = listener;
   },
 
-  onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
+  onDataAvailable: function(request, context, inputStream, offset, count) {
     // From https://developer.mozilla.org/en/Reading_textual_data
-    var is = Cc["@mozilla.org/intl/converter-input-stream;1"].
-      createInstance(Ci.nsIConverterInputStream);
-    is.init(aInputStream, this.charset, -1,
+    let is = Cc["@mozilla.org/intl/converter-input-stream;1"]
+      .createInstance(Ci.nsIConverterInputStream);
+    is.init(inputStream, this.charset, -1,
       Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
 
     // Seed it with something positive
-    var bytesRead = 1;
-    while (aCount) {
-      var str = {};
-      var bytesRead = is.readString(aCount, str);
+    while (count) {
+      let str = {};
+      let bytesRead = is.readString(count, str);
       if (!bytesRead) {
         break;
       }
-      aCount -= bytesRead;
+      count -= bytesRead;
       this.data += str.value;
     }
   },
 
-  onStartRequest: function(aRequest, aContext) {
+  onStartRequest: function(request, context) {
     this.data = "";
-    this.uri = aRequest.QueryInterface(Ci.nsIChannel).URI.spec;
+    this.uri = request.QueryInterface(Ci.nsIChannel).URI.spec;
 
     // Sets the charset if it is available. (For documents loaded from the
     // filesystem, this is not set.)
-    this.charset = aRequest.QueryInterface(Ci.nsIChannel).contentCharset || 'UTF-8';
+    this.charset =
+      request.QueryInterface(Ci.nsIChannel).contentCharset || "UTF-8";
 
-    this.channel = aRequest;
+    this.channel = request;
     this.channel.contentType = "text/html";
     this.channel.contentCharset = "UTF-8";
 
-    this.listener.onStartRequest(this.channel, aContext);
+    this.listener.onStartRequest(this.channel, context);
   },
 
   /**
    * This should go something like this:
    * 1. Make sure we have a unicode string.
    * 2. Convert it to a Javascript object.
    * 2.1 Removes the callback
    * 3. Convert that to HTML? Or XUL?
    * 4. Spit it back out at the listener
    */
-  onStopRequest: function(aRequest, aContext, aStatusCode) {
+  onStopRequest: function(request, context, statusCode) {
     let headers = {
       response: [],
       request: []
-    }
+    };
 
-    let win = NetworkHelper.getWindowForRequest(aRequest);
+    let win = NetworkHelper.getWindowForRequest(request);
 
     let Locale = {
       $STR: key => {
         try {
           return jsonViewStrings.GetStringFromName(key);
         } catch (err) {
           Cu.reportError(err);
         }
@@ -134,159 +137,165 @@ var Converter = Class({
     };
 
     JsonViewUtils.exportIntoContentScope(win, Locale, "Locale");
 
     Events.once(win, "DOMContentLoaded", event => {
       Cu.exportFunction(this.postChromeMessage.bind(this), win, {
         defineAs: "postChromeMessage"
       });
-    })
+    });
 
     // The request doesn't have to be always nsIHttpChannel
     // (e.g. in case of data: URLs)
-    if (aRequest instanceof Ci.nsIHttpChannel) {
-      aRequest.visitResponseHeaders({
+    if (request instanceof Ci.nsIHttpChannel) {
+      request.visitResponseHeaders({
         visitHeader: function(name, value) {
           headers.response.push({name: name, value: value});
         }
       });
 
-      aRequest.visitRequestHeaders({
+      request.visitRequestHeaders({
         visitHeader: function(name, value) {
           headers.request.push({name: name, value: value});
         }
       });
     }
 
     let outputDoc = "";
 
     try {
       headers = JSON.stringify(headers);
       outputDoc = this.toHTML(this.data, headers, this.uri);
     } catch (e) {
       Cu.reportError("JSON Viewer ERROR " + e);
       outputDoc = this.toErrorPage(e, this.data, this.uri);
     }
 
-    var storage = Cc["@mozilla.org/storagestream;1"].createInstance(Ci.nsIStorageStream);
+    let storage = Cc["@mozilla.org/storagestream;1"]
+      .createInstance(Ci.nsIStorageStream);
+
     storage.init(SEGMENT_SIZE, 0xffffffff, null);
-    var out = storage.getOutputStream(0);
+    let out = storage.getOutputStream(0);
 
-    var binout = Cc["@mozilla.org/binaryoutputstream;1"]
+    let binout = Cc["@mozilla.org/binaryoutputstream;1"]
       .createInstance(Ci.nsIBinaryOutputStream);
 
     binout.setOutputStream(out);
     binout.writeUtf8Z(outputDoc);
     binout.close();
 
     // We need to trim 4 bytes off the front (this could be underlying bug).
-    var trunc = 4;
-    var instream = storage.newInputStream(trunc);
+    let trunc = 4;
+    let instream = storage.newInputStream(trunc);
 
     // Pass the data to the main content listener
-    this.listener.onDataAvailable(this.channel, aContext, instream, 0,
+    this.listener.onDataAvailable(this.channel, context, instream, 0,
       instream.available());
 
-    this.listener.onStopRequest(this.channel, aContext, aStatusCode);
+    this.listener.onStopRequest(this.channel, context, statusCode);
 
     this.listener = null;
   },
 
   htmlEncode: function(t) {
-    return t !== null ? t.toString().replace(/&/g,"&amp;").
-      replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;") : '';
+    return t !== null ? t.toString()
+      .replace(/&/g, "&amp;")
+      .replace(/"/g, "&quot;")
+      .replace(/</g, "&lt;")
+      .replace(/>/g, "&gt;") : "";
   },
 
   toHTML: function(json, headers, title) {
-    var themeClassName = "theme-" + JsonViewUtils.getCurrentTheme();
-    var clientBaseUrl = "resource://devtools/client/";
-    var baseUrl = clientBaseUrl + "jsonview/";
-    var themeVarsUrl = clientBaseUrl + "themes/variables.css";
+    let themeClassName = "theme-" + JsonViewUtils.getCurrentTheme();
+    let clientBaseUrl = "resource://devtools/client/";
+    let baseUrl = clientBaseUrl + "jsonview/";
+    let themeVarsUrl = clientBaseUrl + "themes/variables.css";
 
-    return '<!DOCTYPE html>\n' +
-      '<html class="' + themeClassName + '">' +
-      '<head><title>' + this.htmlEncode(title) + '</title>' +
-      '<base href="' + this.htmlEncode(baseUrl) + '">' +
-      '<link rel="stylesheet" type="text/css" href="' + themeVarsUrl + '">' +
-      '<link rel="stylesheet" type="text/css" href="css/main.css">' +
-      '<script data-main="viewer-config" src="lib/require.js"></script>' +
-      '</head><body>' +
-      '<div id="content"></div>' +
-      '<div id="json">' + this.htmlEncode(json) + '</div>' +
-      '<div id="headers">' + this.htmlEncode(headers) + '</div>' +
-      '</body></html>';
+    return "<!DOCTYPE html>\n" +
+      "<html class=\"" + themeClassName + "\">" +
+      "<head><title>" + this.htmlEncode(title) + "</title>" +
+      "<base href=\"" + this.htmlEncode(baseUrl) + "\">" +
+      "<link rel=\"stylesheet\" type=\"text/css\" href=\"" +
+        themeVarsUrl + "\">" +
+      "<link rel=\"stylesheet\" type=\"text/css\" href=\"css/main.css\">" +
+      "<script data-main=\"viewer-config\" src=\"lib/require.js\"></script>" +
+      "</head><body>" +
+      "<div id=\"content\"></div>" +
+      "<div id=\"json\">" + this.htmlEncode(json) + "</div>" +
+      "<div id=\"headers\">" + this.htmlEncode(headers) + "</div>" +
+      "</body></html>";
   },
 
   toErrorPage: function(error, data, uri) {
     // Escape unicode nulls
     data = data.replace("\u0000", "\uFFFD");
 
-    var errorInfo = error + "";
+    let errorInfo = error + "";
 
-    var output = '<div id="error">' + _('errorParsing')
+    let output = "<div id=\"error\">" + "error parsing";
     if (errorInfo.message) {
-      output += '<div class="errormessage">' + errorInfo.message + '</div>';
+      output += "<div class=\"errormessage\">" + errorInfo.message + "</div>";
     }
 
-    output += '</div><div id="json">' + this.highlightError(data,
-      errorInfo.line, errorInfo.column) + '</div>';
+    output += "</div><div id=\"json\">" + this.highlightError(data,
+      errorInfo.line, errorInfo.column) + "</div>";
 
-    return '<!DOCTYPE html>\n' +
-      '<html><head><title>' + this.htmlEncode(uri + ' - Error') + '</title>' +
-      '<base href="' + this.htmlEncode(self.data.url()) + '">' +
-      '</head><body>' +
+    return "<!DOCTYPE html>\n" +
+      "<html><head><title>" + this.htmlEncode(uri + " - Error") + "</title>" +
+      "<base href=\"" + this.htmlEncode(this.data.url()) + "\">" +
+      "</head><body>" +
       output +
-      '</body></html>';
+      "</body></html>";
   },
 
   // Chrome <-> Content communication
 
   postChromeMessage: function(type, args, objects) {
-    var value = args;
+    let value = args;
 
     switch (type) {
-    case "copy":
-      Clipboard.set(value, "text");
-      break;
+      case "copy":
+        Clipboard.set(value, "text");
+        break;
 
-    case "copy-headers":
-      this.copyHeaders(value);
-      break;
+      case "copy-headers":
+        this.copyHeaders(value);
+        break;
 
-    case "save":
-      childProcessMessageManager.sendAsyncMessage(
-        "devtools:jsonview:save", value);
+      case "save":
+        childProcessMessageManager.sendAsyncMessage(
+          "devtools:jsonview:save", value);
     }
   },
 
   copyHeaders: function(headers) {
-    var value = "";
-    var eol = (Services.appinfo.OS !== "WINNT") ? "\n" : "\r\n";
+    let value = "";
+    let eol = (Services.appinfo.OS !== "WINNT") ? "\n" : "\r\n";
 
-    var responseHeaders = headers.response;
-    for (var i=0; i<responseHeaders.length; i++) {
-      var header = responseHeaders[i];
+    let responseHeaders = headers.response;
+    for (let i = 0; i < responseHeaders.length; i++) {
+      let header = responseHeaders[i];
       value += header.name + ": " + header.value + eol;
     }
 
     value += eol;
 
-    var requestHeaders = headers.request;
-    for (var i=0; i<requestHeaders.length; i++) {
-      var header = requestHeaders[i];
+    let requestHeaders = headers.request;
+    for (let i = 0; i < requestHeaders.length; i++) {
+      let header = requestHeaders[i];
       value += header.name + ": " + header.value + eol;
     }
 
     Clipboard.set(value, "text");
   }
 });
 
 // Stream converter component definition
-var service = xpcom.Service({
+let service = xpcom.Service({
   id: components.ID(CLASS_ID),
   contract: CONTRACT_ID,
   Component: Converter,
   register: false,
   unregister: false
 });
 
 function register() {
@@ -303,9 +312,9 @@ function unregister() {
     return true;
   }
   return false;
 }
 
 exports.JsonViewService = {
   register: register,
   unregister: unregister
-}
+};
--- a/devtools/client/jsonview/converter-observer.js
+++ b/devtools/client/jsonview/converter-observer.js
@@ -2,18 +2,16 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const Cu = Components.utils;
-const Cc = Components.classes;
-const Ci = Components.interfaces;
 
 const {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
 const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
 
 // Load devtools module lazily.
 XPCOMUtils.defineLazyGetter(this, "devtools", function() {
   const {devtools} = Cu.import("resource://devtools/shared/Loader.jsm", {});
   return devtools;
@@ -56,17 +54,17 @@ ConverterObserver.prototype = {
   observe: function(subject, topic, data) {
     switch (topic) {
       case "xpcom-shutdown":
         this.onShutdown();
         break;
       case "nsPref:changed":
         this.onPrefChanged();
         break;
-    };
+    }
   },
 
   onShutdown: function() {
     Services.prefs.removeObserver(JSON_VIEW_PREF, observer);
     Services.obs.removeObserver(observer, "xpcom-shutdown");
   },
 
   onPrefChanged: function() {
--- a/devtools/client/jsonview/converter-sniffer.js
+++ b/devtools/client/jsonview/converter-sniffer.js
@@ -6,20 +6,21 @@
 
 "use strict";
 
 const {Cc, Ci, components} = require("chrome");
 const xpcom = require("sdk/platform/xpcom");
 const {Unknown} = require("sdk/platform/xpcom");
 const {Class} = require("sdk/core/heritage");
 
-const categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
+const categoryManager = Cc["@mozilla.org/categorymanager;1"]
+  .getService(Ci.nsICategoryManager);
 
 loader.lazyRequireGetter(this, "NetworkHelper",
-                               "devtools/shared/webconsole/network-helper");
+  "devtools/shared/webconsole/network-helper");
 
 // Constants
 const JSON_TYPE = "application/json";
 const CONTRACT_ID = "@mozilla.org/devtools/jsonview-sniffer;1";
 const CLASS_ID = "{4148c488-dca1-49fc-a621-2a0097a62422}";
 const JSON_VIEW_MIME_TYPE = "application/vnd.mozilla.json.view";
 const JSON_VIEW_TYPE = "JSON View";
 const CONTENT_SNIFFER_CATEGORY = "net-content-sniffers";
@@ -38,34 +39,35 @@ var Sniffer = Class({
   interfaces: [
     "nsIContentSniffer",
   ],
 
   get wrappedJSObject() {
     return this;
   },
 
-  getMIMETypeFromContent: function(aRequest, aData, aLength) {
+  getMIMETypeFromContent: function(request, data, length) {
     // JSON View is enabled only for top level loads only.
-    if (!NetworkHelper.isTopLevelLoad(aRequest)) {
+    if (!NetworkHelper.isTopLevelLoad(request)) {
       return "";
     }
 
-    if (aRequest instanceof Ci.nsIChannel) {
+    if (request instanceof Ci.nsIChannel) {
       try {
-        if (aRequest.contentDisposition == Ci.nsIChannel.DISPOSITION_ATTACHMENT) {
+        if (request.contentDisposition ==
+          Ci.nsIChannel.DISPOSITION_ATTACHMENT) {
           return "";
         }
       } catch (e) {
         // Channel doesn't support content dispositions
       }
 
       // Check the response content type and if it's application/json
       // change it to new internal type consumed by JSON View.
-      if (aRequest.contentType == JSON_TYPE) {
+      if (request.contentType == JSON_TYPE) {
         return JSON_VIEW_MIME_TYPE;
       }
     }
 
     return "";
   }
 });
 
@@ -86,19 +88,19 @@ function register() {
   }
 
   return false;
 }
 
 function unregister() {
   if (xpcom.isRegistered(service)) {
     categoryManager.deleteCategoryEntry(CONTENT_SNIFFER_CATEGORY,
-      JSON_VIEW_TYPE, false)
+      JSON_VIEW_TYPE, false);
     xpcom.unregister(service);
     return true;
   }
   return false;
 }
 
 exports.JsonViewSniffer = {
   register: register,
   unregister: unregister
-}
+};
--- a/devtools/client/jsonview/json-viewer.js
+++ b/devtools/client/jsonview/json-viewer.js
@@ -1,98 +1,98 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* global postChromeMessage */
+
+"use strict";
 
 define(function(require, exports, module) {
+  // ReactJS
+  const ReactDOM = require("devtools/client/shared/vendor/react-dom");
+  const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
+  const { MainTabbedArea } = createFactories(require("./components/main-tabbed-area"));
 
-// ReactJS
-const ReactDOM = require("devtools/client/shared/vendor/react-dom");
-const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
-const { MainTabbedArea } = createFactories(require("./components/main-tabbed-area"));
+  const json = document.getElementById("json");
+  const headers = document.getElementById("headers");
 
-const json = document.getElementById("json");
-const headers = document.getElementById("headers");
-
-var jsonData;
+  let jsonData;
 
-try {
-  jsonData = JSON.parse(json.textContent);
-} catch (err) {
-  jsonData = err + "";
-}
+  try {
+    jsonData = JSON.parse(json.textContent);
+  } catch (err) {
+    jsonData = err + "";
+  }
 
-// Application state object.
-var input = {
-  jsonText: json.textContent,
-  jsonPretty : null,
-  json: jsonData,
-  headers: JSON.parse(headers.textContent),
-  tabActive: 1,
-  prettified: false
-}
-
-json.remove();
-headers.remove();
+  // Application state object.
+  let input = {
+    jsonText: json.textContent,
+    jsonPretty: null,
+    json: jsonData,
+    headers: JSON.parse(headers.textContent),
+    tabActive: 1,
+    prettified: false
+  };
 
-/**
- * Application actions/commands. This list implements all commands
- * available for the JSON viewer.
- */
-input.actions = {
-  onCopyJson: function() {
-    var value = input.prettified ? input.jsonPretty : input.jsonText;
-    postChromeMessage("copy", value);
-  },
+  json.remove();
+  headers.remove();
 
-  onSaveJson: function() {
-    var value = input.prettified ? input.jsonPretty : input.jsonText;
-    postChromeMessage("save", value);
-  },
+  /**
+   * Application actions/commands. This list implements all commands
+   * available for the JSON viewer.
+   */
+  input.actions = {
+    onCopyJson: function() {
+      let value = input.prettified ? input.jsonPretty : input.jsonText;
+      postChromeMessage("copy", value);
+    },
 
-  onCopyHeaders: function() {
-    postChromeMessage("copy-headers", input.headers);
-  },
+    onSaveJson: function() {
+      let value = input.prettified ? input.jsonPretty : input.jsonText;
+      postChromeMessage("save", value);
+    },
 
-  onSearch: function(value) {
-    theApp.setState({searchFilter: value});
-  },
+    onCopyHeaders: function() {
+      postChromeMessage("copy-headers", input.headers);
+    },
 
-  onPrettify: function(data) {
-    if (input.prettified) {
-      theApp.setState({jsonText: input.jsonText});
-    } else {
-      if (!input.jsonPretty) {
-        input.jsonPretty = JSON.stringify(jsonData, null, "  ");
+    onSearch: function(value) {
+      theApp.setState({searchFilter: value});
+    },
+
+    onPrettify: function(data) {
+      if (input.prettified) {
+        theApp.setState({jsonText: input.jsonText});
+      } else {
+        if (!input.jsonPretty) {
+          input.jsonPretty = JSON.stringify(jsonData, null, "  ");
+        }
+        theApp.setState({jsonText: input.jsonPretty});
       }
-      theApp.setState({jsonText: input.jsonPretty});
-    }
-
-    input.prettified = !input.prettified;
-  },
-}
 
-/**
- * Render the main application component. It's the main tab bar displayed
- * at the top of the window. This component also represents ReacJS root.
- */
-var content = document.getElementById("content");
-var theApp = ReactDOM.render(MainTabbedArea(input), content);
+      input.prettified = !input.prettified;
+    },
+  };
+
+  /**
+   * Render the main application component. It's the main tab bar displayed
+   * at the top of the window. This component also represents ReacJS root.
+   */
+  let content = document.getElementById("content");
+  let theApp = ReactDOM.render(MainTabbedArea(input), content);
 
-var onResize = event => {
-  window.document.body.style.height = window.innerHeight + "px";
-  window.document.body.style.width = window.innerWidth + "px";
-}
-
-window.addEventListener("resize", onResize);
-onResize();
+  let onResize = event => {
+    window.document.body.style.height = window.innerHeight + "px";
+    window.document.body.style.width = window.innerWidth + "px";
+  };
 
-// Send notification event to the window. Can be useful for
-// tests as well as extensions.
-var event = new CustomEvent("JSONViewInitialized", {});
-window.jsonViewInitialized = true;
-window.dispatchEvent(event);
+  window.addEventListener("resize", onResize);
+  onResize();
 
-// End of json-viewer.js
+  // Send notification event to the window. Can be useful for
+  // tests as well as extensions.
+  let event = new CustomEvent("JSONViewInitialized", {});
+  window.jsonViewInitialized = true;
+  window.dispatchEvent(event);
 });
 
--- a/devtools/client/jsonview/main.js
+++ b/devtools/client/jsonview/main.js
@@ -1,20 +1,21 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* globals JsonViewUtils*/
 
 "use strict";
 
-const {Cu, Ci, Cc} = require("chrome");
+const { Cu } = require("chrome");
 const Services = require("Services");
 
-const {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
+const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
 
 XPCOMUtils.defineLazyGetter(this, "JsonViewService", function() {
   return require("devtools/client/jsonview/utils");
 });
 
 /**
  * Singleton object that represents the JSON View in-content tool.
  * It has the same lifetime as the browser. Initialization done by
--- a/devtools/client/jsonview/test/browser_jsonview_copy_headers.js
+++ b/devtools/client/jsonview/test/browser_jsonview_copy_headers.js
@@ -5,29 +5,29 @@
 
 "use strict";
 
 const TEST_JSON_URL = URL_ROOT + "valid_json.json";
 
 add_task(function* () {
   info("Test valid JSON started");
 
-  let tab = yield addJsonViewTab(TEST_JSON_URL);
+  yield addJsonViewTab(TEST_JSON_URL);
 
   // Select the RawData tab
   yield selectJsonViewContentTab("headers");
 
   // Check displayed headers
   let count = yield getElementCount(".headersPanelBox .netHeadersGroup");
   is(count, 2, "There must be two header groups");
 
   let text = yield getElementText(".headersPanelBox .netInfoHeadersTable");
   isnot(text, "", "Headers text must not be empty");
 
-  let browser = gBrowser.selectedBrowser
+  let browser = gBrowser.selectedBrowser;
 
   // Verify JSON copy into the clipboard.
   yield waitForClipboardPromise(function setup() {
     BrowserTestUtils.synthesizeMouseAtCenter(
       ".headersPanelBox .toolbar button.copy",
       {}, browser);
   }, function validator(value) {
     return value.indexOf("application/json") > 0;
--- a/devtools/client/jsonview/test/browser_jsonview_copy_json.js
+++ b/devtools/client/jsonview/test/browser_jsonview_copy_json.js
@@ -5,27 +5,27 @@
 
 "use strict";
 
 const TEST_JSON_URL = URL_ROOT + "simple_json.json";
 
 add_task(function* () {
   info("Test copy JSON started");
 
-  let tab = yield addJsonViewTab(TEST_JSON_URL);
+  yield addJsonViewTab(TEST_JSON_URL);
 
   let countBefore = yield getElementCount(".jsonPanelBox .domTable .memberRow");
   ok(countBefore == 1, "There must be one row");
 
   let text = yield getElementText(".jsonPanelBox .domTable .memberRow");
   is(text, "name\"value\"", "There must be proper JSON displayed");
 
   // Verify JSON copy into the clipboard.
   let value = "{\"name\": \"value\"}\n";
-  let browser = gBrowser.selectedBrowser
+  let browser = gBrowser.selectedBrowser;
   let selector = ".jsonPanelBox .toolbar button.copy";
   yield waitForClipboardPromise(function setup() {
     BrowserTestUtils.synthesizeMouseAtCenter(selector, {}, browser);
   }, function validator(result) {
     let str = normalizeNewLines(result);
     return str == value;
   });
 });
--- a/devtools/client/jsonview/test/browser_jsonview_copy_rawdata.js
+++ b/devtools/client/jsonview/test/browser_jsonview_copy_rawdata.js
@@ -8,42 +8,43 @@
 const TEST_JSON_URL = URL_ROOT + "simple_json.json";
 
 let jsonText = "{\"name\": \"value\"}\n";
 let prettyJson = "{\n  \"name\": \"value\"\n}";
 
 add_task(function* () {
   info("Test copy raw data started");
 
-  let tab = yield addJsonViewTab(TEST_JSON_URL);
+  yield addJsonViewTab(TEST_JSON_URL);
 
   // Select the RawData tab
   yield selectJsonViewContentTab("rawdata");
 
   // Check displayed JSON
   let text = yield getElementText(".textPanelBox .data");
   is(text, jsonText, "Proper JSON must be displayed in DOM");
 
-  let browser = gBrowser.selectedBrowser
+  let browser = gBrowser.selectedBrowser;
 
   // Verify JSON copy into the clipboard.
   yield waitForClipboardPromise(function setup() {
     BrowserTestUtils.synthesizeMouseAtCenter(
       ".textPanelBox .toolbar button.copy",
       {}, browser);
   }, jsonText);
 
   // Click 'Pretty Print' button
   yield BrowserTestUtils.synthesizeMouseAtCenter(
     ".textPanelBox .toolbar button.prettyprint",
     {}, browser);
 
   let prettyText = yield getElementText(".textPanelBox .data");
   prettyText = normalizeNewLines(prettyText);
-  ok(prettyText.startsWith(prettyJson), "Pretty printed JSON must be displayed");
+  ok(prettyText.startsWith(prettyJson),
+    "Pretty printed JSON must be displayed");
 
   // Verify JSON copy into the clipboard.
   yield waitForClipboardPromise(function setup() {
     BrowserTestUtils.synthesizeMouseAtCenter(
       ".textPanelBox .toolbar button.copy",
       {}, browser);
   }, function validator(value) {
     let str = normalizeNewLines(value);
--- a/devtools/client/jsonview/test/browser_jsonview_filter.js
+++ b/devtools/client/jsonview/test/browser_jsonview_filter.js
@@ -5,23 +5,24 @@
 
 "use strict";
 
 const TEST_JSON_URL = URL_ROOT + "array_json.json";
 
 add_task(function* () {
   info("Test valid JSON started");
 
-  let tab = yield addJsonViewTab(TEST_JSON_URL);
+  yield addJsonViewTab(TEST_JSON_URL);
 
   let count = yield getElementCount(".jsonPanelBox .domTable .memberRow");
   is(count, 3, "There must be three rows");
 
   // XXX use proper shortcut to focus the filter box
   // as soon as bug Bug 1178771 is fixed.
   yield sendString("h", ".jsonPanelBox .searchBox");
 
   // The filtering is done asynchronously so, we need to wait.
   yield waitForFilter();
 
-  let hiddenCount = yield getElementCount(".jsonPanelBox .domTable .memberRow.hidden");
+  let hiddenCount = yield getElementCount(
+    ".jsonPanelBox .domTable .memberRow.hidden");
   is(hiddenCount, 2, "There must be two hidden rows");
 });
--- a/devtools/client/jsonview/test/browser_jsonview_invalid_json.js
+++ b/devtools/client/jsonview/test/browser_jsonview_invalid_json.js
@@ -5,16 +5,16 @@
 
 "use strict";
 
 const TEST_JSON_URL = URL_ROOT + "invalid_json.json";
 
 add_task(function* () {
   info("Test invalid JSON started");
 
-  let tab = yield addJsonViewTab(TEST_JSON_URL);
+  yield addJsonViewTab(TEST_JSON_URL);
 
   let count = yield getElementCount(".jsonPanelBox .domTable .memberRow");
   ok(count == 0, "There must be no row");
 
   let text = yield getElementText(".jsonPanelBox .jsonParseError");
   ok(text, "There must be an error description");
 });
--- a/devtools/client/jsonview/test/browser_jsonview_valid_json.js
+++ b/devtools/client/jsonview/test/browser_jsonview_valid_json.js
@@ -5,17 +5,17 @@
 
 "use strict";
 
 const TEST_JSON_URL = URL_ROOT + "valid_json.json";
 
 add_task(function* () {
   info("Test valid JSON started");
 
-  let tab = yield addJsonViewTab(TEST_JSON_URL);
+  yield addJsonViewTab(TEST_JSON_URL);
 
   let countBefore = yield getElementCount(".jsonPanelBox .domTable .memberRow");
   ok(countBefore == 1, "There must be one row");
 
   yield expandJsonNode(".jsonPanelBox .domTable .memberLabel");
 
   let countAfter = yield getElementCount(".jsonPanelBox .domTable .memberRow");
   ok(countAfter == 3, "There must be three rows");
--- a/devtools/client/jsonview/test/doc_frame_script.js
+++ b/devtools/client/jsonview/test/doc_frame_script.js
@@ -1,27 +1,28 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 /* globals Services, sendAsyncMessage, addMessageListener */
 
-// XXX Some helper API could go to testing/mochitest/tests/SimpleTest/AsyncContentUtils.js
+// XXX Some helper API could go to:
+// testing/mochitest/tests/SimpleTest/AsyncContentUtils.js
 // (or at least to share test API in devtools)
 
 // Set up a dummy environment so that EventUtils works. We need to be careful to
 // pass a window object into each EventUtils method we call rather than having
 // it rely on the |window| global.
 let EventUtils = {};
 EventUtils.window = content;
 EventUtils.parent = EventUtils.window;
-EventUtils._EU_Ci = Components.interfaces;
-EventUtils._EU_Cc = Components.classes;
+EventUtils._EU_Ci = Components.interfaces; // eslint-disable-line
+EventUtils._EU_Cc = Components.classes; // eslint-disable-line
 EventUtils.navigator = content.navigator;
 EventUtils.KeyboardEvent = content.KeyboardEvent;
 
 Services.scriptloader.loadSubScript(
   "chrome://mochikit/content/tests/SimpleTest/EventUtils.js", EventUtils);
 
 /**
  * When the JSON View is done rendering it triggers custom event
@@ -75,17 +76,17 @@ addMessageListener("Test:JsonView:WaitFo
 
   // Check if the filter is already set.
   if (firstRow.classList.contains("hidden")) {
     sendAsyncMessage(msg.name);
     return;
   }
 
   // Wait till the first row has 'hidden' class set.
-  var observer = new content.MutationObserver(function(mutations) {
+  let observer = new content.MutationObserver(function(mutations) {
     for (let i = 0; i < mutations.length; i++) {
       let mutation = mutations[i];
       if (mutation.attributeName == "class") {
         if (firstRow.classList.contains("hidden")) {
           observer.disconnect();
           sendAsyncMessage(msg.name);
           break;
         }
--- a/devtools/client/jsonview/test/head.js
+++ b/devtools/client/jsonview/test/head.js
@@ -1,11 +1,14 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
+/* eslint no-unused-vars: [2, {"vars": "local", "args": "none"}] */
+/* import-globals-from ../../framework/test/shared-head.js */
+/* import-globals-from ../../framework/test/head.js */
 
 "use strict";
 
 // shared-head.js handles imports, constants, and utility functions
 Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/devtools/client/framework/test/head.js", this);
 
 const JSON_VIEW_PREF = "devtools.jsonview.enabled";
@@ -76,29 +79,31 @@ function selectJsonViewContentTab(name) 
 
 function getElementCount(selector) {
   info("Get element count: '" + selector + "'");
 
   let data = {
     selector: selector
   };
 
-  return executeInContent("Test:JsonView:GetElementCount", data).then(result => {
+  return executeInContent("Test:JsonView:GetElementCount", data)
+  .then(result => {
     return result.count;
   });
 }
 
 function getElementText(selector) {
   info("Get element text: '" + selector + "'");
 
   let data = {
     selector: selector
   };
 
-  return executeInContent("Test:JsonView:GetElementText", data).then(result => {
+  return executeInContent("Test:JsonView:GetElementText", data)
+  .then(result => {
     return result.text;
   });
 }
 
 function focusElement(selector) {
   info("Focus element: '" + selector + "'");
 
   let data = {
@@ -120,19 +125,19 @@ function sendString(str, selector) {
   let data = {
     selector: selector,
     str: str
   };
 
   return executeInContent("Test:JsonView:SendString", data);
 }
 
-function waitForTime(aDelay) {
+function waitForTime(delay) {
   let deferred = promise.defer();
-  setTimeout(deferred.resolve, aDelay);
+  setTimeout(deferred.resolve, delay);
   return deferred.promise;
 }
 
 function waitForClipboardPromise(setup, expected) {
   return new Promise((resolve, reject) => {
     SimpleTest.waitForClipboard(expected, setup, resolve, reject);
   });
 }
--- a/devtools/client/jsonview/utils.js
+++ b/devtools/client/jsonview/utils.js
@@ -1,101 +1,101 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const {Cu, Cc, Ci} = require("chrome");
+const { Cu, Cc, Ci } = require("chrome");
 const Services = require("Services");
-const {getMostRecentBrowserWindow} = require("sdk/window/utils");
+const { getMostRecentBrowserWindow } = require("sdk/window/utils");
 
 const OPEN_FLAGS = {
-  RDONLY: parseInt("0x01"),
-  WRONLY: parseInt("0x02"),
-  CREATE_FILE: parseInt("0x08"),
-  APPEND: parseInt("0x10"),
-  TRUNCATE: parseInt("0x20"),
-  EXCL: parseInt("0x80")
+  RDONLY: parseInt("0x01", 16),
+  WRONLY: parseInt("0x02", 16),
+  CREATE_FILE: parseInt("0x08", 16),
+  APPEND: parseInt("0x10", 16),
+  TRUNCATE: parseInt("0x20", 16),
+  EXCL: parseInt("0x80", 16)
 };
 
 /**
  * Open File Save As dialog and let the user to pick proper file location.
  */
 exports.getTargetFile = function() {
-  var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+  let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
 
-  var win = getMostRecentBrowserWindow();
+  let win = getMostRecentBrowserWindow();
   fp.init(win, null, Ci.nsIFilePicker.modeSave);
-  fp.appendFilter("JSON Files","*.json; *.jsonp;");
+  fp.appendFilter("JSON Files", "*.json; *.jsonp;");
   fp.appendFilters(Ci.nsIFilePicker.filterText);
   fp.appendFilters(Ci.nsIFilePicker.filterAll);
   fp.filterIndex = 0;
 
-  var rv = fp.show();
+  let rv = fp.show();
   if (rv == Ci.nsIFilePicker.returnOK || rv == Ci.nsIFilePicker.returnReplace) {
     return fp.file;
   }
 
   return null;
-}
+};
 
 /**
  * Save JSON to a file
  */
 exports.saveToFile = function(file, jsonString) {
-  var foStream = Cc["@mozilla.org/network/file-output-stream;1"].
-    createInstance(Ci.nsIFileOutputStream);
+  let foStream = Cc["@mozilla.org/network/file-output-stream;1"]
+    .createInstance(Ci.nsIFileOutputStream);
 
   // write, create, truncate
   let openFlags = OPEN_FLAGS.WRONLY | OPEN_FLAGS.CREATE_FILE |
     OPEN_FLAGS.TRUNCATE;
 
   let permFlags = parseInt("0666", 8);
   foStream.init(file, openFlags, permFlags, 0);
 
-  var converter = Cc["@mozilla.org/intl/converter-output-stream;1"].
-    createInstance(Ci.nsIConverterOutputStream);
+  let converter = Cc["@mozilla.org/intl/converter-output-stream;1"]
+    .createInstance(Ci.nsIConverterOutputStream);
 
   converter.init(foStream, "UTF-8", 0, 0);
 
   // The entire jsonString can be huge so, write the data in chunks.
-  var chunkLength = 1024*1204;
-  for (var i=0; i<=jsonString.length; i++) {
-    var data = jsonString.substr(i, chunkLength+1);
+  let chunkLength = 1024 * 1204;
+  for (let i = 0; i <= jsonString.length; i++) {
+    let data = jsonString.substr(i, chunkLength + 1);
     if (data) {
       converter.writeString(data);
     }
     i = i + chunkLength;
   }
 
   // this closes foStream
   converter.close();
-}
+};
 
 /**
  * Get the current theme from preferences.
  */
 exports.getCurrentTheme = function() {
   return Services.prefs.getCharPref("devtools.theme");
-}
+};
 
 /**
  * Export given object into the target window scope.
  */
 exports.exportIntoContentScope = function(win, obj, defineAs) {
-  var clone = Cu.createObjectIn(win, {
+  let clone = Cu.createObjectIn(win, {
     defineAs: defineAs
   });
 
-  var props = Object.getOwnPropertyNames(obj);
-  for (var i=0; i<props.length; i++) {
-    var propName = props[i];
-    var propValue = obj[propName];
+  let props = Object.getOwnPropertyNames(obj);
+  for (let i = 0; i < props.length; i++) {
+    let propName = props[i];
+    let propValue = obj[propName];
     if (typeof propValue == "function") {
       Cu.exportFunction(propValue, clone, {
         defineAs: propName
       });
     }
   }
-}
+};
--- a/devtools/client/jsonview/viewer-config.js
+++ b/devtools/client/jsonview/viewer-config.js
@@ -1,13 +1,16 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* global requirejs */
+
+"use strict";
 
 /**
  * RequireJS configuration for JSON Viewer.
  *
  * ReactJS library is shared among DevTools. Both, the minified (production)
  * version and developer versions of the library are available.
  *
  * In order to use the developer version you need to specify the following