Skip to content

Commit

Permalink
correct cache the alias mapper, fix #1
Browse files Browse the repository at this point in the history
  • Loading branch information
Kaciras committed Sep 16, 2024
1 parent 7b84df1 commit 2716300
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 21 deletions.
6 changes: 3 additions & 3 deletions src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,11 @@ let importedCompileFn: CompileFn;
export async function transform(code: string, filename: string, format?: ScriptType) {
importedCompileFn ??= await detectTypeScriptCompiler();

const tsconfig = await getTSConfig(filename);
if (!tsconfig) {
const found = await getTSConfig(filename);
if (!found) {
throw new Error(`Cannot find tsconfig.json for ${filename}`);
}
const compilerOptions = { ...tsconfig.compilerOptions };
const compilerOptions = { ...found.tsconfig.compilerOptions };

// Resolve `compilerOptions.module` and `format`.
if (format === "module") {
Expand Down
38 changes: 20 additions & 18 deletions src/tsconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import { join, resolve as resolvePath } from "path";
import { fileURLToPath } from "url";
import { parse, TSConfckCache } from "tsconfck";

interface AliasEntry {
root: string;
maps?: PathAlias[];
}

export const tsconfigCache = new TSConfckCache<any>();
export const aliasCache = new Map<string, AliasEntry>();

const EMPTY: readonly string[] = [];

interface TSConfigEssentialProperties {
root: string;
alias?: PathAlias[];
compilerOptions: any;
}

/**
* Parse the closest tsconfig.json, and normalize some options.
*
Expand All @@ -20,31 +20,32 @@ interface TSConfigEssentialProperties {
* @return tsconfig JSON object, with some additional properties.
*/
export async function getTSConfig(file: string) {
const { tsconfig, tsconfigFile } = await parse(file, {
cache: tsconfigCache,
});
const result = await parse(file, { cache: tsconfigCache });
const { tsconfig, tsconfigFile } = result;
if (!tsconfigFile) {
return;
}
if (!tsconfig.root) {
if (!aliasCache.has(tsconfigFile)) {
const options = tsconfig.compilerOptions ??= {};
const { paths, baseUrl = "" } = options;
tsconfig.root = resolvePath(tsconfigFile, "..", baseUrl);

options.inlineSourceMap = true;
options.removeComments = true;

// Avoid modify source path in the source map.
delete options.outDir;

const root = resolvePath(tsconfigFile, "..", baseUrl);
let maps: PathAlias[] | undefined;
if (paths) {
tsconfig.alias = PathAlias.parse(tsconfig, paths);
maps = PathAlias.parse(root, paths);
}
aliasCache.set(tsconfigFile, { root, maps });

options.target &&= options.target.toLowerCase();
options.module &&= options.module.toLowerCase();
}
return tsconfig as TSConfigEssentialProperties;
return result;
}

class PathAlias {
Expand Down Expand Up @@ -89,7 +90,7 @@ class PathAlias {
return templates.map(t => t.replace("*", s));
}

static parse({ root }: any, paths: Record<string, string[]>) {
static parse(root: string, paths: Record<string, string[]>) {
const alias: PathAlias[] = [];
for (const [key, templates] of Object.entries(paths)) {
alias.push(new PathAlias(root, key, templates));
Expand All @@ -115,12 +116,13 @@ export async function getAlias(id: string, parent?: string) {
) {
return EMPTY;
}
const tsconfig = await getTSConfig(fileURLToPath(parent));
if (!tsconfig) {
const found = await getTSConfig(fileURLToPath(parent));
if (!found) {
return EMPTY; // The package of `parent` does not have tsconfig.
}
const { alias, compilerOptions, root } = tsconfig;
const match = alias?.find(item => item.test(id));
const { compilerOptions } = found.tsconfig;
const { maps, root } = aliasCache.get(found.tsconfigFile)!;
const match = maps?.find(item => item.test(id));
if (match) {
return match.getPaths(id);
}
Expand Down
Empty file added test/alias/src/file.js
Empty file.
6 changes: 6 additions & 0 deletions test/loader.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,17 @@ describe("Path Alias", () => {

it("should skip declaration files", () => {
assert.strictEqual(import.meta.resolve("_pkg", top), pkgEntry);
assert.strictEqual(import.meta.resolve("prefix/module.ts", top), moduleTs);
});

it("should not inherit alias options", () => {
assert.throws(() => import.meta.resolve("exact-match", nested));
});

it("should correct cache the alias mapper", () => {
const importer = import.meta.resolve("./src/file.js", top);
assert.strictEqual(import.meta.resolve("node:fs", importer), "node:fs");
});
});

describe("transform", () => {
Expand Down

0 comments on commit 2716300

Please sign in to comment.