Skip to content

Commit 06dbfb7

Browse files
committed
Merge branch 'master' into extensibility-model
2 parents dec0bf8 + 6be7d9c commit 06dbfb7

File tree

82 files changed

+718
-78
lines changed

Some content is hidden

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

82 files changed

+718
-78
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,4 @@ internal/
4949
**/.vscode
5050
!**/.vscode/tasks.json
5151
!tests/cases/projects/projectOption/**/node_modules
52+
!tests/cases/projects/NodeModulesSearch/**/*

issue_template.md

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,13 @@
1-
<!--
2-
Thank you for contributing to TypeScript! Please review this checklist
3-
before submitting your issue.
4-
[ ] Many common issues and suggestions are addressed in the FAQ
5-
https://github.com/Microsoft/TypeScript/wiki/FAQ
6-
[ ] Search for duplicates before logging new issues
7-
https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=is%3Aissue
8-
[ ] Questions are best asked and answered at Stack Overflow
9-
http://stackoverflow.com/questions/tagged/typescript
1+
<!-- BUGS: Please use this template. -->
2+
<!-- QUESTIONS: This is not a general support forum! Ask Qs at http://stackoverflow.com/questions/tagged/typescript -->
3+
<!-- SUGGESTIONS: See https://github.com/Microsoft/TypeScript-wiki/blob/master/Writing-Good-Design-Proposals.md -->
104

11-
For bug reports, please include the information below.
12-
__________________________________________________________ -->
13-
14-
**TypeScript Version:**
15-
16-
1.7.5 / 1.8.0-beta / nightly (1.9.0-dev.20160217)
5+
**TypeScript Version:** 1.8.0 / nightly (2.0.0-dev.201xxxxx)
176

187
**Code**
198

209
```ts
21-
// A self-contained demonstration of the problem follows...
10+
// A *self-contained* demonstration of the problem follows...
2211

2312
```
2413

src/compiler/commandLineParser.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,11 @@ namespace ts {
380380
type: "boolean",
381381
description: Diagnostics.Do_not_emit_use_strict_directives_in_module_output
382382
},
383+
{
384+
name: "maxNodeModuleJsDepth",
385+
type: "number",
386+
description: Diagnostics.The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files
387+
},
383388
{
384389
name: "listEmittedFiles",
385390
type: "boolean"

src/compiler/core.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,8 @@ namespace ts {
11561156
export const supportedJavascriptExtensions = [".js", ".jsx"];
11571157
const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions);
11581158

1159-
export function getSupportedExtensions(options?: CompilerOptions): string[] {
1159+
export function getSupportedExtensions(options?: CompilerOptions, loadJS?: boolean): string[] {
1160+
if (loadJS) return supportedJavascriptExtensions;
11601161
return options && options.allowJs ? allSupportedExtensions : supportedTypeScriptExtensions;
11611162
}
11621163

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2804,6 +2804,10 @@
28042804
"category": "Message",
28052805
"code": 6135
28062806
},
2807+
"The maximum dependency depth to search under node_modules and load JavaScript files": {
2808+
"category": "Message",
2809+
"code": 6136
2810+
},
28072811

28082812
"List of compiler extensions to require.": {
28092813
"category": "Message",

src/compiler/program.ts

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,9 @@ namespace ts {
153153
const { config } = readConfigFile(packageJsonPath, state.host.readFile);
154154
if (config) {
155155
return getPackageEntryAsPath(config, packageJsonPath, "typings", state)
156-
|| getPackageEntryAsPath(config, packageJsonPath, "types", state);
156+
|| getPackageEntryAsPath(config, packageJsonPath, "types", state)
157+
// Use the main module for inferring types if no types package specified and the allowJs is set
158+
|| (state.compilerOptions.allowJs && getPackageEntryAsPath(config, packageJsonPath, "main", state));
157159
}
158160
else {
159161
if (state.traceEnabled) {
@@ -610,7 +612,7 @@ namespace ts {
610612
failedLookupLocations, supportedExtensions, state);
611613

612614
let isExternalLibraryImport = false;
613-
if (!resolvedFileName) {
615+
if (!resolvedFileName) {
614616
if (moduleHasNonRelativeName(moduleName)) {
615617
if (traceEnabled) {
616618
trace(host, Diagnostics.Loading_module_0_from_node_modules_folder, moduleName);
@@ -735,13 +737,14 @@ namespace ts {
735737
const nodeModulesFolder = combinePaths(directory, "node_modules");
736738
const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host);
737739
const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
738-
// Load only typescript files irrespective of allowJs option if loading from node modules
739-
const extensionsSearched = loadJS ? supportedJavascriptExtensions : supportedTypeScriptExtensions;
740-
let result = loadModuleFromFile(candidate, extensionsSearched, failedLookupLocations, !nodeModulesFolderExists, state);
740+
741+
const supportedExtensions = getSupportedExtensions(state.compilerOptions, loadJS);
742+
743+
let result = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, !nodeModulesFolderExists, state);
741744
if (result) {
742745
return result;
743746
}
744-
result = loadNodeModuleFromDirectory(extensionsSearched, candidate, failedLookupLocations, !nodeModulesFolderExists, state, loadJS);
747+
result = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state, loadJS);
745748
if (result) {
746749
return result;
747750
}
@@ -1055,6 +1058,23 @@ namespace ts {
10551058
let resolvedTypeReferenceDirectives: Map<ResolvedTypeReferenceDirective> = {};
10561059
let fileProcessingDiagnostics = createDiagnosticCollection();
10571060

1061+
// The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules.
1062+
// This works as imported modules are discovered recursively in a depth first manner, specifically:
1063+
// - For each root file, findSourceFile is called.
1064+
// - This calls processImportedModules for each module imported in the source file.
1065+
// - This calls resolveModuleNames, and then calls findSourceFile for each resolved module.
1066+
// As all these operations happen - and are nested - within the createProgram call, they close over the below variables.
1067+
// The current resolution depth is tracked by incrementing/decrementing as the depth first search progresses.
1068+
const maxNodeModulesJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 2;
1069+
let currentNodeModulesJsDepth = 0;
1070+
1071+
// If a module has some of its imports skipped due to being at the depth limit under node_modules, then track
1072+
// this, as it may be imported at a shallower depth later, and then it will need its skipped imports processed.
1073+
const modulesWithElidedImports: Map<boolean> = {};
1074+
1075+
// Track source files that are JavaScript files found by searching under node_modules, as these shouldn't be compiled.
1076+
const jsFilesFoundSearchingNodeModules: Map<boolean> = {};
1077+
10581078
const start = new Date().getTime();
10591079

10601080
host = host || createCompilerHost(options);
@@ -1286,6 +1306,7 @@ namespace ts {
12861306
(oldOptions.rootDir !== options.rootDir) ||
12871307
(oldOptions.configFilePath !== options.configFilePath) ||
12881308
(oldOptions.baseUrl !== options.baseUrl) ||
1309+
(oldOptions.maxNodeModuleJsDepth !== options.maxNodeModuleJsDepth) ||
12891310
!arrayIsEqualTo(oldOptions.typeRoots, oldOptions.typeRoots) ||
12901311
!arrayIsEqualTo(oldOptions.rootDirs, options.rootDirs) ||
12911312
!mapIsEqualTo(oldOptions.paths, options.paths)) {
@@ -1410,6 +1431,7 @@ namespace ts {
14101431
getSourceFile: program.getSourceFile,
14111432
getSourceFileByPath: program.getSourceFileByPath,
14121433
getSourceFiles: program.getSourceFiles,
1434+
getFilesFromNodeModules: () => jsFilesFoundSearchingNodeModules,
14131435
writeFile: writeFileCallback || (
14141436
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),
14151437
isEmitBlocked,
@@ -2027,6 +2049,14 @@ namespace ts {
20272049
reportFileNamesDifferOnlyInCasingError(fileName, file.fileName, refFile, refPos, refEnd);
20282050
}
20292051

2052+
// See if we need to reprocess the imports due to prior skipped imports
2053+
if (file && lookUp(modulesWithElidedImports, file.path)) {
2054+
if (currentNodeModulesJsDepth < maxNodeModulesJsDepth) {
2055+
modulesWithElidedImports[file.path] = false;
2056+
processImportedModules(file, getDirectoryPath(fileName));
2057+
}
2058+
}
2059+
20302060
return file;
20312061
}
20322062

@@ -2165,16 +2195,38 @@ namespace ts {
21652195
for (let i = 0; i < moduleNames.length; i++) {
21662196
const resolution = resolutions[i];
21672197
setResolvedModule(file, moduleNames[i], resolution);
2198+
const resolvedPath = resolution ? toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName) : undefined;
2199+
21682200
// add file to program only if:
21692201
// - resolution was successful
21702202
// - noResolve is falsy
21712203
// - module name comes from the list of imports
2172-
const shouldAddFile = resolution &&
2173-
!options.noResolve &&
2174-
i < file.imports.length;
2204+
// - it's not a top level JavaScript module that exceeded the search max
2205+
const isJsFileUnderNodeModules = resolution && resolution.isExternalLibraryImport &&
2206+
hasJavaScriptFileExtension(resolution.resolvedFileName);
2207+
2208+
if (isJsFileUnderNodeModules) {
2209+
jsFilesFoundSearchingNodeModules[resolvedPath] = true;
2210+
currentNodeModulesJsDepth++;
2211+
}
2212+
2213+
const elideImport = isJsFileUnderNodeModules && currentNodeModulesJsDepth > maxNodeModulesJsDepth;
2214+
const shouldAddFile = resolution && !options.noResolve && i < file.imports.length && !elideImport;
2215+
2216+
if (elideImport) {
2217+
modulesWithElidedImports[file.path] = true;
2218+
}
2219+
else if (shouldAddFile) {
2220+
findSourceFile(resolution.resolvedFileName,
2221+
resolvedPath,
2222+
/*isDefaultLib*/ false, /*isReference*/ false,
2223+
file,
2224+
skipTrivia(file.text, file.imports[i].pos),
2225+
file.imports[i].end);
2226+
}
21752227

2176-
if (shouldAddFile) {
2177-
findSourceFile(resolution.resolvedFileName, toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName), /*isDefaultLib*/ false, /*isReference*/ false, file, skipTrivia(file.text, file.imports[i].pos), file.imports[i].end);
2228+
if (isJsFileUnderNodeModules) {
2229+
currentNodeModulesJsDepth--;
21782230
}
21792231
}
21802232
}

src/compiler/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2540,6 +2540,7 @@ namespace ts {
25402540
declaration?: boolean;
25412541
declarationDir?: string;
25422542
/* @internal */ diagnostics?: boolean;
2543+
disableSizeLimit?: boolean;
25432544
emitBOM?: boolean;
25442545
emitDecoratorMetadata?: boolean;
25452546
experimentalDecorators?: boolean;
@@ -2555,6 +2556,7 @@ namespace ts {
25552556
/*@internal*/listFiles?: boolean;
25562557
locale?: string;
25572558
mapRoot?: string;
2559+
maxNodeModuleJsDepth?: number;
25582560
module?: ModuleKind;
25592561
moduleResolution?: ModuleResolutionKind;
25602562
newLine?: NewLineKind;
@@ -2593,7 +2595,6 @@ namespace ts {
25932595
/* @internal */ suppressOutputPathCheck?: boolean;
25942596
target?: ScriptTarget;
25952597
traceResolution?: boolean;
2596-
disableSizeLimit?: boolean;
25972598
types?: string[];
25982599
/** Paths used to used to compute primary types search locations */
25992600
typeRoots?: string[];

src/compiler/utilities.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ namespace ts {
3535
export interface EmitHost extends ScriptReferenceHost {
3636
getSourceFiles(): SourceFile[];
3737

38+
/* @internal */
39+
getFilesFromNodeModules(): Map<boolean>;
40+
3841
getCommonSourceDirectory(): string;
3942
getCanonicalFileName(fileName: string): string;
4043
getNewLine(): string;
@@ -2291,8 +2294,10 @@ namespace ts {
22912294
}
22922295
else {
22932296
const sourceFiles = targetSourceFile === undefined ? host.getSourceFiles() : [targetSourceFile];
2297+
const nodeModulesFiles = host.getFilesFromNodeModules();
22942298
for (const sourceFile of sourceFiles) {
2295-
if (!isDeclarationFile(sourceFile)) {
2299+
// Don't emit if source file is a declaration file, or was located under node_modules
2300+
if (!isDeclarationFile(sourceFile) && !lookUp(nodeModulesFiles, sourceFile.path)) {
22962301
onSingleFileEmit(host, sourceFile);
22972302
}
22982303
}
@@ -2324,11 +2329,14 @@ namespace ts {
23242329
}
23252330

23262331
function onBundledEmit(host: EmitHost) {
2327-
// Can emit only sources that are not declaration file and are either non module code or module with --module or --target es6 specified
2328-
const bundledSources = filter(host.getSourceFiles(), sourceFile =>
2329-
!isDeclarationFile(sourceFile) // Not a declaration file
2330-
&& (!isExternalModule(sourceFile) || !!getEmitModuleKind(options))); // and not a module, unless module emit enabled
2331-
2332+
// Can emit only sources that are not declaration file and are either non module code or module with
2333+
// --module or --target es6 specified. Files included by searching under node_modules are also not emitted.
2334+
const nodeModulesFiles = host.getFilesFromNodeModules();
2335+
const bundledSources = filter(host.getSourceFiles(),
2336+
sourceFile => !isDeclarationFile(sourceFile) &&
2337+
!lookUp(nodeModulesFiles, sourceFile.path) &&
2338+
(!isExternalModule(sourceFile) ||
2339+
!!getEmitModuleKind(options)));
23322340
if (bundledSources.length) {
23332341
const jsFilePath = options.outFile || options.out;
23342342
const emitFileNames: EmitFileNames = {

src/harness/runnerbase.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,12 @@ abstract class RunnerBase {
3131

3232
/** Replaces instances of full paths with fileNames only */
3333
static removeFullPaths(path: string) {
34-
let fixedPath = path;
35-
36-
// full paths either start with a drive letter or / for *nix, shouldn't have \ in the path at this point
37-
const fullPath = /(\w+:|\/)?([\w+\-\.]|\/)*\.tsx?/g;
38-
const fullPathList = fixedPath.match(fullPath);
39-
if (fullPathList) {
40-
fullPathList.forEach((match: string) => fixedPath = fixedPath.replace(match, Harness.Path.getFileName(match)));
41-
}
34+
// If its a full path (starts with "C:" or "/") replace with just the filename
35+
let fixedPath = /^(\w:|\/)/.test(path) ? Harness.Path.getFileName(path) : path;
4236

4337
// when running in the browser the 'full path' is the host name, shows up in error baselines
4438
const localHost = /http:\/localhost:\d+/g;
4539
fixedPath = fixedPath.replace(localHost, "");
4640
return fixedPath;
4741
}
48-
}
42+
}

tests/baselines/reference/declarationEmit_invalidReference2.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ tests/cases/compiler/declarationEmit_invalidReference2.ts(1,1): error TS6053: Fi
44
==== tests/cases/compiler/declarationEmit_invalidReference2.ts (1 errors) ====
55
/// <reference path="invalid.ts" />
66
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7-
!!! error TS6053: File 'invalid.ts' not found.
7+
!!! error TS6053: File 'tests/cases/compiler/invalid.ts' not found.
88
var x = 0;

tests/baselines/reference/declarationFileOverwriteError.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
error TS5055: Cannot write file 'tests/cases/compiler/a.d.ts' because it would overwrite input file.
22

33

4-
!!! error TS5055: Cannot write file 'a.d.ts' because it would overwrite input file.
4+
!!! error TS5055: Cannot write file 'tests/cases/compiler/a.d.ts' because it would overwrite input file.
55
==== tests/cases/compiler/a.d.ts (0 errors) ====
66

77
declare class c {

tests/baselines/reference/declarationFileOverwriteErrorWithOut.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
error TS5055: Cannot write file 'tests/cases/compiler/out.d.ts' because it would overwrite input file.
22

33

4-
!!! error TS5055: Cannot write file 'out.d.ts' because it would overwrite input file.
4+
!!! error TS5055: Cannot write file 'tests/cases/compiler/out.d.ts' because it would overwrite input file.
55
==== tests/cases/compiler/out.d.ts (0 errors) ====
66

77
declare class c {

tests/baselines/reference/exportStarFromEmptyModule.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ tests/cases/compiler/exportStarFromEmptyModule_module4.ts(4,5): error TS2339: Pr
1414
==== tests/cases/compiler/exportStarFromEmptyModule_module3.ts (1 errors) ====
1515
export * from "./exportStarFromEmptyModule_module2";
1616
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17-
!!! error TS2306: File 'exportStarFromEmptyModule_module2.ts' is not a module.
17+
!!! error TS2306: File 'tests/cases/compiler/exportStarFromEmptyModule_module2.ts' is not a module.
1818
export * from "./exportStarFromEmptyModule_module1";
1919

2020
export class A {

tests/baselines/reference/importNonExternalModule.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ tests/cases/conformance/externalModules/foo_1.ts(1,22): error TS2306: File 'test
44
==== tests/cases/conformance/externalModules/foo_1.ts (1 errors) ====
55
import foo = require("./foo_0");
66
~~~~~~~~~
7-
!!! error TS2306: File 'foo_0.ts' is not a module.
7+
!!! error TS2306: File 'tests/cases/conformance/externalModules/foo_0.ts' is not a module.
88
// Import should fail. foo_0 not an external module
99
if(foo.answer === 42){
1010

tests/baselines/reference/invalidTripleSlashReference.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ tests/cases/compiler/invalidTripleSlashReference.ts(2,1): error TS6053: File 'te
55
==== tests/cases/compiler/invalidTripleSlashReference.ts (2 errors) ====
66
/// <reference path='filedoesnotexist.ts'/>
77
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8-
!!! error TS6053: File 'filedoesnotexist.ts' not found.
8+
!!! error TS6053: File 'tests/cases/compiler/filedoesnotexist.ts' not found.
99
/// <reference path='otherdoesnotexist.d.ts'/>
1010
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11-
!!! error TS6053: File 'otherdoesnotexist.d.ts' not found.
11+
!!! error TS6053: File 'tests/cases/compiler/otherdoesnotexist.d.ts' not found.
1212

1313
// this test doesn't actually give the errors you want due to the way the compiler reports errors
1414
var x = 1;

tests/baselines/reference/jsFileCompilationWithDeclarationEmitPathSameAsInput.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
error TS5055: Cannot write file 'tests/cases/compiler/a.d.ts' because it would overwrite input file.
22

33

4-
!!! error TS5055: Cannot write file 'a.d.ts' because it would overwrite input file.
4+
!!! error TS5055: Cannot write file 'tests/cases/compiler/a.d.ts' because it would overwrite input file.
55
==== tests/cases/compiler/a.ts (0 errors) ====
66
class c {
77
}

tests/baselines/reference/jsFileCompilationWithOutDeclarationFileNameSameAsInputJsFile.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
error TS5055: Cannot write file 'tests/cases/compiler/b.d.ts' because it would overwrite input file.
22

33

4-
!!! error TS5055: Cannot write file 'b.d.ts' because it would overwrite input file.
4+
!!! error TS5055: Cannot write file 'tests/cases/compiler/b.d.ts' because it would overwrite input file.
55
==== tests/cases/compiler/a.ts (0 errors) ====
66
class c {
77
}

tests/baselines/reference/library-reference-5.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
==== /node_modules/bar/index.d.ts (1 errors) ====
1919
/// <reference types="alpha" />
2020
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21-
!!! message TS4090: Conflicting library definitions for 'alpha' found at 'index.d.ts' and 'index.d.ts'. Copy the correct file to the 'typings' folder to resolve this conflict.
21+
!!! message TS4090: Conflicting library definitions for 'alpha' found at '/node_modules/bar/node_modules/alpha/index.d.ts' and '/node_modules/foo/node_modules/alpha/index.d.ts'. Copy the correct file to the 'typings' folder to resolve this conflict.
2222
declare var bar: any;
2323

2424
==== /node_modules/bar/node_modules/alpha/index.d.ts (0 errors) ====

0 commit comments

Comments
 (0)