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

tools: don't use global Buffer and add linter rule for it #1794

Closed
wants to merge 4 commits into from

Conversation

silverwind
Copy link
Contributor

This does a few things to the linter configuration:

  • instead of relying on the predefined node environment, specify all our globals manually and as read-only.
  • enable no-undef to error on undefined variable access.
  • add globalReturn which allows to return from the top scope. This was implied by the node option before.

A number of tests intentionally use undefined globals to trigger an error or set globals (in the vm tests). I had to exclude those tests with an eslint-disable comment. If these comments are too noisy, we could alternatively disable that rule for all tests.

I might have missed a few globals from the v8 environment. Object.keys(global) doesn't list many of them, presumably because they are unenumerable. Any better ideas on how to discover globals?

cc: @Fishrock123 @domenic

@silverwind
Copy link
Contributor Author

@Fishrock123 what's the plan exactly with Buffer usage mentioned in #1770? Should it error as soon as Buffer is used inside lib?

@@ -106,16 +106,12 @@ function checkResults(expected_results, results) {
var actual = results[k],
expected = expected_results[k];

if (typeof expected === 'function') {
expected(r[k]);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

@Fishrock123
Copy link
Member

@Fishrock123 what's the plan exactly with Buffer usage mentioned in #1770? Should it error as soon as Buffer is used inside lib?

Probably? How else would it work?

@@ -1,3 +1,4 @@
/* eslint-disable no-undef */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps disable for all tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think it's better that way, less noisy comments all over the tests, will work something out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no-undef is one of the few rules that do something good (as opposed to the most eslint rules that do nothing except for enforcing a religion code style). I don't think it should be disabled for all tests, because it could catch real errors.

What about explicitly declaring globals in every file?

/* globals: undefined_reference_error_maker */

I don't remember the exact syntax, but I think you can add globals on per-file basis. And most linters (jshint, eslint) respect that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree generally to using no-undef, but it is pretty common to use undefined globals in tests to trigger an error. With the rule enabled, one would have to research how to configure the linter when writing a test, which I'd like to avoid.

Using a global comment is pretty equivalent to disabling the rule, both require additional ugly comments. I think we're fine with just disabling no-undef in the test directory.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe ask people to trigger an error differently?

my favorite way is []()

@silverwind
Copy link
Contributor Author

@Fishrock123 I'll just comment out the Buffer global in .eslintrc to indicate it's there but not allowed to be used directly. We want to use require('buffer').Buffer in place of it, right?

@Fishrock123
Copy link
Member

@silverwind correct.

@silverwind
Copy link
Contributor Author

Rebased and disabled no-undef for tests, also moved the rule to the correct category in .eslintrc.

@Fishrock123 There are 83 occasions where Buffer is used directly in lib. Should I go for it and replace them with a non-global?

@silverwind
Copy link
Contributor Author

@Fishrock123 I'll follow up with a port of nodejs/node-v0.x-archive@523929c in another PR. Does this one LGTY?

@Fishrock123
Copy link
Member

@silverwind I'd prefer if you did the commits in this order: fix tests, apply full remove-global-buffer patch, add linting.

That being said, this still doesn't seem to catch global Buffer use with ./iojs tools/eslint/bin/eslint.js src lib test --reset?

@silverwind
Copy link
Contributor Author

Well I suppose I can split these up into multiple commits and add the Buffer thing too in its own commit.

@silverwind silverwind force-pushed the linter-global branch 2 times, most recently from 002a770 to c38e3cb Compare May 29, 2015 17:42
@silverwind
Copy link
Contributor Author

Alright, split up in 3 commits now. The circular dependency described in nodejs/node-v0.x-archive#8603 (comment) didn't happen, so no workaround was needed.

@silverwind
Copy link
Contributor Author

@silverwind
Copy link
Contributor Author

Updated and cleaned up the list of globals, which is now sorted in categories. @Fishrock123 PTAL

__dirname : false
global : false
GLOBAL : false
root : false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GLOBAL and root are going to be deprecated (#1838). Are they still being used in the code base ? If not they do not need to be here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But they ll still be there till removal, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They're not used and no one sane would use them, so good call on removing them.

@silverwind
Copy link
Contributor Author

Filed sindresorhus/globals#33 for the missing DataView builtin in eslint, until then we probably have to keep it listed for correctness (it's only used in one test).

@silverwind
Copy link
Contributor Author

Also filed eslint/eslint#2657 for a simpler way to undefine globals.

@silverwind
Copy link
Contributor Author

Don't review yet, I'll try creating a custom eslint rule for the Buffer case, which would drastically simplify the current changes to globals and also print a nice custom error message in the linter.

@silverwind
Copy link
Contributor Author

Here's my current custom rule, which @xjamundx graciously provided:

'use strict';

module.exports = function(context) {
  var required = false;
  return {
    CallExpression: function(node) {
      if (node.callee.type === 'Identifier' &&
          node.callee.name === 'require') {
        if (node.arguments.length && node.arguments[0].value === 'buffer') {
          required = true;
        }
      }
    },
    Identifier: function(node) {
      if (!required && node.name === 'Buffer') {
        context.report(node, "Make sure to require('buffer').Buffer before using Buffer");
      }
    }
  }
}

It's almost working, except that it does detect an error on the require line itself:

const Buffer = require('buffer').Buffer;
//    ^--- errors here

Any suggestions?

@rlidwka
Copy link
Contributor

rlidwka commented Jun 7, 2015

I think your suggestion in eslint/eslint#2657 is much better than this headache with custom rules. Maybe re-open it?

@silverwind silverwind changed the title tools: strictly define globals in eslint tools: don't use global Buffer and add linter rule for it Jun 7, 2015
@silverwind
Copy link
Contributor Author

Up for review again!

@trevnorris
Copy link
Contributor

I'm realizing right now that unless we make the exports Buffer property read only it can still be overridden just as easily by users. So what's the point of forcing it to be required in all files?

@silverwind
Copy link
Contributor Author

I don't see writable Buffer as an problem really. It could allow for a custom Buffer implementation and a lot of things in node can be overridden right now anyways.

As for the reason of this change, there's a series of issues/prs that lead to it:

nodejs/node-v0.x-archive#8588
nodejs/node-v0.x-archive#8603
#1770

@trevnorris
Copy link
Contributor

Ah yes. I forgot about the REPL issue. Thanks for the reminder.

I don't see the same change here for assert.js as in the final commit in nodejs/node-v0.x-archive@523929c (using b.Buffer instead). Has that issue been fixed?

@silverwind
Copy link
Contributor Author

Yes, I think so. Tests were passing so I assumed it was fixed.

@Fishrock123
Copy link
Member

@trevnorris I looked at that while attempting to port the original patch... I'm not sure why that was done in the first place?

Oh, found it here: nodejs/node-v0.x-archive#8603 (comment) Looks like there was a circular dependancy issue?

@silverwind
Copy link
Contributor Author

@Fishrock123 @trevnorris @vkurchatkin I don't understand why this race condition happened last time, but it seems to be gone now, all tests are passing so I assume it must've been fixed in the meanwhile.

I rebased and did a minor correction to the require-buffer rule (switched useless some for forEach). I also caught two errors through no-undef that were introduced in 5795e83, fix for that in #1951.

Enables the following rules:

- no-undef: Valuable rule to error on usage of undefined variables
- require-buffer: Custom rule that forbids usage of the global Buffer
  inside lib/ because of REPL issues.
@silverwind
Copy link
Contributor Author

Did another small correction to the printed message. Please review.

@@ -1,3 +1,4 @@
/* eslint-disable require-buffer */
'use strict';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought 'use strict' had to go on the first line of either the file or function. Does that exclude comments?

/cc @domenic

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nm. see it doesn't matter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure it does exclude comments, considering the amount of files with copyright hats at the very top.

@trevnorris
Copy link
Contributor

Have one nit, but LGTM.


module.exports = function(context) {
return {
"Program:exit": function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above ^^

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix that.

@trevnorris
Copy link
Contributor

Great thanks. I'm cool with this change.

silverwind added a commit that referenced this pull request Jun 11, 2015
Fixes all cases of undeclared variable access as uncovered by the
no-undef rule of eslint.

PR-URL: #1794
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
silverwind added a commit that referenced this pull request Jun 11, 2015
Port of nodejs/node-v0.x-archive#8603

The race condition present in the original PR didn't occur, so no
workaround was needed.

PR-URL: #1794
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
silverwind added a commit that referenced this pull request Jun 11, 2015
Enables the following rules:

- no-undef: Valuable rule to error on usage of undefined variables
- require-buffer: Custom rule that forbids usage of the global Buffer
  inside lib/ because of REPL issues.

PR-URL: #1794
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
@silverwind
Copy link
Contributor Author

Thanks! Landed in ff8202c .. 6e4d302.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants