fix(compiler-sfc): check lang before attempt to compile script (#13508)

close #8368
This commit is contained in:
Alex Snezhko 2025-09-02 02:39:29 -07:00 committed by GitHub
parent 1e8b65aa49
commit 55922ff316
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 42 additions and 18 deletions

View File

@ -1550,4 +1550,19 @@ describe('compileScript', () => {
)
assertCode(content)
})
test('should not compile unrecognized language', () => {
const { content, lang, scriptAst } = compile(
`<script lang="coffee">
export default
data: ->
myVal: 0
</script>`,
)
expect(content).toMatch(`export default
data: ->
myVal: 0`)
expect(lang).toBe('coffee')
expect(scriptAst).not.toBeDefined()
})
})

View File

@ -56,7 +56,13 @@ import { DEFINE_EXPOSE, processDefineExpose } from './script/defineExpose'
import { DEFINE_OPTIONS, processDefineOptions } from './script/defineOptions'
import { DEFINE_SLOTS, processDefineSlots } from './script/defineSlots'
import { DEFINE_MODEL, processDefineModel } from './script/defineModel'
import { getImportedName, isCallOf, isLiteralNode } from './script/utils'
import {
getImportedName,
isCallOf,
isJS,
isLiteralNode,
isTS,
} from './script/utils'
import { analyzeScriptBindings } from './script/analyzeScriptBindings'
import { isImportUsed } from './script/importUsageCheck'
import { processAwait } from './script/topLevelAwait'
@ -173,6 +179,8 @@ export function compileScript(
const scopeId = options.id ? options.id.replace(/^data-v-/, '') : ''
const scriptLang = script && script.lang
const scriptSetupLang = scriptSetup && scriptSetup.lang
const isJSOrTS =
isJS(scriptLang, scriptSetupLang) || isTS(scriptLang, scriptSetupLang)
if (script && scriptSetup && scriptLang !== scriptSetupLang) {
throw new Error(
@ -181,21 +189,28 @@ export function compileScript(
)
}
const ctx = new ScriptCompileContext(sfc, options)
if (!scriptSetup) {
if (!script) {
throw new Error(`[@vue/compiler-sfc] SFC contains no <script> tags.`)
}
// normal <script> only
if (script.lang && !isJSOrTS) {
// do not process non js/ts script blocks
return script
}
const ctx = new ScriptCompileContext(sfc, options)
return processNormalScript(ctx, scopeId)
}
if (scriptSetupLang && !ctx.isJS && !ctx.isTS) {
if (scriptSetupLang && !isJSOrTS) {
// do not process non js/ts script blocks
return scriptSetup
}
const ctx = new ScriptCompileContext(sfc, options)
// metadata that needs to be returned
// const ctx.bindingMetadata: BindingMetadata = {}
const scriptBindings: Record<string, BindingTypes> = Object.create(null)

View File

@ -9,6 +9,7 @@ import type { BindingMetadata } from '../../../compiler-core/src'
import MagicString from 'magic-string'
import type { TypeScope } from './resolveType'
import { warn } from '../warn'
import { isJS, isTS } from './utils'
export class ScriptCompileContext {
isJS: boolean
@ -87,16 +88,8 @@ export class ScriptCompileContext {
const scriptLang = script && script.lang
const scriptSetupLang = scriptSetup && scriptSetup.lang
this.isJS =
scriptLang === 'js' ||
scriptLang === 'jsx' ||
scriptSetupLang === 'js' ||
scriptSetupLang === 'jsx'
this.isTS =
scriptLang === 'ts' ||
scriptLang === 'tsx' ||
scriptSetupLang === 'ts' ||
scriptSetupLang === 'tsx'
this.isJS = isJS(scriptLang, scriptSetupLang)
this.isTS = isTS(scriptLang, scriptSetupLang)
const customElement = options.customElement
const filename = this.descriptor.filename

View File

@ -12,10 +12,6 @@ export function processNormalScript(
scopeId: string,
): SFCScriptBlock {
const script = ctx.descriptor.script!
if (script.lang && !ctx.isJS && !ctx.isTS) {
// do not process non js/ts script blocks
return script
}
try {
let content = script.content
let map = script.map

View File

@ -121,3 +121,8 @@ export const propNameEscapeSymbolsRE: RegExp =
export function getEscapedPropName(key: string): string {
return propNameEscapeSymbolsRE.test(key) ? JSON.stringify(key) : key
}
export const isJS = (...langs: (string | null | undefined)[]): boolean =>
langs.some(lang => lang === 'js' || lang === 'jsx')
export const isTS = (...langs: (string | null | undefined)[]): boolean =>
langs.some(lang => lang === 'ts' || lang === 'tsx')