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

Migrate to ES2015 #2948

Merged
merged 9 commits into from
Mar 15, 2018
Merged

Migrate to ES2015 #2948

merged 9 commits into from
Mar 15, 2018

Conversation

devoto13
Copy link
Collaborator

@devoto13 devoto13 commented Mar 5, 2018

So this is another take on migrating code base to ES2015 classes, const/let and arrow functions. With Node 4 reaching end-of-life in 2 months developers soon can enjoy full support of ES2015 😄

Using mentioned syntaxes should give cleaner, more structured and therefore more maintainable code.

I originally tried to base my work on #2904 from @EzraBrooks, but rebasing on master turned out to be very nasty, so I gave up and started over.

The goal of this PR is exclusively migration to ES2015 and NOT change of a DI mechanism. I monkey-patched di module to support ES classes for now. Everything should work exactly the same as it worked for functions. The DI migration can be done later (if needed).

I'm looking for confirmation that this approach is fine by maintainers and than I will continue to refactor more classes.

}

bindSocketEvents (socket) {
// TODO: check which of these events are actually emitted by socket
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this change, while probably a good direction, should be separate so we don't get sources of errors mixed up.

Copy link
Collaborator Author

@devoto13 devoto13 Mar 6, 2018

Choose a reason for hiding this comment

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

Methods in class declarations are not enumerable properties, so bindAll does not work over ES2015 classes... We'll either have to change bindAll implementation somehow or do this one. I think being explicit here is better (it took me some time to figure out why it was failing). I can extract this into separate commit explaining the change if you prefer it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, thanks, I do think making this change separately and before the classes would be good strategy.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Extracted this change into a separate commit: a51505a.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks! I think for a change of this magnitude and one that (necessarily) differs in style we should have other folks like @dignifiedquire weigh in. The 'browser' changes look good to me.

Copy link
Member

Choose a reason for hiding this comment

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

I am all for the explicit version 👍

lib/helper.js Outdated
@@ -166,3 +166,64 @@ exports.defer = function () {
promise: promise
}
}

/**
* Patches di module to support ES2015 classes.
Copy link
Contributor

Choose a reason for hiding this comment

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

While I think it is cool that you worked this out, I am not keen on this strategy and this implementation. The karma-special "DI" system makes karma difficult to work with until one spends time decoding what it does. To me, this DI patching approach makes the problem worse: now we have another layer of confusion hiding the first confusion.

The migration to ES classes will make the karma code easier to read for most developers. Can we find a way to achieve that without the DI patching?

The karma DI works through instances exported and matched with some funky $inject coding. The conversion to classes changes source which is fundamentally singleton into class structure, which then requires object creation to fit back into the DI system. Rather than hacking the DI system to create instances from exported classes, consider leaving the DI and module interfaces unchanged in this first pass. Create instances in the new ES modules, export them just as karma does now. That gives us ES class support without obscuring the obscure. It also avoids bundling changes that will make bug tracking very difficult. Then we can tackle the DI issue separately.

Copy link
Collaborator Author

@devoto13 devoto13 Mar 6, 2018

Choose a reason for hiding this comment

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

Well, after reading the source code of di module I find it very straightforward and simple to understand DI implementation 😄 And the fact that it worked all this time without breaking only confirms the fact. Not sure why users are having difficulties working with it, maybe a bit of documentation can completely resolve the problem.

I doubt there is a much better/more type safe dependency injection mechanism possible using plain JS at the moment.

Can we find a way to achieve that without the DI patching?

I think I can convert all instantiate() calls and type providers to use invoke() and factory methods instead and it will work without a DI patch. I'll check it later today.

Something like here:

- capturedBrowsers: ['type', BrowserCollection],
+ capturedBrowsers: ['factory', function (emitter) { return new BrowserCollection(emitter) }],

Copy link
Contributor

Choose a reason for hiding this comment

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

Documentation would be awesome.

I agree that the DI system has proven useful. Nevertheless it is unusual and unique, requiring users to read the code for a probably unrelated subsystem to make progress on changes. For your change however, the issue is only to not make things more complex if we can achieve your goal within the current system.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've removed a di patch and replaced with factory functions.

@johnjbarton
Copy link
Contributor

The changes look good to me. Looks like the last one tripped some issue in the continuous integration tests.

@devoto13
Copy link
Collaborator Author

devoto13 commented Mar 8, 2018

@johnjbarton the issue is in all commits actually. Tests fail in Node 4 only. As I pointed in the original post:

With Node 4 reaching end-of-life in 2 months developers soon can enjoy full support of ES2015 😄

So I was hoping to get this in together with dropping Node 4 support. I can probably try to support Node 4 as well, but not sure if it worths the effort given that it is reaching end-of-life on 30th of April and has quite poor ES2015 support.

@dignifiedquire
Copy link
Member

I don't think we should drop Node 4 support that soon, so I would like for now to make sure it works on Node 4.

@dignifiedquire
Copy link
Member

@devoto13 also if you could simply add strict mode to all files we should be good even on Node 4 (strict mode is preferable anyway)

@devoto13
Copy link
Collaborator Author

devoto13 commented Mar 12, 2018

@dignifiedquire rest/spread is not supported in the Node 4 either... And it is very convenient alternative to using arguments and fn.apply(). But ok, I'll make sure it works on Node 4 as well.

@devoto13
Copy link
Collaborator Author

I've updated to support Node 4. One test is failing in Firefox 59 not because of my changes. There is same error in master branch. Any ideas how to fix it?

@devoto13
Copy link
Collaborator Author

Turns out the not-standard version property was removed in Firefox 59. From MDN:

Note: in Firefox you could specify the version of JavaScript contained in a <script> element by including a non-standard version parameter inside the type attribute — for example type="application/javascript;version=1.8". This has been removed in Firefox 59 (see bug 1428745).

I've added quick fix to ignore it in Firefox 59+ and deprecation warning for the jsVersion property. Do you think it is the right way to handle it? If so I will submit it in a separate PR.

@johnjbarton
Copy link
Contributor

fix to ignore it in Firefox 59+ and deprecation warning for the jsVersion property.

Yes, in a separate PR.

Copy link
Member

@dignifiedquire dignifiedquire left a comment

Choose a reason for hiding this comment

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

LGTM thanks for doing this, once the firefox issue is fixed on master, this is rebased ontop and CI is green I'll merge it

This makes code easier to understand, because all listeners are added
explicitly. Now it is clear what methods are called in response to which
events and what parameters are passed to them.

Also it is a preparation for migration to ES2015 classes, where original
approach won't work, because methods in ES2015 classes are added as not
enumerable properties, so it is harder to loop through them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants