-
Notifications
You must be signed in to change notification settings - Fork 12.8k
fix: const enums + isolatedModules emit invalid code #41933
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
Conversation
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.
Can we add a test for only using the type side of a const enum too? Like
// @isolatedModules: true
// @Filename: /enum.ts
export const enum Foo { Bar }
// @Filename: /index.ts
import { Foo } from "./enum";
function f(foo: Foo) { return; }
I think it’s worth considering adding an error too, but that can be done separately. I see no reason not to take this fix regardless of whether we add an error in the future. |
860dab4
to
7012959
Compare
That test is simple enough, and does what I expect (the import, which is only used in type context, is deleted). It doesn't even run the new code. Added. |
7012959
to
372bbfd
Compare
fe99edd
to
b39e650
Compare
In `isolatedModules` mode, the compiler does not inline const enums, but also decides not to `import` them, leaving invalid code that throws a `ReferenceError` at runtime. This code: ``` import { SomeEnum } from './bar'; sink(SomeEnum.VALUE); ``` ..should compile to either: ``` var { SomeEnum } = require('./bar'); sink(SomeEnum.VALUE); ``` ..or (with const enum inlining): ``` sink(1 /* VALUE */); ``` ..but actually compiles to: ``` sink(SomeEnum.VALUE); ``` ..with no imports, which throws a ReferenceError at runtime. --- The compiler has already realised that the symbol is a referenced const enum, it just doesn't use this information when it comes to deciding whether to emit an import. This commit additionally checks that information, if we are compiling in isolatedModules mode. --- In my opinion, this is not the correct fix, but it is the simplest. In `isolatedModules` mode, `const enum` should probably be a compile error (because there are no benefits and the complexity is high, and, apparently, buggy). If not, the compiler should not be checking whether something is a const enum, and should just be treating it as a regular enum, and checking as if it was? Fixes microsoft#40499.
Co-authored-by: Andrew Branch <[email protected]>
b39e650
to
38cef4b
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.
Thanks @FauxFaux!
@andrewbranch @sheetalkamat is this ready to go in? From the comment history, it looks like @sheetalkamat 's comments were addressed and @andrewbranch reviewed them, but I want to make sure before merging. |
I believe it’s ready, just wanted another team member to review. |
})(ConstEnumOnlyModule = exports.ConstEnumOnlyModule || (exports.ConstEnumOnlyModule = {})); | ||
//// [reexport.js] | ||
"use strict"; | ||
var Foo = require("./foo"); |
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.
A bit of a separate bug, but closely inspecting checkPropertyAccessExpressionOrQualifiedName
led me to discover that this import was missing until I added the check for isExportOrExportExpression
.
Thanks @FauxFaux! Sorry this ended up being more complicated than you bargained for 😅 |
In
isolatedModules
mode, the compiler does not inline const enums, but also decides not toimport
them, leaving invalid code that throws aReferenceError
at runtime.This code:
..should compile to either:
..or (with const enum inlining):
..but actually compiles to:
..with no imports, which throws a ReferenceError at runtime.
The compiler has already realised that the symbol is a referenced const enum, it just doesn't use this information when it comes to deciding whether to emit an import. This commit additionally checks that information, if we are compiling in isolatedModules mode.
In my opinion, this is not the correct fix, but it is the simplest. In
isolatedModules
mode,const enum
should probably be a compile error (because there are no benefits and the complexity is high, and, apparently, buggy). If not, the compiler should not be checking whether something is a const enum, and should just be treating it as a regular enum, and checking as if it was?Fixes #40499.