Skip to content

Commit 3bdff73

Browse files
authored
Merge pull request #11819 from Microsoft/vladima/11752
treat ambient non-aliased 'require' as commonjs 'require'
2 parents 1884c89 + b7ea3e5 commit 3bdff73

9 files changed

+192
-4
lines changed

src/compiler/checker.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12825,16 +12825,41 @@ namespace ts {
1282512825
}
1282612826

1282712827
// In JavaScript files, calls to any identifier 'require' are treated as external module imports
12828-
if (isInJavaScriptFile(node) &&
12829-
isRequireCall(node, /*checkArgumentIsStringLiteral*/true) &&
12830-
// Make sure require is not a local function
12831-
!resolveName(node.expression, (<Identifier>node.expression).text, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined)) {
12828+
if (isInJavaScriptFile(node) && isCommonJsRequire(node)) {
1283212829
return resolveExternalModuleTypeByLiteral(<StringLiteral>node.arguments[0]);
1283312830
}
1283412831

1283512832
return getReturnTypeOfSignature(signature);
1283612833
}
1283712834

12835+
function isCommonJsRequire(node: Node) {
12836+
if (!isRequireCall(node, /*checkArgumentIsStringLiteral*/true)) {
12837+
return false;
12838+
}
12839+
// Make sure require is not a local function
12840+
const resolvedRequire = resolveName(node.expression, (<Identifier>node.expression).text, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
12841+
if (!resolvedRequire) {
12842+
// project does not contain symbol named 'require' - assume commonjs require
12843+
return true;
12844+
}
12845+
// project includes symbol named 'require' - make sure that it it ambient and local non-alias
12846+
if (resolvedRequire.flags & SymbolFlags.Alias) {
12847+
return false;
12848+
}
12849+
12850+
const targetDeclarationKind = resolvedRequire.flags & SymbolFlags.Function
12851+
? SyntaxKind.FunctionDeclaration
12852+
: resolvedRequire.flags & SymbolFlags.Variable
12853+
? SyntaxKind.VariableDeclaration
12854+
: SyntaxKind.Unknown;
12855+
if (targetDeclarationKind !== SyntaxKind.Unknown) {
12856+
const decl = getDeclarationOfKind(resolvedRequire, targetDeclarationKind);
12857+
// function/variable declaration should be ambient
12858+
return isInAmbientContext(decl);
12859+
}
12860+
return false;
12861+
}
12862+
1283812863
function checkTaggedTemplateExpression(node: TaggedTemplateExpression): Type {
1283912864
return getReturnTypeOfSignature(getResolvedSignature(node));
1284012865
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//// [tests/cases/compiler/ambientRequireFunction.ts] ////
2+
3+
//// [node.d.ts]
4+
5+
6+
declare function require(moduleName: string): any;
7+
8+
declare module "fs" {
9+
export function readFileSync(s: string): string;
10+
}
11+
12+
//// [app.js]
13+
/// <reference path="node.d.ts"/>
14+
15+
const fs = require("fs");
16+
const text = fs.readFileSync("/a/b/c");
17+
18+
//// [app.js]
19+
/// <reference path="node.d.ts"/>
20+
var fs = require("fs");
21+
var text = fs.readFileSync("/a/b/c");
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
=== tests/cases/compiler/app.js ===
2+
/// <reference path="node.d.ts"/>
3+
4+
const fs = require("fs");
5+
>fs : Symbol(fs, Decl(app.js, 2, 5))
6+
>require : Symbol(require, Decl(node.d.ts, 0, 0))
7+
>"fs" : Symbol("fs", Decl(node.d.ts, 2, 50))
8+
9+
const text = fs.readFileSync("/a/b/c");
10+
>text : Symbol(text, Decl(app.js, 3, 5))
11+
>fs.readFileSync : Symbol(readFileSync, Decl(node.d.ts, 4, 21))
12+
>fs : Symbol(fs, Decl(app.js, 2, 5))
13+
>readFileSync : Symbol(readFileSync, Decl(node.d.ts, 4, 21))
14+
15+
=== tests/cases/compiler/node.d.ts ===
16+
17+
18+
declare function require(moduleName: string): any;
19+
>require : Symbol(require, Decl(node.d.ts, 0, 0))
20+
>moduleName : Symbol(moduleName, Decl(node.d.ts, 2, 25))
21+
22+
declare module "fs" {
23+
export function readFileSync(s: string): string;
24+
>readFileSync : Symbol(readFileSync, Decl(node.d.ts, 4, 21))
25+
>s : Symbol(s, Decl(node.d.ts, 5, 33))
26+
}
27+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
=== tests/cases/compiler/app.js ===
2+
/// <reference path="node.d.ts"/>
3+
4+
const fs = require("fs");
5+
>fs : typeof "fs"
6+
>require("fs") : typeof "fs"
7+
>require : (moduleName: string) => any
8+
>"fs" : "fs"
9+
10+
const text = fs.readFileSync("/a/b/c");
11+
>text : string
12+
>fs.readFileSync("/a/b/c") : string
13+
>fs.readFileSync : (s: string) => string
14+
>fs : typeof "fs"
15+
>readFileSync : (s: string) => string
16+
>"/a/b/c" : "/a/b/c"
17+
18+
=== tests/cases/compiler/node.d.ts ===
19+
20+
21+
declare function require(moduleName: string): any;
22+
>require : (moduleName: string) => any
23+
>moduleName : string
24+
25+
declare module "fs" {
26+
export function readFileSync(s: string): string;
27+
>readFileSync : (s: string) => string
28+
>s : string
29+
}
30+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//// [app.js]
2+
3+
function require(a) {
4+
return a;
5+
}
6+
7+
const fs = require("fs");
8+
const text = fs.readFileSync("/a/b/c");
9+
10+
//// [app.js]
11+
function require(a) {
12+
return a;
13+
}
14+
var fs = require("fs");
15+
var text = fs.readFileSync("/a/b/c");
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
=== tests/cases/compiler/app.js ===
2+
3+
function require(a) {
4+
>require : Symbol(require, Decl(app.js, 0, 0))
5+
>a : Symbol(a, Decl(app.js, 1, 17))
6+
7+
return a;
8+
>a : Symbol(a, Decl(app.js, 1, 17))
9+
}
10+
11+
const fs = require("fs");
12+
>fs : Symbol(fs, Decl(app.js, 5, 5))
13+
>require : Symbol(require, Decl(app.js, 0, 0))
14+
15+
const text = fs.readFileSync("/a/b/c");
16+
>text : Symbol(text, Decl(app.js, 6, 5))
17+
>fs : Symbol(fs, Decl(app.js, 5, 5))
18+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
=== tests/cases/compiler/app.js ===
2+
3+
function require(a) {
4+
>require : (a: any) => any
5+
>a : any
6+
7+
return a;
8+
>a : any
9+
}
10+
11+
const fs = require("fs");
12+
>fs : any
13+
>require("fs") : any
14+
>require : (a: any) => any
15+
>"fs" : "fs"
16+
17+
const text = fs.readFileSync("/a/b/c");
18+
>text : any
19+
>fs.readFileSync("/a/b/c") : any
20+
>fs.readFileSync : any
21+
>fs : any
22+
>readFileSync : any
23+
>"/a/b/c" : "/a/b/c"
24+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// @module: commonjs
2+
// @allowJs: true
3+
// @outDir: ./out/
4+
5+
// @filename: node.d.ts
6+
7+
declare function require(moduleName: string): any;
8+
9+
declare module "fs" {
10+
export function readFileSync(s: string): string;
11+
}
12+
13+
// @filename: app.js
14+
/// <reference path="node.d.ts"/>
15+
16+
const fs = require("fs");
17+
const text = fs.readFileSync("/a/b/c");
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// @module: commonjs
2+
// @allowJs: true
3+
// @outDir: ./out/
4+
5+
// @filename: app.js
6+
function require(a) {
7+
return a;
8+
}
9+
10+
const fs = require("fs");
11+
const text = fs.readFileSync("/a/b/c");

0 commit comments

Comments
 (0)