lml-main
Version:
This is now a mono repository published into many standalone packages.
186 lines (185 loc) • 8.64 kB
JavaScript
;
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var path = require("path");
var loaderUtils = require("loader-utils");
var instances_1 = require("./instances");
var utils_1 = require("./utils");
var constants = require("./constants");
var webpackInstances = [];
var loaderOptionsCache = {};
/**
* The entry point for ts-loader
*/
function loader(contents) {
this.cacheable && this.cacheable();
var callback = this.async();
var options = getLoaderOptions(this);
var instanceOrError = instances_1.getTypeScriptInstance(options, this);
if (instanceOrError.error !== undefined) {
callback(instanceOrError.error);
return;
}
return successLoader(this, contents, callback, options, instanceOrError.instance);
}
function successLoader(loader, contents, callback, options, instance) {
var rawFilePath = path.normalize(loader.resourcePath);
var filePath = options.appendTsSuffixTo.length > 0 || options.appendTsxSuffixTo.length > 0
? utils_1.appendSuffixesIfMatch({
'.ts': options.appendTsSuffixTo,
'.tsx': options.appendTsxSuffixTo,
}, rawFilePath)
: rawFilePath;
var fileVersion = updateFileInCache(filePath, contents, instance);
var _a = options.transpileOnly
? getTranspilationEmit(filePath, contents, instance, loader)
: getEmit(rawFilePath, filePath, instance, loader), outputText = _a.outputText, sourceMapText = _a.sourceMapText;
if (outputText === null || outputText === undefined) {
var additionalGuidance = filePath.indexOf('node_modules') !== -1
? "\nYou should not need to recompile .ts files in node_modules.\nPlease contact the package author to advise them to use --declaration --outDir.\nMore https://github.com/Microsoft/TypeScript/issues/12358"
: "";
throw new Error("Typescript emitted no output for " + filePath + "." + additionalGuidance);
}
var _b = makeSourceMap(sourceMapText, outputText, filePath, contents, loader), sourceMap = _b.sourceMap, output = _b.output;
// _module.meta is not available inside happypack
if (!options.happyPackMode) {
// Make sure webpack is aware that even though the emitted JavaScript may be the same as
// a previously cached version the TypeScript may be different and therefore should be
// treated as new
loader._module.meta.tsLoaderFileVersion = fileVersion;
}
callback(null, output, sourceMap);
}
/**
* either retrieves loader options from the cache
* or creates them, adds them to the cache and returns
*/
function getLoaderOptions(loader) {
// differentiate the TypeScript instance based on the webpack instance
var webpackIndex = webpackInstances.indexOf(loader._compiler);
if (webpackIndex === -1) {
webpackIndex = webpackInstances.push(loader._compiler) - 1;
}
var queryOptions = loaderUtils.getOptions(loader) || {};
var configFileOptions = loader.options.ts || {};
var instanceName = webpackIndex + '_' + (queryOptions.instance || configFileOptions.instance || 'default');
if (utils_1.hasOwnProperty(loaderOptionsCache, instanceName)) {
return loaderOptionsCache[instanceName];
}
var options = Object.assign({}, {
silent: false,
logLevel: 'INFO',
logInfoToStdOut: false,
compiler: 'typescript',
configFile: 'tsconfig.json',
transpileOnly: false,
visualStudioErrorFormat: false,
compilerOptions: {},
appendTsSuffixTo: [],
appendTsxSuffixTo: [],
transformers: {},
entryFileIsJs: false,
happyPackMode: false,
}, configFileOptions, queryOptions);
// Use deprecated `configFileName` as fallback for `configFile`
if (queryOptions.configFileName) {
if (queryOptions.configFile) {
throw new Error('ts-loader options `configFile` and `configFileName` are mutually exclusive');
}
else {
options.configFile = queryOptions.configFileName;
}
}
options.ignoreDiagnostics = utils_1.arrify(options.ignoreDiagnostics).map(Number);
options.logLevel = options.logLevel.toUpperCase();
options.instance = instanceName;
// happypack can be used only together with transpileOnly mode
options.transpileOnly = options.happyPackMode ? true : options.transpileOnly;
loaderOptionsCache[instanceName] = options;
return options;
}
/**
* Either add file to the overall files cache or update it in the cache when the file contents have changed
* Also add the file to the modified files
*/
function updateFileInCache(filePath, contents, instance) {
// Update file contents
var file = instance.files[filePath];
if (file === undefined) {
file = instance.files[filePath] = { version: 0 };
}
if (file.text !== contents) {
file.version++;
file.text = contents;
instance.version++;
}
// push this file to modified files hash.
if (!instance.modifiedFiles) {
instance.modifiedFiles = {};
}
instance.modifiedFiles[filePath] = file;
return file.version;
}
function getEmit(rawFilePath, filePath, instance, loader) {
// Emit Javascript
var output = instance.languageService.getEmitOutput(filePath);
loader.clearDependencies();
loader.addDependency(rawFilePath);
var allDefinitionFiles = Object.keys(instance.files).filter(function (defFilePath) { return defFilePath.match(constants.dtsDtsxRegex); });
// Make this file dependent on *all* definition files in the program
var addDependency = loader.addDependency.bind(loader);
allDefinitionFiles.forEach(addDependency);
// Additionally make this file dependent on all imported files
var fileDependencies = instance.dependencyGraph[filePath];
var additionalDependencies = fileDependencies === undefined
? []
: fileDependencies.map(function (module) { return module.originalFileName; });
if (additionalDependencies) {
additionalDependencies.forEach(addDependency);
}
loader._module.meta.tsLoaderDefinitionFileVersions = allDefinitionFiles
.concat(additionalDependencies)
.map(function (defFilePath) { return defFilePath + '@' + (instance.files[defFilePath] || { version: '?' }).version; });
var outputFile = output.outputFiles.filter(function (outputFile) { return outputFile.name.match(constants.jsJsx); }).pop();
var outputText = (outputFile) ? outputFile.text : undefined;
var sourceMapFile = output.outputFiles.filter(function (outputFile) { return outputFile.name.match(constants.jsJsxMap); }).pop();
var sourceMapText = (sourceMapFile) ? sourceMapFile.text : undefined;
return { outputText: outputText, sourceMapText: sourceMapText };
}
/**
* Transpile file
*/
function getTranspilationEmit(filePath, contents, instance, loader) {
var fileName = path.basename(filePath);
var _a = instance.compiler.transpileModule(contents, {
compilerOptions: __assign({}, instance.compilerOptions, { rootDir: undefined }),
transformers: instance.transformers,
reportDiagnostics: true,
fileName: fileName,
}), outputText = _a.outputText, sourceMapText = _a.sourceMapText, diagnostics = _a.diagnostics;
// _module.errors is not available inside happypack - see https://github.com/TypeStrong/ts-loader/issues/336
if (!instance.loaderOptions.happyPackMode) {
utils_1.registerWebpackErrors(loader._module.errors, utils_1.formatErrors(diagnostics, instance.loaderOptions, instance.compiler, { module: loader._module }));
}
return { outputText: outputText, sourceMapText: sourceMapText };
}
function makeSourceMap(sourceMapText, outputText, filePath, contents, loader) {
if (sourceMapText === undefined) {
return { output: outputText, sourceMap: undefined };
}
return {
output: outputText.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, ''),
sourceMap: Object.assign(JSON.parse(sourceMapText), {
sources: [loaderUtils.getRemainingRequest(loader)],
file: filePath,
sourcesContent: [contents]
})
};
}
module.exports = loader;