fix(compiler-sfc): throw error when import macro as alias (#11041)

This commit is contained in:
Kevin Deng 三咲智子 2024-05-31 17:08:54 +08:00 committed by GitHub
parent f8994da00f
commit 34a97edd2c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 32 additions and 16 deletions

View File

@ -49,7 +49,7 @@ import {
} from './script/defineEmits'
import { DEFINE_EXPOSE, processDefineExpose } from './script/defineExpose'
import { DEFINE_OPTIONS, processDefineOptions } from './script/defineOptions'
import { processDefineSlots } from './script/defineSlots'
import { DEFINE_SLOTS, processDefineSlots } from './script/defineSlots'
import { DEFINE_MODEL, processDefineModel } from './script/defineModel'
import { getImportedName, isCallOf, isLiteralNode } from './script/utils'
import { analyzeScriptBindings } from './script/analyzeScriptBindings'
@ -135,6 +135,16 @@ export interface ImportBinding {
isUsedInTemplate: boolean
}
const MACROS = [
DEFINE_PROPS,
DEFINE_EMITS,
DEFINE_EXPOSE,
DEFINE_OPTIONS,
DEFINE_SLOTS,
DEFINE_MODEL,
WITH_DEFAULTS,
]
/**
* Compile `<script setup>`
* It requires the whole SFC descriptor because we need to handle and merge
@ -317,15 +327,18 @@ export function compileScript(
const imported = getImportedName(specifier)
const source = node.source.value
const existing = ctx.userImports[local]
if (
source === 'vue' &&
(imported === DEFINE_PROPS ||
imported === DEFINE_EMITS ||
imported === DEFINE_EXPOSE)
) {
warnOnce(
`\`${imported}\` is a compiler macro and no longer needs to be imported.`,
)
if (source === 'vue' && MACROS.includes(imported)) {
if (local === imported) {
warnOnce(
`\`${imported}\` is a compiler macro and no longer needs to be imported.`,
)
} else {
ctx.error(
`\`${imported}\` is a compiler macro and cannot be aliased to ` +
`a different name.`,
specifier,
)
}
removeSpecifier(i)
} else if (existing) {
if (existing.source === source && existing.imported === imported) {
@ -1054,13 +1067,16 @@ function walkDeclaration(
// export const foo = ...
for (const { id, init: _init } of node.declarations) {
const init = _init && unwrapTSNode(_init)
const isDefineCall = !!(
const isConstMacroCall =
isConst &&
isCallOf(
init,
c => c === DEFINE_PROPS || c === DEFINE_EMITS || c === WITH_DEFAULTS,
c =>
c === DEFINE_PROPS ||
c === DEFINE_EMITS ||
c === WITH_DEFAULTS ||
c === DEFINE_SLOTS,
)
)
if (id.type === 'Identifier') {
let bindingType
const userReactiveBinding = userImportAliases['reactive']
@ -1077,7 +1093,7 @@ function walkDeclaration(
} else if (
// if a declaration is a const literal, we can mark it so that
// the generated render fn code doesn't need to unref() it
isDefineCall ||
isConstMacroCall ||
(isConst && canNeverBeRef(init!, userReactiveBinding))
) {
bindingType = isCallOf(init, DEFINE_PROPS)
@ -1109,9 +1125,9 @@ function walkDeclaration(
continue
}
if (id.type === 'ObjectPattern') {
walkObjectPattern(id, bindings, isConst, isDefineCall)
walkObjectPattern(id, bindings, isConst, isConstMacroCall)
} else if (id.type === 'ArrayPattern') {
walkArrayPattern(id, bindings, isConst, isDefineCall)
walkArrayPattern(id, bindings, isConst, isConstMacroCall)
}
}
}