Commit f8d94f0
authored
fix(core): fix module runner dynamicRequest relative URL resolution (#599)
## Summary
- Fix a bug in vite's `ModuleRunner.directRequest()` where `dynamicRequest` uses the raw URL for relative path resolution, which breaks for `file://` URLs
- Re-enable the `VITE_TEST_BUILD=1 vp run tests-e2e#test` VitePress E2E test in CI
Stacked on #597.
## Root Cause
In `ModuleRunner.directRequest()` (`runner.ts:347-352`), the `dynamicRequest` closure resolves relative deps with:
```typescript
dep = posixResolve(posixDirname(url), dep)
```
The `url` captured here is the **raw, unnormalized URL** that flows through `import()` → `cachedRequest()` → `directRequest()`. But the server already resolved and normalized this URL — the normalized version is stored in `mod.url` (e.g. `/@fs/path/.temp/app.js`). The code uses the wrong one.
When `url` is a `file://` URL (e.g. `file:///path/.temp/app.js` from VitePress's `import(pathToFileURL(entryPath).href)`), `pathe.resolve` doesn't recognize it as absolute (it starts with `f`, not `/`), so it prepends CWD, producing malformed paths like `<cwd>/file:/path/.temp/page.md.js`.
### Why it doesn't happen with vanilla vitest
With vanilla vitest, VitePress is a regular npm dependency living in `node_modules/`. Vitest's externalization check (`id.includes('/node_modules/')`) returns `true`, so VitePress is **externalized** — loaded via native Node.js `import()` which handles `file://` URLs correctly. The module runner's `dynamicRequest` is never involved.
In vite-plus's ecosystem-ci, VitePress is a `workspace:*` dependency. Its files aren't in `node_modules/`, so it's **inlined** (SSR-transformed). Its `import(pathToFileURL(...))` becomes `__vite_ssr_dynamic_import__('file://...')`, which flows through `dynamicRequest` and hits the bug.
### Why it didn't fail before #588
Before #588, `vp test` commands had caching enabled. When CI ran `vp run tests-e2e#test` (without `VITE_TEST_BUILD`), it succeeded and created a cache entry. The next step `VITE_TEST_BUILD=1 vp run tests-e2e#test` ignored `VITE_TEST_BUILD` since it wasn't in the fingerprinted envs, hit the cache, and `vp test` never actually ran with `VITE_TEST_BUILD=1`. #588 disabled caching on `vp test` commands, so the second step actually ran for the first time and exposed the bug.
## Fix
Use `mod.url` (the server-normalized URL) instead of the raw `url` parameter in the `dynamicRequest` closure:
```typescript
// Before (broken for file:// URLs):
dep = posixResolve(posixDirname(url), dep)
// After (uses server-normalized URL):
dep = posixResolve(posixDirname(mod.url), dep)
```
`mod.url` is always a properly normalized URL from the server (e.g. `/@fs/...` or `/src/...`) that `posixResolve` handles correctly. Applied as a build-time transform in `packages/core/build.ts`.1 parent dd9f320 commit f8d94f0
2 files changed
Lines changed: 26 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
212 | 212 | | |
213 | 213 | | |
214 | 214 | | |
| 215 | + | |
215 | 216 | | |
216 | 217 | | |
217 | 218 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
96 | 121 | | |
97 | 122 | | |
98 | 123 | | |
| |||
0 commit comments