소스 검색

feat(compiler): annotate patchFlags in generated code

Evan You 6 년 전
부모
커밋
4fc963bc5a

+ 3 - 3
packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap

@@ -20,7 +20,7 @@ return function render() {
           _createVNode(\\"span\\", null, _toString(value + index))
         ])
       })))
-    ], 2)
+    ], 2 /* CLASS */)
   }
 }"
 `;
@@ -43,7 +43,7 @@ return function render() {
         createVNode(\\"span\\", null, toString(value + index))
       ])
     })))
-  ], 2)
+  ], 2 /* CLASS */)
 }"
 `;
 
@@ -65,6 +65,6 @@ export default function render() {
         createVNode(\\"span\\", null, _toString(value + index))
       ])
     })))
-  ], 2)
+  ], 2 /* CLASS */)
 }"
 `;

+ 1 - 1
packages/compiler-core/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap

@@ -16,7 +16,7 @@ return function render() {
       toString(_ctx.foo),
       toString(bar)
     ]
-  }, 256)
+  }, 256 /* DYNAMIC_SLOTS */)
 }"
 `;
 

+ 25 - 11
packages/compiler-core/__tests__/transforms/transformElement.spec.ts

@@ -319,7 +319,7 @@ describe('compiler: element transform', () => {
             ]
           },
           `null`,
-          String(PatchFlags.NEED_PATCH) // should generate appropriate flag
+          `${PatchFlags.NEED_PATCH} /* NEED_PATCH */` // should generate appropriate flag
         ]
       },
       {
@@ -565,19 +565,19 @@ describe('compiler: element transform', () => {
     test('CLASS', () => {
       const { node } = parseWithBind(`<div :class="foo" />`)
       expect(node.arguments.length).toBe(4)
-      expect(node.arguments[3]).toBe(String(PatchFlags.CLASS))
+      expect(node.arguments[3]).toBe(`${PatchFlags.CLASS} /* CLASS */`)
     })
 
     test('STYLE', () => {
       const { node } = parseWithBind(`<div :style="foo" />`)
       expect(node.arguments.length).toBe(4)
-      expect(node.arguments[3]).toBe(String(PatchFlags.STYLE))
+      expect(node.arguments[3]).toBe(`${PatchFlags.STYLE} /* STYLE */`)
     })
 
     test('PROPS', () => {
       const { node } = parseWithBind(`<div id="foo" :foo="bar" :baz="qux" />`)
       expect(node.arguments.length).toBe(5)
-      expect(node.arguments[3]).toBe(String(PatchFlags.PROPS))
+      expect(node.arguments[3]).toBe(`${PatchFlags.PROPS} /* PROPS */`)
       expect(node.arguments[4]).toBe(`["foo", "baz"]`)
     })
 
@@ -587,7 +587,9 @@ describe('compiler: element transform', () => {
       )
       expect(node.arguments.length).toBe(5)
       expect(node.arguments[3]).toBe(
-        String(PatchFlags.PROPS | PatchFlags.CLASS | PatchFlags.STYLE)
+        `${PatchFlags.PROPS |
+          PatchFlags.CLASS |
+          PatchFlags.STYLE} /* CLASS, STYLE, PROPS */`
       )
       expect(node.arguments[4]).toBe(`["foo", "baz"]`)
     })
@@ -595,13 +597,17 @@ describe('compiler: element transform', () => {
     test('FULL_PROPS (v-bind)', () => {
       const { node } = parseWithBind(`<div v-bind="foo" />`)
       expect(node.arguments.length).toBe(4)
-      expect(node.arguments[3]).toBe(String(PatchFlags.FULL_PROPS))
+      expect(node.arguments[3]).toBe(
+        `${PatchFlags.FULL_PROPS} /* FULL_PROPS */`
+      )
     })
 
     test('FULL_PROPS (dynamic key)', () => {
       const { node } = parseWithBind(`<div :[foo]="bar" />`)
       expect(node.arguments.length).toBe(4)
-      expect(node.arguments[3]).toBe(String(PatchFlags.FULL_PROPS))
+      expect(node.arguments[3]).toBe(
+        `${PatchFlags.FULL_PROPS} /* FULL_PROPS */`
+      )
     })
 
     test('FULL_PROPS (w/ others)', () => {
@@ -609,26 +615,34 @@ describe('compiler: element transform', () => {
         `<div id="foo" v-bind="bar" :class="cls" />`
       )
       expect(node.arguments.length).toBe(4)
-      expect(node.arguments[3]).toBe(String(PatchFlags.FULL_PROPS))
+      expect(node.arguments[3]).toBe(
+        `${PatchFlags.FULL_PROPS} /* FULL_PROPS */`
+      )
     })
 
     test('NEED_PATCH (static ref)', () => {
       const { node } = parseWithBind(`<div ref="foo" />`)
       expect(node.arguments.length).toBe(4)
-      expect(node.arguments[3]).toBe(String(PatchFlags.NEED_PATCH))
+      expect(node.arguments[3]).toBe(
+        `${PatchFlags.NEED_PATCH} /* NEED_PATCH */`
+      )
     })
 
     test('NEED_PATCH (dynamic ref)', () => {
       const { node } = parseWithBind(`<div :ref="foo" />`)
       expect(node.arguments.length).toBe(4)
-      expect(node.arguments[3]).toBe(String(PatchFlags.NEED_PATCH))
+      expect(node.arguments[3]).toBe(
+        `${PatchFlags.NEED_PATCH} /* NEED_PATCH */`
+      )
     })
 
     test('NEED_PATCH (custom directives)', () => {
       const { node } = parseWithBind(`<div v-foo />`)
       const vnodeCall = node.arguments[0] as CallExpression
       expect(vnodeCall.arguments.length).toBe(4)
-      expect(vnodeCall.arguments[3]).toBe(String(PatchFlags.NEED_PATCH))
+      expect(vnodeCall.arguments[3]).toBe(
+        `${PatchFlags.NEED_PATCH} /* NEED_PATCH */`
+      )
     })
   })
 })

+ 10 - 2
packages/compiler-core/src/transforms/transformElement.ts

@@ -16,7 +16,7 @@ import {
   Property,
   SourceLocation
 } from '../ast'
-import { isArray, PatchFlags } from '@vue/shared'
+import { isArray, PatchFlags, PatchFlagNames } from '@vue/shared'
 import { createCompilerError, ErrorCodes } from '../errors'
 import {
   CREATE_VNODE,
@@ -99,7 +99,15 @@ export const transformElement: NodeTransform = (node, context) => {
           }
           args.push(`null`)
         }
-        args.push(String(patchFlag))
+        if (__DEV__) {
+          const flagNames = Object.keys(PatchFlagNames)
+            .filter(n => patchFlag & Number(n))
+            .map(n => PatchFlagNames[n as any])
+            .join(`, `)
+          args.push(patchFlag + ` /* ${flagNames} */`)
+        } else {
+          args.push(patchFlag + '')
+        }
         if (dynamicPropNames && dynamicPropNames.length) {
           args.push(
             `[${dynamicPropNames.map(n => JSON.stringify(n)).join(`, `)}]`

+ 9 - 4
packages/runtime-core/__tests__/rendererFragment.spec.ts

@@ -107,7 +107,12 @@ describe('renderer: fragment', () => {
   it('patch fragment children (compiler generated, unkeyed)', () => {
     const root = nodeOps.createElement('div')
     render(
-      createVNode(Fragment, null, [h('div', 'one'), 'two'], PatchFlags.UNKEYED),
+      createVNode(
+        Fragment,
+        null,
+        [h('div', 'one'), 'two'],
+        PatchFlags.UNKEYED_V_FOR
+      ),
       root
     )
     expect(serializeInner(root)).toBe(`<!----><div>one</div>two<!---->`)
@@ -117,7 +122,7 @@ describe('renderer: fragment', () => {
         Fragment,
         null,
         [h('div', 'foo'), 'bar', 'baz'],
-        PatchFlags.UNKEYED
+        PatchFlags.UNKEYED_V_FOR
       ),
       root
     )
@@ -132,7 +137,7 @@ describe('renderer: fragment', () => {
         Fragment,
         null,
         [h('div', { key: 1 }, 'one'), h('div', { key: 2 }, 'two')],
-        PatchFlags.KEYED
+        PatchFlags.KEYED_V_FOR
       ),
       root
     )
@@ -146,7 +151,7 @@ describe('renderer: fragment', () => {
         Fragment,
         null,
         [h('div', { key: 2 }, 'two'), h('div', { key: 1 }, 'one')],
-        PatchFlags.KEYED
+        PatchFlags.KEYED_V_FOR
       ),
       root
     )

+ 2 - 2
packages/runtime-core/src/createRenderer.ts

@@ -1230,7 +1230,7 @@ export function createRenderer<
     // fast path
     const { patchFlag, shapeFlag } = n2
     if (patchFlag) {
-      if (patchFlag & PatchFlags.KEYED) {
+      if (patchFlag & PatchFlags.KEYED_V_FOR) {
         // this could be either fully-keyed or mixed (some keyed some not)
         // presence of patchFlag means children are guaranteed to be arrays
         patchKeyedChildren(
@@ -1244,7 +1244,7 @@ export function createRenderer<
           optimized
         )
         return
-      } else if (patchFlag & PatchFlags.UNKEYED) {
+      } else if (patchFlag & PatchFlags.UNKEYED_V_FOR) {
         // unkeyed
         patchUnkeyedChildren(
           c1 as HostVNode[],

+ 20 - 7
packages/shared/src/patchFlags.ts

@@ -47,12 +47,11 @@ export const enum PatchFlags {
   // value.
   NEED_PATCH = 1 << 5,
 
-  // Indicates a fragment or element with keyed or partially-keyed v-for
-  // children
-  KEYED = 1 << 6,
+  // Indicates a v-for fragment with keyed or partially keyed children
+  KEYED_V_FOR = 1 << 6,
 
-  // Indicates a fragment or element that contains unkeyed v-for children
-  UNKEYED = 1 << 7,
+  // Indicates a v-for fragment with unkeyed children.
+  UNKEYED_V_FOR = 1 << 7,
 
   // Indicates a component with dynamic slots (e.g. slot that references a v-for
   // iterated value, or dynamic slot names).
@@ -68,6 +67,20 @@ export const PublicPatchFlags = {
   PROPS: PatchFlags.PROPS,
   NEED_PATCH: PatchFlags.NEED_PATCH,
   FULL_PROPS: PatchFlags.FULL_PROPS,
-  KEYED: PatchFlags.KEYED,
-  UNKEYED: PatchFlags.UNKEYED
+  KEYED_V_FOR: PatchFlags.KEYED_V_FOR,
+  UNKEYED_V_FOR: PatchFlags.UNKEYED_V_FOR,
+  DYNAMIC_SLOTS: PatchFlags.DYNAMIC_SLOTS
+}
+
+// dev only flag -> name mapping
+export const PatchFlagNames = {
+  [PatchFlags.TEXT]: `TEXT`,
+  [PatchFlags.CLASS]: `CLASS`,
+  [PatchFlags.STYLE]: `STYLE`,
+  [PatchFlags.PROPS]: `PROPS`,
+  [PatchFlags.NEED_PATCH]: `NEED_PATCH`,
+  [PatchFlags.FULL_PROPS]: `FULL_PROPS`,
+  [PatchFlags.KEYED_V_FOR]: `KEYED_V_FOR`,
+  [PatchFlags.UNKEYED_V_FOR]: `UNKEYED_V_FOR`,
+  [PatchFlags.DYNAMIC_SLOTS]: `DYNAMIC_SLOTS`
 }