Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
@distributive/eslint-config
Advanced tools
The shareable ESLint configuration used at Distributive when contributing to the Distributive Compute Protocol (DCP).
This document is an incomplete draft of a proposed style guide for JavaScript written at Distributive.
Last Updated: July 2021, July 2023
CommonJS is preferred, either 1.0 or 2.0 with the BravoJS cjs-node shim.
Either ESMs or BravoJS (CommonJS modules 2.0) are acceptable. WebPack is also acceptable, however should only be used if there is a significant technical or maintenance advantage for the specific project; there are WebPack interoperability gotchas with dcp-client etc.
Either traditional ES5 or ES6 class syntax is acceptable.
NodeJS implements a module system which is nearly CommonJS Modules/1.0.0 compliant, however they all several extensions which are not.
The most important property to be aware of is that CommonsJS modules are intended to be singletons, returning only one exports object from the first use of require
to address a given module. Failure to follow this guidance produces modules which can have problems with cyclical dependency graphs.
Do not use: exports object replacement via return
return exports; /* replace exports object */
Do not use: exports object replacement via assignment
module.exports = { some_new_object }; /* replace exports object */
Don't decorate the exports
object via Object.assign()
with nested declaration. Instead, decorate it via Object.assign()
without nesting, or via property assignment.
// Bad
Object.assign(exports, {
a: function a() {},
b: function b() {},
});
// Good
function a() {}
function b() {}
Object.assign(exports, { a, b });
// Good
exports.a = function a() {}
exports.b = function b() {};
{
and before }
if
, for
, and function
keywords are always followed by a spaceif ((a + b) > (c + d))
{
print('Hello, world');
}
kebab-case
.camelCase
window.XMLHttpRequest
at Distributive, it would have been called window.xmlHttpRequest
.CamelCaseWithUppercaseFirstCharacter
this
, it should be called that
and assigned as close to the top of its scope as possible.error
codePointAt
and friends whenever possible, rather than manipulating surrogate pairsEither British, Canadian, or American English are acceptable throughout the code base, however public APIs must always use American English.
Referrer is always spelling wrong - referer
. Don't blame me, blame Phillip Hallam-Baker.
Upper case and lower case are each two words.
There are two bracing styles in use simultaneously throughout the Distributive JS Style:
,
, )
, or ;
. "1tbs Style".Lexical Braces.
function helloWorld()
{
console.log('hello, world');
}
Lexical Braces. Zero-statement blocks may use both braces on one line. One-statement blocks may omit the braces unless the block is below an else statement.
// Good
try
{
for (let i=0; i < 10; i++)
{
console.log(i);
}
}
catch(error) {}
// Good
if (Math.random() > 1)
console.error('something very bad just happened');
// Good
if (a)
console.log('yes');
else
{
console.log('no');
throw new Error('uh-oh');
}
Not Allowed:
// Bad
if (!a)
{
console.log('no');
throw new Error('uh-oh');
}
else
console.log('yes');
Literal Braces. Very short objects may appear on a single line. Trailing commas in property lists are allowed but not required.
var ballDuck = {
type: 'base',
color: 'white',
stiching: { color: 'red' },
};
Same as object literals, but use square brackets in place of literal braces.
var a = [ 1, 2, 3 ];
var b = [ 4,
5,
6,
];
Literal Braces. When combined with an assignment to a property of the module exports
object, either Literal Braces OR Lexical Braces are permitted.
var foo = function foo() {
var a = [1, 2, 3];
};
var bar = () => {
var b = [4, 5, 6];
};
module.exports.foo2 = function foo2() {
var a = [1, 2, 3];
};
Comments should explain what the program, module, or block does. They should not explain JavaScript syntax or APIs of other units.
/* information
* more information
*/
a) the opening brace it is paired with is at the incorrect indentation level; for example, when the module.declare boilerplate is used but the module code still begins at column 0, or b) the opening brace is more than 50 line of code away (Note that this generally means that your program should be refactored for a flatter layout)
console.log('hello, world');
console.log("nice day, isn't it?");
.eslintrc.js
, such as dcpConfig
and window
.const
, must be manually hoisted to the top of their scopevar
or const
declarations are preferred for variables which have module-wide or function scope__
.const that=this
; use lightweight functions instead if that is what you need._
loop invariants should be declared with const
or let
(never var
) within the loop initializer whenever possible.
for (let i = 0; i < 10; i++)
{
// ...
}
Lexical bracing may be used within case statements, provided it is used consistently throughout a given switch statement.
switch (true)
is expressly prohibited.switch (type)
{
case 'medicine':
usedForFun = false; // fall through
case 'base':
case 'volley':
colour = 'white'; // fall through
case 'basket':
round = true;
break;
case 'foot':
round = false;
break;
}
Long expressions not joined by &&
and ||
should break so the operator starts on the second line and starting in the same column as the beginning of the expression in the first line. This applies to ?:
, binary arithmetic operators including +
, and member-of operators. Rationale: an operator at the front of the continuation line makes for faster visual scanning, as there is no need to read to the end of line. Also there exists a context-sensitive keyword hazard in JavaScript (https://bugzilla.mozilla.org/show_bug.cgi?id=442099) which can be avoided by putting .
at the start of a continuation line, in long member expression.
==
is preferred to ===
Unary keyword operators, such as typeof
, should not have their operand parenthesized; e.g. use typeof 'foo' === 'string'
.
Types should be coerced as explicitly as possible
==
and friends, use ===
etc==
must be used for a coerced comparison, a comment is probably warranted.!!abc
and +xyz
; use Boolean(abc)
and Number(xyz)
instead.Prefer then(onFulfilled).catch(onRejected)
over then(onFulfilled, onRejected)
.
Why? In the second form,
onFulfilled()
rejecting isn't caught beonRejected()
. Although, you know, if you specifically need the first behaviour, go ahead and use it, but if the reason is not obvious it probably deserves a comment.
Always write comparisons with laser precision:
if (x > a)
.if (!(x > a))
NOT if (x <= a)
.... unless your test also tests to make sure that both x and are numbers which are not NaN.x == true
or x == false
. Use (x)
or (!x)
instead. x == true
, is certainly different from if (x)
! Compare objects to null
, numbers to 0
or strings to ""
, if there is chance for confusion.Is never a good idea. Inherit from the standard classes instead.
Avoid multi-tier function chaining when possible. Use intermediate variables to break up the chain. This makes it easier to inspect links in the chain with the debugger, and provides an opportunity for documentation via naming.
There is no reason in DCP to use any JavaScript dialect which predates ES-5, including detecting excessively-old engines. You are free to pretend these do not exist unless unless you have a very, very, very specific use-case.
This code should be avoided, unless it is technically infeasible to so. Note that source files cannot be naively converted from non-strict to strict; they must be thoroughly tested during the maintenance cycle.
Never count on automatic hoisting of functions declared in block-level statements in ES-5 non-strict code: you can create cross-browser bugs here, as the behaviour was underspecified in ES-3 and remains so in ES-5 non-strict. See https://bugzilla.mozilla.org/show_bug.cgi?id=585536 for a full treatise.
Do Not Use: this code throws a reference error in some implementations because returnData is undefined.
exports.getGroups = function (x)
{
{
var query = { success: returnData, error: cbFailure, method: 'get', table: 'Token' };
query.prototype = { value: x[index] };
for (let index = 0; index < x.length; index++)
{
function cbFailure(res) { }
function returnData(data) { }
db.act(query);
}
}
}
.js
extension#! /usr/bin/env node
Example Program:
#! /usr/bin/env node
/**
* @file cgadm Compute Group Administration tool
* A tool for administering compute groups for scheduler sysadmins
* @author Wes Garland, wes@distributive.network
* @date June 2021
*/
'use strict';
const path = require('path');
const process = require('process');
async function main()
{
var r = Math.random();
console.log('Hello, world');
for (let i=0; i < r*100; i++)
{
if (i % 3 === 0)
console.log('hello', i);
}
}
EventEmitter
-like object, use addEventListener
and removeEventListener
.
Why?
EventEmitter
-like objects have 3 different ways of doing the same thing:addEventListeer
/removeEventListener
,addListener
/removeListener
, andon
/off
. Sticking with the naming convention of the interface for theEventTarget
Web API results in a more consistent codebase.
FAQs
The shareable ESLint configuration used at Distributive when contributing to the Distributive Compute Protocol (DCP).
We found that @distributive/eslint-config demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.