Skip to content

Commit cefb741

Browse files
committed
Merge branch 'master' into fixFindReferencesOnExports
2 parents 9b01783 + 93e942e commit cefb741

8 files changed

Lines changed: 373 additions & 325 deletions

File tree

src/compiler/program.ts

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ namespace ts {
5353
if (getRootLength(moduleName) !== 0 || nameStartsWithDotSlashOrDotDotSlash(moduleName)) {
5454
const failedLookupLocations: string[] = [];
5555
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
56-
let resolvedFileName = loadNodeModuleFromFile(supportedExtensions, candidate, failedLookupLocations, host);
56+
let resolvedFileName = loadNodeModuleFromFile(supportedExtensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, host);
5757

5858
if (resolvedFileName) {
5959
return { resolvedModule: { resolvedFileName }, failedLookupLocations };
6060
}
6161

62-
resolvedFileName = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, host);
62+
resolvedFileName = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, host);
6363
return resolvedFileName
6464
? { resolvedModule: { resolvedFileName }, failedLookupLocations }
6565
: { resolvedModule: undefined, failedLookupLocations };
@@ -69,12 +69,22 @@ namespace ts {
6969
}
7070
}
7171

72-
function loadNodeModuleFromFile(extensions: string[], candidate: string, failedLookupLocation: string[], host: ModuleResolutionHost): string {
72+
/* @internal */
73+
export function directoryProbablyExists(directoryName: string, host: { directoryExists?: (directoryName: string) => boolean } ): boolean {
74+
// if host does not support 'directoryExists' assume that directory will exist
75+
return !host.directoryExists || host.directoryExists(directoryName);
76+
}
77+
78+
/**
79+
* @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary
80+
* in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations.
81+
*/
82+
function loadNodeModuleFromFile(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, host: ModuleResolutionHost): string {
7383
return forEach(extensions, tryLoad);
7484

7585
function tryLoad(ext: string): string {
7686
const fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext;
77-
if (host.fileExists(fileName)) {
87+
if (!onlyRecordFailures && host.fileExists(fileName)) {
7888
return fileName;
7989
}
8090
else {
@@ -84,9 +94,10 @@ namespace ts {
8494
}
8595
}
8696

87-
function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], host: ModuleResolutionHost): string {
97+
function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, host: ModuleResolutionHost): string {
8898
const packageJsonPath = combinePaths(candidate, "package.json");
89-
if (host.fileExists(packageJsonPath)) {
99+
const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, host);
100+
if (directoryExists && host.fileExists(packageJsonPath)) {
90101

91102
let jsonContent: { typings?: string };
92103

@@ -100,7 +111,8 @@ namespace ts {
100111
}
101112

102113
if (typeof jsonContent.typings === "string") {
103-
const result = loadNodeModuleFromFile(extensions, normalizePath(combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host);
114+
const path = normalizePath(combinePaths(candidate, jsonContent.typings));
115+
const result = loadNodeModuleFromFile(extensions, path, failedLookupLocation, !directoryProbablyExists(getDirectoryPath(path), host), host);
104116
if (result) {
105117
return result;
106118
}
@@ -111,7 +123,7 @@ namespace ts {
111123
failedLookupLocation.push(packageJsonPath);
112124
}
113125

114-
return loadNodeModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocation, host);
126+
return loadNodeModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocation, !directoryExists, host);
115127
}
116128

117129
function loadModuleFromNodeModules(moduleName: string, directory: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
@@ -121,14 +133,15 @@ namespace ts {
121133
const baseName = getBaseFileName(directory);
122134
if (baseName !== "node_modules") {
123135
const nodeModulesFolder = combinePaths(directory, "node_modules");
136+
const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, host);
124137
const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
125138
// Load only typescript files irrespective of allowJs option if loading from node modules
126-
let result = loadNodeModuleFromFile(supportedTypeScriptExtensions, candidate, failedLookupLocations, host);
139+
let result = loadNodeModuleFromFile(supportedTypeScriptExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, host);
127140
if (result) {
128141
return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations };
129142
}
130143

131-
result = loadNodeModuleFromDirectory(supportedTypeScriptExtensions, candidate, failedLookupLocations, host);
144+
result = loadNodeModuleFromDirectory(supportedTypeScriptExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, host);
132145
if (result) {
133146
return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations };
134147
}
@@ -281,7 +294,8 @@ namespace ts {
281294
getCanonicalFileName,
282295
getNewLine: () => newLine,
283296
fileExists: fileName => sys.fileExists(fileName),
284-
readFile: fileName => sys.readFile(fileName)
297+
readFile: fileName => sys.readFile(fileName),
298+
directoryExists: directoryName => sys.directoryExists(directoryName)
285299
};
286300
}
287301

src/compiler/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2650,6 +2650,8 @@ namespace ts {
26502650
// readFile function is used to read arbitrary text files on disk, i.e. when resolution procedure needs the content of 'package.json'
26512651
// to determine location of bundled typings for node module
26522652
readFile(fileName: string): string;
2653+
2654+
directoryExists?(directoryName: string): boolean;
26532655
}
26542656

26552657
export interface ResolvedModule {

src/harness/harnessLanguageService.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,10 @@ namespace Harness.LanguageService {
267267
log(s: string): void { this.nativeHost.log(s); }
268268
trace(s: string): void { this.nativeHost.trace(s); }
269269
error(s: string): void { this.nativeHost.error(s); }
270+
directoryExists(directoryName: string): boolean {
271+
// for tests pessimistically assume that directory always exists
272+
return true;
273+
}
270274
}
271275

272276
class ClassifierShimProxy implements ts.Classifier {

src/lib/dom.generated.d.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ interface AudioContext extends EventTarget {
321321
destination: AudioDestinationNode;
322322
listener: AudioListener;
323323
sampleRate: number;
324+
state: string;
324325
createAnalyser(): AnalyserNode;
325326
createBiquadFilter(): BiquadFilterNode;
326327
createBuffer(numberOfChannels: number, length: number, sampleRate: number): AudioBuffer;
@@ -2774,6 +2775,7 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec
27742775
tagName: string;
27752776
id: string;
27762777
className: string;
2778+
innerHTML: string;
27772779
getAttribute(name?: string): string;
27782780
getAttributeNS(namespaceURI: string, localName: string): string;
27792781
getAttributeNode(name: string): Attr;
@@ -2969,7 +2971,7 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec
29692971
removeAttributeNode(oldAttr: Attr): Attr;
29702972
requestFullscreen(): void;
29712973
requestPointerLock(): void;
2972-
setAttribute(name?: string, value?: string): void;
2974+
setAttribute(name: string, value: string): void;
29732975
setAttributeNS(namespaceURI: string, qualifiedName: string, value: string): void;
29742976
setAttributeNode(newAttr: Attr): Attr;
29752977
setAttributeNodeNS(newAttr: Attr): Attr;
@@ -5512,7 +5514,7 @@ interface HTMLMediaElement extends HTMLElement {
55125514
* Gets or sets the current playback position, in seconds.
55135515
*/
55145516
preload: string;
5515-
readyState: any;
5517+
readyState: number;
55165518
/**
55175519
* Returns a TimeRanges object that represents the ranges of the current media resource that can be seeked.
55185520
*/
@@ -6169,6 +6171,7 @@ interface HTMLSelectElement extends HTMLElement {
61696171
* Returns whether an element will successfully validate based on forms validation rules and constraints.
61706172
*/
61716173
willValidate: boolean;
6174+
selectedOptions: HTMLCollection;
61726175
/**
61736176
* Adds an element to the areas, controlRange, or options collection.
61746177
* @param element Variant of type Number that specifies the index position in the collection where the element is placed. If no value is given, the method places the element at the end of the collection.

src/server/editorServices.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ namespace ts.server {
100100
this.filenameToScript = createFileMap<ScriptInfo>();
101101
this.moduleResolutionHost = {
102102
fileExists: fileName => this.fileExists(fileName),
103-
readFile: fileName => this.host.readFile(fileName)
103+
readFile: fileName => this.host.readFile(fileName),
104+
directoryExists: directoryName => this.host.directoryExists(directoryName)
104105
};
105106
}
106107

src/services/services.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,7 @@ namespace ts {
10341034
* host specific questions using 'getScriptSnapshot'.
10351035
*/
10361036
resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[];
1037+
directoryExists?(directoryName: string): boolean;
10371038
}
10381039

10391040
//
@@ -1911,7 +1912,8 @@ namespace ts {
19111912
getCurrentDirectory: () => "",
19121913
getNewLine: () => newLine,
19131914
fileExists: (fileName): boolean => fileName === inputFileName,
1914-
readFile: (fileName): string => ""
1915+
readFile: (fileName): string => "",
1916+
directoryExists: directoryExists => true
19151917
};
19161918

19171919
const program = createProgram([inputFileName], options, compilerHost);
@@ -2768,6 +2770,10 @@ namespace ts {
27682770
// stub missing host functionality
27692771
const entry = hostCache.getOrCreateEntry(fileName);
27702772
return entry && entry.scriptSnapshot.getText(0, entry.scriptSnapshot.getLength());
2773+
},
2774+
directoryExists: directoryName => {
2775+
Debug.assert(!host.resolveModuleNames);
2776+
return directoryProbablyExists(directoryName, host);
27712777
}
27722778
};
27732779

0 commit comments

Comments
 (0)