diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap index 205a1347..c3678c7a 100644 --- a/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap +++ b/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap @@ -172,12 +172,7 @@ exports[`compiler: hoistStatic transform prefixIdentifiers hoist nested static t "const _Vue = Vue const { createVNode: _createVNode } = _Vue -const _hoisted_1 = _createVNode(\\"span\\", null, [ - \\"foo \\", - _toDisplayString(1), - \\" \\", - _toDisplayString(true) -]) +const _hoisted_1 = _createVNode(\\"span\\", null, \\"foo \\" + _toDisplayString(1) + \\" \\" + _toDisplayString(true)) return function render(_ctx, _cache) { with (this) { @@ -244,12 +239,14 @@ exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist expr return function render(_ctx, _cache) { with (this) { - const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue + const { toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, resolveComponent: _resolveComponent, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue const _component_Comp = _resolveComponent(\\"Comp\\") return (_openBlock(), _createBlock(_component_Comp, null, { - default: ({ foo }) => [_toDisplayString(_ctx.foo)], + default: ({ foo }) => [ + _createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */) + ], _compiled: true })) } diff --git a/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts b/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts index 3989805e..50240312 100644 --- a/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts +++ b/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts @@ -11,7 +11,8 @@ import { CREATE_VNODE, WITH_DIRECTIVES, FRAGMENT, - RENDER_LIST + RENDER_LIST, + CREATE_TEXT } from '../../src/runtimeHelpers' import { transformElement } from '../../src/transforms/transformElement' import { transformExpression } from '../../src/transforms/transformExpression' @@ -21,6 +22,7 @@ import { transformBind } from '../../src/transforms/vBind' import { transformOn } from '../../src/transforms/vOn' import { createObjectMatcher, genFlagText } from '../testUtils' import { PatchFlags } from '@vue/shared' +import { transformText } from '../../src/transforms/transformText' function transformWithHoist(template: string, options: CompilerOptions = {}) { const ast = parse(template) @@ -30,7 +32,8 @@ function transformWithHoist(template: string, options: CompilerOptions = {}) { transformIf, transformFor, ...(options.prefixIdentifiers ? [transformExpression] : []), - transformElement + transformElement, + transformText ], directiveTransforms: { on: transformOn, @@ -467,6 +470,24 @@ describe('compiler: hoistStatic transform', () => { expect(generate(root).code).toMatchSnapshot() }) + test('hoist static text node between elements', () => { + const { root } = transformWithHoist(`
static
static
`) + expect(root.hoists).toMatchObject([ + { + callee: CREATE_TEXT, + arguments: [ + { + type: NodeTypes.TEXT, + content: `static` + } + ] + }, + { + callee: CREATE_VNODE + } + ]) + }) + describe('prefixIdentifiers', () => { test('hoist nested static tree with static interpolation', () => { const { root, args } = transformWithHoist( @@ -482,32 +503,9 @@ describe('compiler: hoistStatic transform', () => { arguments: [ `"span"`, `null`, - [ - { - type: NodeTypes.TEXT, - content: `foo ` - }, - { - type: NodeTypes.INTERPOLATION, - content: { - content: `1`, - isStatic: false, - isConstant: true - } - }, - { - type: NodeTypes.TEXT, - content: ` ` - }, - { - type: NodeTypes.INTERPOLATION, - content: { - content: `true`, - isStatic: false, - isConstant: true - } - } - ] + { + type: NodeTypes.COMPOUND_EXPRESSION + } ] } ]) diff --git a/packages/compiler-core/src/ast.ts b/packages/compiler-core/src/ast.ts index 602af41d..0039b6e0 100644 --- a/packages/compiler-core/src/ast.ts +++ b/packages/compiler-core/src/ast.ts @@ -243,7 +243,7 @@ export interface ForNode extends Node { export interface TextCallNode extends Node { type: NodeTypes.TEXT_CALL content: TextNode | InterpolationNode | CompoundExpressionNode - codegenNode: CallExpression + codegenNode: CallExpression | SimpleExpressionNode // when hoisted } // JS Node Types --------------------------------------------------------------- diff --git a/packages/compiler-core/src/transforms/hoistStatic.ts b/packages/compiler-core/src/transforms/hoistStatic.ts index 7dd38b46..f04f2444 100644 --- a/packages/compiler-core/src/transforms/hoistStatic.ts +++ b/packages/compiler-core/src/transforms/hoistStatic.ts @@ -21,6 +21,8 @@ export function hoistStatic(root: RootNode, context: TransformContext) { root.children, context, new Map(), + // Root node is unfortuantely non-hoistable due to potential parent + // fallthrough attributes. isSingleElementRoot(root, root.children[0]) ) } @@ -86,6 +88,11 @@ function walk( // Do not hoist v-if single child because it has to be a block walk(branchChildren, context, resultCache, branchChildren.length === 1) } + } else if ( + child.type === NodeTypes.TEXT_CALL && + isStaticNode(child.content, resultCache) + ) { + child.codegenNode = context.hoist(child.codegenNode) } } } diff --git a/packages/compiler-dom/src/index.ts b/packages/compiler-dom/src/index.ts index 07f427e5..5ae5c1b5 100644 --- a/packages/compiler-dom/src/index.ts +++ b/packages/compiler-dom/src/index.ts @@ -41,7 +41,7 @@ export function compile( template: string, options: CompilerOptions = {} ): CodegenResult { - return baseCompile(template, { + const result = baseCompile(template, { ...parserOptions, ...options, nodeTransforms: [...DOMNodeTransforms, ...(options.nodeTransforms || [])], @@ -50,6 +50,8 @@ export function compile( ...(options.directiveTransforms || {}) } }) + // debugger + return result } export function parse(template: string, options: ParserOptions = {}): RootNode {