diff --git a/packages/vite/src/module-runner/evaluatedModules.ts b/packages/vite/src/module-runner/evaluatedModules.ts index 4063e1dfd9f051..ae1804df814444 100644 --- a/packages/vite/src/module-runner/evaluatedModules.ts +++ b/packages/vite/src/module-runner/evaluatedModules.ts @@ -108,8 +108,13 @@ export class EvaluatedModules { if (!mod) return null if (mod.map) return mod.map if (!mod.meta || !('code' in mod.meta)) return null + + const pattern = `//# ${SOURCEMAPPING_URL}=data:application/json;base64,` + const lastIndex = mod.meta.code.lastIndexOf(pattern) + if (lastIndex === -1) return null + const mapString = MODULE_RUNNER_SOURCEMAPPING_REGEXP.exec( - mod.meta.code, + mod.meta.code.slice(lastIndex), )?.[1] if (!mapString) return null mod.map = new DecodedMap(JSON.parse(decodeBase64(mapString)), mod.file) diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/string-literal-sourcemap.ts b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/string-literal-sourcemap.ts new file mode 100644 index 00000000000000..296ebc2a016162 --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/string-literal-sourcemap.ts @@ -0,0 +1,12 @@ +// This file contains sourceMappingURL pattern in string literals +// which should not crash the module runner + +const text = '//# sourceMappingURL=data:application/json;base64,invalidbase64' + +export function getMessage() { + return text +} + +export function throwError() { + throw new Error('Test error for stacktrace') +} 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 6e3238dfee51fc..92c6db9b287162 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 @@ -93,4 +93,20 @@ describe('module runner initialization', async () => { ' at Module.main (/fixtures/has-error-deep.ts:6:3)', ]) }) + + it('should not crash when sourceMappingURL pattern appears in string literals', async ({ + runner, + server, + }) => { + const mod = await runner.import('/fixtures/string-literal-sourcemap.ts') + expect(mod.getMessage()).toBe( + '//# sourceMappingURL=data:application/json;base64,invalidbase64', + ) + const error = await getError(() => mod.throwError()) + expect(error.message).toBe('Test error for stacktrace') + expect(serializeStackDeep(server, error).slice(0, 2)).toEqual([ + 'Error: Test error for stacktrace', + ' at Module.throwError (/fixtures/string-literal-sourcemap.ts:11:9)', + ]) + }) })