import {
type SimpleExpressionNode,
createSimpleExpression,
- isStaticNode,
walkIdentifiers,
} from '@vue/compiler-dom'
import { genBlockContent } from './block'
genCall,
genMulti,
} from './utils'
-import {
- type Expression,
- type Identifier,
- type Node,
- isNodesEquivalent,
-} from '@babel/types'
+import type { Expression, Identifier, Node } from '@babel/types'
import { parseExpression } from '@babel/parser'
import { VaporVForFlags } from '../../../shared/src/vaporFlags'
import { walk } from 'estree-walker'
render.effect = render.effect.filter(effect => {
if (keyProp !== undefined) {
- const selector = matchSelectorPattern(effect, keyProp.ast, idMap)
+ const selector = matchSelectorPattern(effect, keyProp.content, idMap)
if (selector) {
selectorPatterns.push(selector)
return false
}
- const keyOnly = matchKeyOnlyBindingPattern(effect, keyProp.ast)
+ const keyOnly = matchKeyOnlyBindingPattern(effect, keyProp.content)
if (keyOnly) {
keyOnlyBindingPatterns.push(keyOnly)
return false
function matchKeyOnlyBindingPattern(
effect: IREffect,
- keyAst: any,
+ key: string,
):
| {
effect: IREffect
| undefined {
// TODO: expressions can be multiple?
if (effect.expressions.length === 1) {
- const ast = effect.expressions[0].ast
+ const { ast, content } = effect.expressions[0]
if (typeof ast === 'object' && ast !== null) {
- if (isKeyOnlyBinding(ast, keyAst)) {
+ if (isKeyOnlyBinding(ast, key, content)) {
return { effect }
}
}
function matchSelectorPattern(
effect: IREffect,
- keyAst: any,
+ key: string,
idMap: Record<string, string | SimpleExpressionNode | null>,
):
| {
| undefined {
// TODO: expressions can be multiple?
if (effect.expressions.length === 1) {
- const ast = effect.expressions[0].ast
+ const { ast, content } = effect.expressions[0]
if (typeof ast === 'object' && ast) {
const matcheds: [key: Expression, selector: Expression][] = []
[left, right],
[right, left],
]) {
- const aIsKey = isKeyOnlyBinding(a, keyAst)
- const bIsKey = isKeyOnlyBinding(b, keyAst)
+ const aIsKey = isKeyOnlyBinding(a, key, content)
+ const bIsKey = isKeyOnlyBinding(b, key, content)
const bVars = analyzeVariableScopes(b, idMap)
- if (aIsKey && !bIsKey && !bVars.locals.length) {
+ if (aIsKey && !bIsKey && !bVars.length) {
matcheds.push([a, b])
}
}
const content = effect.expressions[0].content
let hasExtraId = false
- const parentStackMap = new Map<Identifier, Node[]>()
- const parentStack: Node[] = []
walkIdentifiers(
ast,
id => {
if (id.start !== key.start && id.start !== selector.start) {
hasExtraId = true
}
- parentStackMap.set(id, parentStack.slice())
},
false,
- parentStack,
)
if (!hasExtraId) {
}
}
}
-
- const content = effect.expressions[0].content
- if (
- typeof ast === 'object' &&
- ast &&
- ast.type === 'ConditionalExpression' &&
- ast.test.type === 'BinaryExpression' &&
- ast.test.operator === '===' &&
- ast.test.left.type !== 'PrivateName' &&
- isStaticNode(ast.consequent) &&
- isStaticNode(ast.alternate)
- ) {
- const left = ast.test.left
- const right = ast.test.right
- for (const [a, b] of [
- [left, right],
- [right, left],
- ]) {
- const aIsKey = isKeyOnlyBinding(a, keyAst)
- const bIsKey = isKeyOnlyBinding(b, keyAst)
- const bVars = analyzeVariableScopes(b, idMap)
- if (aIsKey && !bIsKey && !bVars.locals.length) {
- return {
- effect,
- // @ts-expect-error
- selector: {
- content: content.slice(b.start! - 1, b.end! - 1),
- ast: b,
- loc: b.loc as any,
- isStatic: false,
- },
- }
- }
- }
- }
}
}
ast: Node,
idMap: Record<string, string | SimpleExpressionNode | null>,
) {
- let globals: string[] = []
let locals: string[] = []
const ids: Identifier[] = []
- const parentStackMap = new Map<Identifier, Node[]>()
- const parentStack: Node[] = []
walkIdentifiers(
ast,
id => {
ids.push(id)
- parentStackMap.set(id, parentStack.slice())
},
false,
- parentStack,
)
for (const id of ids) {
}
if (idMap[id.name]) {
locals.push(id.name)
- } else {
- globals.push(id.name)
}
}
- return { globals, locals }
+ return locals
}
-function isKeyOnlyBinding(expr: Node, keyAst: any) {
+function isKeyOnlyBinding(expr: Node, key: string, source: string) {
let only = true
walk(expr, {
enter(node) {
- if (isNodesEquivalent(node, keyAst)) {
+ if (source.slice(node.start! - 1, node.end! - 1) === key) {
this.skip()
return
}