From 2fce5f30982849d2cb0aa543461bbe5d07780f72 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Fri, 23 Dec 2022 18:51:50 +0300 Subject: [PATCH 1/2] fix: start tracking module resolution as soon as possible for easier tracking --- packages/vite-node/src/client.ts | 14 +++++++++++++- packages/vite-node/src/types.ts | 1 + packages/vitest/src/utils/import.ts | 20 +++++++++++--------- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/packages/vite-node/src/client.ts b/packages/vite-node/src/client.ts index f7e3d789a73e..9fb43146ce5b 100644 --- a/packages/vite-node/src/client.ts +++ b/packages/vite-node/src/client.ts @@ -197,7 +197,7 @@ export class ViteNodeRunner { return !isInternalRequest(id) && !isNodeBuiltin(id) } - async resolveUrl(id: string, importee?: string): Promise<[url: string, fsPath: string]> { + private async _resolveUrl(id: string, importee?: string): Promise<[url: string, fsPath: string]> { if (!this.shouldResolveId(id)) return [id, id] // we don't pass down importee here, because otherwise Vite doesn't resolve it correctly @@ -215,6 +215,18 @@ export class ViteNodeRunner { return [resolvedId, fsPath] } + async resolveUrl(id: string, importee?: string) { + const resolveKey = `resolve:${id}` + // put info about new import as soon as possible, so we can start tracking it + this.moduleCache.set(resolveKey, { resolving: true }) + try { + return await this._resolveUrl(id, importee) + } + finally { + this.moduleCache.delete(resolveKey) + } + } + /** @internal */ async dependencyRequest(id: string, fsPath: string, callstack: string[]) { const getStack = () => { diff --git a/packages/vite-node/src/types.ts b/packages/vite-node/src/types.ts index 606c0f00666a..58d327e673e3 100644 --- a/packages/vite-node/src/types.ts +++ b/packages/vite-node/src/types.ts @@ -45,6 +45,7 @@ export interface ModuleCache { promise?: Promise exports?: any evaluated?: boolean + resolving?: boolean code?: string map?: RawSourceMap /** diff --git a/packages/vitest/src/utils/import.ts b/packages/vitest/src/utils/import.ts index 2c964054d032..16dab1312edf 100644 --- a/packages/vitest/src/utils/import.ts +++ b/packages/vitest/src/utils/import.ts @@ -1,21 +1,23 @@ import { getWorkerState } from './global' import { setTimeout } from './timers' -export async function waitForImportsToResolve(tries = 0) { - await new Promise(resolve => setTimeout(resolve, 0)) +function waitNextTick() { + return new Promise(resolve => setTimeout(resolve, 0)) +} + +export async function waitForImportsToResolve() { + await waitNextTick() const state = getWorkerState() const promises: Promise[] = [] + let resolvingCount = 0 for (const mod of state.moduleCache.values()) { if (mod.promise && !mod.evaluated) promises.push(mod.promise) + if (mod.resolving) + resolvingCount++ } - if (!promises.length && tries >= 3) + if (!promises.length && !resolvingCount) return await Promise.allSettled(promises) - // wait until the end of the loop, so `.then` on modules is called, - // like in import('./example').then(...) - // also call dynamicImportSettled again in case new imports were added - await new Promise(resolve => setTimeout(resolve, 1)) - .then(() => Promise.resolve()) - .then(() => waitForImportsToResolve(tries + 1)) + await waitForImportsToResolve() } From a23131c144d378310e1f9a7907d2b46a3d4867da Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Sun, 25 Dec 2022 15:11:58 +0100 Subject: [PATCH 2/2] chore: reduce normalization overhead --- packages/vite-node/src/client.ts | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/packages/vite-node/src/client.ts b/packages/vite-node/src/client.ts index 9fb43146ce5b..39d1317a2337 100644 --- a/packages/vite-node/src/client.ts +++ b/packages/vite-node/src/client.ts @@ -64,21 +64,30 @@ export class ModuleCacheMap extends Map { return this } + setByModuleId(modulePath: string, mod: ModuleCache) { + return super.set(modulePath, mod) + } + set(fsPath: string, mod: ModuleCache) { - fsPath = this.normalizePath(fsPath) - return super.set(fsPath, mod) + return this.setByModuleId(this.normalizePath(fsPath), mod) + } + + getByModuleId(modulePath: string): ModuleCache { + if (!super.has(modulePath)) + super.set(modulePath, {}) + return super.get(modulePath)! } get(fsPath: string): ModuleCache { - fsPath = this.normalizePath(fsPath) - if (!super.has(fsPath)) - super.set(fsPath, {}) - return super.get(fsPath)! + return this.getByModuleId(this.normalizePath(fsPath)) + } + + deleteByModuleId(modulePath: string): boolean { + return super.delete(modulePath) } delete(fsPath: string) { - fsPath = this.normalizePath(fsPath) - return super.delete(fsPath) + return this.deleteByModuleId(this.normalizePath(fsPath)) } /** @@ -218,12 +227,12 @@ export class ViteNodeRunner { async resolveUrl(id: string, importee?: string) { const resolveKey = `resolve:${id}` // put info about new import as soon as possible, so we can start tracking it - this.moduleCache.set(resolveKey, { resolving: true }) + this.moduleCache.setByModuleId(resolveKey, { resolving: true }) try { return await this._resolveUrl(id, importee) } finally { - this.moduleCache.delete(resolveKey) + this.moduleCache.deleteByModuleId(resolveKey) } } @@ -258,7 +267,7 @@ export class ViteNodeRunner { const moduleId = normalizeModuleId(fsPath) const callstack = [..._callstack, moduleId] - const mod = this.moduleCache.get(fsPath) + const mod = this.moduleCache.getByModuleId(moduleId) const request = async (dep: string) => { const [id, depFsPath] = await this.resolveUrl(dep, fsPath)