Merge pull request #11819 from Microsoft/vladima/11752

treat ambient non-aliased 'require' as commonjs 'require'
This commit is contained in:
Vladimir Matveev
2016-10-24 16:26:32 -07:00
committed by GitHub
9 changed files with 192 additions and 4 deletions

View File

@@ -12825,16 +12825,41 @@ namespace ts {
}
// In JavaScript files, calls to any identifier 'require' are treated as external module imports
if (isInJavaScriptFile(node) &&
isRequireCall(node, /*checkArgumentIsStringLiteral*/true) &&
// Make sure require is not a local function
!resolveName(node.expression, (<Identifier>node.expression).text, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined)) {
if (isInJavaScriptFile(node) && isCommonJsRequire(node)) {
return resolveExternalModuleTypeByLiteral(<StringLiteral>node.arguments[0]);
}
return getReturnTypeOfSignature(signature);
}
function isCommonJsRequire(node: Node) {
if (!isRequireCall(node, /*checkArgumentIsStringLiteral*/true)) {
return false;
}
// Make sure require is not a local function
const resolvedRequire = resolveName(node.expression, (<Identifier>node.expression).text, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
if (!resolvedRequire) {
// project does not contain symbol named 'require' - assume commonjs require
return true;
}
// project includes symbol named 'require' - make sure that it it ambient and local non-alias
if (resolvedRequire.flags & SymbolFlags.Alias) {
return false;
}
const targetDeclarationKind = resolvedRequire.flags & SymbolFlags.Function
? SyntaxKind.FunctionDeclaration
: resolvedRequire.flags & SymbolFlags.Variable
? SyntaxKind.VariableDeclaration
: SyntaxKind.Unknown;
if (targetDeclarationKind !== SyntaxKind.Unknown) {
const decl = getDeclarationOfKind(resolvedRequire, targetDeclarationKind);
// function/variable declaration should be ambient
return isInAmbientContext(decl);
}
return false;
}
function checkTaggedTemplateExpression(node: TaggedTemplateExpression): Type {
return getReturnTypeOfSignature(getResolvedSignature(node));
}

View File

@@ -0,0 +1,21 @@
//// [tests/cases/compiler/ambientRequireFunction.ts] ////
//// [node.d.ts]
declare function require(moduleName: string): any;
declare module "fs" {
export function readFileSync(s: string): string;
}
//// [app.js]
/// <reference path="node.d.ts"/>
const fs = require("fs");
const text = fs.readFileSync("/a/b/c");
//// [app.js]
/// <reference path="node.d.ts"/>
var fs = require("fs");
var text = fs.readFileSync("/a/b/c");

View File

@@ -0,0 +1,27 @@
=== tests/cases/compiler/app.js ===
/// <reference path="node.d.ts"/>
const fs = require("fs");
>fs : Symbol(fs, Decl(app.js, 2, 5))
>require : Symbol(require, Decl(node.d.ts, 0, 0))
>"fs" : Symbol("fs", Decl(node.d.ts, 2, 50))
const text = fs.readFileSync("/a/b/c");
>text : Symbol(text, Decl(app.js, 3, 5))
>fs.readFileSync : Symbol(readFileSync, Decl(node.d.ts, 4, 21))
>fs : Symbol(fs, Decl(app.js, 2, 5))
>readFileSync : Symbol(readFileSync, Decl(node.d.ts, 4, 21))
=== tests/cases/compiler/node.d.ts ===
declare function require(moduleName: string): any;
>require : Symbol(require, Decl(node.d.ts, 0, 0))
>moduleName : Symbol(moduleName, Decl(node.d.ts, 2, 25))
declare module "fs" {
export function readFileSync(s: string): string;
>readFileSync : Symbol(readFileSync, Decl(node.d.ts, 4, 21))
>s : Symbol(s, Decl(node.d.ts, 5, 33))
}

View File

@@ -0,0 +1,30 @@
=== tests/cases/compiler/app.js ===
/// <reference path="node.d.ts"/>
const fs = require("fs");
>fs : typeof "fs"
>require("fs") : typeof "fs"
>require : (moduleName: string) => any
>"fs" : "fs"
const text = fs.readFileSync("/a/b/c");
>text : string
>fs.readFileSync("/a/b/c") : string
>fs.readFileSync : (s: string) => string
>fs : typeof "fs"
>readFileSync : (s: string) => string
>"/a/b/c" : "/a/b/c"
=== tests/cases/compiler/node.d.ts ===
declare function require(moduleName: string): any;
>require : (moduleName: string) => any
>moduleName : string
declare module "fs" {
export function readFileSync(s: string): string;
>readFileSync : (s: string) => string
>s : string
}

View File

@@ -0,0 +1,15 @@
//// [app.js]
function require(a) {
return a;
}
const fs = require("fs");
const text = fs.readFileSync("/a/b/c");
//// [app.js]
function require(a) {
return a;
}
var fs = require("fs");
var text = fs.readFileSync("/a/b/c");

View File

@@ -0,0 +1,18 @@
=== tests/cases/compiler/app.js ===
function require(a) {
>require : Symbol(require, Decl(app.js, 0, 0))
>a : Symbol(a, Decl(app.js, 1, 17))
return a;
>a : Symbol(a, Decl(app.js, 1, 17))
}
const fs = require("fs");
>fs : Symbol(fs, Decl(app.js, 5, 5))
>require : Symbol(require, Decl(app.js, 0, 0))
const text = fs.readFileSync("/a/b/c");
>text : Symbol(text, Decl(app.js, 6, 5))
>fs : Symbol(fs, Decl(app.js, 5, 5))

View File

@@ -0,0 +1,24 @@
=== tests/cases/compiler/app.js ===
function require(a) {
>require : (a: any) => any
>a : any
return a;
>a : any
}
const fs = require("fs");
>fs : any
>require("fs") : any
>require : (a: any) => any
>"fs" : "fs"
const text = fs.readFileSync("/a/b/c");
>text : any
>fs.readFileSync("/a/b/c") : any
>fs.readFileSync : any
>fs : any
>readFileSync : any
>"/a/b/c" : "/a/b/c"

View File

@@ -0,0 +1,17 @@
// @module: commonjs
// @allowJs: true
// @outDir: ./out/
// @filename: node.d.ts
declare function require(moduleName: string): any;
declare module "fs" {
export function readFileSync(s: string): string;
}
// @filename: app.js
/// <reference path="node.d.ts"/>
const fs = require("fs");
const text = fs.readFileSync("/a/b/c");

View File

@@ -0,0 +1,11 @@
// @module: commonjs
// @allowJs: true
// @outDir: ./out/
// @filename: app.js
function require(a) {
return a;
}
const fs = require("fs");
const text = fs.readFileSync("/a/b/c");