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

valid-typeof does not report invalid comparisons to undefined #6698

Closed
not-an-aardvark opened this issue Jul 17, 2016 · 18 comments
Closed

valid-typeof does not report invalid comparisons to undefined #6698

not-an-aardvark opened this issue Jul 17, 2016 · 18 comments
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 enhancement This change enhances an existing feature of ESLint rule Relates to ESLint's core rules

Comments

@not-an-aardvark
Copy link
Member

What version of ESLint are you using? 3.1.0

What parser (default, Babel-ESLint, etc.) are you using? default

Please show your full configuration:

{
  "rules": {
    "valid-typeof": 2
  }
}

What did you do? Please include the actual source code causing the issue.

// oops, this was probably supposed to be the string 'undefined'
if (typeof window === undefined) {
  foo();
}

What did you expect to happen?

I expect ESLint to report an error, since the global undefined value is not a valid typeof comparison.

What actually happened? Please include the actual, raw output from ESLint.

ESLint did not detect any errors.

@eslintbot eslintbot added the triage An ESLint team member will look at this issue soon label Jul 17, 2016
@ilyavolodin ilyavolodin added question This issue asks a question about ESLint and removed triage An ESLint team member will look at this issue soon labels Jul 17, 2016
@ilyavolodin
Copy link
Member

How should we handle the case like this:

var undefined = "undefined";
if (typeof window === undefined) {
  foo();
}

ESLint is a static analysis tool. We can't track values of variables, and undefined can be reassigned when using ES3.

@ljharb
Copy link
Sponsor Contributor

ljharb commented Jul 17, 2016

undefined can be redefined everywhere, except in the global scope in ES5+.

That said, eslint certainly should be able to track the values of variables in the same file, and couldn't var undefined, let undefined, or const undefined being present cause the requested warning to be skipped?

@not-an-aardvark
Copy link
Member Author

Thanks for the explanation @ilyavolodin; I had forgotten that it was possible to redeclare undefined as a local variable.

Based on this table, it seems like all modern browsers don't allow undefined to be redeclared in the global scope. I'm unsure of whether ESLint supports any of the environments that do allow redeclaration. (If I'm understanding it correctly, @ljharb's solution only works if the global undefined value is immutable.)

@ilyavolodin
Copy link
Member

ilyavolodin commented Jul 17, 2016

Unfortunately, tracking value in JS is not quite that easy:

eval("var und" + "efined = \"undefined\""); //or a million other ways to set a value of a variable
if (typeof window === undefined) {
  foo();
}

We currently don't have a way to reliably track variable values. It's something we want to look into in the future, but nothing is currently available for this.

@not-an-aardvark We don't set requirements for JS support, there are plenty of sites that still have to support IE8 (or even IE6 in some cases) out there, so we can't assume that everyone is writing ES5+ (I know I don't, most of the time).

@ljharb
Copy link
Sponsor Contributor

ljharb commented Jul 17, 2016

@ilyavolodin would it not be reasonable to say that if a user is doing something like that, they are welcome to turn off the linter rule?

@not-an-aardvark
Copy link
Member Author

@ilyavolodin Fair enough. While I understand your reasoning, it's unfortunate that we have to account for that, since I'm guessing statements such as typeof x === undefined are errors much more often than not.

@ilyavolodin
Copy link
Member

@ljharb That's one way to go, but there are much simpler cases too:

var undefined = require('./my-file');

In any case, while we can track variable declarations currently through Escope, it doesn't track variable values. As I said, that's something we want to look into in the future. For now we just don't have the tools required to do this.

@ljharb
Copy link
Sponsor Contributor

ljharb commented Jul 17, 2016

I think this would still be useful, even if there exists some edge cases it would be a false positive on. Anyone doing var undefined = is violating (what should be) another linter rule anyways :-p

eslint isn't just to catch errors, and most rules don't apply to every scenario, which is why they're configurable. If this was an option - especially defaulted to off - then any users who wish to redefine undefined would certainly want to leave that option disabled, and the rest of us can still benefit from it.

@ilyavolodin ilyavolodin added enhancement This change enhances an existing feature of ESLint rule Relates to ESLint's core rules evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion and removed question This issue asks a question about ESLint labels Jul 17, 2016
@ilyavolodin
Copy link
Member

Very well, that's a valid argument. I marked this issue as evaluating and enhancement. Let's see what the team thinks.

@platinumazure
Copy link
Member

platinumazure commented Jul 18, 2016

I definitely think valid-typeof should enforce comparisons against string literals, since most of the time that is the intent. If this needs to be behind an option to avoid breaking existing behavior, I would be fine with that, but I strongly believe it should be possible for users to restrict valid-typeof to compare against only literals containing the strings that the typeof operator can return.

And I would argue that this concern (wanting to compare against string) has nothing whatsoever to do with the value of undefined. I consider this equal to wanting to flag typeof foo === string (except that no-undef should catch the bad string variable). The whole point is that typeof returns a string and so users should compare it to a string literal (and ideally one of the known return values).

@nzakas
Copy link
Member

nzakas commented Jul 18, 2016

I think the only way we can possibly do something that makes sense is to add an option like requireStringLiterals that ensures the RHS is always a string. Anything else is just guessing and not appropriate for this rule.

@not-an-aardvark
Copy link
Member Author

Ping on this issue; is there enough support for it that a PR to add the requireStringLiterals option would be accepted?

@platinumazure
Copy link
Member

I can get behind that option. 👍 from me.

@ilyavolodin
Copy link
Member

I'll support an option for comparing to literals only. 👍

@platinumazure
Copy link
Member

@ilyavolodin Literals === string literals, or any literals? Not much point in allowing comparisons to boolean or numeric literals, no?

@ilyavolodin
Copy link
Member

Sorry, I meant string literals.

@vitorbal
Copy link
Member

I'll 👍 a requireStringLiterals option too, but we still need a champion!

not-an-aardvark added a commit to not-an-aardvark/eslint that referenced this issue Aug 17, 2016
not-an-aardvark added a commit to not-an-aardvark/eslint that referenced this issue Aug 18, 2016
@btmills
Copy link
Member

btmills commented Aug 18, 2016

👍 I'll champion, marking as accepted! I'll review #6923 later today.

@btmills btmills 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 Aug 18, 2016
not-an-aardvark added a commit to not-an-aardvark/eslint that referenced this issue Aug 19, 2016
@eslint-deprecated eslint-deprecated bot locked and limited conversation to collaborators Feb 6, 2018
@eslint-deprecated eslint-deprecated bot added the archived due to age This issue has been archived; please open a new issue for any further discussion label Feb 6, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
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 enhancement This change enhances an existing feature of ESLint rule Relates to ESLint's core rules
Projects
None yet
Development

No branches or pull requests

8 participants