mirror of https://github.com/vuejs/core.git
parent
9a09e47667
commit
f3145a915a
|
@ -354,5 +354,20 @@ describe('sfc props transform', () => {
|
||||||
)
|
)
|
||||||
).toThrow(`Default value of prop "foo" does not match declared type.`)
|
).toThrow(`Default value of prop "foo" does not match declared type.`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #8017
|
||||||
|
test('should not throw an error if the variable is not a props', () => {
|
||||||
|
expect(() =>
|
||||||
|
compile(
|
||||||
|
`<script setup lang='ts'>
|
||||||
|
import { watch } from 'vue'
|
||||||
|
const { userId } = defineProps({ userId: Number })
|
||||||
|
const { error: e, info } = useRequest();
|
||||||
|
watch(e, () => {});
|
||||||
|
watch(info, () => {});
|
||||||
|
</script>`
|
||||||
|
)
|
||||||
|
).not.toThrowError()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {
|
||||||
isCallOf,
|
isCallOf,
|
||||||
unwrapTSNode
|
unwrapTSNode
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { hasOwn, genPropsAccessExp } from '@vue/shared'
|
import { genPropsAccessExp } from '@vue/shared'
|
||||||
import { PropsDestructureBindings } from './compileScript'
|
import { PropsDestructureBindings } from './compileScript'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,6 +47,15 @@ export function transformDestructuredProps(
|
||||||
propsLocalToPublicMap[local] = key
|
propsLocalToPublicMap[local] = key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pushScope() {
|
||||||
|
scopeStack.push((currentScope = Object.create(currentScope)))
|
||||||
|
}
|
||||||
|
|
||||||
|
function popScope() {
|
||||||
|
scopeStack.pop()
|
||||||
|
currentScope = scopeStack[scopeStack.length - 1] || null
|
||||||
|
}
|
||||||
|
|
||||||
function registerLocalBinding(id: Identifier) {
|
function registerLocalBinding(id: Identifier) {
|
||||||
excludedIds.add(id)
|
excludedIds.add(id)
|
||||||
if (currentScope) {
|
if (currentScope) {
|
||||||
|
@ -108,54 +117,41 @@ export function transformDestructuredProps(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function rewriteId(
|
function rewriteId(id: Identifier, parent: Node, parentStack: Node[]) {
|
||||||
scope: Scope,
|
if (
|
||||||
id: Identifier,
|
(parent.type === 'AssignmentExpression' && id === parent.left) ||
|
||||||
parent: Node,
|
parent.type === 'UpdateExpression'
|
||||||
parentStack: Node[]
|
) {
|
||||||
): boolean {
|
error(`Cannot assign to destructured props as they are readonly.`, id)
|
||||||
if (hasOwn(scope, id.name)) {
|
}
|
||||||
const binding = scope[id.name]
|
|
||||||
|
if (isStaticProperty(parent) && parent.shorthand) {
|
||||||
if (binding) {
|
// let binding used in a property shorthand
|
||||||
if (
|
// skip for destructure patterns
|
||||||
(parent.type === 'AssignmentExpression' && id === parent.left) ||
|
if (
|
||||||
parent.type === 'UpdateExpression'
|
!(parent as any).inPattern ||
|
||||||
) {
|
isInDestructureAssignment(parent, parentStack)
|
||||||
error(`Cannot assign to destructured props as they are readonly.`, id)
|
) {
|
||||||
}
|
// { prop } -> { prop: __props.prop }
|
||||||
|
s.appendLeft(
|
||||||
if (isStaticProperty(parent) && parent.shorthand) {
|
id.end! + offset,
|
||||||
// let binding used in a property shorthand
|
`: ${genPropsAccessExp(propsLocalToPublicMap[id.name])}`
|
||||||
// skip for destructure patterns
|
)
|
||||||
if (
|
}
|
||||||
!(parent as any).inPattern ||
|
} else {
|
||||||
isInDestructureAssignment(parent, parentStack)
|
// x --> __props.x
|
||||||
) {
|
s.overwrite(
|
||||||
// { prop } -> { prop: __props.prop }
|
id.start! + offset,
|
||||||
s.appendLeft(
|
id.end! + offset,
|
||||||
id.end! + offset,
|
genPropsAccessExp(propsLocalToPublicMap[id.name])
|
||||||
`: ${genPropsAccessExp(propsLocalToPublicMap[id.name])}`
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// x --> __props.x
|
|
||||||
s.overwrite(
|
|
||||||
id.start! + offset,
|
|
||||||
id.end! + offset,
|
|
||||||
genPropsAccessExp(propsLocalToPublicMap[id.name])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkUsage(node: Node, method: string, alias = method) {
|
function checkUsage(node: Node, method: string, alias = method) {
|
||||||
if (isCallOf(node, alias)) {
|
if (isCallOf(node, alias)) {
|
||||||
const arg = unwrapTSNode(node.arguments[0])
|
const arg = unwrapTSNode(node.arguments[0])
|
||||||
if (arg.type === 'Identifier') {
|
if (arg.type === 'Identifier' && currentScope[arg.name]) {
|
||||||
error(
|
error(
|
||||||
`"${arg.name}" is a destructured prop and should not be passed directly to ${method}(). ` +
|
`"${arg.name}" is a destructured prop and should not be passed directly to ${method}(). ` +
|
||||||
`Pass a getter () => ${arg.name} instead.`,
|
`Pass a getter () => ${arg.name} instead.`,
|
||||||
|
@ -187,7 +183,7 @@ export function transformDestructuredProps(
|
||||||
|
|
||||||
// function scopes
|
// function scopes
|
||||||
if (isFunctionType(node)) {
|
if (isFunctionType(node)) {
|
||||||
scopeStack.push((currentScope = {}))
|
pushScope()
|
||||||
walkFunctionParams(node, registerLocalBinding)
|
walkFunctionParams(node, registerLocalBinding)
|
||||||
if (node.body.type === 'BlockStatement') {
|
if (node.body.type === 'BlockStatement') {
|
||||||
walkScope(node.body)
|
walkScope(node.body)
|
||||||
|
@ -197,7 +193,7 @@ export function transformDestructuredProps(
|
||||||
|
|
||||||
// catch param
|
// catch param
|
||||||
if (node.type === 'CatchClause') {
|
if (node.type === 'CatchClause') {
|
||||||
scopeStack.push((currentScope = {}))
|
pushScope()
|
||||||
if (node.param && node.param.type === 'Identifier') {
|
if (node.param && node.param.type === 'Identifier') {
|
||||||
registerLocalBinding(node.param)
|
registerLocalBinding(node.param)
|
||||||
}
|
}
|
||||||
|
@ -207,7 +203,7 @@ export function transformDestructuredProps(
|
||||||
|
|
||||||
// non-function block scopes
|
// non-function block scopes
|
||||||
if (node.type === 'BlockStatement' && !isFunctionType(parent!)) {
|
if (node.type === 'BlockStatement' && !isFunctionType(parent!)) {
|
||||||
scopeStack.push((currentScope = {}))
|
pushScope()
|
||||||
walkScope(node)
|
walkScope(node)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -217,12 +213,8 @@ export function transformDestructuredProps(
|
||||||
isReferencedIdentifier(node, parent!, parentStack) &&
|
isReferencedIdentifier(node, parent!, parentStack) &&
|
||||||
!excludedIds.has(node)
|
!excludedIds.has(node)
|
||||||
) {
|
) {
|
||||||
// walk up the scope chain to check if id should be appended .value
|
if (currentScope[node.name]) {
|
||||||
let i = scopeStack.length
|
rewriteId(node, parent!, parentStack)
|
||||||
while (i--) {
|
|
||||||
if (rewriteId(scopeStack[i], node, parent!, parentStack)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,8 +225,7 @@ export function transformDestructuredProps(
|
||||||
(node.type === 'BlockStatement' && !isFunctionType(parent!)) ||
|
(node.type === 'BlockStatement' && !isFunctionType(parent!)) ||
|
||||||
isFunctionType(node)
|
isFunctionType(node)
|
||||||
) {
|
) {
|
||||||
scopeStack.pop()
|
popScope()
|
||||||
currentScope = scopeStack[scopeStack.length - 1] || null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue