feat(compiler): annotate patchFlags in generated code
This commit is contained in:
parent
4021307f4c
commit
4fc963bc5a
@ -20,7 +20,7 @@ return function render() {
|
|||||||
_createVNode(\\"span\\", null, _toString(value + index))
|
_createVNode(\\"span\\", null, _toString(value + index))
|
||||||
])
|
])
|
||||||
})))
|
})))
|
||||||
], 2)
|
], 2 /* CLASS */)
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
@ -43,7 +43,7 @@ return function render() {
|
|||||||
createVNode(\\"span\\", null, toString(value + index))
|
createVNode(\\"span\\", null, toString(value + index))
|
||||||
])
|
])
|
||||||
})))
|
})))
|
||||||
], 2)
|
], 2 /* CLASS */)
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -65,6 +65,6 @@ export default function render() {
|
|||||||
createVNode(\\"span\\", null, _toString(value + index))
|
createVNode(\\"span\\", null, _toString(value + index))
|
||||||
])
|
])
|
||||||
})))
|
})))
|
||||||
], 2)
|
], 2 /* CLASS */)
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
@ -16,7 +16,7 @@ return function render() {
|
|||||||
toString(_ctx.foo),
|
toString(_ctx.foo),
|
||||||
toString(bar)
|
toString(bar)
|
||||||
]
|
]
|
||||||
}, 256)
|
}, 256 /* DYNAMIC_SLOTS */)
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ describe('compiler: element transform', () => {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
`null`,
|
`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', () => {
|
test('CLASS', () => {
|
||||||
const { node } = parseWithBind(`<div :class="foo" />`)
|
const { node } = parseWithBind(`<div :class="foo" />`)
|
||||||
expect(node.arguments.length).toBe(4)
|
expect(node.arguments.length).toBe(4)
|
||||||
expect(node.arguments[3]).toBe(String(PatchFlags.CLASS))
|
expect(node.arguments[3]).toBe(`${PatchFlags.CLASS} /* CLASS */`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('STYLE', () => {
|
test('STYLE', () => {
|
||||||
const { node } = parseWithBind(`<div :style="foo" />`)
|
const { node } = parseWithBind(`<div :style="foo" />`)
|
||||||
expect(node.arguments.length).toBe(4)
|
expect(node.arguments.length).toBe(4)
|
||||||
expect(node.arguments[3]).toBe(String(PatchFlags.STYLE))
|
expect(node.arguments[3]).toBe(`${PatchFlags.STYLE} /* STYLE */`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('PROPS', () => {
|
test('PROPS', () => {
|
||||||
const { node } = parseWithBind(`<div id="foo" :foo="bar" :baz="qux" />`)
|
const { node } = parseWithBind(`<div id="foo" :foo="bar" :baz="qux" />`)
|
||||||
expect(node.arguments.length).toBe(5)
|
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"]`)
|
expect(node.arguments[4]).toBe(`["foo", "baz"]`)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -587,7 +587,9 @@ describe('compiler: element transform', () => {
|
|||||||
)
|
)
|
||||||
expect(node.arguments.length).toBe(5)
|
expect(node.arguments.length).toBe(5)
|
||||||
expect(node.arguments[3]).toBe(
|
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"]`)
|
expect(node.arguments[4]).toBe(`["foo", "baz"]`)
|
||||||
})
|
})
|
||||||
@ -595,13 +597,17 @@ describe('compiler: element transform', () => {
|
|||||||
test('FULL_PROPS (v-bind)', () => {
|
test('FULL_PROPS (v-bind)', () => {
|
||||||
const { node } = parseWithBind(`<div v-bind="foo" />`)
|
const { node } = parseWithBind(`<div v-bind="foo" />`)
|
||||||
expect(node.arguments.length).toBe(4)
|
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)', () => {
|
test('FULL_PROPS (dynamic key)', () => {
|
||||||
const { node } = parseWithBind(`<div :[foo]="bar" />`)
|
const { node } = parseWithBind(`<div :[foo]="bar" />`)
|
||||||
expect(node.arguments.length).toBe(4)
|
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)', () => {
|
test('FULL_PROPS (w/ others)', () => {
|
||||||
@ -609,26 +615,34 @@ describe('compiler: element transform', () => {
|
|||||||
`<div id="foo" v-bind="bar" :class="cls" />`
|
`<div id="foo" v-bind="bar" :class="cls" />`
|
||||||
)
|
)
|
||||||
expect(node.arguments.length).toBe(4)
|
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)', () => {
|
test('NEED_PATCH (static ref)', () => {
|
||||||
const { node } = parseWithBind(`<div ref="foo" />`)
|
const { node } = parseWithBind(`<div ref="foo" />`)
|
||||||
expect(node.arguments.length).toBe(4)
|
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)', () => {
|
test('NEED_PATCH (dynamic ref)', () => {
|
||||||
const { node } = parseWithBind(`<div :ref="foo" />`)
|
const { node } = parseWithBind(`<div :ref="foo" />`)
|
||||||
expect(node.arguments.length).toBe(4)
|
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)', () => {
|
test('NEED_PATCH (custom directives)', () => {
|
||||||
const { node } = parseWithBind(`<div v-foo />`)
|
const { node } = parseWithBind(`<div v-foo />`)
|
||||||
const vnodeCall = node.arguments[0] as CallExpression
|
const vnodeCall = node.arguments[0] as CallExpression
|
||||||
expect(vnodeCall.arguments.length).toBe(4)
|
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 */`
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -16,7 +16,7 @@ import {
|
|||||||
Property,
|
Property,
|
||||||
SourceLocation
|
SourceLocation
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { isArray, PatchFlags } from '@vue/shared'
|
import { isArray, PatchFlags, PatchFlagNames } from '@vue/shared'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { createCompilerError, ErrorCodes } from '../errors'
|
||||||
import {
|
import {
|
||||||
CREATE_VNODE,
|
CREATE_VNODE,
|
||||||
@ -99,7 +99,15 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||||||
}
|
}
|
||||||
args.push(`null`)
|
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) {
|
if (dynamicPropNames && dynamicPropNames.length) {
|
||||||
args.push(
|
args.push(
|
||||||
`[${dynamicPropNames.map(n => JSON.stringify(n)).join(`, `)}]`
|
`[${dynamicPropNames.map(n => JSON.stringify(n)).join(`, `)}]`
|
||||||
|
@ -107,7 +107,12 @@ describe('renderer: fragment', () => {
|
|||||||
it('patch fragment children (compiler generated, unkeyed)', () => {
|
it('patch fragment children (compiler generated, unkeyed)', () => {
|
||||||
const root = nodeOps.createElement('div')
|
const root = nodeOps.createElement('div')
|
||||||
render(
|
render(
|
||||||
createVNode(Fragment, null, [h('div', 'one'), 'two'], PatchFlags.UNKEYED),
|
createVNode(
|
||||||
|
Fragment,
|
||||||
|
null,
|
||||||
|
[h('div', 'one'), 'two'],
|
||||||
|
PatchFlags.UNKEYED_V_FOR
|
||||||
|
),
|
||||||
root
|
root
|
||||||
)
|
)
|
||||||
expect(serializeInner(root)).toBe(`<!----><div>one</div>two<!---->`)
|
expect(serializeInner(root)).toBe(`<!----><div>one</div>two<!---->`)
|
||||||
@ -117,7 +122,7 @@ describe('renderer: fragment', () => {
|
|||||||
Fragment,
|
Fragment,
|
||||||
null,
|
null,
|
||||||
[h('div', 'foo'), 'bar', 'baz'],
|
[h('div', 'foo'), 'bar', 'baz'],
|
||||||
PatchFlags.UNKEYED
|
PatchFlags.UNKEYED_V_FOR
|
||||||
),
|
),
|
||||||
root
|
root
|
||||||
)
|
)
|
||||||
@ -132,7 +137,7 @@ describe('renderer: fragment', () => {
|
|||||||
Fragment,
|
Fragment,
|
||||||
null,
|
null,
|
||||||
[h('div', { key: 1 }, 'one'), h('div', { key: 2 }, 'two')],
|
[h('div', { key: 1 }, 'one'), h('div', { key: 2 }, 'two')],
|
||||||
PatchFlags.KEYED
|
PatchFlags.KEYED_V_FOR
|
||||||
),
|
),
|
||||||
root
|
root
|
||||||
)
|
)
|
||||||
@ -146,7 +151,7 @@ describe('renderer: fragment', () => {
|
|||||||
Fragment,
|
Fragment,
|
||||||
null,
|
null,
|
||||||
[h('div', { key: 2 }, 'two'), h('div', { key: 1 }, 'one')],
|
[h('div', { key: 2 }, 'two'), h('div', { key: 1 }, 'one')],
|
||||||
PatchFlags.KEYED
|
PatchFlags.KEYED_V_FOR
|
||||||
),
|
),
|
||||||
root
|
root
|
||||||
)
|
)
|
||||||
|
@ -1230,7 +1230,7 @@ export function createRenderer<
|
|||||||
// fast path
|
// fast path
|
||||||
const { patchFlag, shapeFlag } = n2
|
const { patchFlag, shapeFlag } = n2
|
||||||
if (patchFlag) {
|
if (patchFlag) {
|
||||||
if (patchFlag & PatchFlags.KEYED) {
|
if (patchFlag & PatchFlags.KEYED_V_FOR) {
|
||||||
// this could be either fully-keyed or mixed (some keyed some not)
|
// this could be either fully-keyed or mixed (some keyed some not)
|
||||||
// presence of patchFlag means children are guaranteed to be arrays
|
// presence of patchFlag means children are guaranteed to be arrays
|
||||||
patchKeyedChildren(
|
patchKeyedChildren(
|
||||||
@ -1244,7 +1244,7 @@ export function createRenderer<
|
|||||||
optimized
|
optimized
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
} else if (patchFlag & PatchFlags.UNKEYED) {
|
} else if (patchFlag & PatchFlags.UNKEYED_V_FOR) {
|
||||||
// unkeyed
|
// unkeyed
|
||||||
patchUnkeyedChildren(
|
patchUnkeyedChildren(
|
||||||
c1 as HostVNode[],
|
c1 as HostVNode[],
|
||||||
|
@ -47,12 +47,11 @@ export const enum PatchFlags {
|
|||||||
// value.
|
// value.
|
||||||
NEED_PATCH = 1 << 5,
|
NEED_PATCH = 1 << 5,
|
||||||
|
|
||||||
// Indicates a fragment or element with keyed or partially-keyed v-for
|
// Indicates a v-for fragment with keyed or partially keyed children
|
||||||
// children
|
KEYED_V_FOR = 1 << 6,
|
||||||
KEYED = 1 << 6,
|
|
||||||
|
|
||||||
// Indicates a fragment or element that contains unkeyed v-for children
|
// Indicates a v-for fragment with unkeyed children.
|
||||||
UNKEYED = 1 << 7,
|
UNKEYED_V_FOR = 1 << 7,
|
||||||
|
|
||||||
// Indicates a component with dynamic slots (e.g. slot that references a v-for
|
// Indicates a component with dynamic slots (e.g. slot that references a v-for
|
||||||
// iterated value, or dynamic slot names).
|
// iterated value, or dynamic slot names).
|
||||||
@ -68,6 +67,20 @@ export const PublicPatchFlags = {
|
|||||||
PROPS: PatchFlags.PROPS,
|
PROPS: PatchFlags.PROPS,
|
||||||
NEED_PATCH: PatchFlags.NEED_PATCH,
|
NEED_PATCH: PatchFlags.NEED_PATCH,
|
||||||
FULL_PROPS: PatchFlags.FULL_PROPS,
|
FULL_PROPS: PatchFlags.FULL_PROPS,
|
||||||
KEYED: PatchFlags.KEYED,
|
KEYED_V_FOR: PatchFlags.KEYED_V_FOR,
|
||||||
UNKEYED: PatchFlags.UNKEYED
|
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`
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user