mirror of
https://github.com/denoland/deno.git
synced 2024-12-29 02:29:06 -05:00
d9ff4eccb5
Basically this does pre-processing of TypeScript files and gathers all the dependencies asynchronously. Only then after all the dependencies are gathered, does it do a compile, which at that point all the dependencies are cached in memory in the compiler, so with the exception of the hard coded assets, there are no ops during the compilation. Because op_fetch_source_files is now handled asynchronously in the runtime, we can eliminate the tokio_util::block_on() which was causing the increase in threads. Benchmarking on my machine has shown about a 5% improvement in speed when dealing with compiling TypeScript. Still a long way to go, but an improvement. In theory the module name resolution and the fetching of the source files could be broken out as two different ops. This would prevent situations of sending the full source file all the time when actually the module is the same module referenced by multiple modules, but that could be done subsequently to this.
91 lines
2.7 KiB
TypeScript
91 lines
2.7 KiB
TypeScript
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
|
|
|
interface FileReference {
|
|
fileName: string;
|
|
pos: number;
|
|
end: number;
|
|
}
|
|
|
|
/** Remap the module name based on any supplied type directives passed. */
|
|
export function getMappedModuleName(
|
|
source: FileReference,
|
|
typeDirectives: Map<FileReference, string>
|
|
): string {
|
|
const { fileName: sourceFileName, pos: sourcePos } = source;
|
|
for (const [{ fileName, pos }, value] of typeDirectives.entries()) {
|
|
if (sourceFileName === fileName && sourcePos === pos) {
|
|
return value;
|
|
}
|
|
}
|
|
return source.fileName;
|
|
}
|
|
|
|
/** Matches directives that look something like this and parses out the value
|
|
* of the directive:
|
|
*
|
|
* // @deno-types="./foo.d.ts"
|
|
*
|
|
* [See Diagram](http://bit.ly/31nZPCF)
|
|
*/
|
|
const typeDirectiveRegEx = /@deno-types\s*=\s*(["'])((?:(?=(\\?))\3.)*?)\1/gi;
|
|
|
|
/** Matches `import`, `import from` or `export from` statements and parses out the value of the
|
|
* module specifier in the second capture group:
|
|
*
|
|
* import "./foo.js"
|
|
* import * as foo from "./foo.js"
|
|
* export { a, b, c } from "./bar.js"
|
|
*
|
|
* [See Diagram](http://bit.ly/2lOsp0K)
|
|
*/
|
|
const importExportRegEx = /(?:import|export)(?:\s+|\s+[\s\S]*?from\s+)?(["'])((?:(?=(\\?))\3.)*?)\1/;
|
|
|
|
/** Parses out any Deno type directives that are part of the source code, or
|
|
* returns `undefined` if there are not any.
|
|
*/
|
|
export function parseTypeDirectives(
|
|
sourceCode: string | undefined
|
|
): Map<FileReference, string> | undefined {
|
|
if (!sourceCode) {
|
|
return;
|
|
}
|
|
|
|
// collect all the directives in the file and their start and end positions
|
|
const directives: FileReference[] = [];
|
|
let maybeMatch: RegExpExecArray | null = null;
|
|
while ((maybeMatch = typeDirectiveRegEx.exec(sourceCode))) {
|
|
const [matchString, , fileName] = maybeMatch;
|
|
const { index: pos } = maybeMatch;
|
|
directives.push({
|
|
fileName,
|
|
pos,
|
|
end: pos + matchString.length
|
|
});
|
|
}
|
|
if (!directives.length) {
|
|
return;
|
|
}
|
|
|
|
// work from the last directive backwards for the next `import`/`export`
|
|
// statement
|
|
directives.reverse();
|
|
const results = new Map<FileReference, string>();
|
|
for (const { end, fileName, pos } of directives) {
|
|
const searchString = sourceCode.substring(end);
|
|
const maybeMatch = importExportRegEx.exec(searchString);
|
|
if (maybeMatch) {
|
|
const [matchString, , targetFileName] = maybeMatch;
|
|
const targetPos =
|
|
end + maybeMatch.index + matchString.indexOf(targetFileName) - 1;
|
|
const target: FileReference = {
|
|
fileName: targetFileName,
|
|
pos: targetPos,
|
|
end: targetPos + targetFileName.length
|
|
};
|
|
results.set(target, fileName);
|
|
}
|
|
sourceCode = sourceCode.substring(0, pos);
|
|
}
|
|
|
|
return results;
|
|
}
|