From e15802590479e775c84071a9b7d037a9316cf94b Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Thu, 16 May 2024 19:29:33 +0200 Subject: [PATCH 1/6] perf(sfc): lazy initiatate hoisted vnodes --- packages/compiler-core/src/codegen.ts | 7 +++++-- packages/compiler-core/src/runtimeHelpers.ts | 2 ++ packages/compiler-core/src/transform.ts | 2 +- packages/compiler-core/src/transforms/hoistStatic.ts | 2 ++ packages/runtime-core/src/index.ts | 8 +++++++- packages/runtime-core/src/vnode.ts | 10 ++++++++++ 6 files changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/compiler-core/src/codegen.ts b/packages/compiler-core/src/codegen.ts index 987293d5124..58f697c9a89 100644 --- a/packages/compiler-core/src/codegen.ts +++ b/packages/compiler-core/src/codegen.ts @@ -42,6 +42,7 @@ import { CREATE_STATIC, CREATE_TEXT, CREATE_VNODE, + HOIST_LAZY, OPEN_BLOCK, POP_SCOPE_ID, PUSH_SCOPE_ID, @@ -476,6 +477,7 @@ function genModulePreamble( if (genScopeId && ast.hoists.length) { ast.helpers.add(PUSH_SCOPE_ID) ast.helpers.add(POP_SCOPE_ID) + ast.helpers.add(HOIST_LAZY) } // generate import statements for helpers @@ -585,14 +587,15 @@ function genHoists(hoists: (JSChildNode | null)[], context: CodegenContext) { if (exp) { const needScopeIdWrapper = genScopeId && exp.type === NodeTypes.VNODE_CALL push( - `const _hoisted_${i + 1} = ${ - needScopeIdWrapper ? `${PURE_ANNOTATION} _withScopeId(() => ` : `` + `const _hoisted_${i + 1} = ${PURE_ANNOTATION} ${helper(HOIST_LAZY)}(() => (${ + needScopeIdWrapper ? `_withScopeId(() => ` : `` }`, ) genNode(exp, context) if (needScopeIdWrapper) { push(`)`) } + push('))') newline() } } diff --git a/packages/compiler-core/src/runtimeHelpers.ts b/packages/compiler-core/src/runtimeHelpers.ts index 47ab73e011a..fe1e6a376c4 100644 --- a/packages/compiler-core/src/runtimeHelpers.ts +++ b/packages/compiler-core/src/runtimeHelpers.ts @@ -9,6 +9,7 @@ export const CREATE_ELEMENT_BLOCK = Symbol(__DEV__ ? `createElementBlock` : ``) export const CREATE_VNODE = Symbol(__DEV__ ? `createVNode` : ``) export const CREATE_ELEMENT_VNODE = Symbol(__DEV__ ? `createElementVNode` : ``) export const CREATE_COMMENT = Symbol(__DEV__ ? `createCommentVNode` : ``) +export const HOIST_LAZY = Symbol(__DEV__ ? `hoistLazy` : ``) export const CREATE_TEXT = Symbol(__DEV__ ? `createTextVNode` : ``) export const CREATE_STATIC = Symbol(__DEV__ ? `createStaticVNode` : ``) export const RESOLVE_COMPONENT = Symbol(__DEV__ ? `resolveComponent` : ``) @@ -79,6 +80,7 @@ export const helperNameMap: Record = { [POP_SCOPE_ID]: `popScopeId`, [WITH_CTX]: `withCtx`, [UNREF]: `unref`, + [HOIST_LAZY]: `hoistLazy`, [IS_REF]: `isRef`, [WITH_MEMO]: `withMemo`, [IS_MEMO_SAME]: `isMemoSame`, diff --git a/packages/compiler-core/src/transform.ts b/packages/compiler-core/src/transform.ts index 69821f7f879..81b1626778f 100644 --- a/packages/compiler-core/src/transform.ts +++ b/packages/compiler-core/src/transform.ts @@ -288,7 +288,7 @@ export function createTransformContext( if (isString(exp)) exp = createSimpleExpression(exp) context.hoists.push(exp) const identifier = createSimpleExpression( - `_hoisted_${context.hoists.length}`, + `_hoisted_${context.hoists.length}()`, false, exp.loc, ConstantTypes.CAN_HOIST, diff --git a/packages/compiler-core/src/transforms/hoistStatic.ts b/packages/compiler-core/src/transforms/hoistStatic.ts index 70a0468e519..ab3a5d6db0b 100644 --- a/packages/compiler-core/src/transforms/hoistStatic.ts +++ b/packages/compiler-core/src/transforms/hoistStatic.ts @@ -21,6 +21,7 @@ import { PatchFlags, isArray, isString, isSymbol } from '@vue/shared' import { isSlotOutlet } from '../utils' import { GUARD_REACTIVE_PROPS, + HOIST_LAZY, NORMALIZE_CLASS, NORMALIZE_PROPS, NORMALIZE_STYLE, @@ -70,6 +71,7 @@ function walk( : getConstantType(child, context) if (constantType > ConstantTypes.NOT_CONSTANT) { if (constantType >= ConstantTypes.CAN_HOIST) { + context.helper(HOIST_LAZY) ;(child.codegenNode as VNodeCall).patchFlag = PatchFlags.HOISTED + (__DEV__ ? ` /* HOISTED */` : ``) child.codegenNode = context.hoist(child.codegenNode!) diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index 94b2985040a..be233178e34 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -97,7 +97,13 @@ export { getCurrentInstance } from './component' // For raw render function users export { h } from './h' // Advanced render function utilities -export { createVNode, cloneVNode, mergeProps, isVNode } from './vnode' +export { + createVNode, + cloneVNode, + mergeProps, + isVNode, + hoistLazy, +} from './vnode' // VNode types export { Fragment, Text, Comment, Static, type VNodeRef } from './vnode' // Built-in components diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 0e2a4bafcc5..24074ba8217 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -875,3 +875,13 @@ export function invokeVNodeHook( prevVNode, ]) } + +export function hoistLazy(fn: () => T): () => T { + let cache: T | undefined + return (): T => { + if (!cache) { + cache = fn() + } + return cache + } +} From 25193a7c0bc2d13ccc71b511c376b6162e84f535 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Thu, 16 May 2024 19:30:08 +0200 Subject: [PATCH 2/6] test: update snap --- .../__snapshots__/codegen.spec.ts.snap | 4 +- .../__snapshots__/scopeId.spec.ts.snap | 10 +- .../compiler-core/__tests__/codegen.spec.ts | 8 +- .../compiler-core/__tests__/scopeId.spec.ts | 8 +- .../compiler-core/__tests__/transform.spec.ts | 4 +- .../__snapshots__/hoistStatic.spec.ts.snap | 156 ++++---- .../__tests__/transforms/hoistStatic.spec.ts | 36 +- .../stringifyStatic.spec.ts.snap | 70 ++-- .../__snapshots__/compileScript.spec.ts.snap | 6 +- .../templateTransformAssetUrl.spec.ts.snap | 24 +- .../templateTransformSrcset.spec.ts.snap | 334 +++++++++--------- 11 files changed, 332 insertions(+), 328 deletions(-) diff --git a/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap index 2bdb4afa4c0..82697ec1f9d 100644 --- a/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap @@ -134,8 +134,8 @@ return function render(_ctx, _cache) { exports[`compiler: codegen > hoists 1`] = ` " -const _hoisted_1 = hello -const _hoisted_2 = { id: "foo" } +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => (hello)) +const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => ({ id: "foo" })) return function render(_ctx, _cache) { with (_ctx) { diff --git a/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap index 445d3fd13ed..0c58a646f9f 100644 --- a/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap @@ -1,17 +1,17 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`scopeId compiler support > should push scopeId for hoisted nodes 1`] = ` -"import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from "vue" +"import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, hoistLazy as _hoistLazy, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from "vue" const _withScopeId = n => (_pushScopeId("test"),n=n(),_popScopeId(),n) -const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", -1 /* HOISTED */)) -const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", -1 /* HOISTED */)) +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => (_withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", -1 /* HOISTED */)))) +const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => (_withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", -1 /* HOISTED */)))) export function render(_ctx, _cache) { return (_openBlock(), _createElementBlock("div", null, [ - _hoisted_1, + _hoisted_1(), _createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */), - _hoisted_2 + _hoisted_2() ])) }" `; diff --git a/packages/compiler-core/__tests__/codegen.spec.ts b/packages/compiler-core/__tests__/codegen.spec.ts index 9c923075634..a4059b39888 100644 --- a/packages/compiler-core/__tests__/codegen.spec.ts +++ b/packages/compiler-core/__tests__/codegen.spec.ts @@ -154,8 +154,12 @@ describe('compiler: codegen', () => { ], }) const { code } = generate(root) - expect(code).toMatch(`const _hoisted_1 = hello`) - expect(code).toMatch(`const _hoisted_2 = { id: "foo" }`) + expect(code).toMatch( + `const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => (hello))`, + ) + expect(code).toMatch( + `const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => ({ id: "foo" }))`, + ) expect(code).toMatchSnapshot() }) diff --git a/packages/compiler-core/__tests__/scopeId.spec.ts b/packages/compiler-core/__tests__/scopeId.spec.ts index c7a21df7a78..39a3d78a7b3 100644 --- a/packages/compiler-core/__tests__/scopeId.spec.ts +++ b/packages/compiler-core/__tests__/scopeId.spec.ts @@ -72,12 +72,12 @@ describe('scopeId compiler support', () => { expect(ast.hoists.length).toBe(2) ;[ `const _withScopeId = n => (_pushScopeId("test"),n=n(),_popScopeId(),n)`, - `const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", ${genFlagText( + `const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => (_withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", ${genFlagText( PatchFlags.HOISTED, - )}))`, - `const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", ${genFlagText( + )})))`, + `const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => (_withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", ${genFlagText( PatchFlags.HOISTED, - )}))`, + )})))`, ].forEach(c => expect(code).toMatch(c)) expect(code).toMatchSnapshot() }) diff --git a/packages/compiler-core/__tests__/transform.spec.ts b/packages/compiler-core/__tests__/transform.spec.ts index a56be51bc5c..2ee14b9474b 100644 --- a/packages/compiler-core/__tests__/transform.spec.ts +++ b/packages/compiler-core/__tests__/transform.spec.ts @@ -197,8 +197,8 @@ describe('compiler: transform', () => { nodeTransforms: [mock], }) expect(ast.hoists).toMatchObject(hoisted) - expect((ast as any).children[0].props[0].exp.content).toBe(`_hoisted_1`) - expect((ast as any).children[1].props[0].exp.content).toBe(`_hoisted_2`) + expect((ast as any).children[0].props[0].exp.content).toBe(`_hoisted_1()`) + expect((ast as any).children[1].props[0].exp.content).toBe(`_hoisted_2()`) }) test('context.filename and selfName', () => { 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 ef3e2b8f4d6..b62789e335e 100644 --- a/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap +++ b/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap @@ -4,16 +4,16 @@ exports[`compiler: hoistStatic transform > hoist element with static key 1`] = ` "const _Vue = Vue const { createElementVNode: _createElementVNode } = _Vue -const _hoisted_1 = /*#__PURE__*/_createElementVNode("div", { key: "foo" }, null, -1 /* HOISTED */) -const _hoisted_2 = [ - _hoisted_1 -] +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => (/*#__PURE__*/_createElementVNode("div", { key: "foo" }, null, -1 /* HOISTED */))) +const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => ([ + _hoisted_1() +])) return function render(_ctx, _cache) { with (_ctx) { - const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue + const { createElementVNode: _createElementVNode, hoistLazy: _hoistLazy, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue - return (_openBlock(), _createElementBlock("div", null, _hoisted_2)) + return (_openBlock(), _createElementBlock("div", null, _hoisted_2())) } }" `; @@ -22,19 +22,19 @@ exports[`compiler: hoistStatic transform > hoist nested static tree 1`] = ` "const _Vue = Vue const { createElementVNode: _createElementVNode } = _Vue -const _hoisted_1 = /*#__PURE__*/_createElementVNode("p", null, [ +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => (/*#__PURE__*/_createElementVNode("p", null, [ /*#__PURE__*/_createElementVNode("span"), /*#__PURE__*/_createElementVNode("span") -], -1 /* HOISTED */) -const _hoisted_2 = [ - _hoisted_1 -] +], -1 /* HOISTED */))) +const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => ([ + _hoisted_1() +])) return function render(_ctx, _cache) { with (_ctx) { - const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue + const { createElementVNode: _createElementVNode, hoistLazy: _hoistLazy, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue - return (_openBlock(), _createElementBlock("div", null, _hoisted_2)) + return (_openBlock(), _createElementBlock("div", null, _hoisted_2())) } }" `; @@ -43,18 +43,18 @@ exports[`compiler: hoistStatic transform > hoist nested static tree with comment "const _Vue = Vue const { createElementVNode: _createElementVNode, createCommentVNode: _createCommentVNode } = _Vue -const _hoisted_1 = /*#__PURE__*/_createElementVNode("div", null, [ +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => (/*#__PURE__*/_createElementVNode("div", null, [ /*#__PURE__*/_createCommentVNode("comment") -], -1 /* HOISTED */) -const _hoisted_2 = [ - _hoisted_1 -] +], -1 /* HOISTED */))) +const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => ([ + _hoisted_1() +])) return function render(_ctx, _cache) { with (_ctx) { - const { createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue + const { createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, hoistLazy: _hoistLazy, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue - return (_openBlock(), _createElementBlock("div", null, _hoisted_2)) + return (_openBlock(), _createElementBlock("div", null, _hoisted_2())) } }" `; @@ -63,18 +63,18 @@ exports[`compiler: hoistStatic transform > hoist siblings with common non-hoista "const _Vue = Vue const { createElementVNode: _createElementVNode } = _Vue -const _hoisted_1 = /*#__PURE__*/_createElementVNode("span", null, null, -1 /* HOISTED */) -const _hoisted_2 = /*#__PURE__*/_createElementVNode("div", null, null, -1 /* HOISTED */) -const _hoisted_3 = [ - _hoisted_1, - _hoisted_2 -] +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => (/*#__PURE__*/_createElementVNode("span", null, null, -1 /* HOISTED */))) +const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => (/*#__PURE__*/_createElementVNode("div", null, null, -1 /* HOISTED */))) +const _hoisted_3 = /*#__PURE__*/ _hoistLazy(() => ([ + _hoisted_1(), + _hoisted_2() +])) return function render(_ctx, _cache) { with (_ctx) { - const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue + const { createElementVNode: _createElementVNode, hoistLazy: _hoistLazy, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue - return (_openBlock(), _createElementBlock("div", null, _hoisted_3)) + return (_openBlock(), _createElementBlock("div", null, _hoisted_3())) } }" `; @@ -83,16 +83,16 @@ exports[`compiler: hoistStatic transform > hoist simple element 1`] = ` "const _Vue = Vue const { createElementVNode: _createElementVNode } = _Vue -const _hoisted_1 = /*#__PURE__*/_createElementVNode("span", { class: "inline" }, "hello", -1 /* HOISTED */) -const _hoisted_2 = [ - _hoisted_1 -] +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => (/*#__PURE__*/_createElementVNode("span", { class: "inline" }, "hello", -1 /* HOISTED */))) +const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => ([ + _hoisted_1() +])) return function render(_ctx, _cache) { with (_ctx) { - const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue + const { createElementVNode: _createElementVNode, hoistLazy: _hoistLazy, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue - return (_openBlock(), _createElementBlock("div", null, _hoisted_2)) + return (_openBlock(), _createElementBlock("div", null, _hoisted_2())) } }" `; @@ -101,7 +101,7 @@ exports[`compiler: hoistStatic transform > hoist static props for elements with "const _Vue = Vue const { createElementVNode: _createElementVNode } = _Vue -const _hoisted_1 = { id: "foo" } +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => ({ id: "foo" })) return function render(_ctx, _cache) { with (_ctx) { @@ -110,7 +110,7 @@ return function render(_ctx, _cache) { const _directive_foo = _resolveDirective("foo") return (_openBlock(), _createElementBlock("div", null, [ - _withDirectives(_createElementVNode("div", _hoisted_1, null, 512 /* NEED_PATCH */), [ + _withDirectives(_createElementVNode("div", _hoisted_1(), null, 512 /* NEED_PATCH */), [ [_directive_foo] ]) ])) @@ -122,14 +122,14 @@ exports[`compiler: hoistStatic transform > hoist static props for elements with "const _Vue = Vue const { createElementVNode: _createElementVNode } = _Vue -const _hoisted_1 = { id: "foo" } +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => ({ id: "foo" })) return function render(_ctx, _cache) { with (_ctx) { const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue return (_openBlock(), _createElementBlock("div", null, [ - _createElementVNode("div", _hoisted_1, _toDisplayString(hello), 1 /* TEXT */) + _createElementVNode("div", _hoisted_1(), _toDisplayString(hello), 1 /* TEXT */) ])) } }" @@ -139,7 +139,7 @@ exports[`compiler: hoistStatic transform > hoist static props for elements with "const _Vue = Vue const { createVNode: _createVNode, createElementVNode: _createElementVNode } = _Vue -const _hoisted_1 = { id: "foo" } +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => ({ id: "foo" })) return function render(_ctx, _cache) { with (_ctx) { @@ -148,7 +148,7 @@ return function render(_ctx, _cache) { const _component_Comp = _resolveComponent("Comp") return (_openBlock(), _createElementBlock("div", null, [ - _createElementVNode("div", _hoisted_1, [ + _createElementVNode("div", _hoisted_1(), [ _createVNode(_component_Comp) ]) ])) @@ -160,16 +160,16 @@ exports[`compiler: hoistStatic transform > prefixIdentifiers > hoist class with "const _Vue = Vue const { createElementVNode: _createElementVNode } = _Vue -const _hoisted_1 = { +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => ({ class: /*#__PURE__*/_normalizeClass({ foo: true }) -} +})) return function render(_ctx, _cache) { with (_ctx) { const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue return (_openBlock(), _createElementBlock("div", null, [ - _createElementVNode("span", _hoisted_1, _toDisplayString(_ctx.bar), 1 /* TEXT */) + _createElementVNode("span", _hoisted_1(), _toDisplayString(_ctx.bar), 1 /* TEXT */) ])) } }" @@ -179,16 +179,16 @@ exports[`compiler: hoistStatic transform > prefixIdentifiers > hoist nested stat "const _Vue = Vue const { createElementVNode: _createElementVNode } = _Vue -const _hoisted_1 = /*#__PURE__*/_createElementVNode("span", null, "foo " + /*#__PURE__*/_toDisplayString(1) + " " + /*#__PURE__*/_toDisplayString(true), -1 /* HOISTED */) -const _hoisted_2 = [ - _hoisted_1 -] +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => (/*#__PURE__*/_createElementVNode("span", null, "foo " + /*#__PURE__*/_toDisplayString(1) + " " + /*#__PURE__*/_toDisplayString(true), -1 /* HOISTED */))) +const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => ([ + _hoisted_1() +])) return function render(_ctx, _cache) { with (_ctx) { - const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue + const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, hoistLazy: _hoistLazy, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue - return (_openBlock(), _createElementBlock("div", null, _hoisted_2)) + return (_openBlock(), _createElementBlock("div", null, _hoisted_2())) } }" `; @@ -197,16 +197,16 @@ exports[`compiler: hoistStatic transform > prefixIdentifiers > hoist nested stat "const _Vue = Vue const { createElementVNode: _createElementVNode } = _Vue -const _hoisted_1 = /*#__PURE__*/_createElementVNode("span", { foo: 0 }, /*#__PURE__*/_toDisplayString(1), -1 /* HOISTED */) -const _hoisted_2 = [ - _hoisted_1 -] +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => (/*#__PURE__*/_createElementVNode("span", { foo: 0 }, /*#__PURE__*/_toDisplayString(1), -1 /* HOISTED */))) +const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => ([ + _hoisted_1() +])) return function render(_ctx, _cache) { with (_ctx) { - const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue + const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, hoistLazy: _hoistLazy, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue - return (_openBlock(), _createElementBlock("div", null, _hoisted_2)) + return (_openBlock(), _createElementBlock("div", null, _hoisted_2())) } }" `; @@ -215,19 +215,19 @@ exports[`compiler: hoistStatic transform > prefixIdentifiers > should NOT hoist "const _Vue = Vue const { createElementVNode: _createElementVNode } = _Vue -const _hoisted_1 = /*#__PURE__*/_createElementVNode("path", { d: "M2,3H5.5L12" }, null, -1 /* HOISTED */) -const _hoisted_2 = [ - _hoisted_1 -] +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => (/*#__PURE__*/_createElementVNode("path", { d: "M2,3H5.5L12" }, null, -1 /* HOISTED */))) +const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => ([ + _hoisted_1() +])) return function render(_ctx, _cache) { with (_ctx) { - const { createElementVNode: _createElementVNode, resolveDirective: _resolveDirective, openBlock: _openBlock, createElementBlock: _createElementBlock, withDirectives: _withDirectives } = _Vue + const { createElementVNode: _createElementVNode, resolveDirective: _resolveDirective, openBlock: _openBlock, createElementBlock: _createElementBlock, withDirectives: _withDirectives, hoistLazy: _hoistLazy } = _Vue const _directive_foo = _resolveDirective("foo") return (_openBlock(), _createElementBlock("div", null, [ - _withDirectives((_openBlock(), _createElementBlock("svg", null, _hoisted_2)), [ + _withDirectives((_openBlock(), _createElementBlock("svg", null, _hoisted_2())), [ [_directive_foo] ]) ])) @@ -369,14 +369,14 @@ exports[`compiler: hoistStatic transform > should NOT hoist element with dynamic "const _Vue = Vue const { createElementVNode: _createElementVNode } = _Vue -const _hoisted_1 = ["id"] +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => (["id"])) return function render(_ctx, _cache) { with (_ctx) { const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue return (_openBlock(), _createElementBlock("div", null, [ - _createElementVNode("div", { id: foo }, null, 8 /* PROPS */, _hoisted_1) + _createElementVNode("div", { id: foo }, null, 8 /* PROPS */, _hoisted_1()) ])) } }" @@ -412,19 +412,19 @@ exports[`compiler: hoistStatic transform > should hoist v-for children if static "const _Vue = Vue const { createElementVNode: _createElementVNode } = _Vue -const _hoisted_1 = { id: "foo" } -const _hoisted_2 = /*#__PURE__*/_createElementVNode("span", null, null, -1 /* HOISTED */) -const _hoisted_3 = [ - _hoisted_2 -] +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => ({ id: "foo" })) +const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => (/*#__PURE__*/_createElementVNode("span", null, null, -1 /* HOISTED */))) +const _hoisted_3 = /*#__PURE__*/ _hoistLazy(() => ([ + _hoisted_2() +])) return function render(_ctx, _cache) { with (_ctx) { - const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createElementVNode: _createElementVNode } = _Vue + const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createElementVNode: _createElementVNode, hoistLazy: _hoistLazy } = _Vue return (_openBlock(), _createElementBlock("div", null, [ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(list, (i) => { - return (_openBlock(), _createElementBlock("div", _hoisted_1, _hoisted_3)) + return (_openBlock(), _createElementBlock("div", _hoisted_1(), _hoisted_3())) }), 256 /* UNKEYED_FRAGMENT */)) ])) } @@ -435,22 +435,22 @@ exports[`compiler: hoistStatic transform > should hoist v-if props/children if s "const _Vue = Vue const { createElementVNode: _createElementVNode, createCommentVNode: _createCommentVNode } = _Vue -const _hoisted_1 = { +const _hoisted_1 = /*#__PURE__*/ _hoistLazy(() => ({ key: 0, id: "foo" -} -const _hoisted_2 = /*#__PURE__*/_createElementVNode("span", null, null, -1 /* HOISTED */) -const _hoisted_3 = [ - _hoisted_2 -] +})) +const _hoisted_2 = /*#__PURE__*/ _hoistLazy(() => (/*#__PURE__*/_createElementVNode("span", null, null, -1 /* HOISTED */))) +const _hoisted_3 = /*#__PURE__*/ _hoistLazy(() => ([ + _hoisted_2() +])) return function render(_ctx, _cache) { with (_ctx) { - const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode } = _Vue + const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode, hoistLazy: _hoistLazy } = _Vue return (_openBlock(), _createElementBlock("div", null, [ ok - ? (_openBlock(), _createElementBlock("div", _hoisted_1, _hoisted_3)) + ? (_openBlock(), _createElementBlock("div", _hoisted_1(), _hoisted_3())) : _createCommentVNode("v-if", true) ])) } diff --git a/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts b/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts index d6c46b52eb3..650a8005cce 100644 --- a/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts +++ b/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts @@ -31,7 +31,7 @@ const hoistedChildrenArrayMatcher = (startIndex = 1, length = 1) => ({ type: NodeTypes.ELEMENT, codegenNode: { type: NodeTypes.SIMPLE_EXPRESSION, - content: `_hoisted_${startIndex + i}`, + content: `_hoisted_${startIndex + i}()`, }, })), }) @@ -91,7 +91,7 @@ describe('compiler: hoistStatic transform', () => { expect(root.codegenNode).toMatchObject({ tag: `"div"`, props: undefined, - children: { content: `_hoisted_2` }, + children: { content: `_hoisted_2()` }, }) expect(generate(root).code).toMatchSnapshot() }) @@ -111,7 +111,7 @@ describe('compiler: hoistStatic transform', () => { hoistedChildrenArrayMatcher(), ]) expect((root.codegenNode as VNodeCall).children).toMatchObject({ - content: '_hoisted_2', + content: '_hoisted_2()', }) expect(generate(root).code).toMatchSnapshot() }) @@ -128,7 +128,7 @@ describe('compiler: hoistStatic transform', () => { hoistedChildrenArrayMatcher(), ]) expect((root.codegenNode as VNodeCall).children).toMatchObject({ - content: `_hoisted_2`, + content: `_hoisted_2()`, }) expect(generate(root).code).toMatchSnapshot() }) @@ -147,7 +147,7 @@ describe('compiler: hoistStatic transform', () => { hoistedChildrenArrayMatcher(1, 2), ]) expect((root.codegenNode as VNodeCall).children).toMatchObject({ - content: '_hoisted_3', + content: '_hoisted_3()', }) expect(generate(root).code).toMatchSnapshot() }) @@ -183,7 +183,7 @@ describe('compiler: hoistStatic transform', () => { patchFlag: genFlagText(PatchFlags.PROPS), dynamicProps: { type: NodeTypes.SIMPLE_EXPRESSION, - content: `_hoisted_1`, + content: `_hoisted_1()`, isStatic: false, }, }, @@ -206,7 +206,7 @@ describe('compiler: hoistStatic transform', () => { expect(root.codegenNode).toMatchObject({ tag: `"div"`, props: undefined, - children: { content: `_hoisted_2` }, + children: { content: `_hoisted_2()` }, }) expect(generate(root).code).toMatchSnapshot() }) @@ -260,7 +260,7 @@ describe('compiler: hoistStatic transform', () => { tag: `"div"`, props: { type: NodeTypes.SIMPLE_EXPRESSION, - content: `_hoisted_1`, + content: `_hoisted_1()`, }, children: undefined, patchFlag: genFlagText(PatchFlags.NEED_PATCH), @@ -284,7 +284,7 @@ describe('compiler: hoistStatic transform', () => { codegenNode: { type: NodeTypes.VNODE_CALL, tag: `"div"`, - props: { content: `_hoisted_1` }, + props: { content: `_hoisted_1()` }, children: { type: NodeTypes.INTERPOLATION }, patchFlag: genFlagText(PatchFlags.TEXT), }, @@ -302,7 +302,7 @@ describe('compiler: hoistStatic transform', () => { codegenNode: { type: NodeTypes.VNODE_CALL, tag: `"div"`, - props: { content: `_hoisted_1` }, + props: { content: `_hoisted_1()` }, children: [{ type: NodeTypes.ELEMENT, tag: `Comp` }], }, }, @@ -333,8 +333,8 @@ describe('compiler: hoistStatic transform', () => { // blocks should NOT be hoisted type: NodeTypes.VNODE_CALL, tag: `"div"`, - props: { content: `_hoisted_1` }, - children: { content: `_hoisted_3` }, + props: { content: `_hoisted_1()` }, + children: { content: `_hoisted_3()` }, }, }) expect(generate(root).code).toMatchSnapshot() @@ -371,8 +371,8 @@ describe('compiler: hoistStatic transform', () => { expect(innerBlockCodegen.returns).toMatchObject({ type: NodeTypes.VNODE_CALL, tag: `"div"`, - props: { content: `_hoisted_1` }, - children: { content: `_hoisted_3` }, + props: { content: `_hoisted_1()` }, + children: { content: `_hoisted_3()` }, }) expect(generate(root).code).toMatchSnapshot() }) @@ -401,7 +401,7 @@ describe('compiler: hoistStatic transform', () => { props: undefined, children: { type: NodeTypes.SIMPLE_EXPRESSION, - content: `_hoisted_2`, + content: `_hoisted_2()`, }, }) expect(generate(root).code).toMatchSnapshot() @@ -436,7 +436,7 @@ describe('compiler: hoistStatic transform', () => { props: undefined, children: { type: NodeTypes.SIMPLE_EXPRESSION, - content: `_hoisted_2`, + content: `_hoisted_2()`, }, }) expect(generate(root).code).toMatchSnapshot() @@ -486,7 +486,7 @@ describe('compiler: hoistStatic transform', () => { tag: `"span"`, props: { type: NodeTypes.SIMPLE_EXPRESSION, - content: `_hoisted_1`, + content: `_hoisted_1()`, }, children: { type: NodeTypes.INTERPOLATION, @@ -601,7 +601,7 @@ describe('compiler: hoistStatic transform', () => { expect(root.hoists.length).toBe(2) expect(root.codegenNode).toMatchObject({ children: { - content: '[..._hoisted_2]', + content: '[..._hoisted_2()]', }, }) }) diff --git a/packages/compiler-dom/__tests__/transforms/__snapshots__/stringifyStatic.spec.ts.snap b/packages/compiler-dom/__tests__/transforms/__snapshots__/stringifyStatic.spec.ts.snap index 57d880a03f6..e813d2c435a 100644 --- a/packages/compiler-dom/__tests__/transforms/__snapshots__/stringifyStatic.spec.ts.snap +++ b/packages/compiler-dom/__tests__/transforms/__snapshots__/stringifyStatic.spec.ts.snap @@ -1,96 +1,96 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`stringify static html > should bail for