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

How to truly enforce no global pollution in browser code? #4906

Closed
cowchimp opened this issue Jan 10, 2016 · 7 comments
Closed

How to truly enforce no global pollution in browser code? #4906

cowchimp opened this issue Jan 10, 2016 · 7 comments
Labels
archived due to age This issue has been archived; please open a new issue for any further discussion question This issue asks a question about ESLint

Comments

@cowchimp
Copy link
Contributor

Hi.

I'm having difficulty composing existing eslint rules in a way that should be relevant for many people (IMHO).
There's a good chance I'm missing something basic and that this can be achieved. But in case it's not I would be interested in sending in a PR.

My goal is simple:
To make sure no script relies on globals defined in another script.
I'm assuming that's something many people will want to enforce on browser js codebases that used to rely on IIFEs and are slowly migrating them to rely on AMD\Commonjs\ES6 Modules.

The problem:
The no-undef rule is obviously the go-to rule for this.
It will definitely catch globals referenced like this:
SomeCustomGlobalObjectDefinedElsewhere.init();
And it can also catch globals referenced like this:
window.SomeCustomGlobalObjectDefinedElsewhere.init();
but only if you do not specify browser as the environment.
And if you don't do that, then all of a sudden you'll get false reports as if these lines are invalid
window.location.href = 'http://www.github.com';
var item = localStorage.getItem('someKey');
setTimeout(function() { }, 10);
Alternatively, if you do specify browser as the environment then this invalid line becomes valid:
window.SomeCustomGlobalObjectDefinedElsewhere.init();

References:
I looked at no-implicit-globals.
Also looked at the proposed no-restricted-properties (#3218) and no-restricted-globals (#3966) and the open issue about no-console being tricked by referencing window.console (#4826).
But my case is kind of the opposite. I want to allow all of window's native properties, but to disallow piggybacking on window to define globals.

I'm using v2.0.0-alpha-1.

If you need any more info from me, please LMK.

Thanks.

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@eslintbot
Copy link

@cowchimp Thanks for the issue! If you're reporting a bug, please be sure to include:

  1. The version of ESLint you are using (run eslint -v)
  2. What you did (the source code and ESLint configuration)
  3. The actual ESLint output complete with numbers
  4. What you expected to happen instead

Requesting a new rule? Please see Proposing a New Rule for instructions.

@eslintbot eslintbot added the triage An ESLint team member will look at this issue soon label Jan 10, 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 Jan 10, 2016
@ilyavolodin
Copy link
Member

I think this would be hard to do, because no-undef has no way to check properties of generic object for existence. So if you do foo.blah() it would be always OK, but if you do window.blah() it will not? That would be very confusing.

@cowchimp
Copy link
Contributor Author

Thanks for the reply.
Putting aside the implementation complexity for a minute, what do you think about the validity of this use-case?
I think there's value of treating window as a special object. Without this you can always sneak in global references by referencing them off window in browser code.
As for how to implement it- I don't have a strong enough familiarity with the codebase to comment.
I did take a look at the addDeclaredGlobals function and the implementation of no-undef.
Is there no way to identify when window.someProperty is used, and then check someProperty against the list of known browser globals in the globals module?

@nzakas
Copy link
Member

nzakas commented Jan 10, 2016

You can manually look for MemberExpression nodes that have window as the object name and check the property name against a list. However, window is only special in a browser context, and it's not the only special object: self, top, and parent are all similar.

The other problem is knowing if creating globals is allowed. Should window.foo = bar trigger an error if foo doesn't already exist?

So, I think what you're asking for is a bit beyond what we can do in a generic way. You can certainly create a custom rule, though.

@cowchimp
Copy link
Contributor Author

cowchimp commented Mar 1, 2016

Hi guys,
I wrote an eslint plugin with a rule that tries to enforce what I described above.
Could you please take a look, give me feedback, and weigh-in on whether or not it has enough merit to be a built-in eslint rule (feel free to close this issue if it does not).

I called the rule no-restricted-global-extend.
It lets you define an identifier of an object which is a reference to the global scope (e.g. window) and will alert if you try to call a property on that object which does not match a valid variable that's available in the global scope.
There are examples in the README and in the tests for the rule.

I chose that name for the rule because it's similar in a way to the proposed no-restricted-properties rule in #3218 and to no-native-extend, but it can be changed of course.

Also, I think I need to address whether or not the global variable I'm comparing to is writeable or not, so consider this a proof-of-concept at this point.

@ilyavolodin
Copy link
Member

Thanks for the link. Implementation looks reasonable, but I still don't think it's a good fit for the core. There are so many ways of bypassing this rule in real life, that I don't think it would have a lot of value. As @nzakas mention, self, top and parent are also referring to window. But even if you were to add them to the rule through options, the rule will not capture window.document.foo = "bar".

@alberto
Copy link
Member

alberto commented Apr 21, 2016

Closing since question was answered.

@alberto alberto closed this as completed Apr 21, 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
archived due to age This issue has been archived; please open a new issue for any further discussion question This issue asks a question about ESLint
Projects
None yet
Development

No branches or pull requests

5 participants