[go: nahoru, domu]

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

Add eslint and update noVNC to ES6 #1013

Merged
merged 3 commits into from
May 25, 2018
Merged

Conversation

juanjoDiaz
Copy link
Contributor

New attempt to move the library to ES6.

I'd start pushing more simple commits so it's simple to review.

@juanjoDiaz juanjoDiaz changed the title Add eslint and fix reported issues Add eslint and update noVNC to ES6 Feb 1, 2018
@juanjoDiaz juanjoDiaz force-pushed the es6_refactor_2 branch 4 times, most recently from a71503d to ff3c10c Compare February 1, 2018 17:20
@juanjoDiaz
Copy link
Contributor Author

Ok. This is good now. I hope that the smaller and more focused commits help reviewing the changes.

This currently uses eslint:recommended config. That's the loosest configuration and doesn't really enforce anything (for example, it doesn't even enforce using let/const instead of var). So the next step is to put it a more strict eslint config and fix the code accordingly.

I'd suggest airbnb config since it's widely used and imho it's rock solid. Wdyt??

@juanjoDiaz
Copy link
Contributor Author

Hei guys,

Any ETA of when this could be merge?
I have a couple other PRs coming after this one :)

@CendioOssman
Copy link
Member

I'd suggest airbnb config since it's widely used and imho it's rock solid. Wdyt??

Do a separate commit with that config applied and we can see what it will do to the code.

Any ETA of when this could be merge?
I have a couple other PRs coming after this one :)

That would be after 1.0 is out. So unfortunately you got hit with some bad timing here. :/

@CendioOssman CendioOssman self-requested a review February 5, 2018 12:10
@juanjoDiaz juanjoDiaz force-pushed the es6_refactor_2 branch 3 times, most recently from 41e01af to 729eca6 Compare February 6, 2018 04:37
Copy link
Member
@DirectXMan12 DirectXMan12 left a comment

Choose a reason for hiding this comment

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

lots of comments inline. Some good work, some things that I don't think we should do, some stuff that's not quite correct.

In general, ease back on the use of the ternary operator, since, IMO, it generally makes things a bit harder to read for complicated expressions.

(please also look at the "outdated" comments, since some are still relevant for a particular commit)

@@ -48,7 +48,8 @@ Localizer.prototype = {
}

// First pass: perfect match
for (var j = 0;j < supportedLanguages.length;j++) {
var j;
Copy link
Member

Choose a reason for hiding this comment

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

I think this just makes the code harder to read. f we're going to transpile, these should just be let declarations.

Copy link
Member

Choose a reason for hiding this comment

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

nvm, you do it in the next commit

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 tried to keep every commit as small as possible.

core/rfb.js Outdated
@@ -1062,7 +1060,7 @@ RFB.prototype = {
var serverSupportedTypes = [];

for (var i = 0; i < subAuthCount; i++) {
var capNum = this._sock.rQshift32();
this._sock.rQshift32();
Copy link
Member

Choose a reason for hiding this comment

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

this has lost its self-documenting properties. Please add a comment indicating what the shift does instead.

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. I added the comment in the next commit.

@@ -24,8 +24,10 @@ export function init_logging (level) {
_log_level = level;
}

Debug = Info = Warn = Error = function (msg) {};
Debug = Info = Warn = Error = function () {};
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't these have a var declaration somewhere?

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 do. In lines 15-18

package.json Outdated
@@ -7,7 +7,8 @@
"test": "tests"
},
"scripts": {
"test": "PATH=$PATH:node_modules/karma/bin karma start karma.conf.js",
"lint": "eslint app core tests utils",
"test": "karma start karma.conf.js",
Copy link
Member

Choose a reason for hiding this comment

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

why have you dropped the extra PATH setting. It used to be necessary if node_modules wasn't on your path.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

scripts in NPM automatically look in the node_modules folder.

var evt1 = keyevent('keydown', {code: 'KeyA', key: 'a'});
kbd._handleKeyDown(evt1);
expect(evt1.preventDefault).to.have.been.called;
var evt2 = keyevent('keyup', {code: 'KeyA', key: 'a'});
Copy link
Member

Choose a reason for hiding this comment

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

why is this necessary? We can re-use variables...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can. This change was looking forward to the next commit and the javascript best practice of using immutable variables (const) whenever possible.

core/rfb.js Outdated

return this._fail('Security negotiation failed' + context);
}
return this._fail('Security negotiation failed' + context +
Copy link
Member

Choose a reason for hiding this comment

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

template literal

app/ui.js Outdated
import Keyboard from '../core/input/keyboard.js';
import RFB from '../core/rfb.js';
import * as WebUtil from './webutil.js';
import * as Log from '../core/util/logging';
Copy link
Member

Choose a reason for hiding this comment

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

These need to stay in. Support for bare names is unclear in the WHATWG spec, and the module loader polyfill doesn't permit it: https://github.com/ModuleLoader/browser-es-module-loader

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 can bring it back.

It's weird though, that it hadn't fail any of the tests...

@@ -31,7 +31,7 @@ export class Localizer {
? window.navigator.languages
: [navigator.language || navigator.userLanguage];

for (let i = 0; i < userLanguages.length; i++) {
for (let i = 0; i < userLanguages.length; i += 1) {
Copy link
Member

Choose a reason for hiding this comment

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

just because Crockford is afraid of the increment operator doesn't mean we should be too. Please leave these in.

Copy link
Member

Choose a reason for hiding this comment

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

agreed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure.

I found ++i, i++ and i +=1 all over the code. that's why I tried to normalize with one.

++i vs i++ was making not so clear to me what the code was doing in some cases so I preferred i += 1.

In the case of for loops I agree that's irrelevant. But you can't tell eslint to enforce it everywhere except for for loops...

@@ -17,7 +17,7 @@ let Info = () => {};
let Warn = () => {};
let Error = () => {};

export function init_logging (level) {
export function init_logging(level) {
Copy link
Member

Choose a reason for hiding this comment

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

this doesn't look normalized -- some have spaces between parens and the name, some don't. I prefer spaces.

@@ -152,5 +152,5 @@ export class Localizer {
}
}

export let l10n = new Localizer();
export const l10n = new Localizer();
Copy link
Member

Choose a reason for hiding this comment

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

squash all these into the previous let/const/var commit, if possible

Copy link
Member

Choose a reason for hiding this comment

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

This is the let/const/var commit, or am I missing something?

Copy link
Member
@samhed samhed left a comment

Choose a reason for hiding this comment

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

I agree with the comments by @DirectXMan12 and added some more. Did you test this?

core/display.js Outdated
@@ -657,7 +657,7 @@ export default class Display {
return;
}

const cur = []
const cur = [];
Copy link
Member

Choose a reason for hiding this comment

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

The commit-message should be "Add missing semicolons"

core/rfb.js Outdated
@@ -718,6 +715,7 @@ RFB.prototype = {
Log.Error("Got data while disconnected");
break;
case 'connected':
// eslint-disable-next-line no-constant-condition
Copy link
Member

Choose a reason for hiding this comment

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

Meh, I don't like that we need to have this comment here.. Is it just to disable an eslint warning?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup. We could disable it globally. However, I think that's reasonable to assume that a condition on a constant should be an exception and not the norm. So it's disabled globaly and enabled only for this line.

Copy link
Member

Choose a reason for hiding this comment

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

I don't like that we need to disable it in this case though. What is the eslint recommended way for an infinite loop?

Copy link
Member

Choose a reason for hiding this comment

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

@juanjoDiaz, did you check if there was a better way that would make lint happy?

Copy link
Member

Choose a reason for hiding this comment

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

there's apparently a checkLoops setting for exactly this. So I suggest turning on that option.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Endless loops are dangerous. That's why there shouldn't be used unless strictly necessary.
That's why the no-constant-condition and checkLoops rule is enable by default. Disabling it will not indicate endless loop anywhere in the code.
That's why I think that using a comment is good to indicate that this particular endless loop is an exception and not the norm.

If you still disagree and prefer you to completely disable the rule. Let me know and I can do it.

Copy link
Member

Choose a reason for hiding this comment

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

My vote is to disable this rule since I consider this particular pattern to be a common and useful one.

What does everyone else think?

Copy link
Member

Choose a reason for hiding this comment

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

Agreed, +1 for disabling the rule

var Debug = function (msg) {};
var Info = function (msg) {};
var Warn = function (msg) {};
var Error = function (msg) {};
Copy link
Member

Choose a reason for hiding this comment

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

Aren't these function arguments required?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope. Arguments are never required in javascript. And those are never used anyway. It's just a default no-op

@@ -10,7 +10,7 @@
if (typeof Object.assign != 'function') {
// Must be writable: true, enumerable: false, configurable: true
Object.defineProperty(Object, "assign", {
value: function assign(target, varArgs) { // .length of function is 2
Copy link
Member

Choose a reason for hiding this comment

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

this snippet was taken directly from MDN I think, perhaps we should keep it as it was?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's an argument that's not used.

To add it and not have eslint failing we would need to either add a comment to disable the rule here or disable eslint checks for the entire file (which might be trouble if we add here other polyfills.)

Copy link
Member

Choose a reason for hiding this comment

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

ok, it's fine then

}
const userLanguages = (typeof window.navigator.languages === 'object')
? window.navigator.languages
: [navigator.language || navigator.userLanguage];
Copy link
Member

Choose a reason for hiding this comment

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

Code was a lot easier to read before this change

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 see that you all really dislike ternary operators.

We differ on that. But I can keep the if-else blocks.

As mentioned above, the main advantage of if-else is to declare variable as const when they are inmutable after declaration.

Copy link
Member

Choose a reason for hiding this comment

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

In my mind they are fine if the condition and results are simple and you can keep it short.

app/ui.js Outdated
l10n.dictionary = translations;

// wait for translations to load before loading the UI
UI.prime();
}, function (err) {
}, (err) => {
Copy link
Member

Choose a reason for hiding this comment

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

Should be able to skip the '{' and '}' here 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.

yup. But this change was just changed on master

core/rfb.js Outdated
} else {
context = ' on ' + context;
}
context = typeof context === 'undefined'
Copy link
Member

Choose a reason for hiding this comment

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

+1

core/rfb.js Outdated
? { status: security_result_status }
: { status: security_result_status, reason }
});
this.dispatchEvent(event);
Copy link
Member

Choose a reason for hiding this comment

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

in other places you have removed the intermediate event variable in cases like these

@@ -31,7 +31,7 @@ export class Localizer {
? window.navigator.languages
: [navigator.language || navigator.userLanguage];

for (let i = 0; i < userLanguages.length; i++) {
for (let i = 0; i < userLanguages.length; i += 1) {
Copy link
Member

Choose a reason for hiding this comment

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

agreed

@@ -9,6 +9,6 @@
/*
* Decode from UTF-8
*/
export function decodeUTF8 (utf8string) {
export function decodeUTF8(utf8string) {
Copy link
Member

Choose a reason for hiding this comment

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

this commit doesn't seem to bring consistency at all!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Anonymous function
function () {....} // One single space between function and opening parenthesis and between closing parenthesis and opening curly brace

Named function
function funcName() {....} // No space between function name and opening parenthesis and single space between closing parenthesis and opening curly brace

It's the airbnb recommended way. I can follow some other way if you would prefer that.

@juanjoDiaz
Copy link
Contributor Author

Thanks for the thorough review.

I think that our main point of disagreement is the ternary operator. I can live with that :)

I'll try to fix all the comments.

@juanjoDiaz juanjoDiaz force-pushed the es6_refactor_2 branch 13 times, most recently from e953f3a to 92e2ff4 Compare February 9, 2018 23:12
@juanjoDiaz juanjoDiaz force-pushed the es6_refactor_2 branch 2 times, most recently from b162a4b to cdfbad9 Compare May 7, 2018 20:29
@juanjoDiaz
Copy link
Contributor Author

After rebasing, something weird seems to be going on with Edge. Any idea?

@juanjoDiaz juanjoDiaz force-pushed the es6_refactor_2 branch 4 times, most recently from de3ba2e to 5a2c7ef Compare May 8, 2018 20:49
@CendioOssman
Copy link
Member

I think it's just sauce labs that are flaky as hell.

Copy link
Member
@CendioOssman CendioOssman left a comment

Choose a reason for hiding this comment

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

Lots of minor things. But one big thing: transpiling of classes isn't working.

.eslintrc Outdated
"no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }],
"no-constant-condition": ["error", { "checkLoops": false }],
"no-var": "error"
"no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }],
Copy link
Member

Choose a reason for hiding this comment

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

Please move the reindent to the original commit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The whole file is indented to 2 spaces except for this 3 lines.

I'll re-indent the whole file to 4 spaces

.eslintrc Outdated
"no-useless-constructor": "error",
"constructor-super": "error",
"no-this-before-super": "error",
"no-dupe-class-members": "error"
Copy link
Member

Choose a reason for hiding this comment

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

A bunch of these are already in recommended, so why list them here?

function process(elem, enabled) {
function isAnyOf(searchElement, items) {
return items.indexOf(searchElement) !== -1;
}

function translateAttribute(elem, attr) {
const str = self.get(elem.getAttribute(attr));
const str = this.get(elem.getAttribute(attr));
Copy link
Member

Choose a reason for hiding this comment

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

This looks broken.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why?

It was doing const self = this; at the beginning of the function but we are not changing the bindings or calling the function in any scope so this will never change.

elem.setAttribute(attr, str);
}

function translateTextNode(node) {
const str = self.get(node.data.trim());
const str = this.get(node.data.trim());
Copy link
Member

Choose a reason for hiding this comment

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

Ditto.

app/ui.js Outdated
@@ -101,12 +101,10 @@ const UI = {

document.documentElement.classList.remove("noVNC_loading");

let autoconnect = WebUtil.getConfigVar('autoconnect', false);
const autoconnect = WebUtil.getConfigVar('autoconnect', false);
Copy link
Member

Choose a reason for hiding this comment

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

Unrelated. Remove.

client._framebufferUpdate = function () {
this._sock.rQskip8();
return true;
}; // we magically have enough data
Copy link
Member

Choose a reason for hiding this comment

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

Unrelated.

@@ -108,7 +108,7 @@ out +=
"};\n" +
"\n" +
"export default {\n" +
" lookup : function(u) {\n" +
" lookup(u) {\n" +
Copy link
Member

Choose a reason for hiding this comment

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

Unrelated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why unrelated? The whole point of the commit it to get rid of inline functions in favour of arrow function and object/class functions.

If I change keysymdef.js but not the generator, then the next time that you generate the file, the change will be reverted.

const args = Array.prototype.slice.call(arguments);
return new Promise((resolve, reject) => {
original.apply(obj, args.concat((err, value) => {
original.apply(this, args.concat((err, value) => {
Copy link
Member

Choose a reason for hiding this comment

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

This does not have the same behaviour as the previous code. I don't think you can use an arrow function here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why not?

As in the other comment above, const obj = this; and we are not doing any binding or calling the function on any other object so obj will always be equals to this.

Also, what do you mean about not being able to use an arrow function?

return readdir(base_path)
.then(files => {
.then((files) => {
Copy link
Member

Choose a reason for hiding this comment

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

Not needed, 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.

It's the convention that parenthesis are skip on 1-lines but used when using braces.

myArg => myFunc(myArgs)

vs

(myArg) => {
  return myFunc(myArgs);
}

Would you prefer something else?

if (!with_app_dir) {
only_legacy = true;
}
const only_legacy = !with_app_dir;
Copy link
Member

Choose a reason for hiding this comment

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

This is not the same thing.

@juanjoDiaz juanjoDiaz force-pushed the es6_refactor_2 branch 4 times, most recently from 5836d70 to fbcbd8b Compare May 10, 2018 10:43
@juanjoDiaz
Copy link
Contributor Author

I've fixed that issues that you commented and were clear issues and I've commented on the ones that I think that is correct.

Let's agree on what to do about the latter and try to get this merged. :)

I won't be doing any more changes as part of this PR. If I decide to do anything else (ES6 related or not) I'll do it as separate smaller PRs.

@juanjoDiaz
Copy link
Contributor Author
juanjoDiaz commented May 10, 2018

@CendioOssman can you clarify why " transpiling of classes isn't working"??

I run npm run prepare and the transpiled code in the lib folder doesn't contain classes at all.

Edit: I didn't notice that I was supposed to commit and push the vendor/dist folder. Done now :)

@CendioOssman
Copy link
Member
CendioOssman commented May 18, 2018 via email

@juanjoDiaz
Copy link
Contributor Author

@CendioOssman Would it be a solution to revert this to the const/let commit that we were all happy with, get that merged and then submit I can submit a separate PR for classes/arrow functions?

Otherwise, this might take forever, more conflicts will appear, etc.

@samhed
Copy link
Member
samhed commented May 21, 2018 via email

@juanjoDiaz
Copy link
Contributor Author

Ok. Now we just have the 3 commits that were already approved. Let's get those in and I'll do a separate PR for classes and arrow functions.

Btw, I can access the PR just fine and I don't think that we are too far from each other... No clue of what might be the problem that you are having...

@juanjoDiaz
Copy link
Contributor Author

The fail test is Sauce lab being flaky as usual. the changes are exactly the same as have been pushed a million times before and passed :)

Copy link
Member
@samhed samhed left a comment

Choose a reason for hiding this comment

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

I had another look. There were still a few unaddressed comments with some changes unrelated to the themes of the commits. But since we're having such problems viewing this PR and we have been through the code multiple times I think that it looks good enough.

@samhed samhed merged commit fe70a1d into novnc:master May 25, 2018
@samhed samhed added the feature label May 25, 2018
@samhed samhed added this to the v1.1.0 milestone May 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants