Skip to content

New rule: Disallow callbacks with errors and object/array deconstructors at the same time #153

Open
@msiebuhr

Description

@msiebuhr

Purpose

Prevent invalid object/error de-constructing when used with error arguments.

function some_callback(err, {foo, bar}) {
    if (err) { console.error(err); }
    console.log(foo, bar);
 }

// Normal use
some_callback(undefined, {foo: 'some', bar: 'arg'});

// When failures occur, callbacks are usually called with just the error and no further arguments:
some_callback(new Error('Could not foo or bar'))
// TypeError: Cannot destructure property `foo` of 'undefined' or 'null'.

What category of rule is this? (place an "X" next to just one item)

[x] Warns about a potential error (problem)
[ ] Suggests an alternate way of doing something (suggestion)
[ ] Enforces code style (layout)
[ ] Other (please specify:)

Why should this rule be included in ESLint (instead of a plugin)?

I've seen quite a few people make this mistake and not realize that their error-handling flow is itself broken. We found at least two "vanishing errors" in our code-bases and quite a few potential ones by applying this rule.

Rough implementation

module.exports = {
    meta: {
        type: "problem",
        docs: {
            description: "Disabllow function argument deconstructuring with error arguments",
            category: "",
            recommended: true,
            url: ""
        }
    },
    create: function (context) {
        function TestFunctionArguments(node) {
            // Not relevant for functions with less than two arguments
            if (!node.params || node.params.length < 2) { return; }

            // Is the first argument named `err`
            const [firstParam, ...restParams] = node.params;
            if (firstParam.type !== 'Identifier' || firstParam.name !== 'err') { return; }

            for (const r of restParams) {
                if (r.type !== 'ArrayPattern' && r.type !== 'ObjectPattern') { continue; }

                context.report({
                    node: r,
                    message: 'Cannot use `err` argument with an {{ type }}',
                    data: {
                        type: r.type
                    }
                });
            }
        }

        return {
            FunctionDeclaration: TestFunctionArguments,
            FunctionExpression: TestFunctionArguments,
            ArrowFunctionExpression: TestFunctionArguments
        };
    }
};

(Moved from eslint/eslint#11539)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions