The Wayback Machine - https://web.archive.org/web/20231230172354/https://github.com/angular/angular/pull/32424
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): support static evaluation of exports object in CommonJS #32424

Closed
wants to merge 1 commit into from

Conversation

JoostK
Copy link
Member

@JoostK JoostK commented Aug 30, 2019

In CommonJS bundles, the exports object is available as global
variable, without a ts.Declaration nor ts.Expression in the source
file. During static interpretation of expressions that read from the
exports object, ngtsc attempts to resolve the declaration node of the
"exports" variable in order to determine the value it represents. As no
such declaration exists, the evaluation results in a dynamic value.

Since the exports variable represents the source file's exports, the
source file itself can be used as declaration node for any "exports"
variable in CommonJS bundles. Doing so allows ngtsc to evaluate its
value correctly, as source file declarations are interpreted as the
public exports of the source file.

In CommonJS bundles, the `exports` object is available as global
variable, without a `ts.Declaration` nor `ts.Expression` in the source
file. During static interpretation of expressions that read from the
`exports` object, ngtsc attempts to resolve the declaration node of the
"exports" variable in order to determine the value it represents. As no
such declaration exists, the evaluation results in a dynamic value.

Since the `exports` variable represents the source file's exports, the
source file itself can be used as declaration node for any "exports"
variable in CommonJS bundles. Doing so allows ngtsc to evaluate its
value correctly, as source file declarations are interpreted as the
public exports of the source file.
@JoostK JoostK added type: bug/fix action: review The PR is still awaiting reviews from at least one requested reviewer severity3: broken target: major This PR is targeted for the next major release labels Aug 30, 2019
@JoostK JoostK requested a review from a team as a code owner August 30, 2019 20:33
@ngbot ngbot bot added this to the needsTriage milestone Aug 30, 2019
// The "exports" object is available as global in CommonJS bundles, without a `ts.Declaration`
// nor `ts.Expression` in the source file. Since it represents the source file's exports, the
// source file itself can be used as declaration node.
if (id.text === 'exports') {
Copy link
Member

Choose a reason for hiding this comment

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

Do we need to be a bit more careful here? It is possible that the exports identifier is a local variable, no?

Copy link
Member Author

Choose a reason for hiding this comment

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

@petebacondarwin Yes, that is correct. I was actually hoping that this statement could be the fallback check after the regular resolution had failed to resolve a declaration, however that didn't work out as I expected. The thing is, with the following code:

exports.abc = true;

The exports identifier will be resolved to a ts.Symbol with valueDeclaration corresponding with the exports.abc node. Therefore, the regular resolution would end up with a declaration for the identifier, but not the one we desire, preventing the fallback from being considered. I'm not sure if this is a bug in TypeScript or the way it's supposed to work.

We might be able to detect the above situation to be able to differentiate between local vars and the actual exports global, but I'm not really sure what would be the most accurate way.

@gkalpak
Copy link
Member

gkalpak commented Nov 28, 2019

This might not be necessary any more. As I was debugging NativeScript issues, I noticed that super.getDeclarationOfIdentifier(id) eventually returned the same thing ({node: id.getSourceFile(), viaModule: null}).

(Not sure if there are other cases where this is still needed, but it worked for my usecase.)

@petebacondarwin petebacondarwin added target: patch This PR is targeted for the next patch release and removed target: major This PR is targeted for the next major release labels Dec 11, 2019
@petebacondarwin
Copy link
Member

@JoostK - can you determine if this is still necessary and cleanup or close this PR as necessary?

@JoostK JoostK closed this Mar 25, 2020
@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 Apr 25, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: review The PR is still awaiting reviews from at least one requested reviewer 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.

None yet

4 participants