Skip to content

Commit dc9a066

Browse files
authored
Do not merge commonJS exports into an alias (microsoft#28133)
* Do not merge commonsjs exports onto an alias getCommonJSExportEquals merges export assignments and export property assignments. Something like this, which has no equivalent structure in TS: ```js module.exports = function() { } module.exports.expando = 1 ``` However, it is sometimes called with an alias, when its parent, resolveExternalModuleSymbol, is called with dontResolveAlias: true, and when the initialiser of the export assignment is an alias: ```js function alias() { } module.exports = alias module.exports.expando = 1 ``` In this case, (1) the actual value `alias` will have already merged in a previous call to getCommonJSExportEquals and (2) getTypeOfSymbol will follow the alias symbol to get the right type. So getCommonJSExportEquals should do nothing in this case. This bug manifests in the code for dynamic imports, which calls getTypeOfSymbol on the incorrectly merged alias, which now has enough value flags--Function, for example--to take the wrong branch and subsequently crash. * Update baselines
1 parent 070218f commit dc9a066

File tree

5 files changed

+56
-2
lines changed

5 files changed

+56
-2
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2362,7 +2362,7 @@ namespace ts {
23622362
}
23632363

23642364
function getCommonJsExportEquals(exported: Symbol | undefined, moduleSymbol: Symbol): Symbol | undefined {
2365-
if (!exported || exported === unknownSymbol || exported === moduleSymbol || moduleSymbol.exports!.size === 1) {
2365+
if (!exported || exported === unknownSymbol || exported === moduleSymbol || moduleSymbol.exports!.size === 1 || exported.flags & SymbolFlags.Alias) {
23662366
return exported;
23672367
}
23682368
const merged = cloneSymbol(exported);

tests/baselines/reference/errorForConflictingExportEqualsValue.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ export = x;
66
>x : any
77

88
import("./a");
9-
>import("./a") : Promise<typeof import("/a").x>
9+
>import("./a") : Promise<any>
1010
>"./a" : "./a"
1111

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
=== tests/cases/conformance/salsa/bug28014.js ===
2+
exports.version = 1
3+
>exports.version : Symbol(version)
4+
>exports : Symbol(version, Decl(bug28014.js, 0, 0))
5+
>version : Symbol(version, Decl(bug28014.js, 0, 0))
6+
7+
function alias() { }
8+
>alias : Symbol(alias, Decl(bug28014.js, 0, 19))
9+
10+
module.exports = alias
11+
>module.exports : Symbol("tests/cases/conformance/salsa/bug28014", Decl(bug28014.js, 0, 0))
12+
>module : Symbol(export=, Decl(bug28014.js, 1, 20))
13+
>exports : Symbol(export=, Decl(bug28014.js, 1, 20))
14+
>alias : Symbol(alias, Decl(bug28014.js, 0, 19))
15+
16+
=== tests/cases/conformance/salsa/importer.js ===
17+
import('./bug28014')
18+
>'./bug28014' : Symbol("tests/cases/conformance/salsa/bug28014", Decl(bug28014.js, 0, 0))
19+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
=== tests/cases/conformance/salsa/bug28014.js ===
2+
exports.version = 1
3+
>exports.version = 1 : 1
4+
>exports.version : number
5+
>exports : typeof alias
6+
>version : number
7+
>1 : 1
8+
9+
function alias() { }
10+
>alias : typeof alias
11+
12+
module.exports = alias
13+
>module.exports = alias : typeof alias
14+
>module.exports : typeof alias
15+
>module : { "tests/cases/conformance/salsa/bug28014": typeof alias; }
16+
>exports : typeof alias
17+
>alias : typeof alias
18+
19+
=== tests/cases/conformance/salsa/importer.js ===
20+
import('./bug28014')
21+
>import('./bug28014') : Promise<() => void>
22+
>'./bug28014' : "./bug28014"
23+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// @allowJs: true
2+
// @noEmit: true
3+
// @checkJs: true
4+
// @target: esnext
5+
// @module: esnext
6+
// @Filename: bug28014.js
7+
exports.version = 1
8+
function alias() { }
9+
module.exports = alias
10+
11+
// @Filename: importer.js
12+
import('./bug28014')

0 commit comments

Comments
 (0)