-
Notifications
You must be signed in to change notification settings - Fork 27.5k
DI doesn't work with ES6 classes unless the constructor is the first function of the class #14175
Comments
Thanks for the report. I guess it's a bug, even though the use case is pretty rare. Do you want to open a PR with your suggested fix? |
Sure thing, will put something together over the next few days |
I think that putting together a fix will be quite difficult without a lot more machinery. Here is a harder example class Foo {
test() {
class Bar {
constructor() {} // No not pick this one
}
"constructor() {}" // nor this one
}
"constructor"($rootScope) {} // but this one (as an extra quirk, remember that the function name can be in quotes)
} and a few other cases that are not supported in Chrome but are in Firefox class Foo {
["const" + "ructor"]($rootScope) {}
} |
@lgalfaso Shouldn't be as bad as you think, although it's probably not that great either (didn't profile this at all). if (isClass(fn)) {
fn.toString()
// Extract the body of the class
// TODO: Don't match destructuring syntax
.match(/{(.*)}/)[1]
// Remove the body of all functions contained within the class
// so that we don't match inner constructors
.replace(/{.*?}/g, '')
// Find the constructor in the list of functions that remain since it may not be
// the first one in the list
.match(/constructor\s?\([\s\S]*?\)/)[0]
// Extract the arguments
.match(/^[^\(]*\(\s*([^\)]*)\)/m)
} In Firefox 45B, calling As for your concern about class Foo {
["const" + "ructor"]($rootScope) {}
} I just tried that in Firefox, and the constructor isn't invoked on Edit Also, the |
@dcherman I think you are looking for http://www.ecma-international.org/ecma-262/6.0/#sec-function.prototype.tostring at toString Representation Requirements That said, if this can be done reasonable easy, then that is fine with me. The only thing I would not want to end with is with a full ES6 syntax parser to support this. |
I feel like a RegExps will only take us so far. E.g. @dcherman's will break with something like:
I think we all agree that we don't want to support every wicked usecase. |
I agree that regex can only take us so far, that is why I lean towards On Monday, March 7, 2016, Georgios Kalpakas [email protected]
|
Just messing around and I came up with something interesting. I'm really stretching what could be considered reasonable here. This is more because I'm stubborn and wanted to code golf a small solution. var result = Object.getOwnPropertyNames(fn.prototype).reduce(function(result, name) {
if (name === 'constructor') {
return result;
}
// Filter on functions in the real implementation too
return result.replace(fn.prototype[name].toString(), '');
}, fn.toString()); With a reliable class Foo {
prop = {
constructor(a, b, c) {}
}
} Hacky workarounds aside, it seems reasonable to ask consumers to have the first occurrence of class Foo {
test() {
class Bar {
prop = {};
constructor(arg1, arg2) {}
}
}
} |
Any chance this entire feature can be deprecated in a future release? See #14789 (comment) |
You can always enable strictDi, so there I see no need to deprecate this On Friday, June 17, 2016, Aluan Haddad [email protected] wrote:
|
Yes, I always use it indeed. The main reason for deprecating would be because it is not recommended. Or is it still considered acceptable practice? |
Even @johnpapa's styleguide (that you mentioned in the other comment) is suggesting to use this feature (together with It is an optional feature, very useful for quick examples, POCs and prototypes and you can safely opt-out with I don't see any reason to deprecate it tbh. |
@gkalpak I'd like to leave the current behavior as it is. It's impossible to cover all cases and it's way simpler to say that it will always break in non-strict-di mode if |
@mgol, not sure what you mean. I didn't suggest we change anything (not in this thread at least 😉). |
I didn't suggest you suggested. ;) I'd like to close this issue with a "Won't fix" resolution.
It's not in README yet but see olov/ng-annotate#245 (comment) & olov/ng-annotate#253. |
I think enough of us have expressed their preference for leaving things as is, that it is reasonable to close this as "won't fix". I'll let you do the honors 😛 |
OK, thanks for the discussion everyone! |
as a semi-related issue, this also breaks:
('real mixins' as detailed here: http://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/ ) but i get the feeling that would also be closed as wontfix for now the workaround is:
|
Bug
If the constructor doesn't come first in an ES6 class (FYI I'm not using a transpiler, I'm using native ES6 in chrome 49) and there is no explicit annotation then the DI fails and every element is undefined in the constructor e.g.
This works
and this doesn't:
http://plnkr.co/edit/K0IGrbT4SPS9g8mkXc5Y?p=preview
The DI to auto inject services
The example I gave above is contrived, and normally I would just put the constructor first before any controller methods. However for resolves I often do something like this before a constructor, so you see resolves first and then the constructor where the results are injected:
versions of Angular? Please also test with the latest stable and snapshot versions.
1.5.0
I think the fix should be simple enough by modifying the regex here and look for
constructor(
before the arguments.If you need any more info let me know! 😄
The text was updated successfully, but these errors were encountered: