Uh oh!
There was an error while loading. Please reload this page.
Only emit ctorParameters when the class has a constructor - #760
Conversation
mprobst
commented
Mar 7, 2018
@deadalusai can you share what problem exactly this fixes? I'm not sure if we have code (e.g. in Angular) that might depend on these empty constructors params being produced. Evan might know. |
Hi Martin. Sorry for the curt PR - I meant to have a PR up for @angular/angular with links for context, but ran out of time yesterday. I'm working to resolve an issue I found compiling though ng-packagr, where the constructor function generated for a subclass with an implicit constructor does not play nicely with the regex used to detect such a thing in Angular's ReflectionCapabilities._ownParameters. Specifically, functionFooComponent(){__super.apply(this,__tslib.__spread(arguments));}Angular is expecting something like: functionFooComponent(){__super.apply(this,arguments);}
The problem is that the work-around is currently the "official" way to detect this edge case. My goal here is to bring // PseudocodefunctiongetConstructorParams(typeConstructor){// legacy regex check, for old versions of tscif(DELEGATE_CTOR.test...etc){returnnull;}// check for tsickle metadataif(typeConstructor.ctorParameters){returntypeConstructor.ctorParameters;}letmetadata=this._reflect.getOwnMetadata('design:paramtypes',typeConstructor);if(metadata){returnmetadata;}// pass-through constructor, or no metadata availablereturnnull;}// the type either has a real constructor...letparameters=getConstructorParams(constructorType);if(!parameters&&parentType!==Object){// ...or we should use the parent constructorparameters=getConstructorParams(parentType);}returnparameters||[];The regex would be left behind as a legacy check to support code generated with old versions of (The regex check has already grown from one to three different regexes in the last few minor versions of Angular) |
deadalusai
commented
Mar 7, 2018
Just realized my examples above are missing the most important case of a subclass with an implicit constructor. Here's what @InjectableclassBase{constructor(d: Dependency){}}
@InjectableclassSubextendsBase{}Generating: varBase=/** @class */(function(){functionBase(d){}Base=__decorate([Injectable,__metadata("design:paramtypes",[Dependency])],Base);returnBase;}());varSub=/** @class */(function(_super){__extends(Sub,_super);functionSub(){return_super!==null&&_super.apply(this,arguments)||this;}Sub=__decorate([Injectable// NOTE: no "design:paramtypes" metadata for the subclass],Sub);returnSub;}(Base));I'd like tsickle to do the same. |
mprobst
commented
Mar 7, 2018
@mhevery can you figure out who's a good person to coordinate this change? I don't quite understand the interaction and timelines of the components involved. Can you assign a reviewer? |
The Angular PR can be found here: angular/angular#22642
Might have found a solution for the problem I had. Feedback welcome. |
mhevery
commented
Mar 14, 2018
mhevery
commented
Mar 15, 2018
So I looked into it, and the PRs seems reasonable, but it seems like we would have to coordinate angular/angular#22642 with this PR. This seems like an awful lot of work, along with supporting the legacy. Could we just fix https://github.com/dherges/ng-packagr/issues/679 to generate code which would pass current angular checks? |
mhevery
commented
Mar 15, 2018
I gave it some more thought and my recommendation would be to do nothing and wait for angular/angular#21706 to land which will make the whole |
trotyl
commented
Mar 16, 2018
@mhevery It’s only dropped in |
mhevery
commented
Mar 21, 2018
@trotyl I am not sure I understand your comment. Can you expand on it? |
@mhevery In Ivy the metadata constructor dependencies would be reflected in @Injectable()classBaseComp{constructor(myService: MyService){}}
@Component({ ... })classMyCompextendsBaseComp{}Would become: classMyCompextendsBaseComp{staticngComponentDef=defineComponent({factory: ()=>newMyComp(inject(MyService))})}So the If we don't have RegExp match any more and without this change in tsickle, then: In AOT mode, nothing changed in metadata resolution since everything controlled by Imagine that the classes above comes from lib, with the format: classBaseComp{}BaseComp.ctorParameters=()=>[{type: MyService}]classMyCompextendsBaseComp{}MyComp.ctorParameters=()=>[]Then in a JIT'ed Ivy app: import{MyComp}from'my-lib'classCustomCompextendsMyComp{}According to the inheritance semantics the deps for This case may only happen to back patch mode since I'm not sure how does pure Ivy lib looks like, metadata inheritance in Ivy seems not implemented yet, but for supporting JIT usage, there still needs to be record stands for |
deadalusai
commented
Mar 21, 2018
Which (for an implicit constructor) should always be correct? This would eliminate the need to walk up the class hierarchy entirely. Unfortunately |
mhevery
commented
Mar 21, 2018
I see, thanks for the explanation, I see it better now. In which case I think I am for landing this. after angular/angular#22642 lands. |
mhevery
commented
Mar 21, 2018
Could we get this rebased on latest master? |
deadalusai
commented
Mar 21, 2018
@mhevery I can rebase this today. Were you interested in this PR making The behavior would be different to |
…s has a constructor This more closely matches the behavior of TSC which only emits the "design:paramtypes" metadata when the class actually has a constructor function.
deadalusai
commented
Mar 22, 2018
Rebased 👍 |
mprobst
commented
Mar 22, 2018
Merged, thanks for the contribution. |
LinboLen
commented
Apr 9, 2018
Fixes that the table does not render properly when used inside of a ES2015 application. This is due to an ongoing Angular issue which has been caused due to a brittle Regex check [introduced here](angular/angular#22356 (comment)) that should be replaced with a more clean approach for identifying classes that inherit metadata from another class. * angular/angular#22642 * angular/tsickle#760Fixesangular#9329
Fixes that some components does not render properly when used inside of a ES2015 JIT application. This is due to an ongoing Angular issue which has been caused due to a brittle Regex check [introduced here](angular/angular#22356 (comment)) that should be replaced with a more clean approach for identifying classes that inherit metadata from another class. * angular/angular#22642 * angular/tsickle#760 See the more detailed issue here: angular#12760Fixesangular#9329.
Fixes that some components does not render properly when used inside of a ES2015 JIT application. This is due to an ongoing Angular issue which has been caused due to a brittle Regex check [introduced here](angular/angular#22356 (comment)) that should be replaced with a more clean approach for identifying classes that inherit metadata from another class. * angular/angular#22642 * angular/tsickle#760 See the more detailed issue here: #12760Fixes#9329.
Fixes that some components does not render properly when used inside of a ES2015 JIT application. This is due to an ongoing Angular issue which has been caused due to a brittle Regex check [introduced here](angular/angular#22356 (comment)) that should be replaced with a more clean approach for identifying classes that inherit metadata from another class. * angular/angular#22642 * angular/tsickle#760 See the more detailed issue here: #12760Fixes#9329.
Fix DecoratorClassVisitor to only emit
ctorParameterswhen the class has a constructor.This more closely matches the behavior of TSC which only emits the "design:paramtypes" metadata
when the class actually has a constructor. For example, compiling the following TypeScript snippet:
Emits this JavaScript: