|
1 | 1 | import { existsSync, promises as fs } from 'node:fs'
|
| 2 | +import { isMainThread } from 'node:worker_threads' |
2 | 3 | import type { ViteDevServer } from 'vite'
|
3 | 4 | import { mergeConfig } from 'vite'
|
4 | 5 | import { basename, dirname, join, normalize, relative, resolve } from 'pathe'
|
@@ -312,23 +313,50 @@ export class Vitest {
|
312 | 313 | return acc
|
313 | 314 | }, {} as UserConfig)
|
314 | 315 |
|
315 |
| - const projects = filteredWorkspaces.map(async (workspacePath) => { |
316 |
| - // don't start a new server, but reuse existing one |
317 |
| - if ( |
318 |
| - this.server.config.configFile === workspacePath |
319 |
| - ) |
320 |
| - return this.createCoreProject() |
321 |
| - return initializeProject(workspacePath, this, { workspaceConfigPath, test: cliOverrides }) |
322 |
| - }) |
| 316 | + const cwd = process.cwd() |
| 317 | + |
| 318 | + const projects: (() => Promise<WorkspaceProject>)[] = [] |
| 319 | + |
| 320 | + try { |
| 321 | + // we have to resolve them one by one because CWD should depend on the project |
| 322 | + for (const filepath of filteredWorkspaces) { |
| 323 | + if (this.server.config.configFile === filepath) { |
| 324 | + const project = await this.createCoreProject() |
| 325 | + projects.push(() => Promise.resolve(project)) |
| 326 | + continue |
| 327 | + } |
| 328 | + const dir = filepath.endsWith('/') ? filepath.slice(0, -1) : dirname(filepath) |
| 329 | + if (isMainThread) |
| 330 | + process.chdir(dir) |
| 331 | + // this just resolves the config, later we also wait when the server is resolved, |
| 332 | + // but we can do that in parallel because it doesn't depend on process.cwd() |
| 333 | + // this is strictly a performance optimization so we don't need to wait for server to start |
| 334 | + projects.push(await initializeProject(filepath, this, { workspaceConfigPath, test: cliOverrides })) |
| 335 | + } |
| 336 | + } |
| 337 | + finally { |
| 338 | + if (isMainThread) |
| 339 | + process.chdir(cwd) |
| 340 | + } |
| 341 | + |
| 342 | + const projectPromises: Promise<() => Promise<WorkspaceProject>>[] = [] |
323 | 343 |
|
324 | 344 | projectsOptions.forEach((options, index) => {
|
325 |
| - projects.push(initializeProject(index, this, mergeConfig(options, { workspaceConfigPath, test: cliOverrides }) as any)) |
| 345 | + // we can resolve these in parallel because process.cwd() is not changed |
| 346 | + projectPromises.push(initializeProject(index, this, mergeConfig(options, { workspaceConfigPath, test: cliOverrides }) as any)) |
326 | 347 | })
|
327 | 348 |
|
328 |
| - if (!projects.length) |
| 349 | + if (!projects.length && !projectPromises.length) |
329 | 350 | return [await this.createCoreProject()]
|
330 | 351 |
|
331 |
| - const resolvedProjects = await Promise.all(projects) |
| 352 | + const resolvedProjectsReceivers = [ |
| 353 | + ...projects, |
| 354 | + ...await Promise.all(projectPromises), |
| 355 | + ] |
| 356 | + // we need to wait when the server is resolved, we can do that in parallel |
| 357 | + const resolvedProjects = await Promise.all( |
| 358 | + resolvedProjectsReceivers.map(receiver => receiver()), |
| 359 | + ) |
332 | 360 | const names = new Set<string>()
|
333 | 361 |
|
334 | 362 | for (const project of resolvedProjects) {
|
|
0 commit comments