]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler): patchFlag analysis should factor in props returned by directive transforms
authorEvan You <yyx990803@gmail.com>
Fri, 4 Oct 2019 12:37:10 +0000 (08:37 -0400)
committerEvan You <yyx990803@gmail.com>
Fri, 4 Oct 2019 12:37:10 +0000 (08:37 -0400)
packages/compiler-core/__tests__/transforms/transformElement.spec.ts
packages/compiler-core/src/transforms/transformElement.ts

index 5af275be9436b1032503d54ca586177366bc17f5..4bac19e2ab249932e220b92e8993f0bff2d5b5a5 100644 (file)
@@ -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', () => {
-    let _dir: DirectiveNode
     const { root, node } = parseWithElementTransform(
       `<div v-foo:bar="hello" />`,
       {
         directiveTransforms: {
-          foo(dir) {
-            _dir = dir
+          foo() {
             return {
-              props: [createObjectProperty(dir.arg!, dir.exp!)],
+              props: [],
               needRuntime: true
             }
           }
@@ -320,16 +322,7 @@ describe('compiler: element transform', () => {
         callee: `_${CREATE_VNODE}`,
         arguments: [
           `"div"`,
-          {
-            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
         ]
index ceb7fbf292488c4a0fe4893b65ebb47fe26c3658..654b8775a76d38887b94af197f5f6ace478d2e44 100644 (file)
@@ -185,11 +185,30 @@ export function buildProps(
 
   // patchFlag analysis
   let patchFlag = 0
-  const dynamicPropNames: string[] = []
-  let hasDynamicKeys = false
+  let hasRef = false
   let hasClassBinding = 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++) {
     // static attribute
@@ -229,7 +248,8 @@ export function buildProps(
 
       // special case for v-bind and v-on with no argument
       const isBind = name === 'bind'
-      if (!arg && (isBind || name === 'on')) {
+      const isOn = name === 'on'
+      if (!arg && (isBind || isOn)) {
         hasDynamicKeys = true
         if (exp) {
           if (properties.length) {
@@ -262,32 +282,16 @@ export function buildProps(
         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]
       if (directiveTransform) {
         // has built-in directive transform.
         const { props, needRuntime } = directiveTransform(prop, context)
         if (isArray(props)) {
           properties.push(...props)
+          properties.forEach(anaylizePatchFlag)
         } else {
           properties.push(props)
+          anaylizePatchFlag(props)
         }
         if (needRuntime) {
           runtimeDirectives.push(prop)
@@ -325,7 +329,7 @@ export function buildProps(
     )
   }
 
-  // determine the flags to add
+  // patchFlag analysis
   if (hasDynamicKeys) {
     patchFlag |= PatchFlags.FULL_PROPS
   } else {