diff --git a/eslint.config.mjs b/eslint.config.mjs index e212547..b31bd3a 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -7,4 +7,9 @@ export default [ ], }, ...baseConfig, + { + rules: { + "unicorn/no-array-for-each": "off", + }, + }, ]; diff --git a/src/core/precompile.ts b/src/core/precompile.ts index 2267c20..77b5562 100644 --- a/src/core/precompile.ts +++ b/src/core/precompile.ts @@ -61,38 +61,38 @@ export async function precompile( assert(matchedTestFiles.size > 0, "No matched testname"); } - const sourceFunctions = new Map(); + let sourceFunctions: Map | undefined = undefined; if (collectCoverage) { const sourceCodePaths = getRelatedFiles(includes, excludes, (path: string) => !path.endsWith(".test.ts")); const sourceTransformFunction = join(projectRoot, "transform", "listFunctions.mjs"); - // The batchSize = 2 is empirical data after benchmarking - const batchSize = 2; - for (let i = 0; i < sourceCodePaths.length; i += batchSize) { - await Promise.all( - sourceCodePaths.slice(i, i + batchSize).map((sourcePath) => - transform(sourceTransformFunction, sourcePath, flags, () => { - sourceFunctions.set(sourcePath, functionInfos); - }) - ) - ); - } + globalThis.__functionInfos = undefined; + sourceFunctions = await transform(sourceTransformFunction, sourceCodePaths, flags, () => __functionInfos); } - return { testCodePaths: matchedTestFiles.size > 0 ? Array.from(matchedTestFiles) : testCodePaths, matchedTestNames, - sourceFunctions, + sourceFunctions: sourceFunctions || new Map(), }; } -async function transform(transformFunction: string, codePath: string, flags: string, collectCallback: () => void) { - let ascArgv = [codePath, "--noEmit", "--disableWarning", "--transform", transformFunction, "-O0"]; +async function transform( + transformFunction: string, + codePath: string | string[], + flags: string, + collectCallback: () => T +) { + let ascArgv = ["--noEmit", "--disableWarning", "--transform", transformFunction, "-O0"]; + if (typeof codePath === "string") { + ascArgv.push(codePath); + } else { + ascArgv.push(...codePath); + } if (flags) { const argv = flags.split(" "); ascArgv = ascArgv.concat(argv); } await ascMain(ascArgv, true); - collectCallback(); + return collectCallback(); } // a. include in config diff --git a/src/parser/index.ts b/src/parser/index.ts index 6872535..9dcfacb 100644 --- a/src/parser/index.ts +++ b/src/parser/index.ts @@ -77,7 +77,6 @@ export class Parser { this.functionCovTraceMap.set(name, originTraces.concat(traces)); } const lineInfoMap: LineInfoMap = new Map(); - // eslint-disable-next-line unicorn/no-array-for-each info.lineInfo.forEach((ranges: LineRange | null, index: number) => { // If instrument return basic block == null, ignore it. if (ranges === null) return; diff --git a/src/type/global.d.ts b/src/type/global.d.ts index c4caa07..4417f80 100644 --- a/src/type/global.d.ts +++ b/src/type/global.d.ts @@ -1,10 +1,13 @@ import { SourceFunctionInfo } from "../interface.ts"; declare global { + // why use var: [Remove block-scoped bindings from globalThis](https://github.com/microsoft/TypeScript/issues/30547) // store listFunctions transform results in global - let functionInfos: SourceFunctionInfo[]; + // eslint-disable-next-line no-var + var __functionInfos: Map | undefined; // store listTestNames transform results in global - let testNames: string[]; + // eslint-disable-next-line no-var + var testNames: string[]; } export {}; diff --git a/transform/listFunctions.mts b/transform/listFunctions.mts index 19c804d..d9e892f 100644 --- a/transform/listFunctions.mts +++ b/transform/listFunctions.mts @@ -62,12 +62,17 @@ class SourceFunctionTransform extends Transform { afterInitialize(program: Program) { this.#elementsByDeclaration = program.elementsByDeclaration; // There will be two sources with SourceKind.UserEntry, ~lib/rt/index-incremental.ts should be filtered - const entrySource = program.sources.find( - (source) => source.sourceKind === SourceKind.UserEntry && !source.normalizedPath.startsWith("~lib/") - ); - this.visitNode(entrySource); - this.functionInfos.reverse(); - globalThis.functionInfos = this.functionInfos; + program.sources + .filter((source) => source.sourceKind === SourceKind.UserEntry && !source.normalizedPath.startsWith("~lib/")) + .forEach((source) => { + this.functionInfos = []; + this.visitNode(source); + this.functionInfos.reverse(); + const functionInfos = + (globalThis.__functionInfos as Map) || new Map(); + functionInfos.set(source.normalizedPath, this.functionInfos); + globalThis.__functionInfos = functionInfos; + }); throw new Error("TransformDone"); }