-
Notifications
You must be signed in to change notification settings - Fork 24.8k
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): capture UMD/CommonJS inner class implementation nodes correctly #39346
fix(ngcc): capture UMD/CommonJS inner class implementation nodes correctly #39346
Conversation
d7848e3
to
5ca8a45
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a couple of comments:
- It would be cool if we could have an integration test showing all the bits working together (unless it would be too messy).
- Commit message typo:
Fool
-->Foo
😁
@@ -342,7 +342,8 @@ export class StaticInterpreter { | |||
} | |||
|
|||
private visitAmbiguousDeclaration(decl: Declaration, declContext: Context) { | |||
return decl.kind === DeclarationKind.Inline && decl.implementation !== undefined ? | |||
return decl.kind === DeclarationKind.Inline && decl.implementation !== undefined && | |||
!isDeclaration(decl.implementation) ? | |||
// Inline declarations with an `implementation` should be visited as expressions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment could be updated to mention the new requirement for implementation
to be a ts.Expression
.
return SomeClass; | ||
}())`, | ||
'SomeClass', | ||
`SomeClass = (function() {\n function SomeClass() {}\n return SomeClass;\n }())`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
`SomeClass = (function() {\n function SomeClass() {}\n return SomeClass;\n }())`, | |
'SomeClass = (function() {\n function SomeClass() {}\n return SomeClass;\n }())', |
Hmm, an integration test... Let me look into that. Trouble is that we don't have any UMD packages to test against. |
5ca8a45
to
a538f10
Compare
@gkalpak - I managed to create an integration test that actually fails without this fix!! |
…ctly Previously, UMD/CommonJS class inline declarations of the form: ```ts exports.Foo = (function() { function Foo(); return Foo; })(); ``` were capturing the whole IIFE as the implementation, rather than the inner class (i.e. `function Foo() {}` in this case). This caused the interpreter to break when it was trying to access such an export, since it would try to evaluate the IIFE rather than treating it as a class declaration.
b88f13e
to
6c16cbd
Compare
6152d10
to
2d158b3
Compare
The compiler uses a `Reference` abstraction to refer to TS nodes that it needs to refer to from other parts of the source. Such references keep track of any identifiers that represent the referenced node. Prior to this commit, the compiler (and specifically `ReferenceEmitter` classes) assumed that the reference identifiers are always free standing. In other words a reference identifier would be an expression like `FooDirective` in the expression `class FooDirective {}`. But in UMD/CommonJS source, a reference can actually refer to an "exports" declaration of the form `exports.FooDirective = ...`. In such cases the `FooDirective` identifier is not free-standing since it is part of a property access, so the `ReferenceEmitter` should take this into account when emitting an expression that refers to such a `Reference`. This commit changes the `LocalIdentifierStrategy` reference emitter so that if the `node` being referenced is not a declaration itself and is in the current file, then it should be used directly, rather than trying to use one of its identifiers.
2d158b3
to
817c08a
Compare
FYI, presubmit is successful (I've updated g3 status for this PR). |
Thanks @AndrewKushnir |
…ctly (#39346) Previously, UMD/CommonJS class inline declarations of the form: ```ts exports.Foo = (function() { function Foo(); return Foo; })(); ``` were capturing the whole IIFE as the implementation, rather than the inner class (i.e. `function Foo() {}` in this case). This caused the interpreter to break when it was trying to access such an export, since it would try to evaluate the IIFE rather than treating it as a class declaration. PR Close #39346
The compiler uses a `Reference` abstraction to refer to TS nodes that it needs to refer to from other parts of the source. Such references keep track of any identifiers that represent the referenced node. Prior to this commit, the compiler (and specifically `ReferenceEmitter` classes) assumed that the reference identifiers are always free standing. In other words a reference identifier would be an expression like `FooDirective` in the expression `class FooDirective {}`. But in UMD/CommonJS source, a reference can actually refer to an "exports" declaration of the form `exports.FooDirective = ...`. In such cases the `FooDirective` identifier is not free-standing since it is part of a property access, so the `ReferenceEmitter` should take this into account when emitting an expression that refers to such a `Reference`. This commit changes the `LocalIdentifierStrategy` reference emitter so that if the `node` being referenced is not a declaration itself and is in the current file, then it should be used directly, rather than trying to use one of its identifiers. PR Close #39346
The compiler uses a `Reference` abstraction to refer to TS nodes that it needs to refer to from other parts of the source. Such references keep track of any identifiers that represent the referenced node. Prior to this commit, the compiler (and specifically `ReferenceEmitter` classes) assumed that the reference identifiers are always free standing. In other words a reference identifier would be an expression like `FooDirective` in the expression `class FooDirective {}`. But in UMD/CommonJS source, a reference can actually refer to an "exports" declaration of the form `exports.FooDirective = ...`. In such cases the `FooDirective` identifier is not free-standing since it is part of a property access, so the `ReferenceEmitter` should take this into account when emitting an expression that refers to such a `Reference`. This commit changes the `LocalIdentifierStrategy` reference emitter so that if the `node` being referenced is not a declaration itself and is in the current file, then it should be used directly, rather than trying to use one of its identifiers. PR Close #39346
…ctly (#39346) Previously, UMD/CommonJS class inline declarations of the form: ```ts exports.Foo = (function() { function Foo(); return Foo; })(); ``` were capturing the whole IIFE as the implementation, rather than the inner class (i.e. `function Foo() {}` in this case). This caused the interpreter to break when it was trying to access such an export, since it would try to evaluate the IIFE rather than treating it as a class declaration. PR Close #39346
The compiler uses a `Reference` abstraction to refer to TS nodes that it needs to refer to from other parts of the source. Such references keep track of any identifiers that represent the referenced node. Prior to this commit, the compiler (and specifically `ReferenceEmitter` classes) assumed that the reference identifiers are always free standing. In other words a reference identifier would be an expression like `FooDirective` in the expression `class FooDirective {}`. But in UMD/CommonJS source, a reference can actually refer to an "exports" declaration of the form `exports.FooDirective = ...`. In such cases the `FooDirective` identifier is not free-standing since it is part of a property access, so the `ReferenceEmitter` should take this into account when emitting an expression that refers to such a `Reference`. This commit changes the `LocalIdentifierStrategy` reference emitter so that if the `node` being referenced is not a declaration itself and is in the current file, then it should be used directly, rather than trying to use one of its identifiers. PR Close #39346
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Previously, UMD/CommonJS class inline declarations of the form:
were capturing the whole IIFE as the implementation, rather than
the inner class (i.e.
function Foo() {}
in this case). This causedthe interpreter to break when it was trying to access such an export,
since it would try to evaluate the IIFE rather than treating it as a class
declaration.