Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disallow assignment to exports (node/no-exports-assign) #1400

Closed
feross opened this issue Sep 5, 2019 · 6 comments
Closed

Disallow assignment to exports (node/no-exports-assign) #1400

feross opened this issue Sep 5, 2019 · 6 comments

Comments

@feross
Copy link
Member

feross commented Sep 5, 2019

https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-exports-assign.md

Assigning to the exports variable does not work as expected.

// This assigned object is not exported.
// You need to use `module.exports = { ... }`.
exports = {
    foo: 1
}

This rule is aimed at disallowing exports = {}, but allows module.exports = exports = {} to avoid conflict with node/exports-style rule's allowBatchAssign option.

👍 Examples of correct code for this rule:

/*eslint node/no-exports-assign: error */

module.exports.foo = 1
exports.bar = 2

module.exports = {}

// allows `exports = {}` if along with `module.exports =`
module.exports = exports = {}
exports = module.exports = {}

👎 Examples of incorrect code for this rule:

/*eslint node/no-exports-assign: error */

exports = {}

I don't expect this to be controversial

@mightyiam
Copy link
Member

I'm not sure how this rule is not a subset of exports-style.

{
    "node/exports-style": [
        "error",
        "module.exports" // isn't this `no-exports-assign`?
        {
            "allowBatchAssign": false
        }
    ]
}

@feross
Copy link
Member Author

feross commented Sep 5, 2019

This rule specifically catches the mistake of writing e.g.

exports = {}
exports.foo = 42

and expecting that foo has been exported. In fact, the only thing this code does is just update the local variable exports to an object with foo. But module.exports is still the original object.

This is because node.js implicitly does something like this at the top of each module:

// implicitly
var module = {}
var exports = module.exports = {}

And then it uses whatever is on module.exports to decide what is actually exported. So, you can see how exports = {} would just overwrite the local variable exports.

@mightyiam
Copy link
Member

Thank you for the explanation. That part I understand. The part that seems unclear regarding the exports-style rule is whether it already catches that or not. I guess it doesn't...

@mightyiam
Copy link
Member

In which case this seems like a good idea. Of course, const exports = 'foo' is allowed, right? Or var/let.

@feross
Copy link
Member Author

feross commented Sep 5, 2019

Deciding whether to forbid exports vs. module.exports is another discussion. But either way that goes, this rule is useful because it catches code that is always an error. No one should do exports = ....

Haven't tested it with const exports = 'foo' yet but that should be allowed or else this rule has a bug.

@feross feross modified the milestones: standard 15, standard 16 Oct 22, 2020
@feross feross changed the title Disallow assignment to exports Disallow assignment to exports (node/no-exports-assign) Oct 29, 2020
@feross
Copy link
Member Author

feross commented Oct 29, 2020

0% ecosystem failure. This will ship in standard 16!

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 30, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Archived in project
Development

No branches or pull requests

2 participants