Skip to content

Commit

Permalink
fix(compiler/v-model): catch incorrect v-model usage on prop bindings
Browse files Browse the repository at this point in the history
close #5584
  • Loading branch information
yyx990803 committed Nov 10, 2022
1 parent ec795bf commit 001184e
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 1 deletion.
20 changes: 19 additions & 1 deletion packages/compiler-core/__tests__/transforms/vModel.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
ComponentNode,
NodeTypes,
VNodeCall,
NORMALIZE_PROPS
NORMALIZE_PROPS,
BindingTypes
} from '../../src'
import { ErrorCodes } from '../../src/errors'
import { transformModel } from '../../src/transforms/vModel'
Expand Down Expand Up @@ -561,5 +562,22 @@ describe('compiler: transform v-model', () => {
})
)
})

test('used on props', () => {
const onError = jest.fn()
parseWithVModel('<div v-model="p" />', {
onError,
bindingMetadata: {
p: BindingTypes.PROPS
}
})

expect(onError).toHaveBeenCalledTimes(1)
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE
})
)
})
})
})
2 changes: 2 additions & 0 deletions packages/compiler-core/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export const enum ErrorCodes {
X_V_MODEL_NO_EXPRESSION,
X_V_MODEL_MALFORMED_EXPRESSION,
X_V_MODEL_ON_SCOPE_VARIABLE,
X_V_MODEL_ON_PROPS,
X_INVALID_EXPRESSION,
X_KEEP_ALIVE_INVALID_CHILDREN,

Expand Down Expand Up @@ -168,6 +169,7 @@ export const errorMessages: Record<ErrorCodes, string> = {
[ErrorCodes.X_V_MODEL_NO_EXPRESSION]: `v-model is missing expression.`,
[ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION]: `v-model value must be a valid JavaScript member expression.`,
[ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE]: `v-model cannot be used on v-for or v-slot scope variables because they are not writable.`,
[ErrorCodes.X_V_MODEL_ON_PROPS]: `v-model cannot be used on a prop, because local prop bindings are not writable.\nUse a v-bind binding combined with a v-on listener that emits update:x event instead.`,
[ErrorCodes.X_INVALID_EXPRESSION]: `Error parsing JavaScript expression: `,
[ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN]: `<KeepAlive> expects exactly one child component.`,

Expand Down
10 changes: 10 additions & 0 deletions packages/compiler-core/src/transforms/vModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
// im SFC <script setup> inline mode, the exp may have been transformed into
// _unref(exp)
const bindingType = context.bindingMetadata[rawExp]

// check props
if (
bindingType === BindingTypes.PROPS ||
bindingType === BindingTypes.PROPS_ALIASED
) {
context.onError(createCompilerError(ErrorCodes.X_V_MODEL_ON_PROPS, exp.loc))
return createTransformProps()
}

const maybeRef =
!__BROWSER__ &&
context.inline &&
Expand Down

0 comments on commit 001184e

Please sign in to comment.