Skip to content

Commit

Permalink
fix(ssr): stacktrace uses abs path with or without sourcemap
Browse files Browse the repository at this point in the history
  • Loading branch information
fi3ework committed Apr 18, 2023
1 parent 62ebe28 commit 093de39
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 28 deletions.
8 changes: 8 additions & 0 deletions packages/vite/src/node/server/transformRequest.ts
Expand Up @@ -295,6 +295,7 @@ async function loadAndTransform(
// to resolve and display them in a meaningful way (rather than
// with absolute paths).
if (path.isAbsolute(sourcePath)) {
map.sourceRoot = path.dirname(mod.file) + path.sep
map.sources[sourcesIndex] = path.relative(
path.dirname(mod.file),
sourcePath,
Expand All @@ -305,6 +306,13 @@ async function loadAndTransform(
}
}

// no sourcemap for raw js source file
if (!map && mod.file) {
map = {
sources: [mod.file],
} as SourceMap
}

const result =
ssr && !server.config.experimental.skipSsrTransform
? await server.ssrTransform(code, map as SourceMap, url, originalCode)
Expand Down
7 changes: 6 additions & 1 deletion packages/vite/src/node/ssr/ssrTransform.ts
Expand Up @@ -274,13 +274,18 @@ async function ssrTransformScript(
...map,
sources: inMap.sources,
sourcesContent: inMap.sourcesContent,
// sourceRoot: inMap.sourceRoot,
} as RawSourceMap,
inMap as RawSourceMap,
],
false,
) as SourceMap
} else {
map.sources = [url]
if (inMap?.sources) {
map.sources = inMap.sources
} else {
map.sources = [url]
}
// needs to use originalCode instead of code
// because code might be already transformed even if map is null
map.sourcesContent = [originalCode]
Expand Down
1 change: 1 addition & 0 deletions playground/css-sourcemap/__tests__/css-sourcemap.spec.ts
Expand Up @@ -69,6 +69,7 @@ describe.runIf(isServe)('serve', () => {
expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
{
"mappings": "AAAA;EACE,UAAU;AACZ;;ACAA;EACE,UAAU;AACZ",
"sourceRoot": "/root/",
"sources": [
"be-imported.css",
"linked-with-import.css",
Expand Down
1 change: 1 addition & 0 deletions playground/js-sourcemap/__tests__/js-sourcemap.spec.ts
Expand Up @@ -24,6 +24,7 @@ if (!isBuild) {
expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
{
"mappings": "AAAO,aAAM,MAAM;",
"sourceRoot": "/root/",
"sources": [
"bar.ts",
],
Expand Down
45 changes: 28 additions & 17 deletions playground/ssr-html/__tests__/ssr-html.spec.ts
Expand Up @@ -62,23 +62,34 @@ describe.runIf(isServe)('hmr', () => {
describe.runIf(isServe)('stacktrace', () => {
const execFileAsync = promisify(execFile)

for (const sourcemapsEnabled of [false, true]) {
test(`stacktrace is correct when sourcemaps is${
sourcemapsEnabled ? '' : ' not'
} enabled in Node.js`, async () => {
const testStacktraceFile = path.resolve(
__dirname,
'../test-stacktrace.js',
)
for (const ext of ['js', 'ts']) {
for (const sourcemapsEnabled of [false, true]) {
test(`stacktrace of ${ext} is correct when sourcemaps is${
sourcemapsEnabled ? '' : ' not'
} enabled in Node.js`, async () => {
const testStacktraceFile = path.resolve(
__dirname,
'../test-stacktrace.js',
)

const p = await execFileAsync('node', [
testStacktraceFile,
'' + sourcemapsEnabled,
])
const line = p.stdout
.split('\n')
.find((line) => line.includes('Module.error'))
expect(line.trim()).toMatch(/[\\/]src[\\/]error\.js:2:9/)
})
const p = await execFileAsync('node', [
testStacktraceFile,
'' + sourcemapsEnabled,
ext,
])
const lines = p.stdout
.split('\n')
.filter((line) => line.includes('Module.error'))

const reg = new RegExp(
// TODO: ts without sourcemaps will resolve column to 8 which should be 9
path.resolve(__dirname, '../src') + '/error\\.' + ext + ':2:[89]',
)

lines.forEach((line) => {
expect(line.trim()).toMatch(reg)
})
})
}
}
})
3 changes: 3 additions & 0 deletions playground/ssr-html/src/error.ts
@@ -0,0 +1,3 @@
export function error() {
throw new Error('e')
}
29 changes: 19 additions & 10 deletions playground/ssr-html/test-stacktrace.js
Expand Up @@ -3,8 +3,10 @@ import { fileURLToPath } from 'node:url'
import { createServer } from 'vite'

const isSourceMapEnabled = process.argv[2] === 'true'
const ext = process.argv[3]
process.setSourceMapsEnabled(isSourceMapEnabled)
console.log('# sourcemaps enabled:', isSourceMapEnabled)
console.log('# source file extension:', ext)

const version = (() => {
const m = process.version.match(/^v(\d+)\.(\d+)\.\d+$/)
Expand All @@ -31,17 +33,24 @@ const vite = await createServer({
appType: 'custom',
})

const mod = await vite.ssrLoadModule('/src/error.js')
try {
mod.error()
} catch (e) {
// this should not be called
// when sourcemap support for `new Function` is supported and sourcemap is enabled
// because the stacktrace is already rewritten by Node.js
if (!(isSourceMapEnabled && isFunctionSourceMapSupported)) {
vite.ssrFixStacktrace(e)
const dir = path.dirname(fileURLToPath(import.meta.url))

const abs1 = await vite.ssrLoadModule(`/src/error.${ext}`)
const abs2 = await vite.ssrLoadModule(path.resolve(dir, `./src/error.${ext}`))
const relative = await vite.ssrLoadModule(`./src/error.${ext}`)

for (const mod of [abs1, abs2, relative]) {
try {
mod.error()
} catch (e) {
// this should not be called
// when sourcemap support for `new Function` is supported and sourcemap is enabled
// because the stacktrace is already rewritten by Node.js
if (!(isSourceMapEnabled && isFunctionSourceMapSupported)) {
vite.ssrFixStacktrace(e)
}
console.log(e)
}
console.log(e)
}

await vite.close()
3 changes: 3 additions & 0 deletions playground/test-utils.ts
Expand Up @@ -307,6 +307,9 @@ export const formatSourcemapForSnapshot = (map: any): any => {
delete m.file
delete m.names
m.sources = m.sources.map((source) => source.replace(root, '/root'))
if (m.sourceRoot) {
m.sourceRoot = m.sourceRoot.replace(root, '/root')
}
return m
}

Expand Down

0 comments on commit 093de39

Please sign in to comment.