Skip to content

Commit e350c35

Browse files
authored
Alias for module.exports.x = x (microsoft#40228)
* Alias for `module.exports.x = x` This fixes microsoft#40155 in a surprisingly small amount of code. * Treat any aliasable expression as an alias * test internal references to exported class
1 parent 0636b9b commit e350c35

File tree

47 files changed

+588
-190
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+588
-190
lines changed

src/compiler/binder.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -2806,10 +2806,10 @@ namespace ts {
28062806
return symbol;
28072807
});
28082808
if (symbol) {
2809-
const flags = isClassExpression(node.right) ?
2810-
SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.Class :
2811-
SymbolFlags.Property | SymbolFlags.ExportValue;
2812-
declareSymbol(symbol.exports!, symbol, node.left, flags, SymbolFlags.None);
2809+
const isAlias = isAliasableExpression(node.right) && (isExportsIdentifier(node.left.expression) || isModuleExportsAccessExpression(node.left.expression));
2810+
const flags = isAlias ? SymbolFlags.Alias : SymbolFlags.Property | SymbolFlags.ExportValue;
2811+
const excludeFlags = isAlias ? SymbolFlags.AliasExcludes : SymbolFlags.None;
2812+
declareSymbol(symbol.exports!, symbol, node.left, flags, excludeFlags);
28132813
}
28142814
}
28152815

src/compiler/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5562,6 +5562,7 @@ namespace ts {
55625562
export const enum AssignmentDeclarationKind {
55635563
None,
55645564
/// exports.name = expr
5565+
/// module.exports.name = expr
55655566
ExportsProperty,
55665567
/// module.exports = expr
55675568
ModuleExports,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//// [tests/cases/conformance/salsa/commonJSImportClassExpression.ts] ////
2+
3+
//// [main.js]
4+
const { K } = require("./mod1");
5+
/** @param {K} k */
6+
function f(k) {
7+
k.values()
8+
}
9+
10+
//// [mod1.js]
11+
exports.K = class K {
12+
values() {
13+
}
14+
};
15+
16+
17+
//// [mod1.js]
18+
"use strict";
19+
exports.K = /** @class */ (function () {
20+
function K() {
21+
}
22+
K.prototype.values = function () {
23+
};
24+
return K;
25+
}());
26+
//// [main.js]
27+
"use strict";
28+
var K = require("./mod1").K;
29+
/** @param {K} k */
30+
function f(k) {
31+
k.values();
32+
}
33+
34+
35+
//// [mod1.d.ts]
36+
export class K {
37+
values(): void;
38+
}
39+
//// [main.d.ts]
40+
export {};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
=== tests/cases/conformance/salsa/main.js ===
2+
const { K } = require("./mod1");
3+
>K : Symbol(K, Decl(main.js, 0, 7))
4+
>require : Symbol(require)
5+
>"./mod1" : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0))
6+
7+
/** @param {K} k */
8+
function f(k) {
9+
>f : Symbol(f, Decl(main.js, 0, 32))
10+
>k : Symbol(k, Decl(main.js, 2, 11))
11+
12+
k.values()
13+
>k.values : Symbol(K.values, Decl(mod1.js, 0, 21))
14+
>k : Symbol(k, Decl(main.js, 2, 11))
15+
>values : Symbol(K.values, Decl(mod1.js, 0, 21))
16+
}
17+
18+
=== tests/cases/conformance/salsa/mod1.js ===
19+
exports.K = class K {
20+
>exports.K : Symbol(K, Decl(mod1.js, 0, 0))
21+
>exports : Symbol(K, Decl(mod1.js, 0, 0))
22+
>K : Symbol(K, Decl(mod1.js, 0, 0))
23+
>K : Symbol(K, Decl(mod1.js, 0, 11))
24+
25+
values() {
26+
>values : Symbol(K.values, Decl(mod1.js, 0, 21))
27+
}
28+
};
29+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
=== tests/cases/conformance/salsa/main.js ===
2+
const { K } = require("./mod1");
3+
>K : typeof K
4+
>require("./mod1") : typeof import("tests/cases/conformance/salsa/mod1")
5+
>require : any
6+
>"./mod1" : "./mod1"
7+
8+
/** @param {K} k */
9+
function f(k) {
10+
>f : (k: K) => void
11+
>k : K
12+
13+
k.values()
14+
>k.values() : void
15+
>k.values : () => void
16+
>k : K
17+
>values : () => void
18+
}
19+
20+
=== tests/cases/conformance/salsa/mod1.js ===
21+
exports.K = class K {
22+
>exports.K = class K { values() { }} : typeof K
23+
>exports.K : typeof K
24+
>exports : typeof import("tests/cases/conformance/salsa/mod1")
25+
>K : typeof K
26+
>class K { values() { }} : typeof K
27+
>K : typeof K
28+
29+
values() {
30+
>values : () => void
31+
}
32+
};
33+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//// [tests/cases/conformance/salsa/commonJSImportClassTypeReference.ts] ////
2+
3+
//// [main.js]
4+
const { K } = require("./mod1");
5+
/** @param {K} k */
6+
function f(k) {
7+
k.values()
8+
}
9+
10+
//// [mod1.js]
11+
class K {
12+
values() {
13+
return new K()
14+
}
15+
}
16+
exports.K = K;
17+
18+
19+
//// [mod1.js]
20+
"use strict";
21+
var K = /** @class */ (function () {
22+
function K() {
23+
}
24+
K.prototype.values = function () {
25+
return new K();
26+
};
27+
return K;
28+
}());
29+
exports.K = K;
30+
//// [main.js]
31+
"use strict";
32+
var K = require("./mod1").K;
33+
/** @param {K} k */
34+
function f(k) {
35+
k.values();
36+
}
37+
38+
39+
//// [mod1.d.ts]
40+
export class K {
41+
values(): K;
42+
}
43+
//// [main.d.ts]
44+
export {};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
=== tests/cases/conformance/salsa/main.js ===
2+
const { K } = require("./mod1");
3+
>K : Symbol(K, Decl(main.js, 0, 7))
4+
>require : Symbol(require)
5+
>"./mod1" : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0))
6+
7+
/** @param {K} k */
8+
function f(k) {
9+
>f : Symbol(f, Decl(main.js, 0, 32))
10+
>k : Symbol(k, Decl(main.js, 2, 11))
11+
12+
k.values()
13+
>k.values : Symbol(K.values, Decl(mod1.js, 0, 9))
14+
>k : Symbol(k, Decl(main.js, 2, 11))
15+
>values : Symbol(K.values, Decl(mod1.js, 0, 9))
16+
}
17+
18+
=== tests/cases/conformance/salsa/mod1.js ===
19+
class K {
20+
>K : Symbol(K, Decl(mod1.js, 0, 0))
21+
22+
values() {
23+
>values : Symbol(K.values, Decl(mod1.js, 0, 9))
24+
25+
return new K()
26+
>K : Symbol(K, Decl(mod1.js, 0, 0))
27+
}
28+
}
29+
exports.K = K;
30+
>exports.K : Symbol(K, Decl(mod1.js, 4, 1))
31+
>exports : Symbol(K, Decl(mod1.js, 4, 1))
32+
>K : Symbol(K, Decl(mod1.js, 4, 1))
33+
>K : Symbol(K, Decl(mod1.js, 0, 0))
34+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
=== tests/cases/conformance/salsa/main.js ===
2+
const { K } = require("./mod1");
3+
>K : typeof K
4+
>require("./mod1") : typeof import("tests/cases/conformance/salsa/mod1")
5+
>require : any
6+
>"./mod1" : "./mod1"
7+
8+
/** @param {K} k */
9+
function f(k) {
10+
>f : (k: K) => void
11+
>k : K
12+
13+
k.values()
14+
>k.values() : K
15+
>k.values : () => K
16+
>k : K
17+
>values : () => K
18+
}
19+
20+
=== tests/cases/conformance/salsa/mod1.js ===
21+
class K {
22+
>K : K
23+
24+
values() {
25+
>values : () => K
26+
27+
return new K()
28+
>new K() : K
29+
>K : typeof K
30+
}
31+
}
32+
exports.K = K;
33+
>exports.K = K : typeof K
34+
>exports.K : typeof K
35+
>exports : typeof import("tests/cases/conformance/salsa/mod1")
36+
>K : typeof K
37+
>K : typeof K
38+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//// [tests/cases/conformance/salsa/commonJSImportNestedClassTypeReference.ts] ////
2+
3+
//// [main.js]
4+
const { K } = require("./mod1");
5+
/** @param {K} k */
6+
function f(k) {
7+
k.values()
8+
}
9+
10+
//// [mod1.js]
11+
var NS = {}
12+
NS.K =class {
13+
values() {
14+
return new NS.K()
15+
}
16+
}
17+
exports.K = NS.K;
18+
19+
20+
//// [mod1.js]
21+
"use strict";
22+
var NS = {};
23+
NS.K = /** @class */ (function () {
24+
function K() {
25+
}
26+
K.prototype.values = function () {
27+
return new NS.K();
28+
};
29+
return K;
30+
}());
31+
exports.K = NS.K;
32+
//// [main.js]
33+
"use strict";
34+
var K = require("./mod1").K;
35+
/** @param {K} k */
36+
function f(k) {
37+
k.values();
38+
}
39+
40+
41+
//// [mod1.d.ts]
42+
export var K: {
43+
new (): {
44+
values(): any;
45+
};
46+
};
47+
//// [main.d.ts]
48+
export {};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
=== tests/cases/conformance/salsa/main.js ===
2+
const { K } = require("./mod1");
3+
>K : Symbol(K, Decl(main.js, 0, 7))
4+
>require : Symbol(require)
5+
>"./mod1" : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0))
6+
7+
/** @param {K} k */
8+
function f(k) {
9+
>f : Symbol(f, Decl(main.js, 0, 32))
10+
>k : Symbol(k, Decl(main.js, 2, 11))
11+
12+
k.values()
13+
>k.values : Symbol(K.values, Decl(mod1.js, 1, 13))
14+
>k : Symbol(k, Decl(main.js, 2, 11))
15+
>values : Symbol(K.values, Decl(mod1.js, 1, 13))
16+
}
17+
18+
=== tests/cases/conformance/salsa/mod1.js ===
19+
var NS = {}
20+
>NS : Symbol(NS, Decl(mod1.js, 0, 3), Decl(mod1.js, 0, 11))
21+
22+
NS.K =class {
23+
>NS.K : Symbol(K, Decl(mod1.js, 0, 11))
24+
>NS : Symbol(NS, Decl(mod1.js, 0, 3), Decl(mod1.js, 0, 11))
25+
>K : Symbol(K, Decl(mod1.js, 0, 11))
26+
27+
values() {
28+
>values : Symbol(K.values, Decl(mod1.js, 1, 13))
29+
30+
return new NS.K()
31+
>NS.K : Symbol(K, Decl(mod1.js, 0, 11))
32+
>NS : Symbol(NS, Decl(mod1.js, 0, 3), Decl(mod1.js, 0, 11))
33+
>K : Symbol(K, Decl(mod1.js, 0, 11))
34+
}
35+
}
36+
exports.K = NS.K;
37+
>exports.K : Symbol(K, Decl(mod1.js, 5, 1))
38+
>exports : Symbol(K, Decl(mod1.js, 5, 1))
39+
>K : Symbol(K, Decl(mod1.js, 5, 1))
40+
>NS.K : Symbol(K, Decl(mod1.js, 0, 11))
41+
>NS : Symbol(NS, Decl(mod1.js, 0, 3), Decl(mod1.js, 0, 11))
42+
>K : Symbol(K, Decl(mod1.js, 0, 11))
43+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
=== tests/cases/conformance/salsa/main.js ===
2+
const { K } = require("./mod1");
3+
>K : typeof K
4+
>require("./mod1") : typeof import("tests/cases/conformance/salsa/mod1")
5+
>require : any
6+
>"./mod1" : "./mod1"
7+
8+
/** @param {K} k */
9+
function f(k) {
10+
>f : (k: K) => void
11+
>k : K
12+
13+
k.values()
14+
>k.values() : K
15+
>k.values : () => K
16+
>k : K
17+
>values : () => K
18+
}
19+
20+
=== tests/cases/conformance/salsa/mod1.js ===
21+
var NS = {}
22+
>NS : typeof NS
23+
>{} : {}
24+
25+
NS.K =class {
26+
>NS.K =class { values() { return new NS.K() }} : typeof K
27+
>NS.K : typeof K
28+
>NS : typeof NS
29+
>K : typeof K
30+
>class { values() { return new NS.K() }} : typeof K
31+
32+
values() {
33+
>values : () => K
34+
35+
return new NS.K()
36+
>new NS.K() : K
37+
>NS.K : typeof K
38+
>NS : typeof NS
39+
>K : typeof K
40+
}
41+
}
42+
exports.K = NS.K;
43+
>exports.K = NS.K : typeof K
44+
>exports.K : typeof K
45+
>exports : typeof import("tests/cases/conformance/salsa/mod1")
46+
>K : typeof K
47+
>NS.K : typeof K
48+
>NS : typeof NS
49+
>K : typeof K
50+

0 commit comments

Comments
 (0)