summaryrefslogtreecommitdiffstats
path: root/devtools/docs/contributor/contributing/javascript.md
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/docs/contributor/contributing/javascript.md')
-rw-r--r--devtools/docs/contributor/contributing/javascript.md87
1 files changed, 87 insertions, 0 deletions
diff --git a/devtools/docs/contributor/contributing/javascript.md b/devtools/docs/contributor/contributing/javascript.md
new file mode 100644
index 0000000000..25d1f1c251
--- /dev/null
+++ b/devtools/docs/contributor/contributing/javascript.md
@@ -0,0 +1,87 @@
+# 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](http://eslint.org/) 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](./eslint.md).
+
+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.import("...");`,
+* use Maps, Sets, WeakMaps when possible,
+* use [template strings](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) 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
+```javascript
+// 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) 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](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function).
+
+## React & Redux
+
+There are React-specific code style rules in the .eslintrc file.
+
+### Components
+
+* Default to creating components as [stateless function components](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions).
+* 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](https://facebook.github.io/react/docs/reusable-components.html#prop-validation) 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](http://www.mattzabriskie.com/blog/react-validating-children).