diff --git a/packages/vite/src/module-runner/sourcemap/interceptor.ts b/packages/vite/src/module-runner/sourcemap/interceptor.ts index 8173158e97ad81..49b109615ac8aa 100644 --- a/packages/vite/src/module-runner/sourcemap/interceptor.ts +++ b/packages/vite/src/module-runner/sourcemap/interceptor.ts @@ -358,8 +358,8 @@ function wrapCallSite(frame: CallSite, state: State) { // from getScriptNameOrSourceURL() instead const source = frame.getFileName() || frame.getScriptNameOrSourceURL() if (source) { - const line = frame.getLineNumber() as number - const column = (frame.getColumnNumber() as number) - 1 + const line = frame.getLineNumber() ?? 0 + const column = (frame.getColumnNumber() ?? 1) - 1 const position = mapSourcePosition({ name: null, diff --git a/packages/vite/src/node/ssr/runtime/__tests__/server-source-maps.spec.ts b/packages/vite/src/node/ssr/runtime/__tests__/server-source-maps.spec.ts index d3d7a3ffc925d8..6caeea61be17b1 100644 --- a/packages/vite/src/node/ssr/runtime/__tests__/server-source-maps.spec.ts +++ b/packages/vite/src/node/ssr/runtime/__tests__/server-source-maps.spec.ts @@ -1,5 +1,9 @@ +import { runInThisContext } from 'node:vm' +import { resolve } from 'node:path' import { describe, expect } from 'vitest' import type { ViteDevServer } from '../../..' +import type { ModuleRunnerContext } from '../../../../module-runner' +import { ESModulesEvaluator } from '../../../../module-runner' import { createFixtureEditor, createModuleRunnerTester, @@ -135,3 +139,39 @@ describe('module runner initialization', async () => { `) }) }) + +describe('module runner with node:vm executor', async () => { + class Evaluator extends ESModulesEvaluator { + async runInlinedModule(_: ModuleRunnerContext, __: string) { + // Mimics VitestModuleEvaluator + const initModule = runInThisContext( + '() => { throw new Error("example")}', + { + lineOffset: 0, + columnOffset: -100, + filename: resolve(import.meta.dirname, 'fixtures/a.ts'), + }, + ) + + initModule() + } + } + + const it = await createModuleRunnerTester( + {}, + { + sourcemapInterceptor: 'prepareStackTrace', + evaluator: new Evaluator(), + }, + ) + + it('should not crash when error stacktrace contains negative column', async ({ + runner, + }) => { + const error = await runner.import('/fixtures/a.ts').catch((err) => err) + + expect(() => + error.stack.includes('.stack access triggers the bug'), + ).not.toThrow() + }) +})