Skip to content

Commit 3d4e220

Browse files
committed
merge with origin/master
2 parents 73c94d0 + a861913 commit 3d4e220

8 files changed

Lines changed: 357 additions & 233 deletions

File tree

src/compiler/program.ts

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ namespace ts {
189189
}
190190

191191
const failedLookupLocations: string[] = [];
192-
const resolvedFileName = loadModuleFromFile(supportedExtensions, moduleName, failedLookupLocations, host, traceEnabled);
192+
const resolvedFileName = loadModuleFromFile(supportedExtensions, moduleName, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(moduleName), host), host, traceEnabled);
193193
return {
194194
resolvedModule: resolvedFileName ? { resolvedFileName } : undefined,
195195
failedLookupLocations
@@ -265,7 +265,7 @@ namespace ts {
265265
}
266266
}
267267

268-
const resolvedFileName = loadModuleFromFile(supportedExtensions, candidate, failedLookupLocations, host, traceEnabled);
268+
const resolvedFileName = loadModuleFromFile(supportedExtensions, candidate, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), host), host, traceEnabled);
269269
return {
270270
resolvedModule: resolvedFileName ? { resolvedFileName } : undefined,
271271
failedLookupLocations
@@ -323,7 +323,7 @@ namespace ts {
323323
trace(host, Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path);
324324
}
325325

326-
const resolvedFileName = loadModuleFromFile(supportedExtensions, candidate, failedLookupLocations, host, traceEnabled);
326+
const resolvedFileName = loadModuleFromFile(supportedExtensions, candidate, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), host), host, traceEnabled);
327327
if (resolvedFileName) {
328328
return { resolvedModule: { resolvedFileName }, failedLookupLocations };
329329
}
@@ -338,7 +338,7 @@ namespace ts {
338338
trace(host, Diagnostics.Resolving_module_name_0_relative_to_base_url_1_2, moduleName, baseUrl, candidate);
339339
}
340340

341-
const resolvedFileName = loadModuleFromFile(supportedExtensions, candidate, failedLookupLocations, host, traceEnabled);
341+
const resolvedFileName = loadModuleFromFile(supportedExtensions, candidate, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), host), host, traceEnabled);
342342
return {
343343
resolvedModule: resolvedFileName ? { resolvedFileName } : undefined,
344344
failedLookupLocations
@@ -363,18 +363,16 @@ namespace ts {
363363
if (isRootedDiskPath(moduleName) || nameStartsWithDotSlashOrDotDotSlash(moduleName)) {
364364
const failedLookupLocations: string[] = [];
365365
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
366-
367366
if (traceEnabled) {
368367
trace(host, Diagnostics.Loading_module_0_as_file_Slash_folder_candidate_module_location_1, moduleName, candidate);
369368
}
370369

371-
let resolvedFileName = loadModuleFromFile(supportedExtensions, candidate, failedLookupLocations, host, traceEnabled);
372-
370+
let resolvedFileName = loadModuleFromFile(supportedExtensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, host, traceEnabled);
373371
if (resolvedFileName) {
374372
return { resolvedModule: { resolvedFileName }, failedLookupLocations };
375373
}
376374

377-
resolvedFileName = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, host, traceEnabled);
375+
resolvedFileName = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, host, traceEnabled);
378376
return resolvedFileName
379377
? { resolvedModule: { resolvedFileName }, failedLookupLocations }
380378
: { resolvedModule: undefined, failedLookupLocations };
@@ -388,13 +386,22 @@ namespace ts {
388386
}
389387
}
390388

391-
function loadModuleFromFile(extensions: string[], candidate: string, failedLookupLocation: string[], host: ModuleResolutionHost, traceEnabled: boolean): string {
389+
/* @internal */
390+
export function directoryProbablyExists(directoryName: string, host: { directoryExists?: (directoryName: string) => boolean } ): boolean {
391+
// if host does not support 'directoryExists' assume that directory will exist
392+
return !host.directoryExists || host.directoryExists(directoryName);
393+
}
394+
395+
/**
396+
* @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
397+
* 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.
398+
*/
399+
function loadModuleFromFile(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, host: ModuleResolutionHost, traceEnabled: boolean): string {
392400
return forEach(extensions, tryLoad);
393401

394402
function tryLoad(ext: string): string {
395403
const fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext;
396-
397-
if (host.fileExists(fileName)) {
404+
if (!onlyRecordFailures && host.fileExists(fileName)) {
398405
if (traceEnabled) {
399406
trace(host, Diagnostics.File_0_exist_use_it_as_a_module_resolution_result, fileName);
400407
}
@@ -410,9 +417,10 @@ namespace ts {
410417
}
411418
}
412419

413-
function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], host: ModuleResolutionHost, traceEnabled: boolean): string {
420+
function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, host: ModuleResolutionHost, traceEnabled: boolean): string {
414421
const packageJsonPath = combinePaths(candidate, "package.json");
415-
if (host.fileExists(packageJsonPath)) {
422+
const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, host);
423+
if (directoryExists && host.fileExists(packageJsonPath)) {
416424
if (traceEnabled) {
417425
trace(host, Diagnostics.Found_package_json_at_0, packageJsonPath);
418426
}
@@ -434,7 +442,7 @@ namespace ts {
434442
if (traceEnabled) {
435443
trace(host, Diagnostics.package_json_has_typings_field_0_that_references_1, jsonContent.typings, typingsFile);
436444
}
437-
const result = loadModuleFromFile(extensions, typingsFile, failedLookupLocation, host, traceEnabled);
445+
const result = loadModuleFromFile(extensions, typingsFile, failedLookupLocation, !directoryProbablyExists(getDirectoryPath(typingsFile), host), host, traceEnabled);
438446
if (result) {
439447
return result;
440448
}
@@ -457,7 +465,7 @@ namespace ts {
457465
failedLookupLocation.push(packageJsonPath);
458466
}
459467

460-
return loadModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocation, host, traceEnabled);
468+
return loadModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocation, !directoryExists, host, traceEnabled);
461469
}
462470

463471
function loadModuleFromNodeModules(moduleName: string, directory: string, host: ModuleResolutionHost, traceEnabled: boolean): ResolvedModuleWithFailedLookupLocations {
@@ -467,14 +475,14 @@ namespace ts {
467475
const baseName = getBaseFileName(directory);
468476
if (baseName !== "node_modules") {
469477
const nodeModulesFolder = combinePaths(directory, "node_modules");
478+
const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, host);
470479
const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
471480
// Load only typescript files irrespective of allowJs option if loading from node modules
472-
let result = loadModuleFromFile(supportedTypeScriptExtensions, candidate, failedLookupLocations, host, traceEnabled);
481+
let result = loadModuleFromFile(supportedTypeScriptExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, host, traceEnabled);
473482
if (result) {
474483
return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations };
475484
}
476-
477-
result = loadNodeModuleFromDirectory(supportedTypeScriptExtensions, candidate, failedLookupLocations, host, traceEnabled);
485+
result = loadNodeModuleFromDirectory(supportedTypeScriptExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, host, traceEnabled);
478486
if (result) {
479487
return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations };
480488
}
@@ -655,7 +663,8 @@ namespace ts {
655663
getNewLine: () => newLine,
656664
fileExists: fileName => sys.fileExists(fileName),
657665
readFile: fileName => sys.readFile(fileName),
658-
trace: (s: string) => sys.write(s + newLine)
666+
trace: (s: string) => sys.write(s + newLine),
667+
directoryExists: directoryName => sys.directoryExists(directoryName)
659668
};
660669
}
661670

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2667,6 +2667,7 @@ namespace ts {
26672667
// to determine location of bundled typings for node module
26682668
readFile(fileName: string): string;
26692669
trace?(s: string): void;
2670+
directoryExists?(directoryName: string): boolean;
26702671
}
26712672

26722673
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

src/services/shims.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ namespace ts {
6262
useCaseSensitiveFileNames?(): boolean;
6363

6464
getModuleResolutionsForFile?(fileName: string): string;
65+
directoryExists(directoryName: string): boolean;
6566
}
6667

6768
/** Public interface of the the of a config service shim instance.*/
@@ -276,6 +277,7 @@ namespace ts {
276277
private tracingEnabled = false;
277278

278279
public resolveModuleNames: (moduleName: string[], containingFile: string) => ResolvedModule[];
280+
public directoryExists: (directoryName: string) => boolean;
279281

280282
constructor(private shimHost: LanguageServiceShimHost) {
281283
// if shimHost is a COM object then property check will become method call with no arguments.
@@ -289,6 +291,9 @@ namespace ts {
289291
});
290292
};
291293
}
294+
if ("directoryExists" in this.shimHost) {
295+
this.directoryExists = directoryName => this.shimHost.directoryExists(directoryName);
296+
}
292297
}
293298

294299
public log(s: string): void {
@@ -407,9 +412,14 @@ namespace ts {
407412
}
408413
}
409414

410-
export class CoreServicesShimHostAdapter implements ParseConfigHost {
415+
export class CoreServicesShimHostAdapter implements ParseConfigHost, ModuleResolutionHost {
411416

417+
public directoryExists: (directoryName: string) => boolean;
418+
412419
constructor(private shimHost: CoreServicesShimHost) {
420+
if ("directoryExists" in this.shimHost) {
421+
this.directoryExists = directoryName => this.shimHost.directoryExists(directoryName);
422+
}
413423
}
414424

415425
public readDirectory(rootDir: string, extension: string, exclude: string[]): string[] {
@@ -426,11 +436,11 @@ namespace ts {
426436
}
427437
return JSON.parse(encoded);
428438
}
429-
439+
430440
public fileExists(fileName: string): boolean {
431441
return this.shimHost.fileExists(fileName);
432442
}
433-
443+
434444
public readFile(fileName: string): string {
435445
return this.shimHost.readFile(fileName);
436446
}

0 commit comments

Comments
 (0)