diff --git a/examples/basic/test/sourcemap.test.ts b/examples/basic/test/sourcemap.test.ts new file mode 100644 index 000000000000..5642f9155fb0 --- /dev/null +++ b/examples/basic/test/sourcemap.test.ts @@ -0,0 +1,8 @@ +/* eslint-disable @typescript-eslint/quotes */ +import { expect, it } from 'vitest' + +it('should have sourcemaps', () => { + expect('\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9').toBeTruthy() + expect("\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9").toBeTruthy() + expect(`\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9`).toBeTruthy() +}) diff --git a/packages/vite-node/src/source-map.ts b/packages/vite-node/src/source-map.ts index 4adccd27a2d5..e9d67c71bd05 100644 --- a/packages/vite-node/src/source-map.ts +++ b/packages/vite-node/src/source-map.ts @@ -41,7 +41,7 @@ export function withInlineSourcemap(result: TransformResult, options: { }) // to reduce the payload size, we only inline vite node source map, because it's also the only one we use - const OTHER_SOURCE_MAP_REGEXP = new RegExp(`//# ${SOURCEMAPPING_URL}=data:application/json[^,]+base64,(.+)`, 'g') + const OTHER_SOURCE_MAP_REGEXP = new RegExp(`//# ${SOURCEMAPPING_URL}=data:application/json[^,]+base64,([A-Za-z0-9+/=]+)$`, 'gm') while (OTHER_SOURCE_MAP_REGEXP.test(code)) code = code.replace(OTHER_SOURCE_MAP_REGEXP, '') diff --git a/test/vite-node/test/sourcemap.test.ts b/test/vite-node/test/sourcemap.test.ts new file mode 100644 index 000000000000..f8e2365ce557 --- /dev/null +++ b/test/vite-node/test/sourcemap.test.ts @@ -0,0 +1,92 @@ +/* eslint-disable no-template-curly-in-string */ +import type { TransformResult } from 'vite' +import { describe, expect, it } from 'vitest' +import type { SourceMap } from 'rollup' +import { withInlineSourcemap } from '../../../packages/vite-node/src/source-map' + +it('regex match', () => { + const regex = /\/\/# sourceMappingURL=data:application\/json;charset=utf-8;base64,([A-Za-z0-9+/=]+)$/gm + expect('function foo(src) {\n return `//# sourceMappingURL=data:application/json;base64,${src}`;\n}\nObject.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return foo }});\n'.match(regex)).null + expect(`function foo(src) { + return \`//# sourceMappingURL=data:application/json;base64,\${src}\`; + } + Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return foo }}); + + //# sourceMappingSource=vite-node + //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IkFBQU8sU0FBUyxJQUFJLEtBQXFCO0FBQ3ZDLFNBQU8scURBQXFEO0FBQzlEO2lIQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uL2Zvby50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gZm9vKHNyYzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAvLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LCR7c3JjfWBcbn1cbiJdLCJmaWxlIjoiL3NyYy9mb28udHMifQ==`.match(regex)).deep.eq(['//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IkFBQU8sU0FBUyxJQUFJLEtBQXFCO0FBQ3ZDLFNBQU8scURBQXFEO0FBQzlEO2lIQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uL2Zvby50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gZm9vKHNyYzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAvLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LCR7c3JjfWBcbn1cbiJdLCJmaWxlIjoiL3NyYy9mb28udHMifQ==']) + expect(`function foo(src) { + return \`//# sourceMappingURL=data:application/json;base64,\${src}\`; + } + Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return foo }}); + + //# sourceMappingSource=vite-node + //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IkFBQU8sU0FBUyxJQUFJLEtBQXFCO0FBQ3ZDLFNBQU8scURBQXFEO0FBQzlEO2lIQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uL2Zvby50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gZm9vKHNyYzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAvLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LCR7c3JjfWBcbn1cbiJdLCJmaWxlIjoiL3NyYy9mb28udHMifQ==`.replace(regex, '')).not.include('//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IkFBQU8sU0FBUyxJQUFJLEtBQXFCO0FBQ3ZDLFNBQU8scURBQXFEO0FBQzlEO2lIQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uL2Zvby50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gZm9vKHNyYzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAvLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LCR7c3JjfWBcbn1cbiJdLCJmaWxlIjoiL3NyYy9mb28udHMifQ==') +}) + +describe('withInlineSourcemap', () => { + const input: TransformResult = { + code: 'function foo(src) {\n return `//# sourceMappingURL=data:application/json;base64,${src}`;\n}\nObject.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return foo }});\n', + map: { + version: 3, + mappings: 'AAAO,SAAS,IAAI,KAAqB;AACvC,SAAO,qDAAqD;AAC9D;iHAAA', + names: [], + sourceRoot: undefined, + sources: [ + '/foo.ts', + ], + sourcesContent: [ + 'export function foo(src: string): string {\n return `//# sourceMappingURL=data:application/json;base64,${src}`\n}\n', + ], + file: '/src/foo.ts', + } as unknown as SourceMap, + deps: [ + ], + dynamicDeps: [ + ], + } + const options = { + root: '/', + filepath: '/foo.ts', + } + + it('Check that the original sourcemap in the string isnot removed', () => { + expect(withInlineSourcemap(input, options).code).contain('return `//# sourceMappingURL=data:application/json;base64,${src}`') + }) + it('Check that the appended sourcemap is removed', () => { + input.code = `function foo(src) { + return \`//# sourceMappingURL=data:application/json;base64,\${src}\`; + } + Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return foo }}); + + //# sourceMappingSource=other + //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IkFBQU8sU0FBUyxJQUFJLEtBQXFCO0FBQ3ZDLFNBQU8scURBQXFEO0FBQzlEO2lIQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uL2Zvby50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gZm9vKHNyYzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAvLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LCR7c3JjfWBcbn1cbiJdLCJmaWxlIjoiL3NyYy9mb28udtest==` + + expect(withInlineSourcemap(input, options).code).not.toContain('//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IkFBQU8sU0FBUyxJQUFJLEtBQXFCO0FBQ3ZDLFNBQU8scURBQXFEO0FBQzlEO2lIQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uL2Zvby50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gZm9vKHNyYzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAvLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LCR7c3JjfWBcbn1cbiJdLCJmaWxlIjoiL3NyYy9mb28udtest==') + }) + it('Check that the vite-node sourcemap isnot removed', () => { + input.code = `function foo(src) { + return \`//# sourceMappingURL=data:application/json;base64,\${src}\`; + } + Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return foo }}); + + //# sourceMappingSource=vite-node + //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IkFBQU8sU0FBUyxJQUFJLEtBQXFCO0FBQ3ZDLFNBQU8scURBQXFEO0FBQzlEO2lIQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uL2Zvby50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gZm9vKHNyYzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAvLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LCR7c3JjfWBcbn1cbiJdLCJmaWxlIjoiL3NyYy9mb28udHMifQ==` + + expect(withInlineSourcemap(input, options).code).include('//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IkFBQU8sU0FBUyxJQUFJLEtBQXFCO0FBQ3ZDLFNBQU8scURBQXFEO0FBQzlEO2lIQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uL2Zvby50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gZm9vKHNyYzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAvLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LCR7c3JjfWBcbn1cbiJdLCJmaWxlIjoiL3NyYy9mb28udHMifQ==') + }) + it('Check that the vite-node in real code', () => { + input.code = ` +import { expect, it } from 'vitest' + +it('should have sourcemaps', () => { + expect('\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9==').toBeTruthy() + expect("\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9==").toBeTruthy() + expect(\`\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9==\`).toBeTruthy() +}) + ` + expect(withInlineSourcemap(input, options).code) + .include('\'\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9==\'') + .include('"\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9=="') + .include('`\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9==`') + }) +})