JavaScript coding standards

Probably the best piece of advice is to be consistent with the rest of the code in the file.

We use ESLint to analyse JavaScript files automatically, either from within a code editor or from the command line. Here’s our guide to install and configure it.

For quick reference, here are some of the main code style rules:

  • file references to browser globals such as window and document need /* eslint-env browser */ at the top of the file,

  • lines should be 90 characters maximum,

  • indent with 2 spaces (no tabs!),

  • camelCasePlease,

  • don’t open braces on the next line,

  • don’t name function expressions: let o = { doSomething: function doSomething() {} };,

  • use a space before opening paren for anonymous functions, but don’t use one for named functions:

    • anonymous functions: function () {}

    • named functions: function foo() {}

    • anonymous generators: function* () {}

    • named generators: function* foo() {}

  • aim for short functions, 24 lines max (ESLint has a rule that checks for function complexity too),

  • aArguments aAre the aDevil (don’t use them please),

  • "use strict"; globally per module,

  • semicolons; // use them,

  • no comma-first,

  • consider using async/await for nice-looking asynchronous code instead of formatting endless .then chains,

  • use ES6 syntax:

    • function setBreakpoint({url, line, column}) { ... },

    • (...args) => { } rest args are awesome, no need for arguments,

    • for..of loops,

  • don’t use non-standard SpiderMonkey-only syntax:

    • no for each loops,

    • no function () implicitReturnVal,

    • getters / setters require { },

  • only import specific, explicitly-declared symbols into your namespace:

    • const { foo, bar } = require("foo/bar");,

    • const { foo, bar } = ChromeUtils.importESModule("...");,

  • use Maps, Sets, WeakMaps when possible,

  • use template strings whenever possible to avoid concatenation, allow multi-line strings, and interpolation.

Comments

Commenting code is important, but bad comments can hurt too, so it’s important to have a few rules in mind when commenting:

  • If the code can be rewritten to be made more readable, then that should be preferred over writing an explanation as a comment.

  • Instead of writing a comment to explain the meaning of a poorly chosen variable name, then rename that variable.

  • Avoid long separator comments like // ****************** another section below **********. They are often a sign that you should split a file in multiple files.

  • Line comments go above the code they are commenting, not at the end of the line.

  • Sentences in comments start with a capital letter and end with a period.

  • Watch out for typos.

  • Obsolete copy/pasted code hurts, make sure you update comments inside copy/pasted code blocks.

  • A global comment at the very top of a file explaining what the file is about and the major types/classes/functions it contains is a good idea for quickly browsing code.

  • If you are forced to employ some kind of hack in your code, and there’s no way around it, then add a comment that explains the hack and why it is needed. The reviewer is going to ask for one anyway.

  • Bullet points in comments should use stars aligned with the first comment to format each point

// headline comment
// * bullet point 1
// * bullet point 2

Asynchronous code

A lot of code in DevTools is asynchronous, because a lot of it relies on connecting to the DevTools server and getting information from there in an asynchronous fashion.

It’s easy to make mistakes with asynchronous code, so here are a few guidelines that should help:

  • Prefer promises over callbacks.

  • Use the new Promise(() => {}) syntax.

  • Don’t forget to catch rejections by defining a rejection handler: promise.then(() => console.log("resolved"), () => console.log("rejected")); or promise.catch(() => console.log("rejected"));.

  • Make use of async and await.

React & Redux

There are React-specific code style rules in the .eslintrc file.

Components

  • Default to creating components as stateless function components.

  • If you need local state or lifecycle methods, use React.createClass instead of functions.

  • Use React.DOM to create native elements. Assign it to a variable named dom, and use it like dom.div({}, dom.span({})). You may also destructure specific elements directly: const { div, ul } = React.DOM.

PropTypes

  • Use PropTypes to define the expected properties of your component. Each directly accessed property (or child of a property) should have a corresponding PropType.

  • Use isRequired for any required properties.

  • Place the propTypes definition at the top of the component. If using a stateless function component, place it above the declaration of the function.

  • Where the children property is used, consider validating the children.