perf: also hoist all-static children array
This commit is contained in:
		
							parent
							
								
									8bc50cb995
								
							
						
					
					
						commit
						b7ea7c1485
					
				@ -5,14 +5,15 @@ exports[`compiler: hoistStatic transform hoist element with static key 1`] = `
 | 
				
			|||||||
const { createElementVNode: _createElementVNode } = _Vue
 | 
					const { createElementVNode: _createElementVNode } = _Vue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"div\\", { key: \\"foo\\" }, null, -1 /* HOISTED */)
 | 
					const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"div\\", { key: \\"foo\\" }, null, -1 /* HOISTED */)
 | 
				
			||||||
 | 
					const _hoisted_2 = [
 | 
				
			||||||
 | 
					  _hoisted_1
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return function render(_ctx, _cache) {
 | 
					return function render(_ctx, _cache) {
 | 
				
			||||||
  with (_ctx) {
 | 
					  with (_ctx) {
 | 
				
			||||||
    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
					    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (_openBlock(), _createElementBlock(\\"div\\", null, [
 | 
					    return (_openBlock(), _createElementBlock(\\"div\\", null, _hoisted_2))
 | 
				
			||||||
      _hoisted_1
 | 
					 | 
				
			||||||
    ]))
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}"
 | 
					}"
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
@ -25,14 +26,15 @@ const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"p\\", null, [
 | 
				
			|||||||
  /*#__PURE__*/_createElementVNode(\\"span\\"),
 | 
					  /*#__PURE__*/_createElementVNode(\\"span\\"),
 | 
				
			||||||
  /*#__PURE__*/_createElementVNode(\\"span\\")
 | 
					  /*#__PURE__*/_createElementVNode(\\"span\\")
 | 
				
			||||||
], -1 /* HOISTED */)
 | 
					], -1 /* HOISTED */)
 | 
				
			||||||
 | 
					const _hoisted_2 = [
 | 
				
			||||||
 | 
					  _hoisted_1
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return function render(_ctx, _cache) {
 | 
					return function render(_ctx, _cache) {
 | 
				
			||||||
  with (_ctx) {
 | 
					  with (_ctx) {
 | 
				
			||||||
    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
					    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (_openBlock(), _createElementBlock(\\"div\\", null, [
 | 
					    return (_openBlock(), _createElementBlock(\\"div\\", null, _hoisted_2))
 | 
				
			||||||
      _hoisted_1
 | 
					 | 
				
			||||||
    ]))
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}"
 | 
					}"
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
@ -44,14 +46,15 @@ const { createElementVNode: _createElementVNode, createCommentVNode: _createComm
 | 
				
			|||||||
const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"div\\", null, [
 | 
					const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"div\\", null, [
 | 
				
			||||||
  /*#__PURE__*/_createCommentVNode(\\"comment\\")
 | 
					  /*#__PURE__*/_createCommentVNode(\\"comment\\")
 | 
				
			||||||
], -1 /* HOISTED */)
 | 
					], -1 /* HOISTED */)
 | 
				
			||||||
 | 
					const _hoisted_2 = [
 | 
				
			||||||
 | 
					  _hoisted_1
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return function render(_ctx, _cache) {
 | 
					return function render(_ctx, _cache) {
 | 
				
			||||||
  with (_ctx) {
 | 
					  with (_ctx) {
 | 
				
			||||||
    const { createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
					    const { createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (_openBlock(), _createElementBlock(\\"div\\", null, [
 | 
					    return (_openBlock(), _createElementBlock(\\"div\\", null, _hoisted_2))
 | 
				
			||||||
      _hoisted_1
 | 
					 | 
				
			||||||
    ]))
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}"
 | 
					}"
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
@ -62,15 +65,16 @@ const { createElementVNode: _createElementVNode } = _Vue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"span\\", null, null, -1 /* HOISTED */)
 | 
					const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"span\\", null, null, -1 /* HOISTED */)
 | 
				
			||||||
const _hoisted_2 = /*#__PURE__*/_createElementVNode(\\"div\\", null, null, -1 /* HOISTED */)
 | 
					const _hoisted_2 = /*#__PURE__*/_createElementVNode(\\"div\\", null, null, -1 /* HOISTED */)
 | 
				
			||||||
 | 
					const _hoisted_3 = [
 | 
				
			||||||
 | 
					  _hoisted_1,
 | 
				
			||||||
 | 
					  _hoisted_2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return function render(_ctx, _cache) {
 | 
					return function render(_ctx, _cache) {
 | 
				
			||||||
  with (_ctx) {
 | 
					  with (_ctx) {
 | 
				
			||||||
    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
					    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (_openBlock(), _createElementBlock(\\"div\\", null, [
 | 
					    return (_openBlock(), _createElementBlock(\\"div\\", null, _hoisted_3))
 | 
				
			||||||
      _hoisted_1,
 | 
					 | 
				
			||||||
      _hoisted_2
 | 
					 | 
				
			||||||
    ]))
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}"
 | 
					}"
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
@ -80,14 +84,15 @@ exports[`compiler: hoistStatic transform hoist simple element 1`] = `
 | 
				
			|||||||
const { createElementVNode: _createElementVNode } = _Vue
 | 
					const { createElementVNode: _createElementVNode } = _Vue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"span\\", { class: \\"inline\\" }, \\"hello\\", -1 /* HOISTED */)
 | 
					const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"span\\", { class: \\"inline\\" }, \\"hello\\", -1 /* HOISTED */)
 | 
				
			||||||
 | 
					const _hoisted_2 = [
 | 
				
			||||||
 | 
					  _hoisted_1
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return function render(_ctx, _cache) {
 | 
					return function render(_ctx, _cache) {
 | 
				
			||||||
  with (_ctx) {
 | 
					  with (_ctx) {
 | 
				
			||||||
    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
					    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (_openBlock(), _createElementBlock(\\"div\\", null, [
 | 
					    return (_openBlock(), _createElementBlock(\\"div\\", null, _hoisted_2))
 | 
				
			||||||
      _hoisted_1
 | 
					 | 
				
			||||||
    ]))
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}"
 | 
					}"
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
@ -175,14 +180,15 @@ exports[`compiler: hoistStatic transform prefixIdentifiers hoist nested static t
 | 
				
			|||||||
const { createElementVNode: _createElementVNode } = _Vue
 | 
					const { createElementVNode: _createElementVNode } = _Vue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"span\\", null, \\"foo \\" + /*#__PURE__*/_toDisplayString(1) + \\" \\" + /*#__PURE__*/_toDisplayString(true), -1 /* HOISTED */)
 | 
					const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"span\\", null, \\"foo \\" + /*#__PURE__*/_toDisplayString(1) + \\" \\" + /*#__PURE__*/_toDisplayString(true), -1 /* HOISTED */)
 | 
				
			||||||
 | 
					const _hoisted_2 = [
 | 
				
			||||||
 | 
					  _hoisted_1
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return function render(_ctx, _cache) {
 | 
					return function render(_ctx, _cache) {
 | 
				
			||||||
  with (_ctx) {
 | 
					  with (_ctx) {
 | 
				
			||||||
    const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
					    const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (_openBlock(), _createElementBlock(\\"div\\", null, [
 | 
					    return (_openBlock(), _createElementBlock(\\"div\\", null, _hoisted_2))
 | 
				
			||||||
      _hoisted_1
 | 
					 | 
				
			||||||
    ]))
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}"
 | 
					}"
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
@ -192,14 +198,15 @@ exports[`compiler: hoistStatic transform prefixIdentifiers hoist nested static t
 | 
				
			|||||||
const { createElementVNode: _createElementVNode } = _Vue
 | 
					const { createElementVNode: _createElementVNode } = _Vue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"span\\", { foo: 0 }, /*#__PURE__*/_toDisplayString(1), -1 /* HOISTED */)
 | 
					const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"span\\", { foo: 0 }, /*#__PURE__*/_toDisplayString(1), -1 /* HOISTED */)
 | 
				
			||||||
 | 
					const _hoisted_2 = [
 | 
				
			||||||
 | 
					  _hoisted_1
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return function render(_ctx, _cache) {
 | 
					return function render(_ctx, _cache) {
 | 
				
			||||||
  with (_ctx) {
 | 
					  with (_ctx) {
 | 
				
			||||||
    const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
					    const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (_openBlock(), _createElementBlock(\\"div\\", null, [
 | 
					    return (_openBlock(), _createElementBlock(\\"div\\", null, _hoisted_2))
 | 
				
			||||||
      _hoisted_1
 | 
					 | 
				
			||||||
    ]))
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}"
 | 
					}"
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
@ -368,6 +375,9 @@ const { createElementVNode: _createElementVNode } = _Vue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const _hoisted_1 = { id: \\"foo\\" }
 | 
					const _hoisted_1 = { id: \\"foo\\" }
 | 
				
			||||||
const _hoisted_2 = /*#__PURE__*/_createElementVNode(\\"span\\", null, null, -1 /* HOISTED */)
 | 
					const _hoisted_2 = /*#__PURE__*/_createElementVNode(\\"span\\", null, null, -1 /* HOISTED */)
 | 
				
			||||||
 | 
					const _hoisted_3 = [
 | 
				
			||||||
 | 
					  _hoisted_2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return function render(_ctx, _cache) {
 | 
					return function render(_ctx, _cache) {
 | 
				
			||||||
  with (_ctx) {
 | 
					  with (_ctx) {
 | 
				
			||||||
@ -375,9 +385,7 @@ return function render(_ctx, _cache) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return (_openBlock(), _createElementBlock(\\"div\\", null, [
 | 
					    return (_openBlock(), _createElementBlock(\\"div\\", null, [
 | 
				
			||||||
      (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(list, (i) => {
 | 
					      (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(list, (i) => {
 | 
				
			||||||
        return (_openBlock(), _createElementBlock(\\"div\\", _hoisted_1, [
 | 
					        return (_openBlock(), _createElementBlock(\\"div\\", _hoisted_1, _hoisted_3))
 | 
				
			||||||
          _hoisted_2
 | 
					 | 
				
			||||||
        ]))
 | 
					 | 
				
			||||||
      }), 256 /* UNKEYED_FRAGMENT */))
 | 
					      }), 256 /* UNKEYED_FRAGMENT */))
 | 
				
			||||||
    ]))
 | 
					    ]))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -393,6 +401,9 @@ const _hoisted_1 = {
 | 
				
			|||||||
  id: \\"foo\\"
 | 
					  id: \\"foo\\"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
const _hoisted_2 = /*#__PURE__*/_createElementVNode(\\"span\\", null, null, -1 /* HOISTED */)
 | 
					const _hoisted_2 = /*#__PURE__*/_createElementVNode(\\"span\\", null, null, -1 /* HOISTED */)
 | 
				
			||||||
 | 
					const _hoisted_3 = [
 | 
				
			||||||
 | 
					  _hoisted_2
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return function render(_ctx, _cache) {
 | 
					return function render(_ctx, _cache) {
 | 
				
			||||||
  with (_ctx) {
 | 
					  with (_ctx) {
 | 
				
			||||||
@ -400,9 +411,7 @@ return function render(_ctx, _cache) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return (_openBlock(), _createElementBlock(\\"div\\", null, [
 | 
					    return (_openBlock(), _createElementBlock(\\"div\\", null, [
 | 
				
			||||||
      ok
 | 
					      ok
 | 
				
			||||||
        ? (_openBlock(), _createElementBlock(\\"div\\", _hoisted_1, [
 | 
					        ? (_openBlock(), _createElementBlock(\\"div\\", _hoisted_1, _hoisted_3))
 | 
				
			||||||
            _hoisted_2
 | 
					 | 
				
			||||||
          ]))
 | 
					 | 
				
			||||||
        : _createCommentVNode(\\"v-if\\", true)
 | 
					        : _createCommentVNode(\\"v-if\\", true)
 | 
				
			||||||
    ]))
 | 
					    ]))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -26,6 +26,17 @@ import { createObjectMatcher, genFlagText } from '../testUtils'
 | 
				
			|||||||
import { transformText } from '../../src/transforms/transformText'
 | 
					import { transformText } from '../../src/transforms/transformText'
 | 
				
			||||||
import { PatchFlags } from '@vue/shared'
 | 
					import { PatchFlags } from '@vue/shared'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const hoistedChildrenArrayMatcher = (startIndex = 1, length = 1) => ({
 | 
				
			||||||
 | 
					  type: NodeTypes.JS_ARRAY_EXPRESSION,
 | 
				
			||||||
 | 
					  elements: new Array(length).fill(0).map((_, i) => ({
 | 
				
			||||||
 | 
					    type: NodeTypes.ELEMENT,
 | 
				
			||||||
 | 
					    codegenNode: {
 | 
				
			||||||
 | 
					      type: NodeTypes.SIMPLE_EXPRESSION,
 | 
				
			||||||
 | 
					      content: `_hoisted_${startIndex + i}`
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }))
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function transformWithHoist(template: string, options: CompilerOptions = {}) {
 | 
					function transformWithHoist(template: string, options: CompilerOptions = {}) {
 | 
				
			||||||
  const ast = parse(template)
 | 
					  const ast = parse(template)
 | 
				
			||||||
  transform(ast, {
 | 
					  transform(ast, {
 | 
				
			||||||
@ -75,20 +86,13 @@ describe('compiler: hoistStatic transform', () => {
 | 
				
			|||||||
          type: NodeTypes.TEXT,
 | 
					          type: NodeTypes.TEXT,
 | 
				
			||||||
          content: `hello`
 | 
					          content: `hello`
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      },
 | 
				
			||||||
 | 
					      hoistedChildrenArrayMatcher()
 | 
				
			||||||
    ])
 | 
					    ])
 | 
				
			||||||
    expect(root.codegenNode).toMatchObject({
 | 
					    expect(root.codegenNode).toMatchObject({
 | 
				
			||||||
      tag: `"div"`,
 | 
					      tag: `"div"`,
 | 
				
			||||||
      props: undefined,
 | 
					      props: undefined,
 | 
				
			||||||
      children: [
 | 
					      children: { content: `_hoisted_2` }
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          type: NodeTypes.ELEMENT,
 | 
					 | 
				
			||||||
          codegenNode: {
 | 
					 | 
				
			||||||
            type: NodeTypes.SIMPLE_EXPRESSION,
 | 
					 | 
				
			||||||
            content: `_hoisted_1`
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    expect(generate(root).code).toMatchSnapshot()
 | 
					    expect(generate(root).code).toMatchSnapshot()
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@ -104,17 +108,12 @@ describe('compiler: hoistStatic transform', () => {
 | 
				
			|||||||
          { type: NodeTypes.ELEMENT, tag: `span` },
 | 
					          { type: NodeTypes.ELEMENT, tag: `span` },
 | 
				
			||||||
          { type: NodeTypes.ELEMENT, tag: `span` }
 | 
					          { type: NodeTypes.ELEMENT, tag: `span` }
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
      }
 | 
					      },
 | 
				
			||||||
    ])
 | 
					      hoistedChildrenArrayMatcher()
 | 
				
			||||||
    expect((root.codegenNode as VNodeCall).children).toMatchObject([
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        type: NodeTypes.ELEMENT,
 | 
					 | 
				
			||||||
        codegenNode: {
 | 
					 | 
				
			||||||
          type: NodeTypes.SIMPLE_EXPRESSION,
 | 
					 | 
				
			||||||
          content: `_hoisted_1`
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ])
 | 
					    ])
 | 
				
			||||||
 | 
					    expect((root.codegenNode as VNodeCall).children).toMatchObject({
 | 
				
			||||||
 | 
					      content: '_hoisted_2'
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
    expect(generate(root).code).toMatchSnapshot()
 | 
					    expect(generate(root).code).toMatchSnapshot()
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -126,17 +125,12 @@ describe('compiler: hoistStatic transform', () => {
 | 
				
			|||||||
        tag: `"div"`,
 | 
					        tag: `"div"`,
 | 
				
			||||||
        props: undefined,
 | 
					        props: undefined,
 | 
				
			||||||
        children: [{ type: NodeTypes.COMMENT, content: `comment` }]
 | 
					        children: [{ type: NodeTypes.COMMENT, content: `comment` }]
 | 
				
			||||||
      }
 | 
					      },
 | 
				
			||||||
    ])
 | 
					      hoistedChildrenArrayMatcher()
 | 
				
			||||||
    expect((root.codegenNode as VNodeCall).children).toMatchObject([
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        type: NodeTypes.ELEMENT,
 | 
					 | 
				
			||||||
        codegenNode: {
 | 
					 | 
				
			||||||
          type: NodeTypes.SIMPLE_EXPRESSION,
 | 
					 | 
				
			||||||
          content: `_hoisted_1`
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ])
 | 
					    ])
 | 
				
			||||||
 | 
					    expect((root.codegenNode as VNodeCall).children).toMatchObject({
 | 
				
			||||||
 | 
					      content: `_hoisted_2`
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
    expect(generate(root).code).toMatchSnapshot()
 | 
					    expect(generate(root).code).toMatchSnapshot()
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -150,24 +144,12 @@ describe('compiler: hoistStatic transform', () => {
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        type: NodeTypes.VNODE_CALL,
 | 
					        type: NodeTypes.VNODE_CALL,
 | 
				
			||||||
        tag: `"div"`
 | 
					        tag: `"div"`
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ])
 | 
					 | 
				
			||||||
    expect((root.codegenNode as VNodeCall).children).toMatchObject([
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        type: NodeTypes.ELEMENT,
 | 
					 | 
				
			||||||
        codegenNode: {
 | 
					 | 
				
			||||||
          type: NodeTypes.SIMPLE_EXPRESSION,
 | 
					 | 
				
			||||||
          content: `_hoisted_1`
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      hoistedChildrenArrayMatcher(1, 2)
 | 
				
			||||||
        type: NodeTypes.ELEMENT,
 | 
					 | 
				
			||||||
        codegenNode: {
 | 
					 | 
				
			||||||
          type: NodeTypes.SIMPLE_EXPRESSION,
 | 
					 | 
				
			||||||
          content: `_hoisted_2`
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ])
 | 
					    ])
 | 
				
			||||||
 | 
					    expect((root.codegenNode as VNodeCall).children).toMatchObject({
 | 
				
			||||||
 | 
					      content: '_hoisted_3'
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
    expect(generate(root).code).toMatchSnapshot()
 | 
					    expect(generate(root).code).toMatchSnapshot()
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -213,26 +195,19 @@ describe('compiler: hoistStatic transform', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  test('hoist element with static key', () => {
 | 
					  test('hoist element with static key', () => {
 | 
				
			||||||
    const root = transformWithHoist(`<div><div key="foo"/></div>`)
 | 
					    const root = transformWithHoist(`<div><div key="foo"/></div>`)
 | 
				
			||||||
    expect(root.hoists.length).toBe(1)
 | 
					    expect(root.hoists.length).toBe(2)
 | 
				
			||||||
    expect(root.hoists).toMatchObject([
 | 
					    expect(root.hoists).toMatchObject([
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        type: NodeTypes.VNODE_CALL,
 | 
					        type: NodeTypes.VNODE_CALL,
 | 
				
			||||||
        tag: `"div"`,
 | 
					        tag: `"div"`,
 | 
				
			||||||
        props: createObjectMatcher({ key: 'foo' })
 | 
					        props: createObjectMatcher({ key: 'foo' })
 | 
				
			||||||
      }
 | 
					      },
 | 
				
			||||||
 | 
					      hoistedChildrenArrayMatcher()
 | 
				
			||||||
    ])
 | 
					    ])
 | 
				
			||||||
    expect(root.codegenNode).toMatchObject({
 | 
					    expect(root.codegenNode).toMatchObject({
 | 
				
			||||||
      tag: `"div"`,
 | 
					      tag: `"div"`,
 | 
				
			||||||
      props: undefined,
 | 
					      props: undefined,
 | 
				
			||||||
      children: [
 | 
					      children: { content: `_hoisted_2` }
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          type: NodeTypes.ELEMENT,
 | 
					 | 
				
			||||||
          codegenNode: {
 | 
					 | 
				
			||||||
            type: NodeTypes.SIMPLE_EXPRESSION,
 | 
					 | 
				
			||||||
            content: `_hoisted_1`
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    expect(generate(root).code).toMatchSnapshot()
 | 
					    expect(generate(root).code).toMatchSnapshot()
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@ -348,7 +323,8 @@ describe('compiler: hoistStatic transform', () => {
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        type: NodeTypes.VNODE_CALL,
 | 
					        type: NodeTypes.VNODE_CALL,
 | 
				
			||||||
        tag: `"span"`
 | 
					        tag: `"span"`
 | 
				
			||||||
      }
 | 
					      },
 | 
				
			||||||
 | 
					      hoistedChildrenArrayMatcher(2)
 | 
				
			||||||
    ])
 | 
					    ])
 | 
				
			||||||
    expect(
 | 
					    expect(
 | 
				
			||||||
      ((root.children[0] as ElementNode).children[0] as IfNode).codegenNode
 | 
					      ((root.children[0] as ElementNode).children[0] as IfNode).codegenNode
 | 
				
			||||||
@ -359,11 +335,7 @@ describe('compiler: hoistStatic transform', () => {
 | 
				
			|||||||
        type: NodeTypes.VNODE_CALL,
 | 
					        type: NodeTypes.VNODE_CALL,
 | 
				
			||||||
        tag: `"div"`,
 | 
					        tag: `"div"`,
 | 
				
			||||||
        props: { content: `_hoisted_1` },
 | 
					        props: { content: `_hoisted_1` },
 | 
				
			||||||
        children: [
 | 
					        children: { content: `_hoisted_3` }
 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            codegenNode: { content: `_hoisted_2` }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    expect(generate(root).code).toMatchSnapshot()
 | 
					    expect(generate(root).code).toMatchSnapshot()
 | 
				
			||||||
@ -380,7 +352,8 @@ describe('compiler: hoistStatic transform', () => {
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        type: NodeTypes.VNODE_CALL,
 | 
					        type: NodeTypes.VNODE_CALL,
 | 
				
			||||||
        tag: `"span"`
 | 
					        tag: `"span"`
 | 
				
			||||||
      }
 | 
					      },
 | 
				
			||||||
 | 
					      hoistedChildrenArrayMatcher(2)
 | 
				
			||||||
    ])
 | 
					    ])
 | 
				
			||||||
    const forBlockCodegen = ((root.children[0] as ElementNode)
 | 
					    const forBlockCodegen = ((root.children[0] as ElementNode)
 | 
				
			||||||
      .children[0] as ForNode).codegenNode
 | 
					      .children[0] as ForNode).codegenNode
 | 
				
			||||||
@ -399,11 +372,7 @@ describe('compiler: hoistStatic transform', () => {
 | 
				
			|||||||
      type: NodeTypes.VNODE_CALL,
 | 
					      type: NodeTypes.VNODE_CALL,
 | 
				
			||||||
      tag: `"div"`,
 | 
					      tag: `"div"`,
 | 
				
			||||||
      props: { content: `_hoisted_1` },
 | 
					      props: { content: `_hoisted_1` },
 | 
				
			||||||
      children: [
 | 
					      children: { content: `_hoisted_3` }
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          codegenNode: { content: `_hoisted_2` }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    expect(generate(root).code).toMatchSnapshot()
 | 
					    expect(generate(root).code).toMatchSnapshot()
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@ -423,6 +392,17 @@ describe('compiler: hoistStatic transform', () => {
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        type: NodeTypes.VNODE_CALL,
 | 
					        type: NodeTypes.VNODE_CALL,
 | 
				
			||||||
        tag: `"div"`
 | 
					        tag: `"div"`
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        type: NodeTypes.JS_ARRAY_EXPRESSION,
 | 
				
			||||||
 | 
					        elements: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            type: NodeTypes.TEXT_CALL
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            type: NodeTypes.ELEMENT
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ])
 | 
					    ])
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@ -443,20 +423,16 @@ describe('compiler: hoistStatic transform', () => {
 | 
				
			|||||||
          children: {
 | 
					          children: {
 | 
				
			||||||
            type: NodeTypes.COMPOUND_EXPRESSION
 | 
					            type: NodeTypes.COMPOUND_EXPRESSION
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        },
 | 
				
			||||||
 | 
					        hoistedChildrenArrayMatcher()
 | 
				
			||||||
      ])
 | 
					      ])
 | 
				
			||||||
      expect(root.codegenNode).toMatchObject({
 | 
					      expect(root.codegenNode).toMatchObject({
 | 
				
			||||||
        tag: `"div"`,
 | 
					        tag: `"div"`,
 | 
				
			||||||
        props: undefined,
 | 
					        props: undefined,
 | 
				
			||||||
        children: [
 | 
					        children: {
 | 
				
			||||||
          {
 | 
					          type: NodeTypes.SIMPLE_EXPRESSION,
 | 
				
			||||||
            type: NodeTypes.ELEMENT,
 | 
					          content: `_hoisted_2`
 | 
				
			||||||
            codegenNode: {
 | 
					        }
 | 
				
			||||||
              type: NodeTypes.SIMPLE_EXPRESSION,
 | 
					 | 
				
			||||||
              content: `_hoisted_1`
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      expect(generate(root).code).toMatchSnapshot()
 | 
					      expect(generate(root).code).toMatchSnapshot()
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
@ -482,20 +458,16 @@ describe('compiler: hoistStatic transform', () => {
 | 
				
			|||||||
              constType: ConstantTypes.CAN_STRINGIFY
 | 
					              constType: ConstantTypes.CAN_STRINGIFY
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        },
 | 
				
			||||||
 | 
					        hoistedChildrenArrayMatcher()
 | 
				
			||||||
      ])
 | 
					      ])
 | 
				
			||||||
      expect(root.codegenNode).toMatchObject({
 | 
					      expect(root.codegenNode).toMatchObject({
 | 
				
			||||||
        tag: `"div"`,
 | 
					        tag: `"div"`,
 | 
				
			||||||
        props: undefined,
 | 
					        props: undefined,
 | 
				
			||||||
        children: [
 | 
					        children: {
 | 
				
			||||||
          {
 | 
					          type: NodeTypes.SIMPLE_EXPRESSION,
 | 
				
			||||||
            type: NodeTypes.ELEMENT,
 | 
					          content: `_hoisted_2`
 | 
				
			||||||
            codegenNode: {
 | 
					        }
 | 
				
			||||||
              type: NodeTypes.SIMPLE_EXPRESSION,
 | 
					 | 
				
			||||||
              content: `_hoisted_1`
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      expect(generate(root).code).toMatchSnapshot()
 | 
					      expect(generate(root).code).toMatchSnapshot()
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
				
			|||||||
@ -286,6 +286,7 @@ export interface VNodeCall extends Node {
 | 
				
			|||||||
    | TemplateTextChildNode // single text child
 | 
					    | TemplateTextChildNode // single text child
 | 
				
			||||||
    | SlotsExpression // component slots
 | 
					    | SlotsExpression // component slots
 | 
				
			||||||
    | ForRenderListExpression // v-for fragment call
 | 
					    | ForRenderListExpression // v-for fragment call
 | 
				
			||||||
 | 
					    | SimpleExpressionNode // hoisted
 | 
				
			||||||
    | undefined
 | 
					    | undefined
 | 
				
			||||||
  patchFlag: string | undefined
 | 
					  patchFlag: string | undefined
 | 
				
			||||||
  dynamicProps: string | SimpleExpressionNode | undefined
 | 
					  dynamicProps: string | SimpleExpressionNode | undefined
 | 
				
			||||||
@ -338,7 +339,7 @@ export interface Property extends Node {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export interface ArrayExpression extends Node {
 | 
					export interface ArrayExpression extends Node {
 | 
				
			||||||
  type: NodeTypes.JS_ARRAY_EXPRESSION
 | 
					  type: NodeTypes.JS_ARRAY_EXPRESSION
 | 
				
			||||||
  elements: Array<string | JSChildNode>
 | 
					  elements: Array<string | Node>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface FunctionExpression extends Node {
 | 
					export interface FunctionExpression extends Node {
 | 
				
			||||||
 | 
				
			|||||||
@ -840,7 +840,7 @@ function genObjectExpression(node: ObjectExpression, context: CodegenContext) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function genArrayExpression(node: ArrayExpression, context: CodegenContext) {
 | 
					function genArrayExpression(node: ArrayExpression, context: CodegenContext) {
 | 
				
			||||||
  genNodeListAsArray(node.elements, context)
 | 
					  genNodeListAsArray(node.elements as CodegenNode[], context)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function genFunctionExpression(
 | 
					function genFunctionExpression(
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,8 @@ import {
 | 
				
			|||||||
  createCacheExpression,
 | 
					  createCacheExpression,
 | 
				
			||||||
  TemplateLiteral,
 | 
					  TemplateLiteral,
 | 
				
			||||||
  createVNodeCall,
 | 
					  createVNodeCall,
 | 
				
			||||||
  ConstantTypes
 | 
					  ConstantTypes,
 | 
				
			||||||
 | 
					  ArrayExpression
 | 
				
			||||||
} from './ast'
 | 
					} from './ast'
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  isString,
 | 
					  isString,
 | 
				
			||||||
@ -113,7 +114,7 @@ export interface TransformContext
 | 
				
			|||||||
  onNodeRemoved(): void
 | 
					  onNodeRemoved(): void
 | 
				
			||||||
  addIdentifiers(exp: ExpressionNode | string): void
 | 
					  addIdentifiers(exp: ExpressionNode | string): void
 | 
				
			||||||
  removeIdentifiers(exp: ExpressionNode | string): void
 | 
					  removeIdentifiers(exp: ExpressionNode | string): void
 | 
				
			||||||
  hoist(exp: string | JSChildNode): SimpleExpressionNode
 | 
					  hoist(exp: string | JSChildNode | ArrayExpression): SimpleExpressionNode
 | 
				
			||||||
  cache<T extends JSChildNode>(exp: T, isVNode?: boolean): CacheExpression | T
 | 
					  cache<T extends JSChildNode>(exp: T, isVNode?: boolean): CacheExpression | T
 | 
				
			||||||
  constantCache: Map<TemplateChildNode, ConstantTypes>
 | 
					  constantCache: Map<TemplateChildNode, ConstantTypes>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -11,10 +11,11 @@ import {
 | 
				
			|||||||
  VNodeCall,
 | 
					  VNodeCall,
 | 
				
			||||||
  ParentNode,
 | 
					  ParentNode,
 | 
				
			||||||
  JSChildNode,
 | 
					  JSChildNode,
 | 
				
			||||||
  CallExpression
 | 
					  CallExpression,
 | 
				
			||||||
 | 
					  createArrayExpression
 | 
				
			||||||
} from '../ast'
 | 
					} from '../ast'
 | 
				
			||||||
import { TransformContext } from '../transform'
 | 
					import { TransformContext } from '../transform'
 | 
				
			||||||
import { PatchFlags, isString, isSymbol } from '@vue/shared'
 | 
					import { PatchFlags, isString, isSymbol, isArray } from '@vue/shared'
 | 
				
			||||||
import { getVNodeBlockHelper, getVNodeHelper, isSlotOutlet } from '../utils'
 | 
					import { getVNodeBlockHelper, getVNodeHelper, isSlotOutlet } from '../utils'
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  OPEN_BLOCK,
 | 
					  OPEN_BLOCK,
 | 
				
			||||||
@ -51,7 +52,6 @@ function walk(
 | 
				
			|||||||
  context: TransformContext,
 | 
					  context: TransformContext,
 | 
				
			||||||
  doNotHoistNode: boolean = false
 | 
					  doNotHoistNode: boolean = false
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
  let hasHoistedNode = false
 | 
					 | 
				
			||||||
  // Some transforms, e.g. transformAssetUrls from @vue/compiler-sfc, replaces
 | 
					  // Some transforms, e.g. transformAssetUrls from @vue/compiler-sfc, replaces
 | 
				
			||||||
  // static bindings with expressions. These expressions are guaranteed to be
 | 
					  // static bindings with expressions. These expressions are guaranteed to be
 | 
				
			||||||
  // constant so they are still eligible for hoisting, but they are only
 | 
					  // constant so they are still eligible for hoisting, but they are only
 | 
				
			||||||
@ -63,6 +63,9 @@ function walk(
 | 
				
			|||||||
  let canStringify = true
 | 
					  let canStringify = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const { children } = node
 | 
					  const { children } = node
 | 
				
			||||||
 | 
					  const originalCount = children.length
 | 
				
			||||||
 | 
					  let hoistedCount = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (let i = 0; i < children.length; i++) {
 | 
					  for (let i = 0; i < children.length; i++) {
 | 
				
			||||||
    const child = children[i]
 | 
					    const child = children[i]
 | 
				
			||||||
    // only plain elements & text calls are eligible for hoisting.
 | 
					    // only plain elements & text calls are eligible for hoisting.
 | 
				
			||||||
@ -81,7 +84,7 @@ function walk(
 | 
				
			|||||||
          ;(child.codegenNode as VNodeCall).patchFlag =
 | 
					          ;(child.codegenNode as VNodeCall).patchFlag =
 | 
				
			||||||
            PatchFlags.HOISTED + (__DEV__ ? ` /* HOISTED */` : ``)
 | 
					            PatchFlags.HOISTED + (__DEV__ ? ` /* HOISTED */` : ``)
 | 
				
			||||||
          child.codegenNode = context.hoist(child.codegenNode!)
 | 
					          child.codegenNode = context.hoist(child.codegenNode!)
 | 
				
			||||||
          hasHoistedNode = true
 | 
					          hoistedCount++
 | 
				
			||||||
          continue
 | 
					          continue
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
@ -115,7 +118,7 @@ function walk(
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        if (contentType >= ConstantTypes.CAN_HOIST) {
 | 
					        if (contentType >= ConstantTypes.CAN_HOIST) {
 | 
				
			||||||
          child.codegenNode = context.hoist(child.codegenNode)
 | 
					          child.codegenNode = context.hoist(child.codegenNode)
 | 
				
			||||||
          hasHoistedNode = true
 | 
					          hoistedCount++
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -145,9 +148,24 @@ function walk(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (canStringify && hasHoistedNode && context.transformHoist) {
 | 
					  if (canStringify && hoistedCount && context.transformHoist) {
 | 
				
			||||||
    context.transformHoist(children, context, node)
 | 
					    context.transformHoist(children, context, node)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // all children were hoisted - the entire children array is hoistable.
 | 
				
			||||||
 | 
					  if (
 | 
				
			||||||
 | 
					    hoistedCount &&
 | 
				
			||||||
 | 
					    hoistedCount === originalCount &&
 | 
				
			||||||
 | 
					    node.type === NodeTypes.ELEMENT &&
 | 
				
			||||||
 | 
					    node.tagType === ElementTypes.ELEMENT &&
 | 
				
			||||||
 | 
					    node.codegenNode &&
 | 
				
			||||||
 | 
					    node.codegenNode.type === NodeTypes.VNODE_CALL &&
 | 
				
			||||||
 | 
					    isArray(node.codegenNode.children)
 | 
				
			||||||
 | 
					  ) {
 | 
				
			||||||
 | 
					    node.codegenNode.children = context.hoist(
 | 
				
			||||||
 | 
					      createArrayExpression(node.codegenNode.children)
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function getConstantType(
 | 
					export function getConstantType(
 | 
				
			||||||
 | 
				
			|||||||
@ -30,7 +30,6 @@ describe('stringify static html', () => {
 | 
				
			|||||||
    const { ast } = compileWithStringify(
 | 
					    const { ast } = compileWithStringify(
 | 
				
			||||||
      `<div><div><div>hello</div><div>hello</div></div></div>`
 | 
					      `<div><div><div>hello</div><div>hello</div></div></div>`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(ast.hoists.length).toBe(1)
 | 
					 | 
				
			||||||
    // should be a normal vnode call
 | 
					    // should be a normal vnode call
 | 
				
			||||||
    expect(ast.hoists[0]!.type).toBe(NodeTypes.VNODE_CALL)
 | 
					    expect(ast.hoists[0]!.type).toBe(NodeTypes.VNODE_CALL)
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@ -42,21 +41,25 @@ describe('stringify static html', () => {
 | 
				
			|||||||
        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
					        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
				
			||||||
      )}</div></div>`
 | 
					      )}</div></div>`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(ast.hoists.length).toBe(1)
 | 
					 | 
				
			||||||
    // should be optimized now
 | 
					    // should be optimized now
 | 
				
			||||||
    expect(ast.hoists[0]).toMatchObject({
 | 
					    expect(ast.hoists).toMatchObject([
 | 
				
			||||||
      type: NodeTypes.JS_CALL_EXPRESSION,
 | 
					      {
 | 
				
			||||||
      callee: CREATE_STATIC,
 | 
					        type: NodeTypes.JS_CALL_EXPRESSION,
 | 
				
			||||||
      arguments: [
 | 
					        callee: CREATE_STATIC,
 | 
				
			||||||
        JSON.stringify(
 | 
					        arguments: [
 | 
				
			||||||
          `<div>${repeat(
 | 
					          JSON.stringify(
 | 
				
			||||||
            `<span class="foo"></span>`,
 | 
					            `<div>${repeat(
 | 
				
			||||||
            StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
					              `<span class="foo"></span>`,
 | 
				
			||||||
          )}</div>`
 | 
					              StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
				
			||||||
        ),
 | 
					            )}</div>`
 | 
				
			||||||
        '1'
 | 
					          ),
 | 
				
			||||||
      ]
 | 
					          '1'
 | 
				
			||||||
    })
 | 
					        ]
 | 
				
			||||||
 | 
					      }, // the children array is hoisted as well
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        type: NodeTypes.JS_ARRAY_EXPRESSION
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('should work on eligible content (elements > 20)', () => {
 | 
					  test('should work on eligible content (elements > 20)', () => {
 | 
				
			||||||
@ -66,21 +69,26 @@ describe('stringify static html', () => {
 | 
				
			|||||||
        StringifyThresholds.NODE_COUNT
 | 
					        StringifyThresholds.NODE_COUNT
 | 
				
			||||||
      )}</div></div>`
 | 
					      )}</div></div>`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(ast.hoists.length).toBe(1)
 | 
					 | 
				
			||||||
    // should be optimized now
 | 
					    // should be optimized now
 | 
				
			||||||
    expect(ast.hoists[0]).toMatchObject({
 | 
					    expect(ast.hoists).toMatchObject([
 | 
				
			||||||
      type: NodeTypes.JS_CALL_EXPRESSION,
 | 
					      {
 | 
				
			||||||
      callee: CREATE_STATIC,
 | 
					        type: NodeTypes.JS_CALL_EXPRESSION,
 | 
				
			||||||
      arguments: [
 | 
					        callee: CREATE_STATIC,
 | 
				
			||||||
        JSON.stringify(
 | 
					        arguments: [
 | 
				
			||||||
          `<div>${repeat(
 | 
					          JSON.stringify(
 | 
				
			||||||
            `<span></span>`,
 | 
					            `<div>${repeat(
 | 
				
			||||||
            StringifyThresholds.NODE_COUNT
 | 
					              `<span></span>`,
 | 
				
			||||||
          )}</div>`
 | 
					              StringifyThresholds.NODE_COUNT
 | 
				
			||||||
        ),
 | 
					            )}</div>`
 | 
				
			||||||
        '1'
 | 
					          ),
 | 
				
			||||||
      ]
 | 
					          '1'
 | 
				
			||||||
    })
 | 
					        ]
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      // the children array is hoisted as well
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        type: NodeTypes.JS_ARRAY_EXPRESSION
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('should work for multiple adjacent nodes', () => {
 | 
					  test('should work for multiple adjacent nodes', () => {
 | 
				
			||||||
@ -90,25 +98,30 @@ describe('stringify static html', () => {
 | 
				
			|||||||
        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
					        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
				
			||||||
      )}</div>`
 | 
					      )}</div>`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    // should have 5 hoisted nodes, but the other 4 should be null
 | 
					    // should have 6 hoisted nodes (including the entire array),
 | 
				
			||||||
    expect(ast.hoists.length).toBe(5)
 | 
					    // but 2~5 should be null because they are merged into 1
 | 
				
			||||||
    for (let i = 1; i < 5; i++) {
 | 
					    expect(ast.hoists).toMatchObject([
 | 
				
			||||||
      expect(ast.hoists[i]).toBe(null)
 | 
					      {
 | 
				
			||||||
    }
 | 
					        type: NodeTypes.JS_CALL_EXPRESSION,
 | 
				
			||||||
    // should be optimized now
 | 
					        callee: CREATE_STATIC,
 | 
				
			||||||
    expect(ast.hoists[0]).toMatchObject({
 | 
					        arguments: [
 | 
				
			||||||
      type: NodeTypes.JS_CALL_EXPRESSION,
 | 
					          JSON.stringify(
 | 
				
			||||||
      callee: CREATE_STATIC,
 | 
					            repeat(
 | 
				
			||||||
      arguments: [
 | 
					              `<span class="foo"></span>`,
 | 
				
			||||||
        JSON.stringify(
 | 
					              StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
				
			||||||
          repeat(
 | 
					            )
 | 
				
			||||||
            `<span class="foo"></span>`,
 | 
					          ),
 | 
				
			||||||
            StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
					          '5'
 | 
				
			||||||
          )
 | 
					        ]
 | 
				
			||||||
        ),
 | 
					      },
 | 
				
			||||||
        '5'
 | 
					      null,
 | 
				
			||||||
      ]
 | 
					      null,
 | 
				
			||||||
    })
 | 
					      null,
 | 
				
			||||||
 | 
					      null,
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        type: NodeTypes.JS_ARRAY_EXPRESSION
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('serializing constant bindings', () => {
 | 
					  test('serializing constant bindings', () => {
 | 
				
			||||||
@ -118,21 +131,25 @@ describe('stringify static html', () => {
 | 
				
			|||||||
        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
					        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
				
			||||||
      )}</div></div>`
 | 
					      )}</div></div>`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(ast.hoists.length).toBe(1)
 | 
					 | 
				
			||||||
    // should be optimized now
 | 
					    // should be optimized now
 | 
				
			||||||
    expect(ast.hoists[0]).toMatchObject({
 | 
					    expect(ast.hoists).toMatchObject([
 | 
				
			||||||
      type: NodeTypes.JS_CALL_EXPRESSION,
 | 
					      {
 | 
				
			||||||
      callee: CREATE_STATIC,
 | 
					        type: NodeTypes.JS_CALL_EXPRESSION,
 | 
				
			||||||
      arguments: [
 | 
					        callee: CREATE_STATIC,
 | 
				
			||||||
        JSON.stringify(
 | 
					        arguments: [
 | 
				
			||||||
          `<div style="color:red;">${repeat(
 | 
					          JSON.stringify(
 | 
				
			||||||
            `<span class="foo bar">1 + false</span>`,
 | 
					            `<div style="color:red;">${repeat(
 | 
				
			||||||
            StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
					              `<span class="foo bar">1 + false</span>`,
 | 
				
			||||||
          )}</div>`
 | 
					              StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
				
			||||||
        ),
 | 
					            )}</div>`
 | 
				
			||||||
        '1'
 | 
					          ),
 | 
				
			||||||
      ]
 | 
					          '1'
 | 
				
			||||||
    })
 | 
					        ]
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        type: NodeTypes.JS_ARRAY_EXPRESSION
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('escape', () => {
 | 
					  test('escape', () => {
 | 
				
			||||||
@ -143,21 +160,25 @@ describe('stringify static html', () => {
 | 
				
			|||||||
        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
					        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
				
			||||||
      )}</div></div>`
 | 
					      )}</div></div>`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(ast.hoists.length).toBe(1)
 | 
					 | 
				
			||||||
    // should be optimized now
 | 
					    // should be optimized now
 | 
				
			||||||
    expect(ast.hoists[0]).toMatchObject({
 | 
					    expect(ast.hoists).toMatchObject([
 | 
				
			||||||
      type: NodeTypes.JS_CALL_EXPRESSION,
 | 
					      {
 | 
				
			||||||
      callee: CREATE_STATIC,
 | 
					        type: NodeTypes.JS_CALL_EXPRESSION,
 | 
				
			||||||
      arguments: [
 | 
					        callee: CREATE_STATIC,
 | 
				
			||||||
        JSON.stringify(
 | 
					        arguments: [
 | 
				
			||||||
          `<div>${repeat(
 | 
					          JSON.stringify(
 | 
				
			||||||
            `<span class="foo>ar">1 + <</span>` + `<span>&</span>`,
 | 
					            `<div>${repeat(
 | 
				
			||||||
            StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
					              `<span class="foo>ar">1 + <</span>` + `<span>&</span>`,
 | 
				
			||||||
          )}</div>`
 | 
					              StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
				
			||||||
        ),
 | 
					            )}</div>`
 | 
				
			||||||
        '1'
 | 
					          ),
 | 
				
			||||||
      ]
 | 
					          '1'
 | 
				
			||||||
    })
 | 
					        ]
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        type: NodeTypes.JS_ARRAY_EXPRESSION
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('should bail on runtime constant v-bind bindings', () => {
 | 
					  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).toMatchObject([
 | 
				
			||||||
    expect(ast.hoists.length).toBe(1)
 | 
					      {
 | 
				
			||||||
    // ...but the hoisted tree should not be stringified
 | 
					        // the expression and the tree are still hoistable
 | 
				
			||||||
    expect(ast.hoists[0]).toMatchObject({
 | 
					        // but if it's stringified it will be NodeTypes.CALL_EXPRESSION
 | 
				
			||||||
      // if it's stringified it will be NodeTypes.CALL_EXPRESSION
 | 
					        type: NodeTypes.VNODE_CALL
 | 
				
			||||||
      type: NodeTypes.VNODE_CALL
 | 
					      },
 | 
				
			||||||
    })
 | 
					      {
 | 
				
			||||||
 | 
					        type: NodeTypes.JS_ARRAY_EXPRESSION
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // #1128
 | 
					  // #1128
 | 
				
			||||||
@ -209,10 +233,14 @@ describe('stringify static html', () => {
 | 
				
			|||||||
        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
					        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
				
			||||||
      )}</div></div>`
 | 
					      )}</div></div>`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(ast.hoists.length).toBe(1)
 | 
					    expect(ast.hoists).toMatchObject([
 | 
				
			||||||
    expect(ast.hoists[0]).toMatchObject({
 | 
					      {
 | 
				
			||||||
      type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
 | 
					        type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
 | 
				
			||||||
    })
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        type: NodeTypes.JS_ARRAY_EXPRESSION
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const { ast: ast2 } = compileWithStringify(
 | 
					    const { ast: ast2 } = compileWithStringify(
 | 
				
			||||||
      `<div><div><input :indeterminate="true">${repeat(
 | 
					      `<div><div><input :indeterminate="true">${repeat(
 | 
				
			||||||
@ -220,10 +248,14 @@ describe('stringify static html', () => {
 | 
				
			|||||||
        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
					        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
				
			||||||
      )}</div></div>`
 | 
					      )}</div></div>`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(ast2.hoists.length).toBe(1)
 | 
					    expect(ast2.hoists).toMatchObject([
 | 
				
			||||||
    expect(ast2.hoists[0]).toMatchObject({
 | 
					      {
 | 
				
			||||||
      type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
 | 
					        type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
 | 
				
			||||||
    })
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        type: NodeTypes.JS_ARRAY_EXPRESSION
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('should bail on non attribute bindings', () => {
 | 
					  test('should bail on non attribute bindings', () => {
 | 
				
			||||||
@ -233,10 +265,14 @@ describe('stringify static html', () => {
 | 
				
			|||||||
        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
					        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
				
			||||||
      )}<input indeterminate></div></div>`
 | 
					      )}<input indeterminate></div></div>`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(ast.hoists.length).toBe(1)
 | 
					    expect(ast.hoists).toMatchObject([
 | 
				
			||||||
    expect(ast.hoists[0]).toMatchObject({
 | 
					      {
 | 
				
			||||||
      type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
 | 
					        type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
 | 
				
			||||||
    })
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        type: NodeTypes.JS_ARRAY_EXPRESSION
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const { ast: ast2 } = compileWithStringify(
 | 
					    const { ast: ast2 } = compileWithStringify(
 | 
				
			||||||
      `<div><div>${repeat(
 | 
					      `<div><div>${repeat(
 | 
				
			||||||
@ -244,10 +280,14 @@ describe('stringify static html', () => {
 | 
				
			|||||||
        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
					        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
				
			||||||
      )}<input :indeterminate="true"></div></div>`
 | 
					      )}<input :indeterminate="true"></div></div>`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(ast2.hoists.length).toBe(1)
 | 
					    expect(ast2.hoists).toMatchObject([
 | 
				
			||||||
    expect(ast2.hoists[0]).toMatchObject({
 | 
					      {
 | 
				
			||||||
      type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
 | 
					        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)', () => {
 | 
					  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
 | 
					        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
 | 
				
			||||||
      )}</tbody></table>`
 | 
					      )}</tbody></table>`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(ast.hoists.length).toBe(1)
 | 
					    expect(ast.hoists).toMatchObject([
 | 
				
			||||||
    expect(ast.hoists[0]).toMatchObject({
 | 
					      {
 | 
				
			||||||
      type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
 | 
					        type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
 | 
				
			||||||
    })
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        type: NodeTypes.JS_ARRAY_EXPRESSION
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('should bail inside slots', () => {
 | 
					  test('should bail inside slots', () => {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user