fix: const enums + isolatedModules emit invalid code (#41933)
* chore: failing test for const enums and isolatedModules
* fix: const enums + isolatedModules emit invalid code
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 #40499.
* chore: extra test for type-only
* feat: explicitly ban --isolatedModules --preserveConstEnums false
* feat: isolatedModules implies preserveConstEnum
* Update src/compiler/diagnosticMessages.json
Co-authored-by: Andrew Branch <andrewbranch@users.noreply.github.com>
* chore: compiler test for argument incompatibility
* Add and fix test for namespace import of const enum
* Fix additional bug with reexport of const-enum-only module
Co-authored-by: Andrew Branch <andrewbranch@users.noreply.github.com>
Co-authored-by: Andrew Branch <andrew@wheream.io>
2021-01-14 00:51:08 +01:00
|
|
|
=== tests/cases/compiler/enum.ts ===
|
|
|
|
export const enum Foo { Bar }
|
|
|
|
>Foo : Symbol(Foo, Decl(enum.ts, 0, 0))
|
|
|
|
>Bar : Symbol(Foo.Bar, Decl(enum.ts, 0, 23))
|
|
|
|
|
|
|
|
=== tests/cases/compiler/index.ts ===
|
|
|
|
import { Foo } from "./enum";
|
|
|
|
>Foo : Symbol(Foo, Decl(index.ts, 0, 8))
|
|
|
|
|
|
|
|
function f(foo: Foo) { return; }
|
|
|
|
>f : Symbol(f, Decl(index.ts, 0, 29))
|
|
|
|
>foo : Symbol(foo, Decl(index.ts, 1, 11))
|
|
|
|
>Foo : Symbol(Foo, Decl(index.ts, 0, 8))
|
|
|
|
|