fix(compiler): patchFlag analysis should factor in props returned by directive transforms
This commit is contained in:
parent
095f5edf8d
commit
6059fe69e8
@ -292,18 +292,20 @@ describe('compiler: element transform', () => {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
// should factor in props returned by custom directive transforms
|
||||||
|
// in patchFlag analysis
|
||||||
|
expect(node.arguments[3]).toMatch(PatchFlags.PROPS + '')
|
||||||
|
expect(node.arguments[4]).toMatch(`"bar"`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('directiveTransform with needRuntime: true', () => {
|
test('directiveTransform with needRuntime: true', () => {
|
||||||
let _dir: DirectiveNode
|
|
||||||
const { root, node } = parseWithElementTransform(
|
const { root, node } = parseWithElementTransform(
|
||||||
`<div v-foo:bar="hello" />`,
|
`<div v-foo:bar="hello" />`,
|
||||||
{
|
{
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
foo(dir) {
|
foo() {
|
||||||
_dir = dir
|
|
||||||
return {
|
return {
|
||||||
props: [createObjectProperty(dir.arg!, dir.exp!)],
|
props: [],
|
||||||
needRuntime: true
|
needRuntime: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -320,16 +322,7 @@ describe('compiler: element transform', () => {
|
|||||||
callee: `_${CREATE_VNODE}`,
|
callee: `_${CREATE_VNODE}`,
|
||||||
arguments: [
|
arguments: [
|
||||||
`"div"`,
|
`"div"`,
|
||||||
{
|
`null`,
|
||||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
|
||||||
properties: [
|
|
||||||
{
|
|
||||||
type: NodeTypes.JS_PROPERTY,
|
|
||||||
key: _dir!.arg,
|
|
||||||
value: _dir!.exp
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
`null`,
|
`null`,
|
||||||
`${PatchFlags.NEED_PATCH} /* NEED_PATCH */` // should generate appropriate flag
|
`${PatchFlags.NEED_PATCH} /* NEED_PATCH */` // should generate appropriate flag
|
||||||
]
|
]
|
||||||
|
@ -185,11 +185,30 @@ export function buildProps(
|
|||||||
|
|
||||||
// patchFlag analysis
|
// patchFlag analysis
|
||||||
let patchFlag = 0
|
let patchFlag = 0
|
||||||
const dynamicPropNames: string[] = []
|
let hasRef = false
|
||||||
let hasDynamicKeys = false
|
|
||||||
let hasClassBinding = false
|
let hasClassBinding = false
|
||||||
let hasStyleBinding = false
|
let hasStyleBinding = false
|
||||||
let hasRef = false
|
let hasDynamicKeys = false
|
||||||
|
const dynamicPropNames: string[] = []
|
||||||
|
|
||||||
|
const anaylizePatchFlag = ({ key, value }: Property) => {
|
||||||
|
if (key.type === NodeTypes.SIMPLE_EXPRESSION && key.isStatic) {
|
||||||
|
if (value.type !== NodeTypes.SIMPLE_EXPRESSION || !value.isStatic) {
|
||||||
|
const name = key.content
|
||||||
|
if (name === 'ref') {
|
||||||
|
hasRef = true
|
||||||
|
} else if (name === 'class') {
|
||||||
|
hasClassBinding = true
|
||||||
|
} else if (name === 'style') {
|
||||||
|
hasStyleBinding = true
|
||||||
|
} else if (name !== 'key') {
|
||||||
|
dynamicPropNames.push(key.content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hasDynamicKeys = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < props.length; i++) {
|
for (let i = 0; i < props.length; i++) {
|
||||||
// static attribute
|
// static attribute
|
||||||
@ -229,7 +248,8 @@ export function buildProps(
|
|||||||
|
|
||||||
// special case for v-bind and v-on with no argument
|
// special case for v-bind and v-on with no argument
|
||||||
const isBind = name === 'bind'
|
const isBind = name === 'bind'
|
||||||
if (!arg && (isBind || name === 'on')) {
|
const isOn = name === 'on'
|
||||||
|
if (!arg && (isBind || isOn)) {
|
||||||
hasDynamicKeys = true
|
hasDynamicKeys = true
|
||||||
if (exp) {
|
if (exp) {
|
||||||
if (properties.length) {
|
if (properties.length) {
|
||||||
@ -262,32 +282,16 @@ export function buildProps(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// patchFlag analysis
|
|
||||||
if (isBind && arg) {
|
|
||||||
if (arg.type === NodeTypes.SIMPLE_EXPRESSION && arg.isStatic) {
|
|
||||||
const name = arg.content
|
|
||||||
if (name === 'ref') {
|
|
||||||
hasRef = true
|
|
||||||
} else if (name === 'class') {
|
|
||||||
hasClassBinding = true
|
|
||||||
} else if (name === 'style') {
|
|
||||||
hasStyleBinding = true
|
|
||||||
} else if (name !== 'key') {
|
|
||||||
dynamicPropNames.push(name)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
hasDynamicKeys = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const directiveTransform = context.directiveTransforms[name]
|
const directiveTransform = context.directiveTransforms[name]
|
||||||
if (directiveTransform) {
|
if (directiveTransform) {
|
||||||
// has built-in directive transform.
|
// has built-in directive transform.
|
||||||
const { props, needRuntime } = directiveTransform(prop, context)
|
const { props, needRuntime } = directiveTransform(prop, context)
|
||||||
if (isArray(props)) {
|
if (isArray(props)) {
|
||||||
properties.push(...props)
|
properties.push(...props)
|
||||||
|
properties.forEach(anaylizePatchFlag)
|
||||||
} else {
|
} else {
|
||||||
properties.push(props)
|
properties.push(props)
|
||||||
|
anaylizePatchFlag(props)
|
||||||
}
|
}
|
||||||
if (needRuntime) {
|
if (needRuntime) {
|
||||||
runtimeDirectives.push(prop)
|
runtimeDirectives.push(prop)
|
||||||
@ -325,7 +329,7 @@ export function buildProps(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine the flags to add
|
// patchFlag analysis
|
||||||
if (hasDynamicKeys) {
|
if (hasDynamicKeys) {
|
||||||
patchFlag |= PatchFlags.FULL_PROPS
|
patchFlag |= PatchFlags.FULL_PROPS
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user