perf: also hoist all-static children array

This commit is contained in:
Evan You
2021-07-08 16:12:04 -04:00
parent 8bc50cb995
commit b7ea7c1485
7 changed files with 275 additions and 230 deletions

View File

@@ -30,7 +30,6 @@ describe('stringify static html', () => {
const { ast } = compileWithStringify(
`<div><div><div>hello</div><div>hello</div></div></div>`
)
expect(ast.hoists.length).toBe(1)
// should be a normal vnode call
expect(ast.hoists[0]!.type).toBe(NodeTypes.VNODE_CALL)
})
@@ -42,21 +41,25 @@ describe('stringify static html', () => {
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}</div></div>`
)
expect(ast.hoists.length).toBe(1)
// should be optimized now
expect(ast.hoists[0]).toMatchObject({
type: NodeTypes.JS_CALL_EXPRESSION,
callee: CREATE_STATIC,
arguments: [
JSON.stringify(
`<div>${repeat(
`<span class="foo"></span>`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}</div>`
),
'1'
]
})
expect(ast.hoists).toMatchObject([
{
type: NodeTypes.JS_CALL_EXPRESSION,
callee: CREATE_STATIC,
arguments: [
JSON.stringify(
`<div>${repeat(
`<span class="foo"></span>`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}</div>`
),
'1'
]
}, // the children array is hoisted as well
{
type: NodeTypes.JS_ARRAY_EXPRESSION
}
])
})
test('should work on eligible content (elements > 20)', () => {
@@ -66,21 +69,26 @@ describe('stringify static html', () => {
StringifyThresholds.NODE_COUNT
)}</div></div>`
)
expect(ast.hoists.length).toBe(1)
// should be optimized now
expect(ast.hoists[0]).toMatchObject({
type: NodeTypes.JS_CALL_EXPRESSION,
callee: CREATE_STATIC,
arguments: [
JSON.stringify(
`<div>${repeat(
`<span></span>`,
StringifyThresholds.NODE_COUNT
)}</div>`
),
'1'
]
})
expect(ast.hoists).toMatchObject([
{
type: NodeTypes.JS_CALL_EXPRESSION,
callee: CREATE_STATIC,
arguments: [
JSON.stringify(
`<div>${repeat(
`<span></span>`,
StringifyThresholds.NODE_COUNT
)}</div>`
),
'1'
]
},
// the children array is hoisted as well
{
type: NodeTypes.JS_ARRAY_EXPRESSION
}
])
})
test('should work for multiple adjacent nodes', () => {
@@ -90,25 +98,30 @@ describe('stringify static html', () => {
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}</div>`
)
// should have 5 hoisted nodes, but the other 4 should be null
expect(ast.hoists.length).toBe(5)
for (let i = 1; i < 5; i++) {
expect(ast.hoists[i]).toBe(null)
}
// should be optimized now
expect(ast.hoists[0]).toMatchObject({
type: NodeTypes.JS_CALL_EXPRESSION,
callee: CREATE_STATIC,
arguments: [
JSON.stringify(
repeat(
`<span class="foo"></span>`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)
),
'5'
]
})
// should have 6 hoisted nodes (including the entire array),
// but 2~5 should be null because they are merged into 1
expect(ast.hoists).toMatchObject([
{
type: NodeTypes.JS_CALL_EXPRESSION,
callee: CREATE_STATIC,
arguments: [
JSON.stringify(
repeat(
`<span class="foo"></span>`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)
),
'5'
]
},
null,
null,
null,
null,
{
type: NodeTypes.JS_ARRAY_EXPRESSION
}
])
})
test('serializing constant bindings', () => {
@@ -118,21 +131,25 @@ describe('stringify static html', () => {
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}</div></div>`
)
expect(ast.hoists.length).toBe(1)
// should be optimized now
expect(ast.hoists[0]).toMatchObject({
type: NodeTypes.JS_CALL_EXPRESSION,
callee: CREATE_STATIC,
arguments: [
JSON.stringify(
`<div style="color:red;">${repeat(
`<span class="foo bar">1 + false</span>`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}</div>`
),
'1'
]
})
expect(ast.hoists).toMatchObject([
{
type: NodeTypes.JS_CALL_EXPRESSION,
callee: CREATE_STATIC,
arguments: [
JSON.stringify(
`<div style="color:red;">${repeat(
`<span class="foo bar">1 + false</span>`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}</div>`
),
'1'
]
},
{
type: NodeTypes.JS_ARRAY_EXPRESSION
}
])
})
test('escape', () => {
@@ -143,21 +160,25 @@ describe('stringify static html', () => {
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}</div></div>`
)
expect(ast.hoists.length).toBe(1)
// should be optimized now
expect(ast.hoists[0]).toMatchObject({
type: NodeTypes.JS_CALL_EXPRESSION,
callee: CREATE_STATIC,
arguments: [
JSON.stringify(
`<div>${repeat(
`<span class="foo&gt;ar">1 + &lt;</span>` + `<span>&amp;</span>`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}</div>`
),
'1'
]
})
expect(ast.hoists).toMatchObject([
{
type: NodeTypes.JS_CALL_EXPRESSION,
callee: CREATE_STATIC,
arguments: [
JSON.stringify(
`<div>${repeat(
`<span class="foo&gt;ar">1 + &lt;</span>` + `<span>&amp;</span>`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}</div>`
),
'1'
]
},
{
type: NodeTypes.JS_ARRAY_EXPRESSION
}
])
})
test('should bail on runtime constant v-bind bindings', () => {
@@ -192,13 +213,16 @@ describe('stringify static html', () => {
]
}
)
// the expression and the tree are still hoistable
expect(ast.hoists.length).toBe(1)
// ...but the hoisted tree should not be stringified
expect(ast.hoists[0]).toMatchObject({
// if it's stringified it will be NodeTypes.CALL_EXPRESSION
type: NodeTypes.VNODE_CALL
})
expect(ast.hoists).toMatchObject([
{
// the expression and the tree are still hoistable
// but if it's stringified it will be NodeTypes.CALL_EXPRESSION
type: NodeTypes.VNODE_CALL
},
{
type: NodeTypes.JS_ARRAY_EXPRESSION
}
])
})
// #1128
@@ -209,10 +233,14 @@ describe('stringify static html', () => {
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}</div></div>`
)
expect(ast.hoists.length).toBe(1)
expect(ast.hoists[0]).toMatchObject({
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
})
expect(ast.hoists).toMatchObject([
{
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
},
{
type: NodeTypes.JS_ARRAY_EXPRESSION
}
])
const { ast: ast2 } = compileWithStringify(
`<div><div><input :indeterminate="true">${repeat(
@@ -220,10 +248,14 @@ describe('stringify static html', () => {
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}</div></div>`
)
expect(ast2.hoists.length).toBe(1)
expect(ast2.hoists[0]).toMatchObject({
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
})
expect(ast2.hoists).toMatchObject([
{
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
},
{
type: NodeTypes.JS_ARRAY_EXPRESSION
}
])
})
test('should bail on non attribute bindings', () => {
@@ -233,10 +265,14 @@ describe('stringify static html', () => {
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}<input indeterminate></div></div>`
)
expect(ast.hoists.length).toBe(1)
expect(ast.hoists[0]).toMatchObject({
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
})
expect(ast.hoists).toMatchObject([
{
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
},
{
type: NodeTypes.JS_ARRAY_EXPRESSION
}
])
const { ast: ast2 } = compileWithStringify(
`<div><div>${repeat(
@@ -244,10 +280,14 @@ describe('stringify static html', () => {
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}<input :indeterminate="true"></div></div>`
)
expect(ast2.hoists.length).toBe(1)
expect(ast2.hoists[0]).toMatchObject({
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
})
expect(ast2.hoists).toMatchObject([
{
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
},
{
type: NodeTypes.JS_ARRAY_EXPRESSION
}
])
})
test('should bail on tags that has placement constraints (eg.tables related tags)', () => {
@@ -257,10 +297,14 @@ describe('stringify static html', () => {
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
)}</tbody></table>`
)
expect(ast.hoists.length).toBe(1)
expect(ast.hoists[0]).toMatchObject({
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
})
expect(ast.hoists).toMatchObject([
{
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
},
{
type: NodeTypes.JS_ARRAY_EXPRESSION
}
])
})
test('should bail inside slots', () => {