diff --git a/packages/vite/src/node/server/pluginContainer.ts b/packages/vite/src/node/server/pluginContainer.ts index 5e62f00a2e1156..3d412ccae0c502 100644 --- a/packages/vite/src/node/server/pluginContainer.ts +++ b/packages/vite/src/node/server/pluginContainer.ts @@ -600,7 +600,20 @@ export async function createPluginContainer( break } if (!combinedMap) { - combinedMap = m as SourceMap + const sm = m as SourceMap + // sourcemap should not include `sources: [null]` (because `sources` should be string) nor + // `sources: ['']` (because `''` means the path of sourcemap) + // but MagicString generates this when `filename` option is not set. + // Rollup supports these and therefore we support this as well + if (sm.sources.length === 1 && !sm.sources[0]) { + combinedMap = { + ...sm, + sources: [this.filename], + sourcesContent: [this.originalCode], + } + } else { + combinedMap = sm + } } else { combinedMap = combineSourcemaps(cleanUrl(this.filename), [ m as RawSourceMap, diff --git a/playground/js-sourcemap/__tests__/js-sourcemap.spec.ts b/playground/js-sourcemap/__tests__/js-sourcemap.spec.ts index da1a517ca25beb..7c22274b2a3a66 100644 --- a/playground/js-sourcemap/__tests__/js-sourcemap.spec.ts +++ b/playground/js-sourcemap/__tests__/js-sourcemap.spec.ts @@ -31,6 +31,27 @@ if (!isBuild) { `) }) + test('plugin return sourcemap with `sources: [""]`', async () => { + const res = await page.request.get(new URL('./zoo.js', page.url()).href) + const js = await res.text() + expect(js).toContain('// add comment') + + const map = extractSourcemap(js) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + { + "mappings": "AAAA,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;", + "sources": [ + "zoo.js", + ], + "sourcesContent": [ + "export const zoo = 'zoo' + ", + ], + "version": 3, + } + `) + }) + test('js with inline sourcemap injected by a plugin', async () => { const res = await page.request.get( new URL('./foo-with-sourcemap.js', page.url()).href, diff --git a/playground/js-sourcemap/index.html b/playground/js-sourcemap/index.html index f669bf4fc102aa..80ee729d99ce90 100644 --- a/playground/js-sourcemap/index.html +++ b/playground/js-sourcemap/index.html @@ -7,3 +7,4 @@

JS Sourcemap

+ diff --git a/playground/js-sourcemap/package.json b/playground/js-sourcemap/package.json index b002697756a24c..816f80c600f51c 100644 --- a/playground/js-sourcemap/package.json +++ b/playground/js-sourcemap/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { - "@vitejs/test-importee-pkg": "file:importee-pkg" + "@vitejs/test-importee-pkg": "file:importee-pkg", + "magic-string": "^0.30.5" } } diff --git a/playground/js-sourcemap/plugin-foo.js b/playground/js-sourcemap/plugin-foo.js new file mode 100644 index 00000000000000..cb356468240d50 --- /dev/null +++ b/playground/js-sourcemap/plugin-foo.js @@ -0,0 +1 @@ +export const foo = 'foo' diff --git a/playground/js-sourcemap/vite.config.js b/playground/js-sourcemap/vite.config.js index efebbc5ca00dee..41484f2c99d0f3 100644 --- a/playground/js-sourcemap/vite.config.js +++ b/playground/js-sourcemap/vite.config.js @@ -1,8 +1,12 @@ import { defineConfig } from 'vite' import transformFooWithInlineSourceMap from './foo-with-sourcemap-plugin' +import { transformZooWithSourcemapPlugin } from './zoo-with-sourcemap-plugin' export default defineConfig({ - plugins: [transformFooWithInlineSourceMap()], + plugins: [ + transformFooWithInlineSourceMap(), + transformZooWithSourcemapPlugin(), + ], build: { sourcemap: true, rollupOptions: { diff --git a/playground/js-sourcemap/zoo-with-sourcemap-plugin.ts b/playground/js-sourcemap/zoo-with-sourcemap-plugin.ts new file mode 100644 index 00000000000000..6c493278d166c8 --- /dev/null +++ b/playground/js-sourcemap/zoo-with-sourcemap-plugin.ts @@ -0,0 +1,18 @@ +import MagicString from 'magic-string' +import type { Plugin } from 'vite' + +export const transformZooWithSourcemapPlugin: () => Plugin = () => ({ + name: 'sourcemap', + transform(code, id) { + if (id.includes('zoo.js')) { + const ms = new MagicString(code) + ms.append('// add comment') + return { + code: ms.toString(), + // NOTE: MagicString without `filename` option generates + // a sourcemap with `sources: ['']` or `sources: [null]` + map: ms.generateMap({ hires: true }), + } + } + }, +}) diff --git a/playground/js-sourcemap/zoo.js b/playground/js-sourcemap/zoo.js new file mode 100644 index 00000000000000..286343f930d3c3 --- /dev/null +++ b/playground/js-sourcemap/zoo.js @@ -0,0 +1 @@ +export const zoo = 'zoo' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 75ba31ddaaf313..ac69c82f44fb73 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -700,6 +700,9 @@ importers: '@vitejs/test-importee-pkg': specifier: file:importee-pkg version: file:playground/js-sourcemap/importee-pkg + magic-string: + specifier: ^0.30.5 + version: 0.30.5 playground/js-sourcemap/importee-pkg: {}