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

fix(ngcc): use aliased exported types correctly #38666

Closed

Conversation

petebacondarwin
Copy link
Member

If a type has been renamed when it was exported, we need to
reference the external public alias name rather than the internal
original name for the type. Otherwise we will try to import the
type by its internal name, which is not publicly accessible.

Fixes #38238

@petebacondarwin petebacondarwin added type: bug/fix action: review The PR is still awaiting reviews from at least one requested reviewer target: patch This PR is targeted for the next patch release comp: ngcc labels Sep 1, 2020
@ngbot ngbot bot modified the milestone: needsTriage Sep 1, 2020
@petebacondarwin petebacondarwin marked this pull request as draft September 1, 2020 16:20
@petebacondarwin petebacondarwin removed the request for review from AndrewKushnir September 1, 2020 16:20
@petebacondarwin petebacondarwin force-pushed the ngcc-issue-38238 branch 2 times, most recently from d2717e0 to 14c5e4e Compare September 1, 2020 18:48
@petebacondarwin petebacondarwin marked this pull request as ready for review September 2, 2020 15:24
@AndrewKushnir AndrewKushnir requested review from JoostK and removed request for AndrewKushnir September 2, 2020 18:11
@petebacondarwin
Copy link
Member Author

petebacondarwin commented Sep 3, 2020

Thoughts from @JoostK :

viaModule is about external modules, so relative imports won’t have that in which case we’d currently label it as LOCAL type reference, where it really should be IMPORTED
ngtsc typically uses Reference and a ReferenceEmitter to generate an expression that can be used in any context; the type-to-value conversion however does it more manually and assumes that the type reference that it creates is emitted in the same file as it was extracted from
but it will still generate its own import statement for imported symbols for IMPORTED type references; LOCAL however will be emitted as is

in ngcc we do currently use LOCAL even if a relative module import was used; which probably works out fine because it can simply emit the exact same expression in the same file. ngtsc can’t rely on that because it would break for symbols that are only used in type-positions, therefore the import is elided.
In ngcc’s case, I think that the right way to go about it is to use the code I proposed to figure out whether an import is used in the first place, and use that information to either return an IMPORTED type reference or a LOCAL one
so that we’re no longer relying on viaModule, as that’s only correct in few cases.

so the primary job of ngtsc’s typeToValue is to go from a ts.TypeNode to something that eventually becomes a ts.Expression. The TypeValueReference is a way to represent the various possibilities, where it differentiates between local and imported symbols to be able to properly emit import statements (as that is required to safely go from a ts.TypeNode to a ts.Expression).
In ngcc however, the situation is very simple: we already have typeExpression which is a ts.Expression, so we might not need the intermediate representation for an IMPORTED type-value-reference. From that perspective, it may actually be perfectly fine to always use that ts.Expression as a LOCAL type (as it already does if viaModule is null) and not bother with synthesizing a different ts.Expression based on derived information about the original ts.Expression 😵

@petebacondarwin
Copy link
Member Author

@JoostK and @gkalpak I followed Joost's advice and began to unwind what I had written and use his idea. See the beginnings of it here

@petebacondarwin petebacondarwin marked this pull request as draft September 4, 2020 17:33
@petebacondarwin petebacondarwin added state: WIP and removed action: review The PR is still awaiting reviews from at least one requested reviewer labels Sep 4, 2020
@petebacondarwin petebacondarwin force-pushed the ngcc-issue-38238 branch 3 times, most recently from 9a5b522 to 9b11513 Compare September 5, 2020 07:13
@petebacondarwin petebacondarwin marked this pull request as ready for review September 5, 2020 07:13
@petebacondarwin
Copy link
Member Author

OK, I have gone with the simple approach suggested by @JoostK. It appears to work in a reproduction of the original issue for me locally. I have added tests for each of the ngcc ReflectionHosts.

PTAL

@petebacondarwin petebacondarwin added action: review The PR is still awaiting reviews from at least one requested reviewer and removed state: WIP labels Sep 5, 2020
@@ -13,26 +13,36 @@ import {CtorParameter, TypeValueReferenceKind} from '../../../src/ngtsc/reflecti
* names.
*/
export function expectTypeValueReferencesForParameters(
parameters: CtorParameter[], expectedParams: (string|null)[], fromModule: string|null = null) {
parameters: CtorParameter[], expectedParams: (string|null)[],
fromModule: (string|null)[] = []) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Most of the changes here are simply to improve the failure messages

If a type has been renamed when it was exported, we need to
reference the external public alias name rather than the internal
original name for the type. Otherwise we will try to import the
type by its internal name, which is not publicly accessible.

Fixes angular#38238
Copy link
Member

@gkalpak gkalpak left a comment

Choose a reason for hiding this comment

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

👍

Copy link
Member

@JoostK JoostK left a comment

Choose a reason for hiding this comment

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

I like it :-)

@petebacondarwin petebacondarwin added action: merge The PR is ready for merge by the caretaker and removed action: review The PR is still awaiting reviews from at least one requested reviewer labels Sep 6, 2020
@atscott atscott closed this in 7869de6 Sep 8, 2020
atscott pushed a commit that referenced this pull request Sep 8, 2020
If a type has been renamed when it was exported, we need to
reference the external public alias name rather than the internal
original name for the type. Otherwise we will try to import the
type by its internal name, which is not publicly accessible.

Fixes #38238

PR Close #38666
@matheo
Copy link

matheo commented Sep 8, 2020

Will this be released for 9.x too? or just for 10.x?

@petebacondarwin
Copy link
Member Author

^9.0.0 is now in LTS and so I don't expect this fix to land there.

@matheo
Copy link

matheo commented Sep 8, 2020

but then how can it be LTS if it missed this? :(

@petebacondarwin
Copy link
Member Author

@matheo - LTS versions only receive "critical fixes and security patches". I accept that it is somewhat subjective as to what a "critical fix" is. I will check with the team tomorrow.

@matheo
Copy link

matheo commented Sep 9, 2020

Thank you @petebacondarwin

@petebacondarwin
Copy link
Member Author

Hi @matheo - we discussed this last night and I am afraid that this PR does not constitute a critical fix for LTS.

I have put together a PR to change the docs to clarify what fixes will land on LTS versions: #38788

@matheo
Copy link

matheo commented Sep 10, 2020

Got it, ok, we'll start moving to Angular 10 then :)
Thanks for this fix!

JoostK added a commit to JoostK/angular that referenced this pull request Sep 17, 2020
In angular#38666 we changed how ngcc deals with type expressions, where it
would now always emit the original type expression into the generated
code as a "local" type value reference instead of synthesizing new
imports using an "imported" type value reference. This was done as a fix
to properly deal with renamed symbols, however it turns out that the
compiler has special handling for certain imported symbols, e.g.
`ChangeDetectorRef` from `@angular/core`. The "local" type value
reference prevented this special logic from being hit, resulting in
incorrect compilation of pipe factories.

This commit fixes the issue by manually inspecting the import of the
type expression, in order to return an "imported" type value reference.
By manually inspecting the import we continue to handle renamed symbols.

Fixes angular#38883
mhevery pushed a commit that referenced this pull request Sep 18, 2020
#38892)

In #38666 we changed how ngcc deals with type expressions, where it
would now always emit the original type expression into the generated
code as a "local" type value reference instead of synthesizing new
imports using an "imported" type value reference. This was done as a fix
to properly deal with renamed symbols, however it turns out that the
compiler has special handling for certain imported symbols, e.g.
`ChangeDetectorRef` from `@angular/core`. The "local" type value
reference prevented this special logic from being hit, resulting in
incorrect compilation of pipe factories.

This commit fixes the issue by manually inspecting the import of the
type expression, in order to return an "imported" type value reference.
By manually inspecting the import we continue to handle renamed symbols.

Fixes #38883

PR Close #38892
mhevery pushed a commit that referenced this pull request Sep 18, 2020
#38892)

In #38666 we changed how ngcc deals with type expressions, where it
would now always emit the original type expression into the generated
code as a "local" type value reference instead of synthesizing new
imports using an "imported" type value reference. This was done as a fix
to properly deal with renamed symbols, however it turns out that the
compiler has special handling for certain imported symbols, e.g.
`ChangeDetectorRef` from `@angular/core`. The "local" type value
reference prevented this special logic from being hit, resulting in
incorrect compilation of pipe factories.

This commit fixes the issue by manually inspecting the import of the
type expression, in order to return an "imported" type value reference.
By manually inspecting the import we continue to handle renamed symbols.

Fixes #38883

PR Close #38892
@petebacondarwin petebacondarwin deleted the ngcc-issue-38238 branch October 1, 2020 12:51
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Nov 1, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes target: patch This PR is targeted for the next patch release type: bug/fix
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ngcc: doesn't process library prefixed exports properly
5 participants