refactor(compiler): extract shared ast transform utils

Also improve referenced identifier check using isReferenced from  @babel/types
This commit is contained in:
Evan You
2021-08-22 13:24:16 -04:00
parent 6be6c268e8
commit 62f752552a
5 changed files with 105 additions and 174 deletions

View File

@@ -23,14 +23,17 @@ import {
makeMap,
babelParserDefaultPlugins,
hasOwn,
isString
isString,
isReferencedIdentifier,
isInDestructureAssignment,
isStaticProperty,
isStaticPropertyKey,
isFunctionType
} from '@vue/shared'
import { createCompilerError, ErrorCodes } from '../errors'
import {
Node,
Function,
Identifier,
ObjectProperty,
AssignmentExpression,
UpdateExpression
} from '@babel/types'
@@ -279,7 +282,7 @@ export function processExpression(
ids.push(node)
}
}
} else if (isFunction(node)) {
} else if (isFunctionType(node)) {
// walk function expressions and add its arguments to known identifiers
// so that we don't prefix them
node.params.forEach(p =>
@@ -372,97 +375,16 @@ export function processExpression(
return ret
}
const isFunction = (node: Node): node is Function => {
return /Function(?:Expression|Declaration)$|Method$/.test(node.type)
}
const isStaticProperty = (node: Node): node is ObjectProperty =>
node &&
(node.type === 'ObjectProperty' || node.type === 'ObjectMethod') &&
!node.computed
const isStaticPropertyKey = (node: Node, parent: Node) =>
isStaticProperty(parent) && parent.key === node
function shouldPrefix(id: Identifier, parent: Node, parentStack: Node[]) {
// declaration id
if (
(parent.type === 'VariableDeclarator' ||
parent.type === 'ClassDeclaration') &&
parent.id === id
) {
return false
}
if (isFunction(parent)) {
// function decalration/expression id
if ((parent as any).id === id) {
return false
}
// params list
if (parent.params.includes(id)) {
return false
}
}
// property key
// this also covers object destructure pattern
if (isStaticPropertyKey(id, parent)) {
return false
}
// non-assignment array destructure pattern
if (
parent.type === 'ArrayPattern' &&
!isInDestructureAssignment(parent, parentStack)
) {
return false
}
// member expression property
if (
(parent.type === 'MemberExpression' ||
parent.type === 'OptionalMemberExpression') &&
parent.property === id &&
!parent.computed
) {
return false
}
// is a special keyword but parsed as identifier
if (id.name === 'arguments') {
return false
}
// skip whitelisted globals
if (isGloballyWhitelisted(id.name)) {
return false
}
// special case for webpack compilation
if (id.name === 'require') {
return false
}
return true
}
function isInDestructureAssignment(parent: Node, parentStack: Node[]): boolean {
if (
parent &&
(parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')
) {
let i = parentStack.length
while (i--) {
const p = parentStack[i]
if (p.type === 'AssignmentExpression') {
return true
} else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) {
break
}
}
}
return false
return isReferencedIdentifier(id, parent, parentStack)
}
function stringifyExpression(exp: ExpressionNode | string): string {