isCallOf,
unwrapTSNode
} from '@vue/compiler-core'
-import { hasOwn, genPropsAccessExp } from '@vue/shared'
+import { genPropsAccessExp } from '@vue/shared'
import { PropsDestructureBindings } from './compileScript'
/**
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) {
excludedIds.add(id)
if (currentScope) {
}
}
- function rewriteId(
- scope: Scope,
- id: Identifier,
- parent: Node,
- parentStack: Node[]
- ): boolean {
- if (hasOwn(scope, id.name)) {
- const binding = scope[id.name]
-
- if (binding) {
- if (
- (parent.type === 'AssignmentExpression' && id === parent.left) ||
- parent.type === 'UpdateExpression'
- ) {
- error(`Cannot assign to destructured props as they are readonly.`, id)
- }
+ function rewriteId(id: Identifier, parent: Node, parentStack: Node[]) {
+ if (
+ (parent.type === 'AssignmentExpression' && id === parent.left) ||
+ parent.type === 'UpdateExpression'
+ ) {
+ error(`Cannot assign to destructured props as they are readonly.`, id)
+ }
- if (isStaticProperty(parent) && parent.shorthand) {
- // let binding used in a property shorthand
- // skip for destructure patterns
- if (
- !(parent as any).inPattern ||
- isInDestructureAssignment(parent, parentStack)
- ) {
- // { prop } -> { prop: __props.prop }
- s.appendLeft(
- id.end! + offset,
- `: ${genPropsAccessExp(propsLocalToPublicMap[id.name])}`
- )
- }
- } else {
- // x --> __props.x
- s.overwrite(
- id.start! + offset,
- id.end! + offset,
- genPropsAccessExp(propsLocalToPublicMap[id.name])
- )
- }
+ if (isStaticProperty(parent) && parent.shorthand) {
+ // let binding used in a property shorthand
+ // skip for destructure patterns
+ if (
+ !(parent as any).inPattern ||
+ isInDestructureAssignment(parent, parentStack)
+ ) {
+ // { prop } -> { prop: __props.prop }
+ s.appendLeft(
+ id.end! + offset,
+ `: ${genPropsAccessExp(propsLocalToPublicMap[id.name])}`
+ )
}
- return true
+ } else {
+ // x --> __props.x
+ s.overwrite(
+ id.start! + offset,
+ id.end! + offset,
+ genPropsAccessExp(propsLocalToPublicMap[id.name])
+ )
}
- return false
}
function checkUsage(node: Node, method: string, alias = method) {
if (isCallOf(node, alias)) {
const arg = unwrapTSNode(node.arguments[0])
- if (arg.type === 'Identifier') {
+ if (arg.type === 'Identifier' && currentScope[arg.name]) {
error(
`"${arg.name}" is a destructured prop and should not be passed directly to ${method}(). ` +
`Pass a getter () => ${arg.name} instead.`,
// function scopes
if (isFunctionType(node)) {
- scopeStack.push((currentScope = {}))
+ pushScope()
walkFunctionParams(node, registerLocalBinding)
if (node.body.type === 'BlockStatement') {
walkScope(node.body)
// catch param
if (node.type === 'CatchClause') {
- scopeStack.push((currentScope = {}))
+ pushScope()
if (node.param && node.param.type === 'Identifier') {
registerLocalBinding(node.param)
}
// non-function block scopes
if (node.type === 'BlockStatement' && !isFunctionType(parent!)) {
- scopeStack.push((currentScope = {}))
+ pushScope()
walkScope(node)
return
}
isReferencedIdentifier(node, parent!, parentStack) &&
!excludedIds.has(node)
) {
- // walk up the scope chain to check if id should be appended .value
- let i = scopeStack.length
- while (i--) {
- if (rewriteId(scopeStack[i], node, parent!, parentStack)) {
- return
- }
+ if (currentScope[node.name]) {
+ rewriteId(node, parent!, parentStack)
}
}
}
(node.type === 'BlockStatement' && !isFunctionType(parent!)) ||
isFunctionType(node)
) {
- scopeStack.pop()
- currentScope = scopeStack[scopeStack.length - 1] || null
+ popScope()
}
}
})