Skip to content

Commit ccfccec

Browse files
authored
fix(plugin-vue): fix sourcemap when no script block in sfc (close #8601) (#8604)
1 parent 2dd0b49 commit ccfccec

File tree

5 files changed

+108
-38
lines changed

5 files changed

+108
-38
lines changed

packages/plugin-vue/src/main.ts

+44-38
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import path from 'path'
22
import type { SFCBlock, SFCDescriptor } from 'vue/compiler-sfc'
3-
import type { PluginContext, SourceMap, TransformPluginContext } from 'rollup'
3+
import type { PluginContext, TransformPluginContext } from 'rollup'
44
import type { RawSourceMap } from 'source-map'
55
import type { EncodedSourceMap as TraceEncodedSourceMap } from '@jridgewell/trace-mapping'
66
import { TraceMap, eachMapping } from '@jridgewell/trace-mapping'
@@ -46,7 +46,7 @@ export async function transformMain(
4646
const hasScoped = descriptor.styles.some((s) => s.scoped)
4747

4848
// script
49-
const { code: scriptCode, map } = await genScriptCode(
49+
const { code: scriptCode, map: scriptMap } = await genScriptCode(
5050
descriptor,
5151
options,
5252
pluginContext,
@@ -58,7 +58,7 @@ export async function transformMain(
5858
descriptor.template && !isUseInlineTemplate(descriptor, !devServer)
5959

6060
let templateCode = ''
61-
let templateMap: RawSourceMap | undefined
61+
let templateMap: RawSourceMap | undefined = undefined
6262
if (hasTemplateImport) {
6363
;({ code: templateCode, map: templateMap } = await genTemplateCode(
6464
descriptor,
@@ -156,40 +156,46 @@ export async function transformMain(
156156
)
157157
}
158158

159-
// if the template is inlined into the main module (indicated by the presence
160-
// of templateMap, we need to concatenate the two source maps.
161-
let resolvedMap = options.sourceMap ? map : undefined
162-
if (resolvedMap && templateMap) {
163-
const gen = fromMap(
164-
// version property of result.map is declared as string
165-
// but actually it is `3`
166-
map as Omit<RawSourceMap, 'version'> as TraceEncodedSourceMap
167-
)
168-
const tracer = new TraceMap(
169-
// same above
170-
templateMap as Omit<RawSourceMap, 'version'> as TraceEncodedSourceMap
171-
)
172-
const offset = (scriptCode.match(/\r?\n/g)?.length ?? 0) + 1
173-
eachMapping(tracer, (m) => {
174-
if (m.source == null) return
175-
addMapping(gen, {
176-
source: m.source,
177-
original: { line: m.originalLine, column: m.originalColumn },
178-
generated: {
179-
line: m.generatedLine + offset,
180-
column: m.generatedColumn
181-
}
159+
let resolvedMap: RawSourceMap | undefined = undefined
160+
if (options.sourceMap) {
161+
if (scriptMap && templateMap) {
162+
// if the template is inlined into the main module (indicated by the presence
163+
// of templateMap, we need to concatenate the two source maps.
164+
165+
const gen = fromMap(
166+
// version property of result.map is declared as string
167+
// but actually it is `3`
168+
scriptMap as Omit<RawSourceMap, 'version'> as TraceEncodedSourceMap
169+
)
170+
const tracer = new TraceMap(
171+
// same above
172+
templateMap as Omit<RawSourceMap, 'version'> as TraceEncodedSourceMap
173+
)
174+
const offset = (scriptCode.match(/\r?\n/g)?.length ?? 0) + 1
175+
eachMapping(tracer, (m) => {
176+
if (m.source == null) return
177+
addMapping(gen, {
178+
source: m.source,
179+
original: { line: m.originalLine, column: m.originalColumn },
180+
generated: {
181+
line: m.generatedLine + offset,
182+
column: m.generatedColumn
183+
}
184+
})
182185
})
183-
})
184186

185-
// same above
186-
resolvedMap = toEncodedMap(gen) as Omit<
187-
GenEncodedSourceMap,
188-
'version'
189-
> as RawSourceMap
190-
// if this is a template only update, we will be reusing a cached version
191-
// of the main module compile result, which has outdated sourcesContent.
192-
resolvedMap.sourcesContent = templateMap.sourcesContent
187+
// same above
188+
resolvedMap = toEncodedMap(gen) as Omit<
189+
GenEncodedSourceMap,
190+
'version'
191+
> as RawSourceMap
192+
// if this is a template only update, we will be reusing a cached version
193+
// of the main module compile result, which has outdated sourcesContent.
194+
resolvedMap.sourcesContent = templateMap.sourcesContent
195+
} else {
196+
// if one of `scriptMap` and `templateMap` is empty, use the other one
197+
resolvedMap = scriptMap ?? templateMap
198+
}
193199
}
194200

195201
if (!attachedProps.length) {
@@ -287,10 +293,10 @@ async function genScriptCode(
287293
ssr: boolean
288294
): Promise<{
289295
code: string
290-
map: RawSourceMap
296+
map: RawSourceMap | undefined
291297
}> {
292298
let scriptCode = `const _sfc_main = {}`
293-
let map: RawSourceMap | SourceMap | undefined
299+
let map: RawSourceMap | undefined
294300

295301
const script = resolveScript(descriptor, options, ssr)
296302
if (script) {
@@ -322,7 +328,7 @@ async function genScriptCode(
322328
}
323329
return {
324330
code: scriptCode,
325-
map: map as any
331+
map
326332
}
327333
}
328334

playground/vue-sourcemap/Main.vue

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
<SassWithImport />
88
<Less />
99
<SrcImport />
10+
<NoScript />
11+
<NoTemplate />
1012
</template>
1113

1214
<script setup lang="ts">
@@ -17,4 +19,6 @@ import Sass from './Sass.vue'
1719
import SassWithImport from './SassWithImport.vue'
1820
import Less from './Less.vue'
1921
import SrcImport from './src-import/SrcImport.vue'
22+
import NoScript from './NoScript.vue'
23+
import NoTemplate from './NoTemplate.vue'
2024
</script>

playground/vue-sourcemap/NoScript.vue

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<template>
2+
<p>&lt;no-script&gt;</p>
3+
</template>
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
console.log('script')
3+
</script>
4+
5+
<script setup>
6+
console.log('setup')
7+
</script>

playground/vue-sourcemap/__tests__/serve.spec.ts

+50
Original file line numberDiff line numberDiff line change
@@ -334,4 +334,54 @@ describe.runIf(isServe)('serve:vue-sourcemap', () => {
334334
}
335335
`)
336336
})
337+
338+
test('no script', async () => {
339+
const res = await page.request.get(
340+
new URL('./NoScript.vue', page.url()).href
341+
)
342+
const js = await res.text()
343+
const map = extractSourcemap(js)
344+
expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
345+
{
346+
"mappings": ";;;wBACE",
347+
"sources": [
348+
"/root/NoScript.vue",
349+
],
350+
"sourcesContent": [
351+
"<template>
352+
<p>&lt;no-script&gt;</p>
353+
</template>
354+
",
355+
],
356+
"version": 3,
357+
}
358+
`)
359+
})
360+
361+
test('no template', async () => {
362+
const res = await page.request.get(
363+
new URL('./NoTemplate.vue', page.url()).href
364+
)
365+
const js = await res.text()
366+
const map = extractSourcemap(js)
367+
expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
368+
{
369+
"mappings": "2IACA,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;;;;;;AAGP;AACd,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC",
370+
"sources": [
371+
"/root/NoTemplate.vue",
372+
],
373+
"sourcesContent": [
374+
"<script>
375+
console.log('script')
376+
</script>
377+
378+
<script setup>
379+
console.log('setup')
380+
</script>
381+
",
382+
],
383+
"version": 3,
384+
}
385+
`)
386+
})
337387
})

0 commit comments

Comments
 (0)