diff --git a/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap index 0b6816a08f4..a250f325d0a 100644 --- a/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap @@ -3,10 +3,9 @@ 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\\" -_pushScopeId(\\"test\\") -const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"div\\", null, \\"hello\\", -1 /* HOISTED */) -const _hoisted_2 = /*#__PURE__*/_createElementVNode(\\"div\\", null, \\"world\\", -1 /* HOISTED */) -_popScopeId() +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 */)) export function render(_ctx, _cache) { return (_openBlock(), _createElementBlock(\\"div\\", null, [ diff --git a/packages/compiler-core/__tests__/scopeId.spec.ts b/packages/compiler-core/__tests__/scopeId.spec.ts index 1f5f6f71ed1..5f7ea0d2e6a 100644 --- a/packages/compiler-core/__tests__/scopeId.spec.ts +++ b/packages/compiler-core/__tests__/scopeId.spec.ts @@ -70,18 +70,15 @@ describe('scopeId compiler support', () => { expect(ast.helpers).toContain(PUSH_SCOPE_ID) expect(ast.helpers).toContain(POP_SCOPE_ID) expect(ast.hoists.length).toBe(2) - expect(code).toMatch( - [ - `_pushScopeId("test")`, - `const _hoisted_1 = /*#__PURE__*/_createElementVNode("div", null, "hello", ${genFlagText( - PatchFlags.HOISTED - )})`, - `const _hoisted_2 = /*#__PURE__*/_createElementVNode("div", null, "world", ${genFlagText( - PatchFlags.HOISTED - )})`, - `_popScopeId()` - ].join('\n') - ) + ;[ + `const _withScopeId = n => (_pushScopeId("test"),n=n(),_popScopeId(),n)`, + `const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", ${genFlagText( + PatchFlags.HOISTED + )}))`, + `const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", ${genFlagText( + PatchFlags.HOISTED + )}))` + ].forEach(c => expect(code).toMatch(c)) expect(code).toMatchSnapshot() }) }) diff --git a/packages/compiler-core/src/codegen.ts b/packages/compiler-core/src/codegen.ts index 0cc5e105ec6..9f245bf742e 100644 --- a/packages/compiler-core/src/codegen.ts +++ b/packages/compiler-core/src/codegen.ts @@ -470,25 +470,33 @@ function genHoists(hoists: (JSChildNode | null)[], context: CodegenContext) { const genScopeId = !__BROWSER__ && scopeId != null && mode !== 'function' newline() - // push scope Id before initializing hoisted vnodes so that these vnodes - // get the proper scopeId as well. + // generate inlined withScopeId helper if (genScopeId) { - push(`${helper(PUSH_SCOPE_ID)}("${scopeId}")`) + push( + `const _withScopeId = n => (${helper( + PUSH_SCOPE_ID + )}("${scopeId}"),n=n(),${helper(POP_SCOPE_ID)}(),n)` + ) newline() } - hoists.forEach((exp, i) => { + for (let i = 0; i < hoists.length; i++) { + const exp = hoists[i] if (exp) { - push(`const _hoisted_${i + 1} = `) + const needScopeIdWrapper = genScopeId && exp.type === NodeTypes.VNODE_CALL + push( + `const _hoisted_${i + 1} = ${ + needScopeIdWrapper ? `${PURE_ANNOTATION} _withScopeId(() => ` : `` + }` + ) genNode(exp, context) + if (needScopeIdWrapper) { + push(`)`) + } newline() } - }) - - if (genScopeId) { - push(`${helper(POP_SCOPE_ID)}()`) - newline() } + context.pure = false }