perf(compiler-core): treat v-for with constant exp as a stable fragment (#1394)

This commit is contained in:
HcySunYang
2020-06-18 04:13:14 +08:00
committed by GitHub
parent 8899a90fc4
commit 8a2cf21b71
9 changed files with 125 additions and 24 deletions

View File

@@ -102,6 +102,15 @@ return function render(_ctx, _cache) {
}"
`;
exports[`compiler: codegen forNode with constant expression 1`] = `
"
return function render(_ctx, _cache) {
with (_ctx) {
return (_openBlock(), _createBlock(_Fragment, null, _renderList(), 64 /* STABLE_FRAGMENT */))
}
}"
`;
exports[`compiler: codegen function mode preamble 1`] = `
"const _Vue = Vue

View File

@@ -32,7 +32,7 @@ import {
FRAGMENT,
RENDER_LIST
} from '../src/runtimeHelpers'
import { createElementWithCodegen } from './testUtils'
import { createElementWithCodegen, genFlagText } from './testUtils'
import { PatchFlags } from '@vue/shared'
function createRoot(options: Partial<RootNode> = {}): RootNode {
@@ -283,7 +283,7 @@ describe('compiler: codegen', () => {
type: NodeTypes.VNODE_CALL,
tag: FRAGMENT,
isBlock: true,
isForBlock: true,
disableTracking: true,
props: undefined,
children: createCallExpression(RENDER_LIST),
patchFlag: '1',
@@ -298,6 +298,37 @@ describe('compiler: codegen', () => {
expect(code).toMatchSnapshot()
})
test('forNode with constant expression', () => {
const { code } = generate(
createRoot({
codegenNode: {
type: NodeTypes.FOR,
loc: locStub,
source: createSimpleExpression('1 + 2', false, locStub, true),
valueAlias: undefined,
keyAlias: undefined,
objectIndexAlias: undefined,
children: [],
parseResult: {} as any,
codegenNode: {
type: NodeTypes.VNODE_CALL,
tag: FRAGMENT,
isBlock: true,
disableTracking: false,
props: undefined,
children: createCallExpression(RENDER_LIST),
patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT),
dynamicProps: undefined,
directives: undefined,
loc: locStub
} as ForCodegenNode
}
})
)
expect(code).toMatch(`openBlock()`)
expect(code).toMatchSnapshot()
})
test('Element (callExpression + objectExpression + TemplateChildNode[])', () => {
const { code } = generate(
createRoot({

View File

@@ -62,7 +62,7 @@ export function createElementWithCodegen(
dynamicProps,
directives: undefined,
isBlock: false,
isForBlock: false,
disableTracking: false,
loc: locStub
}
}

View File

@@ -150,6 +150,20 @@ return function render(_ctx, _cache) {
}"
`;
exports[`compiler: v-for codegen v-for with constant expression 1`] = `
"const _Vue = Vue
return function render(_ctx, _cache) {
with (_ctx) {
const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock, toDisplayString: _toDisplayString, createVNode: _createVNode } = _Vue
return (_openBlock(), _createBlock(_Fragment, null, _renderList(10, (item) => {
return _createVNode(\\"p\\", null, _toDisplayString(item), 1 /* TEXT */)
}), 64 /* STABLE_FRAGMENT */))
}
}"
`;
exports[`compiler: v-for codegen v-if + v-for 1`] = `
"const _Vue = Vue

View File

@@ -560,15 +560,18 @@ describe('compiler: v-for', () => {
function assertSharedCodegen(
node: ForCodegenNode,
keyed: boolean = false,
customReturn: boolean = false
customReturn: boolean = false,
disableTracking: boolean = true
) {
expect(node).toMatchObject({
type: NodeTypes.VNODE_CALL,
tag: FRAGMENT,
isForBlock: true,
patchFlag: keyed
? genFlagText(PatchFlags.KEYED_FRAGMENT)
: genFlagText(PatchFlags.UNKEYED_FRAGMENT),
disableTracking,
patchFlag: !disableTracking
? genFlagText(PatchFlags.STABLE_FRAGMENT)
: keyed
? genFlagText(PatchFlags.KEYED_FRAGMENT)
: genFlagText(PatchFlags.UNKEYED_FRAGMENT),
children: {
type: NodeTypes.JS_CALL_EXPRESSION,
callee: RENDER_LIST,
@@ -580,7 +583,7 @@ describe('compiler: v-for', () => {
? {}
: {
type: NodeTypes.VNODE_CALL,
isBlock: true
isBlock: disableTracking
}
}
]
@@ -658,6 +661,43 @@ describe('compiler: v-for', () => {
expect(generate(root).code).toMatchSnapshot()
})
test('v-for with constant expression', () => {
const {
root,
node: { codegenNode }
} = parseWithForTransform('<p v-for="item in 10">{{item}}</p>', {
prefixIdentifiers: true
})
expect(
assertSharedCodegen(
codegenNode,
false /* keyed */,
false /* customReturn */,
false /* disableTracking */
)
).toMatchObject({
source: { content: `10`, isConstant: true },
params: [{ content: `item` }],
innerVNodeCall: {
tag: `"p"`,
props: undefined,
isBlock: false,
children: {
type: NodeTypes.INTERPOLATION,
content: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'item',
isStatic: false,
isConstant: false
}
},
patchFlag: genFlagText(PatchFlags.TEXT)
}
})
expect(generate(root).code).toMatchSnapshot()
})
test('template v-for', () => {
const {
root,
@@ -777,7 +817,7 @@ describe('compiler: v-for', () => {
key: `[0]`
}),
isBlock: true,
isForBlock: true,
disableTracking: true,
patchFlag: genFlagText(PatchFlags.UNKEYED_FRAGMENT),
children: {
type: NodeTypes.JS_CALL_EXPRESSION,