Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: try to resolve id, if relative path is provided #2461

Merged
merged 2 commits into from Dec 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/coverage-c8/src/provider.ts
Expand Up @@ -58,7 +58,7 @@ export class C8CoverageProvider implements CoverageProvider {
if (!map)
return

const filepath = result.file || file.split('?')[0]
const filepath = file.split('?')[0]

const url = _url.pathToFileURL(filepath).href

Expand Down
30 changes: 18 additions & 12 deletions packages/vite-node/src/client.ts
Expand Up @@ -4,7 +4,7 @@ import vm from 'vm'
import { dirname, extname, isAbsolute, resolve } from 'pathe'
import { isNodeBuiltin } from 'mlly'
import createDebug from 'debug'
import { isPrimitive, mergeSlashes, normalizeModuleId, normalizeRequestId, slash, toFilePath } from './utils'
import { cleanUrl, isPrimitive, normalizeModuleId, normalizeRequestId, slash, toFilePath } from './utils'
import type { HotContext, ModuleCache, ViteNodeRunnerOptions } from './types'
import { extractSourceMap } from './source-map'

Expand Down Expand Up @@ -221,39 +221,43 @@ export class ViteNodeRunner {

Object.defineProperty(request, 'callstack', { get: () => callstack })

const resolveId = async (dep: string, callstackPosition = 1) => {
const resolveId = async (dep: string, callstackPosition = 1): Promise<[dep: string, id: string | undefined]> => {
if (this.options.resolveId && this.shouldResolveId(dep)) {
let importer = callstack[callstack.length - callstackPosition]
let importer: string | undefined = callstack[callstack.length - callstackPosition]
if (importer && !dep.startsWith('.'))
importer = undefined
if (importer && importer.startsWith('mock:'))
importer = importer.slice(5)
const { id } = await this.options.resolveId(dep, importer) || {}
dep = id && isAbsolute(id) ? mergeSlashes(`/@fs/${id}`) : id || dep
const resolved = await this.options.resolveId(normalizeRequestId(dep), importer)
return [dep, resolved?.id]
}

return dep
return [dep, undefined]
}

const [dep, resolvedId] = await resolveId(id, 2)

const requestStubs = this.options.requestStubs || DEFAULT_REQUEST_STUBS
if (id in requestStubs)
return requestStubs[id]

// eslint-disable-next-line prefer-const
let { code: transformed, externalize, file } = await this.options.fetchModule(id)
let { code: transformed, externalize } = await this.options.fetchModule(resolvedId || dep)

// in case we resolved fsPath incorrectly, Vite will return the correct file path
// in that case we need to update cache, so we don't have the same module as different exports
// but we ignore fsPath that has custom query, because it might need to be different
if (file && !fsPath.includes('?') && fsPath !== file) {
if (this.moduleCache.has(file)) {
mod = this.moduleCache.get(file)
if (resolvedId && !fsPath.includes('?') && fsPath !== resolvedId) {
if (this.moduleCache.has(resolvedId)) {
mod = this.moduleCache.get(resolvedId)
this.moduleCache.set(fsPath, mod)
if (mod.promise)
return mod.promise
if (mod.exports)
return mod.exports
}
else {
this.moduleCache.set(file, mod)
this.moduleCache.set(resolvedId, mod)
}
}

Expand All @@ -267,8 +271,10 @@ export class ViteNodeRunner {
if (transformed == null)
throw new Error(`[vite-node] Failed to load ${id}`)

const file = cleanUrl(resolvedId || fsPath)
// console.log('file', file)
// disambiguate the `<UNIT>:/` on windows: see nodejs/node#31710
const url = pathToFileURL(file || fsPath).href
const url = pathToFileURL(file).href
const meta = { url }
const exports = Object.create(null)
Object.defineProperty(exports, Symbol.toStringTag, {
Expand Down
12 changes: 2 additions & 10 deletions packages/vite-node/src/server.ts
Expand Up @@ -4,7 +4,7 @@ import type { TransformResult, ViteDevServer } from 'vite'
import createDebug from 'debug'
import type { DebuggerOptions, FetchResult, RawSourceMap, ViteNodeResolveId, ViteNodeServerOptions } from './types'
import { shouldExternalize } from './externalize'
import { cleanUrl, normalizeModuleId, toArray, toFilePath } from './utils'
import { normalizeModuleId, toArray, toFilePath } from './utils'
import { Debugger } from './debug'
import { withInlineSourcemap } from './source-map'

Expand Down Expand Up @@ -130,8 +130,6 @@ export class ViteNodeServer {
const module = this.server.moduleGraph.getModuleById(id)
const timestamp = module ? module.lastHMRTimestamp : null
const cache = this.fetchCache.get(filePath)
if (cache?.result.id)
id = cache.result.id
if (timestamp !== null && cache && cache.timestamp >= timestamp)
return cache.result

Expand All @@ -143,16 +141,10 @@ export class ViteNodeServer {
this.debugger?.recordExternalize(id, externalize)
}
else {
let file = module?.file
if (!file) {
const [, resolvedId] = await this.server.moduleGraph.resolveUrl(id, true)
id = resolvedId
file = cleanUrl(resolvedId)
}
const start = performance.now()
const r = await this._transformRequest(id)
duration = performance.now() - start
result = { file, id, code: r?.code, map: r?.map as unknown as RawSourceMap }
result = { code: r?.code, map: r?.map as unknown as RawSourceMap }
}

this.fetchCache.set(filePath, {
Expand Down
2 changes: 0 additions & 2 deletions packages/vite-node/src/types.ts
Expand Up @@ -31,8 +31,6 @@ export interface FetchResult {
code?: string
externalize?: string
map?: RawSourceMap
id?: string
file?: string
}

export type HotContext = Omit<ViteHotContext, 'acceptDeps' | 'decline'>
Expand Down
8 changes: 6 additions & 2 deletions packages/vitest/src/runtime/execute.ts
Expand Up @@ -30,6 +30,10 @@ export class VitestRunner extends ViteNodeRunner {
prepareContext(context: Record<string, any>) {
const request = context.__vite_ssr_import__
const resolveId = context.__vitest_resolve_id__
const resolveUrl = async (dep: string) => {
const [id, resolvedId] = await resolveId(dep)
return resolvedId || id
}

const mocker = new VitestMocker(this.options, this.moduleCache, request)

Expand All @@ -42,8 +46,8 @@ export class VitestRunner extends ViteNodeRunner {
}

return Object.assign(context, {
__vite_ssr_import__: async (dep: string) => mocker.requestWithMock(await resolveId(dep)),
__vite_ssr_dynamic_import__: async (dep: string) => mocker.requestWithMock(await resolveId(dep)),
__vite_ssr_import__: async (dep: string) => mocker.requestWithMock(await resolveUrl(dep)),
__vite_ssr_dynamic_import__: async (dep: string) => mocker.requestWithMock(await resolveUrl(dep)),
__vitest_mocker__: mocker,
})
}
Expand Down