Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 79 additions & 134 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,61 +39,79 @@ const canUseSourceMapConsumer =

const loaderOptionsCache: LoaderOptionsCache = {};

function loader(
async function loader(
this: webpack.LoaderContext<LoaderOptions>,
contents: string,
inputSourceMap?: Record<string, unknown>,
) {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
this.cacheable && this.cacheable();
// Still needed despite `async`: webpack only takes `content` from a
// returned promise, so the source map has to go through the callback.
const callback = this.async();
const configParseErrorMessage = successLoader(
this,
contents,
inputSourceMap,
callback,
);
if (configParseErrorMessage !== undefined) {
// Reconstructed here, in `loader`'s own frame, so the stack trace
// matches classic ts-loader's single `at Object.loader (...)` frame.
callback(new Error(configParseErrorMessage));
let result: { output: string; sourceMap: RawSourceMap | undefined };
try {
result = await compile(this, contents, inputSourceMap);
} catch (error) {
callback(error instanceof Error ? error : new Error(String(error)));
return;
}
callback(null, result.output, result.sourceMap);
}

function successLoader(
async function compile(
loaderContext: webpack.LoaderContext<LoaderOptions>,
contents: string,
inputSourceMap: Record<string, unknown> | undefined,
callback: ReturnType<webpack.LoaderContext<LoaderOptions>['async']>,
): string | undefined {
try {
const options = getLoaderOptions(loaderContext);
const instance = getTypeScriptInstance(options, loaderContext);
const rawFilePath = path.normalize(loaderContext.resourcePath);
const filePath = appendSuffixesIfRequired(rawFilePath, options);
const fileVersion = updateFileInCache(filePath, contents, instance);
const { outputText, sourceMapText, configParseErrorMessage } =
getTypeScriptEmit(filePath, contents, instance, loaderContext);

if (configParseErrorMessage !== undefined) {
return configParseErrorMessage;
}
) {
const options = getLoaderOptions(loaderContext);
const instance = getTypeScriptInstance(options, loaderContext);
const rawFilePath = path.normalize(loaderContext.resourcePath);
const filePath = appendSuffixesIfRequired(rawFilePath, options);
const fileVersion = updateFileInCache(filePath, contents, instance);
const { outputText, sourceMapText, configParseErrorMessage } =
getTypeScriptEmit(filePath, contents, instance, loaderContext);

makeSourceMapAndFinish(
sourceMapText,
outputText,
filePath,
contents,
loaderContext,
fileVersion,
callback,
options.allowTsInNodeModules,
inputSourceMap,
if (configParseErrorMessage !== undefined) {
throw new Error(configParseErrorMessage);
}

setModuleMeta(loaderContext, fileVersion);

if (outputText === null || outputText === undefined) {
// Most commonly a node_modules file: the API skips emit for external
// library files.
const additionalGuidance =
!options.allowTsInNodeModules && filePath.indexOf('node_modules') !== -1
? ' By default, ts-loader will not compile .ts files in node_modules.\n' +
'You should not need to recompile .ts files there, but if you really want to, use the allowTsInNodeModules option.\n' +
'See: https://github.com/Microsoft/TypeScript/issues/12358'
: '';
throw new Error(
`TypeScript emitted no output for ${filePath}.${additionalGuidance}`,
);
} catch (error) {
callback(error instanceof Error ? error : new Error(String(error)));
}
return undefined;

const { sourceMap, output } = makeSourceMap(
sourceMapText,
outputText,
filePath,
contents,
loaderContext,
);

if (sourceMap === undefined || !inputSourceMap || !canUseSourceMapConsumer) {
return { output, sourceMap };
}

return {
output,
sourceMap: await mapToInputSourceMap(
sourceMap,
loaderContext,
inputSourceMap as unknown as RawSourceMap,
),
};
}

function getTypeScriptInstance(
Expand Down Expand Up @@ -515,65 +533,6 @@ function arrify<T>(value: T | T[] | undefined) {
return value === undefined ? [] : Array.isArray(value) ? value : [value];
}

function makeSourceMapAndFinish(
sourceMapText: string | undefined,
outputText: string | undefined,
filePath: string,
contents: string,
loaderContext: webpack.LoaderContext<LoaderOptions>,
fileVersion: number,
callback: ReturnType<webpack.LoaderContext<LoaderOptions>['async']>,
allowTsInNodeModules: boolean,
inputSourceMap?: Record<string, unknown>,
) {
if (outputText === null || outputText === undefined) {
setModuleMeta(loaderContext, fileVersion);
// Most commonly a node_modules file: the API skips emit for external
// library files.
const additionalGuidance =
!allowTsInNodeModules && filePath.indexOf('node_modules') !== -1
? ' By default, ts-loader will not compile .ts files in node_modules.\n' +
'You should not need to recompile .ts files there, but if you really want to, use the allowTsInNodeModules option.\n' +
'See: https://github.com/Microsoft/TypeScript/issues/12358'
: '';
callback(
new Error(
`TypeScript emitted no output for ${filePath}.${additionalGuidance}`,
),
outputText,
undefined,
);
return;
}

const { sourceMap, output } = makeSourceMap(
sourceMapText,
outputText,
filePath,
contents,
loaderContext,
);

setModuleMeta(loaderContext, fileVersion);

if (sourceMap === undefined || !inputSourceMap || !canUseSourceMapConsumer) {
callback(null, output, sourceMap);
return;
}

mapToInputSourceMap(
sourceMap,
loaderContext,
inputSourceMap as unknown as RawSourceMap,
)
.then(mappedSourceMap => {
callback(null, output, mappedSourceMap);
})
.catch((e: Error) => {
callback(e);
});
}

function setModuleMeta(
loaderContext: webpack.LoaderContext<LoaderOptions>,
fileVersion: number,
Expand Down Expand Up @@ -604,46 +563,32 @@ function makeSourceMap(
};
}

function mapToInputSourceMap(
async function mapToInputSourceMap(
sourceMap: RawSourceMap,
loaderContext: webpack.LoaderContext<LoaderOptions>,
inputSourceMap: RawSourceMap,
): Promise<RawSourceMap> {
return new Promise<RawSourceMap>((resolve, reject) => {
const inMap: RawSourceMap = {
file: loaderContext.remainingRequest,
mappings: inputSourceMap.mappings,
names: inputSourceMap.names,
sources: inputSourceMap.sources,
sourceRoot: inputSourceMap.sourceRoot,
sourcesContent: inputSourceMap.sourcesContent,
version: inputSourceMap.version,
};
Promise.all([
new SourceMapConsumer(inMap),
new SourceMapConsumer(sourceMap),
])
.then(sourceMapConsumers => {
try {
const generator = SourceMapGenerator.fromSourceMap(
sourceMapConsumers[1],
);
generator.applySourceMap(sourceMapConsumers[0]);
const mappedSourceMap = generator.toJSON();

sourceMapConsumers.forEach(sourceMapConsumer =>
sourceMapConsumer.destroy(),
);
resolve(mappedSourceMap);
} catch (e) {
sourceMapConsumers.forEach(sourceMapConsumer =>
sourceMapConsumer.destroy(),
);
reject(e);
}
})
.catch(reject);
});
const inMap: RawSourceMap = {
file: loaderContext.remainingRequest,
mappings: inputSourceMap.mappings,
names: inputSourceMap.names,
sources: inputSourceMap.sources,
sourceRoot: inputSourceMap.sourceRoot,
sourcesContent: inputSourceMap.sourcesContent,
version: inputSourceMap.version,
};
const [inputConsumer, outputConsumer] = await Promise.all([
new SourceMapConsumer(inMap),
new SourceMapConsumer(sourceMap),
]);
try {
const generator = SourceMapGenerator.fromSourceMap(outputConsumer);
generator.applySourceMap(inputConsumer);
return generator.toJSON();
} finally {
inputConsumer.destroy();
outputConsumer.destroy();
}
}

export = loader;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ eval("{\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\ncon
\*********************************/
/***/ (() => {

eval("{throw new Error(\"Module build failed (from ../../index.js):/nError: TypeScript emitted no output for /nodeModulesMeaningfulErrorWhenImportingTs/node_modules/a/index.ts. By default, ts-loader will not compile .ts files in node_modules./nYou should not need to recompile .ts files there, but if you really want to, use the allowTsInNodeModules option./nSee: https://github.com/Microsoft/TypeScript/issues/12358/n at makeSourceMapAndFinish (/Users/johnreilly/code/github/ts-loader/dist/index.js:336:18)/n at successLoader (/Users/johnreilly/code/github/ts-loader/dist/index.js:75:9)/n at Object.loader (/Users/johnreilly/code/github/ts-loader/dist/index.js:57:37)\");\n\n//# sourceURL=webpack:///./node_modules/a/index.ts?\n}");
eval("{throw new Error(\"Module build failed (from ../../index.js):/nError: TypeScript emitted no output for /nodeModulesMeaningfulErrorWhenImportingTs/node_modules/a/index.ts. By default, ts-loader will not compile .ts files in node_modules./nYou should not need to recompile .ts files there, but if you really want to, use the allowTsInNodeModules option./nSee: https://github.com/Microsoft/TypeScript/issues/12358/n at compile (/Users/johnreilly/code/github/ts-loader/dist/index.js:89:15)/n at Object.loader (/Users/johnreilly/code/github/ts-loader/dist/index.js:62:24)\");\n\n//# sourceURL=webpack:///./node_modules/a/index.ts?\n}");

/***/ })

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
asset bundle.js 3.22 KiB [emitted] (name: main)
asset bundle.js 3.12 KiB [emitted] (name: main)
./app.ts 117 bytes [built] [code generated]
./node_modules/a/index.ts 39 bytes [built] [code generated] [1 error]

Expand All @@ -7,9 +7,8 @@ Module build failed (from ../../index.js):
Error: TypeScript emitted no output for node_modules/a/index.ts. By default, ts-loader will not compile .ts files in node_modules.
You should not need to recompile .ts files there, but if you really want to, use the allowTsInNodeModules option.
See: https://github.com/Microsoft/TypeScript/issues/12358
at makeSourceMapAndFinish (dist/index.js:336:18)
at successLoader (dist/index.js:75:9)
at Object.loader (dist/index.js:57:37)
at compile (dist/index.js:89:15)
at Object.loader (dist/index.js:62:24)
@ ./app.ts 3:10-22

webpack compiled with 1 error
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
\****************/
/***/ (() => {

eval("{throw new Error(\"Module build failed (from ../../index.js):/nError: /u001b[31merror while parsing tsconfig.json/u001b[39m/n at Object.loader (/Users/johnreilly/code/github/ts-loader/dist/index.js:62:18)\");\n\n//# sourceURL=webpack:///./app.ts?\n}");
eval("{throw new Error(\"Module build failed (from ../../index.js):/nError: /u001b[31merror while parsing tsconfig.json/u001b[39m/n at compile (/Users/johnreilly/code/github/ts-loader/dist/index.js:78:15)/n at Object.loader (/Users/johnreilly/code/github/ts-loader/dist/index.js:62:24)\");\n\n//# sourceURL=webpack:///./app.ts?\n}");

/***/ })

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
asset bundle.js 1.37 KiB [emitted] (name: main)
asset bundle.js 1.44 KiB [emitted] (name: main)
./app.ts 39 bytes [built] [code generated] [3 errors]

ERROR in tsconfig.json
Expand All @@ -14,7 +14,8 @@ ERROR in tsconfig.json
ERROR in ./app.ts
Module build failed (from ../../index.js):
Error: error while parsing tsconfig.json
at Object.loader (dist/index.js:62:18)
at compile (dist/index.js:78:15)
at Object.loader (dist/index.js:62:24)

2 errors have detailed information that is not shown.
Use 'stats.errorDetails: true' resp. '--stats-error-details' to show it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
\****************/
/***/ (() => {

eval("{throw new Error(\"Module build failed (from ../../index.js):/nError: /u001b[31merror while parsing tsconfig.json/u001b[39m/n at Object.loader (/Users/johnreilly/code/github/ts-loader/dist/index.js:62:18)\");\n\n//# sourceURL=webpack:///./app.ts?\n}");
eval("{throw new Error(\"Module build failed (from ../../index.js):/nError: /u001b[31merror while parsing tsconfig.json/u001b[39m/n at compile (/Users/johnreilly/code/github/ts-loader/dist/index.js:78:15)/n at Object.loader (/Users/johnreilly/code/github/ts-loader/dist/index.js:62:24)\");\n\n//# sourceURL=webpack:///./app.ts?\n}");

/***/ })

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
asset bundle.js 1.37 KiB [emitted] (name: main)
asset bundle.js 1.44 KiB [emitted] (name: main)
./app.ts 39 bytes [built] [code generated] [3 errors]

ERROR in tsconfig.json
Expand All @@ -14,7 +14,8 @@ ERROR in tsconfig.json
ERROR in ./app.ts
Module build failed (from ../../index.js):
Error: error while parsing tsconfig.json
at Object.loader (dist/index.js:62:18)
at compile (dist/index.js:78:15)
at Object.loader (dist/index.js:62:24)

2 errors have detailed information that is not shown.
Use 'stats.errorDetails: true' resp. '--stats-error-details' to show it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
\****************/
/***/ (() => {

eval("{throw new Error(\"Module build failed (from ../../index.js):/nError: ts-loader was supplied with an unexpected loader option: notRealOption/n/nPlease take a look at the options you are supplying; the following are valid options:/nsilent / logLevel / logInfoToStdOut / instance / compiler / configFile / transpileOnly / ignoreDiagnostics / errorFormatter / colors / appendTsSuffixTo / appendTsxSuffixTo / getCustomTransformers / reportFiles / allowTsInNodeModules / projectReferences / resolveModuleName / resolveTypeReferenceDirective / useCaseSensitiveFileNames/n/n at validateLoaderOptions (/Users/johnreilly/code/github/ts-loader/dist/index.js:235:19)/n at getLoaderOptions (/Users/johnreilly/code/github/ts-loader/dist/index.js:264:5)/n at successLoader (/Users/johnreilly/code/github/ts-loader/dist/index.js:66:25)/n at Object.loader (/Users/johnreilly/code/github/ts-loader/dist/index.js:57:37)\");\n\n//# sourceURL=webpack:///./app.ts?\n}");
eval("{throw new Error(\"Module build failed (from ../../index.js):/nError: ts-loader was supplied with an unexpected loader option: notRealOption/n/nPlease take a look at the options you are supplying; the following are valid options:/nsilent / logLevel / logInfoToStdOut / instance / compiler / configFile / transpileOnly / ignoreDiagnostics / errorFormatter / colors / appendTsSuffixTo / appendTsxSuffixTo / getCustomTransformers / reportFiles / allowTsInNodeModules / projectReferences / resolveModuleName / resolveTypeReferenceDirective / useCaseSensitiveFileNames/n/n at validateLoaderOptions (/Users/johnreilly/code/github/ts-loader/dist/index.js:330:19)/n at getLoaderOptions (/Users/johnreilly/code/github/ts-loader/dist/index.js:359:5)/n at compile (/Users/johnreilly/code/github/ts-loader/dist/index.js:71:21)/n at Object.loader (/Users/johnreilly/code/github/ts-loader/dist/index.js:62:24)\");\n\n//# sourceURL=webpack:///./app.ts?\n}");

/***/ })

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ Error: ts-loader was supplied with an unexpected loader option: notRealOption
Please take a look at the options you are supplying; the following are valid options:
silent / logLevel / logInfoToStdOut / instance / compiler / configFile / transpileOnly / ignoreDiagnostics / errorFormatter / colors / appendTsSuffixTo / appendTsxSuffixTo / getCustomTransformers / reportFiles / allowTsInNodeModules / projectReferences / resolveModuleName / resolveTypeReferenceDirective / useCaseSensitiveFileNames

at validateLoaderOptions (dist/index.js:235:19)
at getLoaderOptions (dist/index.js:264:5)
at successLoader (dist/index.js:66:25)
at Object.loader (dist/index.js:57:37)
at validateLoaderOptions (dist/index.js:330:19)
at getLoaderOptions (dist/index.js:359:5)
at compile (dist/index.js:71:21)
at Object.loader (dist/index.js:62:24)

webpack compiled with 1 error
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
\****************/
/***/ (() => {

eval("{throw new Error(\"Module build failed (from ../../index.js):/nError: ts-loader was supplied with an unexpected loader option: notRealOption/n/nPlease take a look at the options you are supplying; the following are valid options:/nsilent / logLevel / logInfoToStdOut / instance / compiler / configFile / transpileOnly / ignoreDiagnostics / errorFormatter / colors / appendTsSuffixTo / appendTsxSuffixTo / getCustomTransformers / reportFiles / allowTsInNodeModules / projectReferences / resolveModuleName / resolveTypeReferenceDirective / useCaseSensitiveFileNames/n/n at validateLoaderOptions (/Users/johnreilly/code/github/ts-loader/dist/index.js:235:19)/n at getLoaderOptions (/Users/johnreilly/code/github/ts-loader/dist/index.js:264:5)/n at successLoader (/Users/johnreilly/code/github/ts-loader/dist/index.js:66:25)/n at Object.loader (/Users/johnreilly/code/github/ts-loader/dist/index.js:57:37)\");\n\n//# sourceURL=webpack:///./app.ts?\n}");
eval("{throw new Error(\"Module build failed (from ../../index.js):/nError: ts-loader was supplied with an unexpected loader option: notRealOption/n/nPlease take a look at the options you are supplying; the following are valid options:/nsilent / logLevel / logInfoToStdOut / instance / compiler / configFile / transpileOnly / ignoreDiagnostics / errorFormatter / colors / appendTsSuffixTo / appendTsxSuffixTo / getCustomTransformers / reportFiles / allowTsInNodeModules / projectReferences / resolveModuleName / resolveTypeReferenceDirective / useCaseSensitiveFileNames/n/n at validateLoaderOptions (/Users/johnreilly/code/github/ts-loader/dist/index.js:330:19)/n at getLoaderOptions (/Users/johnreilly/code/github/ts-loader/dist/index.js:359:5)/n at compile (/Users/johnreilly/code/github/ts-loader/dist/index.js:71:21)/n at Object.loader (/Users/johnreilly/code/github/ts-loader/dist/index.js:62:24)\");\n\n//# sourceURL=webpack:///./app.ts?\n}");

/***/ })

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ Error: ts-loader was supplied with an unexpected loader option: notRealOption
Please take a look at the options you are supplying; the following are valid options:
silent / logLevel / logInfoToStdOut / instance / compiler / configFile / transpileOnly / ignoreDiagnostics / errorFormatter / colors / appendTsSuffixTo / appendTsxSuffixTo / getCustomTransformers / reportFiles / allowTsInNodeModules / projectReferences / resolveModuleName / resolveTypeReferenceDirective / useCaseSensitiveFileNames

at validateLoaderOptions (dist/index.js:235:19)
at getLoaderOptions (dist/index.js:264:5)
at successLoader (dist/index.js:66:25)
at Object.loader (dist/index.js:57:37)
at validateLoaderOptions (dist/index.js:330:19)
at getLoaderOptions (dist/index.js:359:5)
at compile (dist/index.js:71:21)
at Object.loader (dist/index.js:62:24)

webpack compiled with 1 error
Loading