Skip to content

Commit ffdb4d5

Browse files
committed
feat: don't use vite-node in coverage packages
1 parent 247d693 commit ffdb4d5

File tree

7 files changed

+48
-44
lines changed

7 files changed

+48
-44
lines changed

packages/coverage-v8/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@
7373
"@types/istanbul-reports": "catalog:",
7474
"@vitest/browser": "workspace:*",
7575
"pathe": "catalog:",
76-
"vite-node": "workspace:*",
7776
"vitest": "workspace:*"
7877
}
7978
}

packages/coverage-v8/src/provider.ts

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import type { CoverageMap } from 'istanbul-lib-coverage'
22
import type { ProxifiedModule } from 'magicast'
33
import type { Profiler } from 'node:inspector'
4-
import type { EncodedSourceMap, FetchResult } from 'vite-node'
5-
import type { AfterSuiteRunMeta } from 'vitest'
6-
import type { CoverageProvider, ReportContext, ResolvedCoverageOptions, TestProject, Vitest } from 'vitest/node'
4+
import type { CoverageProvider, ReportContext, ResolvedCoverageOptions, TestProject, Vite, Vitest } from 'vitest/node'
75
import { promises as fs } from 'node:fs'
86
import { fileURLToPath } from 'node:url'
97
// @ts-expect-error -- untyped
108
import { mergeProcessCovs } from '@bcoe/v8-coverage'
9+
import { cleanUrl } from '@vitest/utils'
1110
import astV8ToIstanbul from 'ast-v8-to-istanbul'
1211
import createDebug from 'debug'
1312
import libCoverage from 'istanbul-lib-coverage'
@@ -18,7 +17,6 @@ import { parseModule } from 'magicast'
1817
import { normalize } from 'pathe'
1918
import { provider } from 'std-env'
2019
import c from 'tinyrainbow'
21-
import { cleanUrl } from 'vite-node/utils'
2220

2321
import { BaseCoverageProvider } from 'vitest/coverage'
2422
import { parseAstAsync } from 'vitest/node'
@@ -28,7 +26,7 @@ export interface ScriptCoverageWithOffset extends Profiler.ScriptCoverage {
2826
startOffset: number
2927
}
3028

31-
type TransformResults = Map<string, FetchResult>
29+
type TransformResults = Map<string, Vite.TransformResult>
3230
interface RawCoverage { result: ScriptCoverageWithOffset[] }
3331

3432
const FILE_PROTOCOL = 'file://'
@@ -148,7 +146,7 @@ export class V8CoverageProvider extends BaseCoverageProvider<ResolvedCoverageOpt
148146

149147
private async getCoverageMapForUncoveredFiles(testedFiles: string[]): Promise<CoverageMap> {
150148
const transformResults = normalizeTransformResults(
151-
this.ctx.vitenode.fetchCache,
149+
this.ctx.vite.environments.ssr.moduleGraph,
152150
)
153151
const transform = this.createUncoveredFileTransformer(this.ctx)
154152

@@ -307,24 +305,24 @@ export class V8CoverageProvider extends BaseCoverageProvider<ResolvedCoverageOpt
307305
)
308306
}
309307

310-
private async getSources<TransformResult extends (FetchResult | Awaited<ReturnType<typeof this.ctx.vitenode.transformRequest>>)>(
308+
private async getSources(
311309
url: string,
312310
transformResults: TransformResults,
313-
onTransform: (filepath: string) => Promise<TransformResult>,
311+
onTransform: (filepath: string) => Promise<Vite.TransformResult | undefined | null>,
314312
functions: Profiler.FunctionCoverage[] = [],
315313
): Promise<{
316314
code: string
317-
map?: EncodedSourceMap
315+
map?: Vite.Rollup.SourceMap
318316
}> {
319317
const filePath = normalize(fileURLToPath(url))
320318

321-
let transformResult: FetchResult | TransformResult | undefined = transformResults.get(filePath)
319+
let transformResult: Vite.TransformResult | undefined | null = transformResults.get(filePath)
322320

323321
if (!transformResult) {
324322
transformResult = await onTransform(removeStartsWith(url, FILE_PROTOCOL)).catch(() => undefined)
325323
}
326324

327-
const map = transformResult?.map as EncodedSourceMap | undefined
325+
const map = transformResult?.map as Vite.Rollup.SourceMap | undefined
328326
const code = transformResult?.code
329327

330328
if (!code) {
@@ -357,31 +355,37 @@ export class V8CoverageProvider extends BaseCoverageProvider<ResolvedCoverageOpt
357355
private async convertCoverage(
358356
coverage: RawCoverage,
359357
project: TestProject = this.ctx.getRootProject(),
360-
transformMode?: AfterSuiteRunMeta['transformMode'],
358+
environment: string,
361359
): Promise<CoverageMap> {
362-
let fetchCache = project.vitenode.fetchCache
360+
if (environment === '__browser__' && !project.browser) {
361+
throw new Error(`Cannot access browser module graph because it was torn down.`)
362+
}
363+
364+
const moduleGraph = environment === '__browser__'
365+
? project.browser!.vite.environments.client.moduleGraph
366+
: project.vite.environments[environment]?.moduleGraph
363367

364-
if (transformMode) {
365-
fetchCache = transformMode === 'browser' ? new Map() : project.vitenode.fetchCaches[transformMode]
368+
if (!moduleGraph) {
369+
throw new Error(`Module graph for environment ${environment} was not defined.`)
366370
}
367371

368-
const transformResults = normalizeTransformResults(fetchCache)
372+
const transformResults = normalizeTransformResults(moduleGraph)
369373

370374
async function onTransform(filepath: string) {
371-
if (transformMode === 'browser' && project.browser) {
375+
if (environment === '__browser__' && project.browser) {
372376
const result = await project.browser.vite.transformRequest(removeStartsWith(filepath, project.config.root))
373377

374378
if (result) {
375379
return { ...result, code: `${result.code}// <inline-source-map>` }
376380
}
377381
}
378-
return project.vitenode.transformRequest(filepath)
382+
return project.vite.environments[environment].transformRequest(filepath)
379383
}
380384

381385
const scriptCoverages = []
382386

383387
for (const result of coverage.result) {
384-
if (transformMode === 'browser') {
388+
if (environment === '__browser__') {
385389
if (result.url.startsWith('/@fs')) {
386390
result.url = `${FILE_PROTOCOL}${removeStartsWith(result.url, '/@fs')}`
387391
}
@@ -466,15 +470,15 @@ function findLongestFunctionLength(functions: Profiler.FunctionCoverage[]) {
466470
}
467471

468472
function normalizeTransformResults(
469-
fetchCache: Map<string, { result: FetchResult }>,
473+
moduleGraph: Vite.EnvironmentModuleGraph,
470474
) {
471475
const normalized: TransformResults = new Map()
472476

473-
for (const [key, value] of fetchCache.entries()) {
477+
for (const [key, value] of moduleGraph.idToModuleMap) {
474478
const cleanEntry = cleanUrl(key)
475479

476-
if (!normalized.has(cleanEntry)) {
477-
normalized.set(cleanEntry, value.result)
480+
if (value.transformResult && !normalized.has(cleanEntry)) {
481+
normalized.set(cleanEntry, value.transformResult)
478482
}
479483
}
480484

packages/utils/src/helpers.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ export function assertTypes(
4646
}
4747
}
4848

49+
const postfixRE = /[?#].*$/
50+
51+
export function cleanUrl(url: string): string {
52+
return url.replace(postfixRE, '')
53+
}
54+
4955
export function isPrimitive(value: unknown): boolean {
5056
return (
5157
value === null || (typeof value !== 'function' && typeof value !== 'object')

packages/utils/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export type { LoupeOptions, StringifyOptions } from './display'
88

99
export {
1010
assertTypes,
11+
cleanUrl,
1112
clone,
1213
createDefer,
1314
createSimpleStackTrace,

packages/vitest/src/node/coverage.ts

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ interface ResolvedThreshold {
4242
type CoverageFiles = Map<
4343
NonNullable<AfterSuiteRunMeta['projectName']> | symbol,
4444
Record<
45-
AfterSuiteRunMeta['transformMode'],
45+
AfterSuiteRunMeta['environment'],
4646
{ [TestFilenames: string]: string }
4747
>
4848
>
@@ -253,19 +253,15 @@ export class BaseCoverageProvider<Options extends ResolvedCoverageOptions<'istan
253253
this.pendingPromises = []
254254
}
255255

256-
onAfterSuiteRun({ coverage, transformMode, projectName, testFiles }: AfterSuiteRunMeta): void {
256+
onAfterSuiteRun({ coverage, environment, projectName, testFiles }: AfterSuiteRunMeta): void {
257257
if (!coverage) {
258258
return
259259
}
260260

261-
if (transformMode !== 'web' && transformMode !== 'ssr' && transformMode !== 'browser') {
262-
throw new Error(`Invalid transform mode: ${transformMode}`)
263-
}
264-
265261
let entry = this.coverageFiles.get(projectName || DEFAULT_PROJECT)
266262

267263
if (!entry) {
268-
entry = { web: {}, ssr: {}, browser: {} }
264+
entry = {}
269265
this.coverageFiles.set(projectName || DEFAULT_PROJECT, entry)
270266
}
271267

@@ -275,8 +271,9 @@ export class BaseCoverageProvider<Options extends ResolvedCoverageOptions<'istan
275271
`coverage-${uniqueId++}.json`,
276272
)
277273

274+
entry[environment] ??= {}
278275
// If there's a result from previous run, overwrite it
279-
entry[transformMode][testFilenames] = filename
276+
entry[environment][testFilenames] = filename
280277

281278
const promise = fs.writeFile(filename, JSON.stringify(coverage), 'utf-8')
282279
this.pendingPromises.push(promise)
@@ -286,7 +283,7 @@ export class BaseCoverageProvider<Options extends ResolvedCoverageOptions<'istan
286283
/** Callback invoked with a single coverage result */
287284
onFileRead: (data: CoverageType) => void
288285
/** Callback invoked once all results of a project for specific transform mode are read */
289-
onFinished: (project: Vitest['projects'][number], transformMode: AfterSuiteRunMeta['transformMode']) => Promise<void>
286+
onFinished: (project: Vitest['projects'][number], environment: AfterSuiteRunMeta['environment']) => Promise<void>
290287
onDebug: ((...logs: any[]) => void) & { enabled: boolean }
291288
}): Promise<void> {
292289
let index = 0
@@ -296,7 +293,7 @@ export class BaseCoverageProvider<Options extends ResolvedCoverageOptions<'istan
296293
this.pendingPromises = []
297294

298295
for (const [projectName, coveragePerProject] of this.coverageFiles.entries()) {
299-
for (const [transformMode, coverageByTestfiles] of Object.entries(coveragePerProject) as Entries<typeof coveragePerProject>) {
296+
for (const [environment, coverageByTestfiles] of Object.entries(coveragePerProject) as Entries<typeof coveragePerProject>) {
300297
const filenames = Object.values(coverageByTestfiles)
301298
const project = this.ctx.getProjectByName(projectName as string)
302299

@@ -315,7 +312,7 @@ export class BaseCoverageProvider<Options extends ResolvedCoverageOptions<'istan
315312
)
316313
}
317314

318-
await onFinished(project, transformMode)
315+
await onFinished(project, environment)
319316
}
320317
}
321318
}
@@ -640,31 +637,31 @@ export class BaseCoverageProvider<Options extends ResolvedCoverageOptions<'istan
640637
...ctx.projects.map(project => ({
641638
root: project.config.root,
642639
isBrowserEnabled: project.isBrowserEnabled(),
643-
vitenode: project.vitenode,
640+
vite: project.vite,
644641
})),
645642
// Check core last as it will match all files anyway
646-
{ root: ctx.config.root, vitenode: ctx.vitenode, isBrowserEnabled: ctx.getRootProject().isBrowserEnabled() },
643+
{ root: ctx.config.root, vite: ctx.vite, isBrowserEnabled: ctx.getRootProject().isBrowserEnabled() },
647644
]
648645

649646
return async function transformFile(filename: string): Promise<TransformResult | null | undefined> {
650647
let lastError
651648

652-
for (const { root, vitenode, isBrowserEnabled } of servers) {
649+
for (const { root, vite, isBrowserEnabled } of servers) {
653650
// On Windows root doesn't start with "/" while filenames do
654651
if (!filename.startsWith(root) && !filename.startsWith(`/${root}`)) {
655652
continue
656653
}
657654

658655
if (isBrowserEnabled) {
659-
const result = await vitenode.transformRequest(filename, undefined, 'web').catch(() => null)
656+
const result = await vite.transformRequest(filename).catch(() => null)
660657

661658
if (result) {
662659
return result
663660
}
664661
}
665662

666663
try {
667-
return await vitenode.transformRequest(filename)
664+
return await vite.transformRequest(filename)
668665
}
669666
catch (error) {
670667
lastError = error

packages/vitest/src/types/general.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export type TransformMode = 'web' | 'ssr'
99
export interface AfterSuiteRunMeta {
1010
coverage?: unknown
1111
testFiles: string[]
12-
transformMode: TransformMode | 'browser'
12+
environment: string
1313
projectName?: string
1414
}
1515

pnpm-lock.yaml

Lines changed: 0 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)