@adpt/core
Version:
AdaptJS core library
143 lines • 6.05 kB
JavaScript
;
/*
* Copyright 2018-2019 Unbounded Systems, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const path = tslib_1.__importStar(require("path"));
const error_1 = require("../error");
const utils_1 = require("../utils");
const hosts_1 = require("./hosts");
const ts = tslib_1.__importStar(require("./tsmod"));
const tsmod = ts.tsmod;
const debugModuleResolution = false;
const dtsRegex = /\.d\.ts$/;
class ModuleResolver extends hosts_1.ChainableHost {
constructor(compilerOptions, chainHost, id) {
super((chainHost && chainHost.cwd) || "/");
this.compilerOptions = compilerOptions;
if (chainHost)
this.setSource(chainHost);
this.cache = new Map();
if (id)
this._id = id;
}
resolveModuleNames(moduleNames, containingFile, reusedNames) {
const resolved = [];
for (const modName of moduleNames) {
// NOTE: ts.CompilerHost allows returning undefined for a module, but
// ts.LanguageServiceHost does not. Fib a little here.
resolved.push(this.resolveModuleName(modName, containingFile, false));
}
return resolved;
}
/**
* Resolve a single module name to a file path
* @param modName The module name, as specified in import/require
* @param containingFile The path to the file that contains the import
* @param runnable Return a file that can be executed, which means either
* a .js file or something that we know how to compile (ts, tsx).
*/
resolveModuleName(modName, containingFile, runnable) {
utils_1.trace(debugModuleResolution, `Trying to resolve ${modName}`);
const fn = this.realFilename(containingFile);
if (!fn)
throw new Error(`Unable to get real filename for ${containingFile}`);
containingFile = fn;
const cacheKey = `${modName}\0${containingFile}\0${runnable}`;
let mod = this.cache.get(cacheKey);
if (mod !== undefined)
return mod === null ? undefined : mod;
const r = tsmod().resolveModuleName(modName, containingFile, this.compilerOptions, this);
if (r) {
mod = r.resolvedModule;
if (runnable) {
const resolved = mod && mod.resolvedFileName;
// FIXME(mark): This isn't quite the right check. It *should*
// be anything we know how to run, which is .js or anything
// we know how to compile. But we don't have immediate access
// to which extensions we know how to compile... In practice,
// rejecting .d.ts is sufficient here.
if (resolved && resolved.match(dtsRegex)) {
utils_1.trace(debugModuleResolution, `Initially resolved to ${resolved}, but rejecting .d.ts ` +
`file because runnable=true`);
mod = resolveJS(modName, containingFile, this);
}
}
}
if (mod) {
utils_1.trace(debugModuleResolution, `Resolved to ${mod.resolvedFileName}`);
this.cache.set(cacheKey, mod);
return mod;
}
utils_1.trace(debugModuleResolution, `FAILED to resolve ${modName}`);
this.cache.set(cacheKey, null);
return undefined;
}
/**
* Called by TS for module tracing and other debug output
* @param s String to be printed to debug output stream
*/
trace(s) {
utils_1.trace(debugModuleResolution, s);
}
}
tslib_1.__decorate([
utils_1.tracef(debugModuleResolution),
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [Array, String, Array]),
tslib_1.__metadata("design:returntype", void 0)
], ModuleResolver.prototype, "resolveModuleNames", null);
tslib_1.__decorate([
utils_1.tracef(debugModuleResolution),
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [String, String, Boolean]),
tslib_1.__metadata("design:returntype", void 0)
], ModuleResolver.prototype, "resolveModuleName", null);
exports.ModuleResolver = ModuleResolver;
function resolveJS(modName, containingFile, host) {
// The function that the TS compiler uses to resolve JS modules is
// exported, but marked @internal. They also changed the name of the
// function somewhere in the 3.x series.
const tsResolve = tsmod().resolveJSModule || // > 3.x name
tsmod().resolveJavaScriptModule; // < 3.x name
if (!tsResolve) {
throw new error_1.InternalError(`Unable to locate the Javascript resolver ` +
`function from the TypeScript library`);
}
const jsFile = tsResolve(modName, path.dirname(containingFile), host);
if (!jsFile) {
utils_1.trace(debugModuleResolution, `JavaScript file resolution failed`);
return null;
}
let ext;
switch (path.extname(jsFile)) {
case tsmod().Extension.Js:
ext = tsmod().Extension.Js;
break;
case tsmod().Extension.Jsx:
ext = tsmod().Extension.Jsx;
break;
default:
throw new Error(`Module file extension ` +
`'${path.extname(jsFile)}' not understood`);
}
return {
resolvedFileName: jsFile,
isExternalLibraryImport: true,
extension: ext,
};
}
//# sourceMappingURL=modules.js.map