Skip to content

Commit b7ea3e5

Browse files
committed
treat ambient non-aliased 'require' as commonjs 'require'
1 parent cef9d85 commit b7ea3e5

File tree

10 files changed

+197
-9
lines changed

10 files changed

+197
-9
lines changed

src/compiler/checker.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12819,16 +12819,41 @@ namespace ts {
1281912819
}
1282012820

1282112821
// In JavaScript files, calls to any identifier 'require' are treated as external module imports
12822-
if (isInJavaScriptFile(node) &&
12823-
isRequireCall(node, /*checkArgumentIsStringLiteral*/true) &&
12824-
// Make sure require is not a local function
12825-
!resolveName(node.expression, (<Identifier>node.expression).text, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined)) {
12822+
if (isInJavaScriptFile(node) && isCommonJsRequire(node)) {
1282612823
return resolveExternalModuleTypeByLiteral(<StringLiteral>node.arguments[0]);
1282712824
}
1282812825

1282912826
return getReturnTypeOfSignature(signature);
1283012827
}
1283112828

12829+
function isCommonJsRequire(node: Node) {
12830+
if (!isRequireCall(node, /*checkArgumentIsStringLiteral*/true)) {
12831+
return false;
12832+
}
12833+
// Make sure require is not a local function
12834+
const resolvedRequire = resolveName(node.expression, (<Identifier>node.expression).text, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
12835+
if (!resolvedRequire) {
12836+
// project does not contain symbol named 'require' - assume commonjs require
12837+
return true;
12838+
}
12839+
// project includes symbol named 'require' - make sure that it it ambient and local non-alias
12840+
if (resolvedRequire.flags & SymbolFlags.Alias) {
12841+
return false;
12842+
}
12843+
12844+
const targetDeclarationKind = resolvedRequire.flags & SymbolFlags.Function
12845+
? SyntaxKind.FunctionDeclaration
12846+
: resolvedRequire.flags & SymbolFlags.Variable
12847+
? SyntaxKind.VariableDeclaration
12848+
: SyntaxKind.Unknown;
12849+
if (targetDeclarationKind !== SyntaxKind.Unknown) {
12850+
const decl = getDeclarationOfKind(resolvedRequire, targetDeclarationKind);
12851+
// function/variable declaration should be ambient
12852+
return isInAmbientContext(decl);
12853+
}
12854+
return false;
12855+
}
12856+
1283212857
function checkTaggedTemplateExpression(node: TaggedTemplateExpression): Type {
1283312858
return getReturnTypeOfSignature(getResolvedSignature(node));
1283412859
}
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");

tests/webTestServer.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ function dir(dirPath: string, spec?: string, options?: any) {
128128
// fs.rmdirSync won't delete directories with files in it
129129
function deleteFolderRecursive(dirPath: string) {
130130
if (fs.existsSync(dirPath)) {
131-
fs.readdirSync(dirPath).forEach((file, index) => {
131+
fs.readdirSync(dirPath).forEach((file) => {
132132
const curPath = path.join(path, file);
133133
if (fs.statSync(curPath).isDirectory()) { // recurse
134134
deleteFolderRecursive(curPath);
@@ -141,7 +141,7 @@ function deleteFolderRecursive(dirPath: string) {
141141
}
142142
};
143143

144-
function writeFile(path: string, data: any, opts: { recursive: boolean }) {
144+
function writeFile(path: string, data: any) {
145145
ensureDirectoriesExist(getDirectoryPath(path));
146146
fs.writeFileSync(path, data);
147147
}
@@ -208,7 +208,7 @@ enum RequestType {
208208
Unknown
209209
}
210210

211-
function getRequestOperation(req: http.ServerRequest, filename: string) {
211+
function getRequestOperation(req: http.ServerRequest) {
212212
if (req.method === "GET" && req.url.indexOf("?") === -1) {
213213
if (req.url.indexOf(".") !== -1) return RequestType.GetFile;
214214
else return RequestType.GetDir;
@@ -258,7 +258,7 @@ function handleRequestOperation(req: http.ServerRequest, res: http.ServerRespons
258258
break;
259259
case RequestType.WriteFile:
260260
processPost(req, res, (data) => {
261-
writeFile(reqPath, data, { recursive: true });
261+
writeFile(reqPath, data);
262262
});
263263
send(ResponseCode.Success, res, undefined);
264264
break;
@@ -306,7 +306,7 @@ http.createServer((req: http.ServerRequest, res: http.ServerResponse) => {
306306
log(`${req.method} ${req.url}`);
307307
const uri = url.parse(req.url).pathname;
308308
const reqPath = path.join(process.cwd(), uri);
309-
const operation = getRequestOperation(req, reqPath);
309+
const operation = getRequestOperation(req);
310310
handleRequestOperation(req, res, operation, reqPath);
311311
}).listen(port);
312312

0 commit comments

Comments
 (0)