coronamap/node_modules/ts-loader/dist/instances.js
2022-08-06 08:12:21 -07:00

376 lines
No EOL
17 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const chalk_1 = require("chalk");
const fs = require("fs");
const path = require("path");
const after_compile_1 = require("./after-compile");
const compilerSetup_1 = require("./compilerSetup");
const config_1 = require("./config");
const constants_1 = require("./constants");
const logger = require("./logger");
const servicesHost_1 = require("./servicesHost");
const utils_1 = require("./utils");
const watch_run_1 = require("./watch-run");
const instances = {};
/**
* The loader is executed once for each file seen by webpack. However, we need to keep
* a persistent instance of TypeScript that contains all of the files in the program
* along with definition files and options. This function either creates an instance
* or returns the existing one. Multiple instances are possible by using the
* `instance` property.
*/
function getTypeScriptInstance(loaderOptions, loader) {
if (instances.hasOwnProperty(loaderOptions.instance)) {
const instance = instances[loaderOptions.instance];
utils_1.ensureProgram(instance);
return { instance: instances[loaderOptions.instance] };
}
const colors = new chalk_1.default.constructor({ enabled: loaderOptions.colors });
const log = logger.makeLogger(loaderOptions, colors);
const compiler = compilerSetup_1.getCompiler(loaderOptions, log);
if (compiler.errorMessage !== undefined) {
return { error: utils_1.makeError(colors.red(compiler.errorMessage), undefined) };
}
return successfulTypeScriptInstance(loaderOptions, loader, log, colors, compiler.compiler, compiler.compilerCompatible, compiler.compilerDetailsLogMessage);
}
exports.getTypeScriptInstance = getTypeScriptInstance;
function successfulTypeScriptInstance(loaderOptions, loader, log, colors, compiler, compilerCompatible, compilerDetailsLogMessage) {
const configFileAndPath = config_1.getConfigFile(compiler, colors, loader, loaderOptions, compilerCompatible, log, compilerDetailsLogMessage);
if (configFileAndPath.configFileError !== undefined) {
const { message, file } = configFileAndPath.configFileError;
return {
error: utils_1.makeError(colors.red('error while reading tsconfig.json:' + constants_1.EOL + message), file)
};
}
const { configFilePath, configFile } = configFileAndPath;
const basePath = loaderOptions.context || path.dirname(configFilePath || '');
const configParseResult = config_1.getConfigParseResult(compiler, configFile, basePath, configFilePath, loaderOptions.projectReferences);
if (configParseResult.errors.length > 0 && !loaderOptions.happyPackMode) {
const errors = utils_1.formatErrors(configParseResult.errors, loaderOptions, colors, compiler, { file: configFilePath }, loader.context);
loader._module.errors.push(...errors);
return {
error: utils_1.makeError(colors.red('error while parsing tsconfig.json'), configFilePath)
};
}
const compilerOptions = compilerSetup_1.getCompilerOptions(configParseResult);
const rootFileNames = new Set();
const files = new Map();
const otherFiles = new Map();
const appendTsTsxSuffixesIfRequired = loaderOptions.appendTsSuffixTo.length > 0 ||
loaderOptions.appendTsxSuffixTo.length > 0
? (filePath) => utils_1.appendSuffixesIfMatch({
'.ts': loaderOptions.appendTsSuffixTo,
'.tsx': loaderOptions.appendTsxSuffixTo
}, filePath)
: (filePath) => filePath;
// same strategy as https://github.com/s-panferov/awesome-typescript-loader/pull/531/files
let { getCustomTransformers: customerTransformers } = loaderOptions;
let getCustomTransformers = Function.prototype;
if (typeof customerTransformers === 'function') {
getCustomTransformers = customerTransformers;
}
else if (typeof customerTransformers === 'string') {
try {
customerTransformers = require(customerTransformers);
}
catch (err) {
throw new Error(`Failed to load customTransformers from "${loaderOptions.getCustomTransformers}": ${err.message}`);
}
if (typeof customerTransformers !== 'function') {
throw new Error(`Custom transformers in "${loaderOptions.getCustomTransformers}" should export a function, got ${typeof getCustomTransformers}`);
}
getCustomTransformers = customerTransformers;
}
// if allowJs is set then we should accept js(x) files
const scriptRegex = configParseResult.options.allowJs === true
? /\.tsx?$|\.jsx?$/i
: /\.tsx?$/i;
if (loaderOptions.transpileOnly) {
// quick return for transpiling
// we do need to check for any issues with TS options though
const transpileInstance = (instances[loaderOptions.instance] = {
compiler,
compilerOptions,
appendTsTsxSuffixesIfRequired,
loaderOptions,
rootFileNames,
files,
otherFiles,
program: undefined,
dependencyGraph: {},
reverseDependencyGraph: {},
transformers: {},
colors
});
tryAndBuildSolutionReferences(transpileInstance, loader, log, scriptRegex, configFilePath);
const program = (transpileInstance.program =
configParseResult.projectReferences !== undefined
? compiler.createProgram({
rootNames: configParseResult.fileNames,
options: configParseResult.options,
projectReferences: configParseResult.projectReferences
})
: compiler.createProgram([], compilerOptions));
// happypack does not have _module.errors - see https://github.com/TypeStrong/ts-loader/issues/336
if (!loaderOptions.happyPackMode) {
const solutionErrors = servicesHost_1.getSolutionErrors(transpileInstance, loader.context);
const diagnostics = program.getOptionsDiagnostics();
const errors = utils_1.formatErrors(diagnostics, loaderOptions, colors, compiler, { file: configFilePath || 'tsconfig.json' }, loader.context);
loader._module.errors.push(...solutionErrors, ...errors);
}
transpileInstance.transformers = getCustomTransformers(program);
return { instance: transpileInstance };
}
// Load initial files (core lib files, any files specified in tsconfig.json)
let normalizedFilePath;
try {
const filesToLoad = loaderOptions.onlyCompileBundledFiles
? configParseResult.fileNames.filter(fileName => constants_1.dtsDtsxOrDtsDtsxMapRegex.test(fileName))
: configParseResult.fileNames;
filesToLoad.forEach(filePath => {
normalizedFilePath = path.normalize(filePath);
files.set(normalizedFilePath, {
text: fs.readFileSync(normalizedFilePath, 'utf-8'),
version: 0
});
rootFileNames.add(normalizedFilePath);
});
}
catch (exc) {
return {
error: utils_1.makeError(colors.red(`A file specified in tsconfig.json could not be found: ${normalizedFilePath}`), normalizedFilePath)
};
}
const instance = (instances[loaderOptions.instance] = {
compiler,
compilerOptions,
appendTsTsxSuffixesIfRequired,
loaderOptions,
rootFileNames,
files,
otherFiles,
languageService: null,
version: 0,
transformers: {},
dependencyGraph: {},
reverseDependencyGraph: {},
colors
});
if (!loader._compiler.hooks) {
throw new Error("You may be using an old version of webpack; please check you're using at least version 4");
}
tryAndBuildSolutionReferences(instance, loader, log, scriptRegex, configFilePath);
if (loaderOptions.experimentalWatchApi && compiler.createWatchProgram) {
log.logInfo('Using watch api');
// If there is api available for watch, use it instead of language service
instance.watchHost = servicesHost_1.makeWatchHost(scriptRegex, log, loader, instance, configParseResult.projectReferences);
instance.watchOfFilesAndCompilerOptions = compiler.createWatchProgram(instance.watchHost);
instance.builderProgram = instance.watchOfFilesAndCompilerOptions.getProgram();
instance.program = instance.builderProgram.getProgram();
instance.transformers = getCustomTransformers(instance.program);
}
else {
const servicesHost = servicesHost_1.makeServicesHost(scriptRegex, log, loader, instance, loaderOptions.experimentalFileCaching, configParseResult.projectReferences);
instance.languageService = compiler.createLanguageService(servicesHost.servicesHost, compiler.createDocumentRegistry());
if (servicesHost.clearCache !== null) {
loader._compiler.hooks.watchRun.tap('ts-loader', servicesHost.clearCache);
}
instance.transformers = getCustomTransformers(instance.languageService.getProgram());
}
loader._compiler.hooks.afterCompile.tapAsync('ts-loader', after_compile_1.makeAfterCompile(instance, configFilePath));
loader._compiler.hooks.watchRun.tapAsync('ts-loader', watch_run_1.makeWatchRun(instance));
return { instance };
}
function tryAndBuildSolutionReferences(instance, loader, log, scriptRegex, configFilePath) {
if (configFilePath &&
utils_1.supportsSolutionBuild(instance.loaderOptions, instance.compiler)) {
// Use solution builder
log.logInfo('Using SolutionBuilder api');
instance.configFilePath = configFilePath;
instance.solutionBuilderHost = servicesHost_1.makeSolutionBuilderHost(scriptRegex, log, loader, instance);
instance.solutionBuilder = instance.compiler.createSolutionBuilderWithWatch(instance.solutionBuilderHost, [configFilePath], { verbose: true });
instance.solutionBuilder.buildReferences(instance.configFilePath);
}
}
function forEachResolvedProjectReference(resolvedProjectReferences, cb) {
let seenResolvedRefs;
return worker(resolvedProjectReferences);
function worker(resolvedRefs) {
if (resolvedRefs) {
for (const resolvedRef of resolvedRefs) {
if (!resolvedRef) {
continue;
}
if (seenResolvedRefs &&
seenResolvedRefs.some(seenRef => seenRef === resolvedRef)) {
// ignore recursives
continue;
}
(seenResolvedRefs || (seenResolvedRefs = [])).push(resolvedRef);
const result = cb(resolvedRef) || worker(resolvedRef.references);
if (result) {
return result;
}
}
}
return undefined;
}
}
exports.forEachResolvedProjectReference = forEachResolvedProjectReference;
// This code is here as a temporary holder
function fileExtensionIs(fileName, ext) {
return fileName.endsWith(ext);
}
function rootDirOfOptions(instance, configFile) {
return (configFile.options.rootDir ||
instance.compiler.getDirectoryPath(configFile.options.configFilePath));
}
function getOutputPathWithoutChangingExt(instance, inputFileName, configFile, ignoreCase, outputDir) {
return outputDir
? instance.compiler.resolvePath(outputDir, instance.compiler.getRelativePathFromDirectory(rootDirOfOptions(instance, configFile), inputFileName, ignoreCase))
: inputFileName;
}
function getOutputJSFileName(instance, inputFileName, configFile, ignoreCase) {
if (configFile.options.emitDeclarationOnly) {
return undefined;
}
const isJsonFile = fileExtensionIs(inputFileName, '.json');
const outputFileName = instance.compiler.changeExtension(getOutputPathWithoutChangingExt(instance, inputFileName, configFile, ignoreCase, configFile.options.outDir), isJsonFile
? '.json'
: fileExtensionIs(inputFileName, '.tsx') &&
configFile.options.jsx === instance.compiler.JsxEmit.Preserve
? '.jsx'
: '.js');
return !isJsonFile ||
instance.compiler.comparePaths(inputFileName, outputFileName, configFile.options.configFilePath, ignoreCase) !== instance.compiler.Comparison.EqualTo
? outputFileName
: undefined;
}
function getOutputFileNames(instance, configFile, inputFileName) {
const ignoreCase = !instance.compiler.sys.useCaseSensitiveFileNames;
if (instance.compiler.getOutputFileNames) {
return instance.compiler.getOutputFileNames(configFile, inputFileName, ignoreCase);
}
const outputs = [];
const addOutput = (fileName) => fileName && outputs.push(fileName);
const js = getOutputJSFileName(instance, inputFileName, configFile, ignoreCase);
addOutput(js);
if (!fileExtensionIs(inputFileName, '.json')) {
if (js && configFile.options.sourceMap) {
addOutput(`${js}.map`);
}
if ((configFile.options.declaration || configFile.options.composite) &&
instance.compiler.hasTSFileExtension(inputFileName)) {
const dts = instance.compiler.getOutputDeclarationFileName(inputFileName, configFile, ignoreCase);
addOutput(dts);
if (configFile.options.declarationMap) {
addOutput(`${dts}.map`);
}
}
}
return outputs;
}
function getOutputFilesFromReference(program, instance, filePath) {
// May be api to get file
return forEachResolvedProjectReference(program.getResolvedProjectReferences(), ({ commandLine }) => {
const { options, fileNames } = commandLine;
if (!options.outFile &&
!options.out &&
fileNames.some(file => path.normalize(file) === filePath)) {
const outputFiles = [];
getOutputFileNames(instance, commandLine, instance.compiler.resolvePath(filePath)).forEach(name => {
const text = instance.compiler.sys.readFile(name);
if (text) {
outputFiles.push({ name, text, writeByteOrderMark: false });
}
});
return outputFiles;
}
return undefined;
});
}
function isReferencedFile(instance, filePath) {
return (!!instance.solutionBuilderHost &&
!!instance.solutionBuilderHost.watchedFiles.get(filePath));
}
exports.isReferencedFile = isReferencedFile;
function getEmitFromWatchHost(instance, filePath) {
const program = utils_1.ensureProgram(instance);
const builderProgram = instance.builderProgram;
if (builderProgram && program) {
if (filePath) {
const existing = instance.watchHost.outputFiles.get(filePath);
if (existing) {
return existing;
}
}
const outputFiles = [];
const writeFile = (fileName, text, writeByteOrderMark) => {
if (fileName.endsWith('.tsbuildinfo')) {
instance.watchHost.tsbuildinfo = {
name: fileName,
writeByteOrderMark,
text
};
}
else {
outputFiles.push({ name: fileName, writeByteOrderMark, text });
}
};
const sourceFile = filePath ? program.getSourceFile(filePath) : undefined;
// Try emit Next file
while (true) {
const result = builderProgram.emitNextAffectedFile(writeFile,
/*cancellationToken*/ undefined,
/*emitOnlyDtsFiles*/ false, instance.transformers);
if (!result) {
break;
}
if (result.affected.fileName) {
instance.watchHost.outputFiles.set(path.resolve(result.affected.fileName), outputFiles.slice());
}
if (result.affected === sourceFile) {
return outputFiles;
}
}
}
return undefined;
}
exports.getEmitFromWatchHost = getEmitFromWatchHost;
function getEmitOutput(instance, filePath) {
if (fileExtensionIs(filePath, instance.compiler.Extension.Dts)) {
return [];
}
const program = utils_1.ensureProgram(instance);
if (program !== undefined) {
const sourceFile = program.getSourceFile(filePath);
if (isReferencedFile(instance, filePath)) {
const builtReferences = getOutputFilesFromReference(program, instance, filePath);
if (builtReferences) {
return builtReferences;
}
}
const outputFiles = [];
const writeFile = (fileName, text, writeByteOrderMark) => outputFiles.push({ name: fileName, writeByteOrderMark, text });
// The source file will be undefined if its part of an unbuilt project reference
if (sourceFile !== undefined || !utils_1.isUsingProjectReferences(instance)) {
const outputFilesFromWatch = getEmitFromWatchHost(instance, filePath);
if (outputFilesFromWatch) {
return outputFilesFromWatch;
}
program.emit(sourceFile, writeFile,
/*cancellationToken*/ undefined,
/*emitOnlyDtsFiles*/ false, instance.transformers);
}
return outputFiles;
}
else {
// Emit Javascript
return instance.languageService.getProgram().getSourceFile(filePath) ===
undefined
? []
: instance.languageService.getEmitOutput(filePath).outputFiles;
}
}
exports.getEmitOutput = getEmitOutput;
//# sourceMappingURL=instances.js.map