export const WITH_SCOPE_ID = Symbol(__DEV__ ? `withScopeId` : ``)
export const WITH_CTX = Symbol(__DEV__ ? `withCtx` : ``)
export const UNREF = Symbol(__DEV__ ? `unref` : ``)
+export const IS_REF = Symbol(__DEV__ ? `isRef` : ``)
// Name mapping for runtime helpers that need to be imported from 'vue' in
// generated code. Make sure these are correctly exported in the runtime!
[POP_SCOPE_ID]: `popScopeId`,
[WITH_SCOPE_ID]: `withScopeId`,
[WITH_CTX]: `withCtx`,
- [UNREF]: `unref`
+ [UNREF]: `unref`,
+ [IS_REF]: `isRef`
}
export function registerRuntimeHelpers(helpers: any) {
hasScopeRef,
isStaticExp
} from '../utils'
+import { helperNameMap, IS_REF, UNREF } from '../runtimeHelpers'
export const transformModel: DirectiveTransform = (dir, node, context) => {
const { exp, arg } = dir
return createTransformProps()
}
+ const rawExp = exp.loc.source
const expString =
- exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : exp.loc.source
+ exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : rawExp
- if (!isMemberExpression(expString)) {
+ // im SFC <script setup> inline mode, the exp may have been transformed into
+ // _unref(exp)
+ const isUnrefExp =
+ !__BROWSER__ && expString.startsWith(`_${helperNameMap[UNREF]}`)
+
+ if (!isMemberExpression(expString) && !isUnrefExp) {
context.onError(
createCompilerError(ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION, exp.loc)
)
: createCompoundExpression(['"onUpdate:" + ', arg])
: `onUpdate:modelValue`
+ const assigmentExp = isUnrefExp
+ ? // v-model used on a potentially ref binding in <script setup> inline mode.
+ // not the most beautiful codegen here but it gets the job done.
+ createSimpleExpression(
+ `$event => { if (${context.helperString(IS_REF)}(${rawExp})) {` +
+ `${rawExp}.value = $event` +
+ ` } else {${context.isTS ? `\n//@ts-ignore\n` : ``}` +
+ `${rawExp} = $event` +
+ ` }}`,
+ false,
+ exp.loc
+ )
+ : createCompoundExpression([`$event => (`, exp, ` = $event)`])
+
const props = [
// modelValue: foo
createObjectProperty(propName, dir.exp!),
// "onUpdate:modelValue": $event => (foo = $event)
- createObjectProperty(
- eventName,
- createCompoundExpression([`$event => (`, exp, ` = $event)`])
- )
+ createObjectProperty(eventName, assigmentExp)
]
// cache v-model handler if applicable (when it doesn't refer any scope vars)
if (isInlineStatement || (shouldCache && isMemberExp)) {
// wrap inline statement in a function expression
exp = createCompoundExpression([
- `${isInlineStatement ? `$event` : `(...args)`} => ${
- hasMultipleStatements ? `{` : `(`
- }`,
+ `${
+ isInlineStatement
+ ? `$event`
+ : `${
+ !__BROWSER__ && context.isTS ? `\n//@ts-ignore\n` : ``
+ }(...args)`
+ } => ${hasMultipleStatements ? `{` : `(`}`,
exp,
hasMultipleStatements ? `}` : `)`
])