Skip to content

Commit e2b4c12

Browse files
authored
Detect unbindable exports before setting CommonJS module indicator (#33784)
* Detect unbindable exports before setting CommonJS module indicator * Fix comment * Fix unrelated lint?
1 parent 8fb50ba commit e2b4c12

File tree

5 files changed

+105
-6
lines changed

5 files changed

+105
-6
lines changed

src/compiler/utilities.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2174,9 +2174,11 @@ namespace ts {
21742174
nextToLast = nextToLast.expression as Exclude<BindableStaticNameExpression, Identifier>;
21752175
}
21762176
const id = nextToLast.expression;
2177-
if (id.escapedText === "exports" ||
2178-
id.escapedText === "module" && getElementOrPropertyAccessName(nextToLast) === "exports") {
2179-
// exports.name = expr OR module.exports.name = expr
2177+
if ((id.escapedText === "exports" ||
2178+
id.escapedText === "module" && getElementOrPropertyAccessName(nextToLast) === "exports") &&
2179+
// ExportsProperty does not support binding with computed names
2180+
isBindableStaticAccessExpression(lhs)) {
2181+
// exports.name = expr OR module.exports.name = expr OR exports["name"] = expr ...
21802182
return AssignmentDeclarationKind.ExportsProperty;
21812183
}
21822184
// F.G...x = expr

tests/baselines/reference/lateBoundAssignmentDeclarationSupport2.symbols

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,20 @@ const _str = "my-fake-sym";
2626

2727
module.exports[_sym] = "ok";
2828
>module.exports : Symbol("tests/cases/conformance/salsa/lateBoundAssignmentDeclarationSupport2", Decl(lateBoundAssignmentDeclarationSupport2.js, 0, 0))
29-
>module : Symbol(module, Decl(lateBoundAssignmentDeclarationSupport2.js, 2, 27))
29+
>module : Symbol(module, Decl(lateBoundAssignmentDeclarationSupport2.js, 5, 28))
3030
>exports : Symbol("tests/cases/conformance/salsa/lateBoundAssignmentDeclarationSupport2", Decl(lateBoundAssignmentDeclarationSupport2.js, 0, 0))
3131
>_sym : Symbol(_sym, Decl(lateBoundAssignmentDeclarationSupport2.js, 1, 5))
3232

3333
module.exports[_str] = "ok";
3434
>module.exports : Symbol("tests/cases/conformance/salsa/lateBoundAssignmentDeclarationSupport2", Decl(lateBoundAssignmentDeclarationSupport2.js, 0, 0))
35-
>module : Symbol(module, Decl(lateBoundAssignmentDeclarationSupport2.js, 2, 27))
35+
>module : Symbol(module, Decl(lateBoundAssignmentDeclarationSupport2.js, 5, 28))
3636
>exports : Symbol("tests/cases/conformance/salsa/lateBoundAssignmentDeclarationSupport2", Decl(lateBoundAssignmentDeclarationSupport2.js, 0, 0))
3737
>_str : Symbol(_str, Decl(lateBoundAssignmentDeclarationSupport2.js, 2, 5))
3838

3939
module.exports.S = _sym;
4040
>module.exports.S : Symbol(S, Decl(lateBoundAssignmentDeclarationSupport2.js, 5, 28))
4141
>module.exports : Symbol(S, Decl(lateBoundAssignmentDeclarationSupport2.js, 5, 28))
42-
>module : Symbol(module, Decl(lateBoundAssignmentDeclarationSupport2.js, 2, 27))
42+
>module : Symbol(module, Decl(lateBoundAssignmentDeclarationSupport2.js, 5, 28))
4343
>exports : Symbol("tests/cases/conformance/salsa/lateBoundAssignmentDeclarationSupport2", Decl(lateBoundAssignmentDeclarationSupport2.js, 0, 0))
4444
>S : Symbol(S, Decl(lateBoundAssignmentDeclarationSupport2.js, 5, 28))
4545
>_sym : Symbol(_sym, Decl(lateBoundAssignmentDeclarationSupport2.js, 1, 5))
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
=== tests/cases/conformance/jsdoc/file1.js ===
2+
// this file _should_ be a global file
3+
var GlobalThing = { x: 12 };
4+
>GlobalThing : Symbol(GlobalThing, Decl(file1.js, 1, 3))
5+
>x : Symbol(x, Decl(file1.js, 1, 19))
6+
7+
/**
8+
* @param {*} type
9+
* @param {*} ctor
10+
* @param {*} exports
11+
*/
12+
function f(type, ctor, exports) {
13+
>f : Symbol(f, Decl(file1.js, 1, 28))
14+
>type : Symbol(type, Decl(file1.js, 8, 11))
15+
>ctor : Symbol(ctor, Decl(file1.js, 8, 16))
16+
>exports : Symbol(exports, Decl(file1.js, 8, 22))
17+
18+
if (typeof exports !== "undefined") {
19+
>exports : Symbol(exports, Decl(file1.js, 8, 22))
20+
21+
exports["AST_" + type] = ctor;
22+
>exports : Symbol(exports, Decl(file1.js, 8, 22))
23+
>type : Symbol(type, Decl(file1.js, 8, 11))
24+
>ctor : Symbol(ctor, Decl(file1.js, 8, 16))
25+
}
26+
}
27+
28+
=== tests/cases/conformance/jsdoc/ref.js ===
29+
GlobalThing.x
30+
>GlobalThing.x : Symbol(x, Decl(file1.js, 1, 19))
31+
>GlobalThing : Symbol(GlobalThing, Decl(file1.js, 1, 3))
32+
>x : Symbol(x, Decl(file1.js, 1, 19))
33+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
=== tests/cases/conformance/jsdoc/file1.js ===
2+
// this file _should_ be a global file
3+
var GlobalThing = { x: 12 };
4+
>GlobalThing : { x: number; }
5+
>{ x: 12 } : { x: number; }
6+
>x : number
7+
>12 : 12
8+
9+
/**
10+
* @param {*} type
11+
* @param {*} ctor
12+
* @param {*} exports
13+
*/
14+
function f(type, ctor, exports) {
15+
>f : (type: any, ctor: any, exports: any) => void
16+
>type : any
17+
>ctor : any
18+
>exports : any
19+
20+
if (typeof exports !== "undefined") {
21+
>typeof exports !== "undefined" : boolean
22+
>typeof exports : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
23+
>exports : any
24+
>"undefined" : "undefined"
25+
26+
exports["AST_" + type] = ctor;
27+
>exports["AST_" + type] = ctor : any
28+
>exports["AST_" + type] : any
29+
>exports : any
30+
>"AST_" + type : string
31+
>"AST_" : "AST_"
32+
>type : any
33+
>ctor : any
34+
}
35+
}
36+
37+
=== tests/cases/conformance/jsdoc/ref.js ===
38+
GlobalThing.x
39+
>GlobalThing.x : number
40+
>GlobalThing : { x: number; }
41+
>x : number
42+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// @noEmit: true
2+
// @checkJs: true
3+
// @allowJs: true
4+
// @strict: true
5+
// @Filename: file1.js
6+
7+
// this file _should_ be a global file
8+
var GlobalThing = { x: 12 };
9+
10+
/**
11+
* @param {*} type
12+
* @param {*} ctor
13+
* @param {*} exports
14+
*/
15+
function f(type, ctor, exports) {
16+
if (typeof exports !== "undefined") {
17+
exports["AST_" + type] = ctor;
18+
}
19+
}
20+
21+
// @Filename: ref.js
22+
GlobalThing.x

0 commit comments

Comments
 (0)