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

Rule Proposal: disallow the updates of imported bindings #12237

Assignees
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion archived due to age This issue has been archived; please open a new issue for any further discussion feature This change adds a new feature to ESLint rule Relates to ESLint's core rules

Comments

@mysticatea
Copy link
Member

Please describe what the rule should do:

Disallows the updates of imported bindings with ES Modules because such an update will cause runtime errors.

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

[X] Warns about a potential error (problem)

Provide 2-3 code examples that this rule will warn about:

import mod, { named } from "./mod.mjs"
import * as mod_ns from "./mod.mjs"

mod = 1 // ERROR: 'mod' is readonly.
named = 2 // ERROR: 'named' is readonly.
mod_ns.named = 3 // ERROR: the members of 'mod_ns' is readonly.
mod_ns = {} // ERROR: 'mod_ns' is readonly.

mod++ // ERROR: 'mod' is readonly.
named++ // ERROR: 'named' is readonly.
mod_ns.named++ // ERROR: the members of 'mod_ns' is readonly.
mod_ns++ // ERROR: 'mod_ns' is readonly.

// Known limitation
function test(obj) {
    obj.named = 4 // Not errored because 'obj' is not namespace objects.
}
test(mod_ns) // Not errored because it doesn't know that 'test' updates the member of the argument.

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

Because this is an essential of the language feature. This rule is very similar to core rules no-const-assign that catches runtime errors.

The rule name may be no-import-assign.

Are you willing to submit a pull request to implement this rule?

Yes.

@mysticatea mysticatea added triage An ESLint team member will look at this issue soon rule Relates to ESLint's core rules feature This change adds a new feature to ESLint labels Sep 7, 2019
@mysticatea mysticatea self-assigned this Sep 7, 2019
@mysticatea mysticatea added evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion and removed triage An ESLint team member will look at this issue soon labels Sep 7, 2019
@mdjermanovic
Copy link
Member

I guess there is no reason not to use this rule, it should be recommended in the next major version?

In mod_ns.named = 3 it doesn't matter whether the 'named' property (named export) exists, because mod_ns is frozen so it's always a runtime error?

Also, the rule should still allow named.foo = 3 and mod_ns.named.foo = 3?

@aladdin-add aladdin-add added accepted There is consensus among the team that this change meets the criteria for inclusion and removed evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion labels Sep 8, 2019
@mysticatea
Copy link
Member Author

I guess there is no reason not to use this rule, it should be recommended in the next major version?

Yes, I think so.

In mod_ns.named = 3 it doesn't matter whether the 'named' property (named export) exists, because mod_ns is frozen so it's always a runtime error?

Correct. The rule reports for all properties of namespace objects. It's runtime errors regardless of the existence of named exported members.

Also, the rule should still allow named.foo = 3 and mod_ns.named.foo = 3?

Correct. named is not a namespace object.

@platinumazure
Copy link
Member

Would no-reassign-imports or no-import-reassign be a clearer name?

I realize that the actual import isn't technically an assignment statement, but I wonder if it would be easier for most users if they see the initial import as an "assignment", and then the actual assignment (that we warn on) would be a "reassignment".

I don't feel strongly about the name, though.

@mysticatea
Copy link
Member Author

I prefer no-import-assign because most of the similar rules have the same naming convention.

  • no-const-assign for const declarations
  • no-func-assign for function declarations
  • no-class-assign for class declarations
  • no-ex-assign for catch bindings
  • no-global-assign for built-in globals

Only one exception is:

  • no-param-reassign for parameters

@ljharb
Copy link
Sponsor Contributor

ljharb commented Sep 9, 2019

Need it wait for a major? Code that can’t possibly execute isn’t really “breaking” people to warn on.

I think no-import-reassign makes the most sense, since it’s closest to no-param-reassign, conceptually.

@mysticatea
Copy link
Member Author

Need it wait for a major?

Yes. our Semantic Versioning Policy has declared it. And it might break people that are using ES Modules syntax with bundlers/transpilers.

@platinumazure
Copy link
Member

New rules can be semver-minor. The only thing that must be semver-major is adding the rule to eslint:recommended.

@mysticatea
Copy link
Member Author

mysticatea commented Sep 9, 2019

I think no-import-reassign makes the most sense, since it’s closest to no-param-reassign, conceptually.

My position is that we should rename no-param-reassign to no-param-assign. Because no-param-reassign sounds like it allows the first assign in order to handle overloads, but not in fact.


I will work on this.

@ljharb
Copy link
Sponsor Contributor

ljharb commented Sep 9, 2019

The first assignment is the function itself; reassign is the correct name imo.

@mysticatea
Copy link
Member Author

mysticatea commented Sep 9, 2019

In my feeling, as I enumerated in #12237 (comment), no-param-reassign is the only exception of similar rules. So I feel there is special reason for the word selection. And overload handling is the one for parameters but not for the others. Therefore, I feel no-param-reassign has chosen the reassign word for overload handling. But it's not right.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.