From 4a3b38b2740665566be596705da873e1d257b879 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 5 Apr 2017 15:24:10 -0700 Subject: [PATCH] Refactor how we (internally) expose JS module resolution Also, provide a useful error if resolution fails. --- src/compiler/moduleNameResolver.ts | 21 +++++++++++++++++---- src/server/server.ts | 7 +++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 5280c794725..9e41d1dd667 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -2,7 +2,6 @@ /// namespace ts { - /* @internal */ export function trace(host: ModuleResolutionHost, message: DiagnosticMessage, ...args: any[]): void; export function trace(host: ModuleResolutionHost): void { @@ -15,6 +14,7 @@ namespace ts { } /** Array that is only intended to be pushed to, never read. */ + /* @internal */ export interface Push { push(value: T): void; } @@ -675,12 +675,25 @@ namespace ts { } export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations { - return nodeModuleNameResolverWorker(moduleName, containingFile, compilerOptions, host, cache, /*jsOnly*/ false); + return nodeModuleNameResolverWorker(moduleName, getDirectoryPath(containingFile), compilerOptions, host, cache, /*jsOnly*/ false); } + /** + * Expose resolution logic to allow us to use Node module resolution logic from arbitrary locations. + * No way to do this with `require()`: https://github.com/nodejs/node/issues/5963 + * Throws an error if the module can't be resolved. + */ /* @internal */ - export function nodeModuleNameResolverWorker(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, jsOnly = false): ResolvedModuleWithFailedLookupLocations { - const containingDirectory = getDirectoryPath(containingFile); + export function resolveJavaScriptModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string { + const { resolvedModule, failedLookupLocations } = + nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ts.ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true); + if (!resolvedModule) { + throw new Error(`Could not resolve JS module ${moduleName} starting at ${initialDir}. Looked in: ${failedLookupLocations.join(", ")}`); + } + return resolvedModule.resolvedFileName; + } + + function nodeModuleNameResolverWorker(moduleName: string, containingDirectory: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache: ModuleResolutionCache | undefined, jsOnly: boolean): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); const failedLookupLocations: string[] = []; diff --git a/src/server/server.ts b/src/server/server.ts index ab746f44f5b..d5ad3c9be05 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -702,12 +702,11 @@ namespace ts.server { } sys.require = (initialDir: string, moduleName: string): RequireResult => { - const result = nodeModuleNameResolverWorker(moduleName, initialDir + "/program.ts", { moduleResolution: ts.ModuleResolutionKind.NodeJs, allowJs: true }, sys, undefined, /*jsOnly*/ true); try { - return { module: require(result.resolvedModule.resolvedFileName), error: undefined }; + return { module: require(resolveJavaScriptModule(moduleName, initialDir, sys)), error: undefined }; } - catch (e) { - return { module: undefined, error: e }; + catch (error) { + return { module: undefined, error }; } };