Skip to content

Commit

Permalink
fix(ssr): preserve fetchModule error details (#18626)
Browse files Browse the repository at this point in the history
  • Loading branch information
hi-ogawa authored Nov 11, 2024
1 parent 9eab231 commit 866a433
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 2 deletions.
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
packages/*/CHANGELOG.md
packages/vite/src/node/ssr/runtime/__tests__/fixtures
packages/vite/src/node/ssr/__tests__/fixtures/errors
playground-temp/
dist/
temp/
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/server/hmr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ export const normalizeHotChannel = (
name: error.name,
message: error.message,
stack: error.stack,
...error, // preserve enumerable properties such as RollupError.loc, frame, plugin
},
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`parse error 1`] = `
{
"frame": "
Expected ";" but found "code"
1 | invalid code
| ^
2 |
",
"id": "<root>/fixtures/errors/syntax-error.ts",
"loc": {
"column": 8,
"file": "<root>/fixtures/errors/syntax-error.ts",
"line": 1,
},
"message": "Transform failed with 1 error:
<root>/fixtures/errors/syntax-error.ts:1:8: ERROR: Expected ";" but found "code"",
}
`;
exports[`parse error 2`] = `
{
"frame": "",
"id": "",
"loc": undefined,
"message": "Expected ';', '}' or <eof>",
}
`;
exports[`parse error 3`] = `
{
"frame": "
Expected ";" but found "code"
1 | invalid code
| ^
2 |
",
"id": "<root>/fixtures/errors/syntax-error.ts",
"loc": {
"column": 8,
"file": "<root>/fixtures/errors/syntax-error.ts",
"line": 1,
},
"message": "Transform failed with 1 error:
<root>/fixtures/errors/syntax-error.ts:1:8: ERROR: Expected ";" but found "code"",
}
`;
exports[`parse error 4`] = `
{
"frame": "",
"id": "",
"loc": undefined,
"message": "Expected ';', '}' or <eof>",
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './syntax-error.js'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './syntax-error.ts'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invalid code
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invalid code
34 changes: 34 additions & 0 deletions packages/vite/src/node/ssr/__tests__/ssrLoadModule.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { fileURLToPath } from 'node:url'
import path from 'node:path'
import { stripVTControlCharacters } from 'node:util'
import { expect, test } from 'vitest'
import { createServer } from '../../server'
import { normalizePath } from '../../utils'
Expand Down Expand Up @@ -178,3 +179,36 @@ test('can access nodejs global', async () => {
const mod = await server.ssrLoadModule('/fixtures/global/test.js')
expect(mod.default).toBe(globalThis)
})

test('parse error', async () => {
const server = await createDevServer()

function stripRoot(s?: string) {
return (s || '').replace(server.config.root, '<root>')
}

for (const file of [
'/fixtures/errors/syntax-error.ts',
'/fixtures/errors/syntax-error.js',
'/fixtures/errors/syntax-error-dep.ts',
'/fixtures/errors/syntax-error-dep.js',
]) {
try {
await server.ssrLoadModule(file)
} catch (e) {
expect(e).toBeInstanceOf(Error)
expect({
message: stripRoot(e.message),
frame: stripVTControlCharacters(e.frame || ''),
id: stripRoot(e.id),
loc: e.loc && {
file: stripRoot(e.loc.file),
column: e.loc.column,
line: e.loc.line,
},
}).toMatchSnapshot()
continue
}
expect.unreachable()
}
})
8 changes: 6 additions & 2 deletions packages/vite/src/shared/moduleRunnerTransport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ type InvokeableModuleRunnerTransport = Omit<ModuleRunnerTransport, 'invoke'> & {
): Promise<ReturnType<Awaited<InvokeMethods[T]>>>
}

function reviveInvokeError(e: any) {
return Object.assign(new Error(e.message || 'Unknown invoke error'), e)
}

const createInvokeableTransport = (
transport: ModuleRunnerTransport,
): InvokeableModuleRunnerTransport => {
Expand All @@ -49,7 +53,7 @@ const createInvokeableTransport = (
} satisfies InvokeSendData,
} satisfies CustomPayload)
if ('e' in result) {
throw result.e
throw reviveInvokeError(result.e)
}
return result.r
},
Expand Down Expand Up @@ -90,7 +94,7 @@ const createInvokeableTransport = (

const { e, r } = data.data
if (e) {
promise.reject(e)
promise.reject(reviveInvokeError(e))
} else {
promise.resolve(r)
}
Expand Down

0 comments on commit 866a433

Please sign in to comment.