diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap index 377dd3df61a..2fb57531881 100644 --- a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap @@ -41,7 +41,7 @@ export function render(_ctx) { const n2 = _createComponentWithFallback(_component_Bar) _withVaporDirectives(n2, [[_directive_hello, void 0, void 0, { world: true }]]) return n3 - }, null, 1, true) + }, null, 17 /* BLOCK_SHAPE, ONCE */) return n0 }) }, true) @@ -277,7 +277,7 @@ export function render(_ctx) { const n1 = _createIf(() => (true), () => { const n3 = t0() return n3 - }, null, 1, true) + }, null, 17 /* BLOCK_SHAPE, ONCE */) _renderEffect(() => _setProp(n4, "disabled", _ctx.foo)) return n6 }" diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/TransformTransition.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/TransformTransition.spec.ts.snap index 82a1d0dcd20..a843242eca7 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/TransformTransition.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/TransformTransition.spec.ts.snap @@ -56,9 +56,9 @@ export function render(_ctx) { }, () => { const n13 = t1() return n13 - }, 5, null, 2) + }, 101 /* BLOCK_SHAPE, INDEX_SHIFT */) return n14 - }, 5, null, 1), 5, null, 0) + }, 69 /* BLOCK_SHAPE, INDEX_SHIFT */), 37 /* BLOCK_SHAPE, INDEX_SHIFT */) return [n0, n3, n7] } }, true) @@ -113,7 +113,7 @@ export function render(_ctx) { const n0 = _createIf(() => (_ctx.show), () => { const n2 = t0() return n2 - }, null, 1) + }) return n0 } }, true) diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/logicalIndex.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/logicalIndex.spec.ts.snap index 20666311567..d02452384c3 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/logicalIndex.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/logicalIndex.spec.ts.snap @@ -61,7 +61,7 @@ export function render(_ctx) { const n1 = _createIf(() => (true), () => { const n3 = t0() return n3 - }, null, 1, true) + }, null, 17 /* BLOCK_SHAPE, ONCE */) return n5 }" `; @@ -80,7 +80,7 @@ export function render(_ctx) { const n1 = _createIf(() => (true), () => { const n3 = t0() return n3 - }, null, 1, true) + }, null, 17 /* BLOCK_SHAPE, ONCE */) return n4 }" `; @@ -100,7 +100,7 @@ export function render(_ctx) { const n1 = _createIf(() => (true), () => { const n3 = t0() return n3 - }, null, 1, true) + }, null, 17 /* BLOCK_SHAPE, ONCE */) return n5 }" `; @@ -344,7 +344,7 @@ export function render(_ctx) { const n0 = _createIf(() => (_ctx.show), () => { const n2 = t0() return n2 - }, null, 1) + }) return n3 }" `; @@ -361,7 +361,7 @@ export function render(_ctx) { const n0 = _createIf(() => (_ctx.show), () => { const n2 = t0() return n2 - }, null, 1) + }) return n4 }" `; @@ -377,7 +377,7 @@ export function render(_ctx) { const n0 = _createIf(() => (_ctx.show), () => { const n2 = t0() return n2 - }, null, 1) + }) return n3 }" `; @@ -399,7 +399,7 @@ export function render(_ctx) { }, () => { const n5 = t1() return n5 - }, 5, null, 0) + }, 37 /* BLOCK_SHAPE, INDEX_SHIFT */) _setInsertionState(n7, null, 2) const n6 = _createAssetComponent("Comp2") return n7 @@ -423,7 +423,7 @@ export function render(_ctx) { }, () => { const n5 = t1() return n5 - }, 5, null, 0) + }, 37 /* BLOCK_SHAPE, INDEX_SHIFT */) return n6 }" `; @@ -444,7 +444,7 @@ export function render(_ctx) { }, () => { const n4 = t1() return n4 - }, 5, null, 0) + }, 37 /* BLOCK_SHAPE, INDEX_SHIFT */) return n6 }" `; @@ -469,7 +469,7 @@ export function render(_ctx) { }, () => { const n6 = t2() return n6 - }, 5, null, 1), 5, null, 0) + }, 69 /* BLOCK_SHAPE, INDEX_SHIFT */), 37 /* BLOCK_SHAPE, INDEX_SHIFT */) return n8 }" `; @@ -489,7 +489,7 @@ export function render(_ctx) { }, () => { const n4 = t1() return n4 - }, 5, null, 0) + }, 37 /* BLOCK_SHAPE, INDEX_SHIFT */) return n5 }" `; @@ -509,7 +509,7 @@ export function render(_ctx) { }, () => { const n4 = t1() return n4 - }, 5, null, 0) + }, 37 /* BLOCK_SHAPE, INDEX_SHIFT */) _setInsertionState(n6, null, 2) const n5 = _createAssetComponent("Comp") return n6 @@ -531,7 +531,7 @@ export function render(_ctx) { }, () => { const n4 = t1() return n4 - }, 5, null, 0) + }, 37 /* BLOCK_SHAPE, INDEX_SHIFT */) return n5 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap index a7b479e73e3..67780441347 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap @@ -12,7 +12,7 @@ export function render(_ctx) { const n0 = _createIf(() => (1), () => { const n2 = t0() return n2 - }, null, 1, true) + }, null, 17 /* BLOCK_SHAPE, ONCE */) return n4 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap index 54bcdb39497..5c2dade12cc 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap @@ -131,7 +131,7 @@ export function render(_ctx) { const n1 = _createIf(() => (_ctx.ok), () => { const n3 = _createComponentWithFallback(_component_Child) return n3 - }, null, 1) + }) return n1 }) }) diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformKey.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformKey.spec.ts.snap index 87321ca4df7..1f85fc87ef3 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformKey.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformKey.spec.ts.snap @@ -127,7 +127,7 @@ export function render(_ctx) { return n5 }) return n4 - }, null, 1), 5, null, 0) + }), 37 /* BLOCK_SHAPE, INDEX_SHIFT */) return n0 }" `; @@ -156,7 +156,7 @@ export function render(_ctx) { return n3 }) return n2 - }, null, 1) + }) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformTemplateRef.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformTemplateRef.spec.ts.snap index 916e5febda2..8693971aa28 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformTemplateRef.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformTemplateRef.spec.ts.snap @@ -175,7 +175,7 @@ export function render(_ctx) { const n2 = t0() _setTemplateRef(n2, "foo") return n2 - }, null, 1, true) + }, null, 17 /* BLOCK_SHAPE, ONCE */) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap index 21277589f1b..145db0d53dc 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap @@ -355,7 +355,7 @@ export function render(_ctx) { }, () => { const n6 = _createComponentWithFallback(_component_Comp) return n6 - }, 10, null, 0) + }, 42 /* BLOCK_SHAPE, INDEX_SHIFT */) return n2 }, undefined, 16) return n0 diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vIf.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vIf.spec.ts.snap index d4602254138..46124b29966 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vIf.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vIf.spec.ts.snap @@ -10,7 +10,7 @@ export function render(_ctx) { const x2 = _txt(n2) _renderEffect(() => _setText(x2, _toDisplayString(_ctx.msg))) return n2 - }, null, 1) + }) return n0 }" `; @@ -36,7 +36,7 @@ export function render(_ctx) { const n10 = t3() const n11 = t4() return [n10, n11] - }, 10, null, 1), 5, null, 0) + }, 74 /* BLOCK_SHAPE, INDEX_SHIFT */), 37 /* BLOCK_SHAPE, INDEX_SHIFT */) const n13 = t5() const x13 = _txt(n13) _renderEffect(() => _setText(x13, _toDisplayString(_ctx.text))) @@ -52,7 +52,7 @@ export function render(_ctx) { const n0 = _createIf(() => (_ctx.ok), () => { const n2 = _createComponentWithFallback(_component_Component, null, null, true) return n2 - }, null, 1) + }) return n0 }" `; @@ -65,11 +65,11 @@ export function render(_ctx) { const n0 = _createIf(() => (_ctx.ok), () => { const n2 = t0() return n2 - }, null, 1) + }) const n3 = _createIf(() => (_ctx.ok), () => { const n5 = t0() return n5 - }, null, 1) + }) return [n0, n3] }" `; @@ -87,11 +87,11 @@ export function render(_ctx) { }, () => _createIf(() => (_ctx.bar), () => { const n4 = t1() return n4 - }, null, 1), 5, null, 0) + }), 37 /* BLOCK_SHAPE, INDEX_SHIFT */) const n6 = _createIf(() => (_ctx.baz), () => { const n8 = t2() return n8 - }, null, 1) + }) return [n0, n6] }" `; @@ -106,7 +106,7 @@ export function render(_ctx) { const n2 = t0() const n3 = t1() return [n2, n3] - }, null, 2) + }, null, 2 /* BLOCK_SHAPE */) return n0 }" `; @@ -119,7 +119,7 @@ export function render(_ctx) { const n0 = _createIf(() => (_ctx.foo), () => { const n2 = t0() return n2 - }, null, 1) + }) return n0 }" `; @@ -132,7 +132,7 @@ export function render(_ctx) { const n0 = _createIf(() => (_ctx.foo), () => { const n2 = t0() return n2 - }, null, 1) + }) return n0 }" `; @@ -148,7 +148,7 @@ export function render(_ctx) { return n4 }, undefined, 8) return n2 - }, null, 1) + }) return n0 }" `; @@ -166,7 +166,7 @@ export function render(_ctx) { return n4 }, (item, index) => (index), 8) return n2 - }, null, 1) + }) return n0 }" `; @@ -185,7 +185,7 @@ export function render(_ctx) { }, () => { const n5 = t2() return n5 - }, 6, null, 0) + }, 38 /* BLOCK_SHAPE, INDEX_SHIFT */) return n0 }" `; @@ -204,7 +204,7 @@ export function render(_ctx) { const x4 = _txt(n4) _renderEffect(() => _setText(x4, _toDisplayString(_ctx.msg))) return [n2, n3, n4] - }, null, 2) + }, null, 2 /* BLOCK_SHAPE */) return n0 }" `; @@ -221,7 +221,7 @@ export function render(_ctx) { }, () => { const n4 = t1() return n4 - }, 5, null, 0) + }, 37 /* BLOCK_SHAPE, INDEX_SHIFT */) return n0 }" `; @@ -245,7 +245,7 @@ export function render(_ctx) { }, () => { const n10 = t2() return n10 - }, 5, true, 2), 5, null, 1), 5, null, 0) + }, 21 /* BLOCK_SHAPE, ONCE */), 69 /* BLOCK_SHAPE, INDEX_SHIFT */), 37 /* BLOCK_SHAPE, INDEX_SHIFT */) return n0 }" `; @@ -262,7 +262,7 @@ export function render(_ctx) { }, () => _createIf(() => (_ctx.orNot), () => { const n4 = t1() return n4 - }, null, 1), 5, null, 0) + }), 37 /* BLOCK_SHAPE, INDEX_SHIFT */) return n0 }" `; @@ -280,7 +280,7 @@ export function render(_ctx) { const n0 = _createIf(() => (_ctx.foo), () => { const n2 = t0() return n2 - }, null, 1) + }) _setInsertionState(n8, null, 1) const n3 = _createIf(() => (_ctx.bar), () => { const n5 = t1() @@ -288,7 +288,7 @@ export function render(_ctx) { }, () => { const n7 = t2() return n7 - }, 5, null, 1) + }, 69 /* BLOCK_SHAPE, INDEX_SHIFT */) return n8 }" `; @@ -306,7 +306,7 @@ export function render(_ctx) { }, () => _createIf(() => (_ctx.bar), () => { const n4 = t1() return n4 - }, null, 1), 5, null, 0) + }), 37 /* BLOCK_SHAPE, INDEX_SHIFT */) const n6 = t2() return [n0, n6] }" @@ -322,7 +322,7 @@ export function render(_ctx) { const x2 = _txt(n2) _setText(x2, _toDisplayString(_ctx.msg)) return n2 - }, null, 1, true) + }, null, 17 /* BLOCK_SHAPE, ONCE */) return n0 }" `; @@ -336,7 +336,7 @@ export function render(_ctx) { const n2 = t0() _renderEffect(() => _setDynamicEvents(n2, { click: _ctx.clickEvent })) return n2 - }, null, 1, true) + }, null, 17 /* BLOCK_SHAPE, ONCE */) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap index 57c8a129001..c74d2212f2e 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap @@ -102,7 +102,7 @@ export function render(_ctx) { const n0 = _createIf(() => (_ctx.expr), () => { const n2 = t0() return n2 - }, null, 1, true) + }, null, 17 /* BLOCK_SHAPE, ONCE */) return n0 }" `; @@ -119,7 +119,7 @@ export function render(_ctx) { }, () => { const n4 = t1() return n4 - }, 5, true, 0) + }, 21 /* BLOCK_SHAPE, ONCE */) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap index 29f4e9326ad..cf767c04cd1 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap @@ -214,7 +214,7 @@ export function render(_ctx) { const n0 = _createIf(() => (_ctx.ok), () => { const n2 = _createSlot("default", null) return n2 - }, null, 1) + }) return n0 }) }, true) @@ -399,7 +399,7 @@ export function render(_ctx) { }, () => { const n5 = _createComponentWithFallback(_component_Bar) return n5 - }, 5, true, 0) + }, 21 /* BLOCK_SHAPE, ONCE */) return n6 }" `; @@ -647,7 +647,7 @@ export function render(_ctx) { _setInsertionState(n3, null, 0) const n2 = _createComponentWithFallback(_component_ChildComp) return n3 - }, null, 1) + }) return n0 }) }, true) @@ -682,7 +682,7 @@ export function render(_ctx) { _setInsertionState(n3, null, 0) const n2 = _createPlainElement("my-element") return n3 - }, null, 1) + }) return n0 }) }, true) @@ -721,9 +721,9 @@ export function render(_ctx) { _setInsertionState(n5, null, 0) const n4 = _createComponentWithFallback(_component_ChildComp) return n5 - }, null, 1) + }) return n6 - }, null, 1) + }) return n0 }) }, true) @@ -812,7 +812,7 @@ export function render(_ctx) { }, () => { const n4 = t1() return n4 - }, 5, null, 0) + }, 37 /* BLOCK_SHAPE, INDEX_SHIFT */) return n0 } }, true) diff --git a/packages/compiler-vapor/__tests__/transforms/vIf.spec.ts b/packages/compiler-vapor/__tests__/transforms/vIf.spec.ts index 55227203314..39f85f6f466 100644 --- a/packages/compiler-vapor/__tests__/transforms/vIf.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vIf.spec.ts @@ -66,6 +66,29 @@ describe('compiler: v-if', () => { expect(code).matchSnapshot() }) + test('omits default single-root flags', () => { + const { code } = compileWithVIf(`
`) + + expect(code).contains(`const n0 = _createIf(() => (_ctx.ok), () => {`) + expect(code).not.contains(`}, null, 1)`) + }) + + test('packs once flag', () => { + const { code } = compileWithVIf(``) + + expect(code).contains(`}, null, 17 /* BLOCK_SHAPE, ONCE */)`) + expect(code).not.contains(`}, null, 1, true)`) + }) + + test('packs branch index', () => { + const { code } = compileWithVIf( + `foo
')(), () => template('bar
')(), - undefined, - true, + ifFlags(singleRootIfElse, true), ) }, }).render() @@ -198,9 +200,7 @@ describe('createIf', () => { () => show.value, () => (branch = t0()), () => (branch = t1()), - undefined, - undefined, - 0, + ifFlags(singleRootIfElse, false, 0), ), ).render() @@ -234,9 +234,7 @@ describe('createIf', () => { () => show.value, () => (branch = t0()), () => (branch = t1()), - undefined, - undefined, - 0, + ifFlags(singleRootIfElse, false, 0), ), ]).render() @@ -270,9 +268,7 @@ describe('createIf', () => { () => show.value, () => (branch = t0()), () => (branch = t1()), - undefined, - undefined, - 0, + ifFlags(singleRootIfElse, false, 0), ), }, true, diff --git a/packages/runtime-vapor/src/apiCreateIf.ts b/packages/runtime-vapor/src/apiCreateIf.ts index 54e4a0a85b1..f4a2038c55a 100644 --- a/packages/runtime-vapor/src/apiCreateIf.ts +++ b/packages/runtime-vapor/src/apiCreateIf.ts @@ -15,15 +15,15 @@ import { import { renderEffect } from './renderEffect' import { DynamicFragment } from './fragment' import { createComment, createTextNode } from './dom/node' -import { VaporBlockShape } from '@vue/shared' +import { VaporBlockShape, VaporIfFlags } from '@vue/shared' export function createIf( condition: () => any, b1: BlockFn, b2?: BlockFn, - blockShape?: number, - once?: boolean, - index?: number, + // Default flags encode true single-root + false empty, matching the compiler's + // only omitted-flags case. + flags: number = VaporBlockShape.SINGLE_ROOT, ): Block { const _insertionParent = insertionParent const _insertionAnchor = insertionAnchor @@ -32,10 +32,10 @@ export function createIf( let branchShape: VaporBlockShape | undefined let frag: Block - if (once) { + if (flags & VaporIfFlags.ONCE) { const ok = condition() if (isHydrating) { - branchShape = decodeIfShape(blockShape!, ok) + branchShape = decodeIfShape(flags, ok) hydrationCursor = enterHydrationCursor( branchShape === VaporBlockShape.MULTI_ROOT, ) @@ -47,7 +47,11 @@ export function createIf( : [__DEV__ ? createComment('if') : createTextNode()] } else { // DynamicFragment should be keyed for correct transition behavior - const keyed = index != null + // and KeepAlive cache identity. The encoded value is index + 1, so 0 is + // the unkeyed sentinel and source index 0 becomes encoded index 1. + const index = flags >> VaporIfFlags.INDEX_SHIFT + const keyed = index > 0 + const keyBase = keyed ? (index - 1) * 2 : 0 frag = isHydrating || __DEV__ ? new DynamicFragment('if', keyed, false) @@ -55,14 +59,14 @@ export function createIf( renderEffect(() => { const ok = condition() if (isHydrating) { - branchShape = decodeIfShape(blockShape!, ok) + branchShape = decodeIfShape(flags, ok) hydrationCursor = enterHydrationCursor( branchShape === VaporBlockShape.MULTI_ROOT, ) } ;(frag as DynamicFragment).update( ok ? b1 : b2, - keyed ? index * 2 + (ok ? 0 : 1) : undefined, + keyed ? keyBase + (ok ? 0 : 1) : undefined, ) }) } diff --git a/packages/shared/src/vaporFlags.ts b/packages/shared/src/vaporFlags.ts index 7939ec83ed1..c4ec7f3aab1 100644 --- a/packages/shared/src/vaporFlags.ts +++ b/packages/shared/src/vaporFlags.ts @@ -36,6 +36,35 @@ export enum VaporBlockShape { MULTI_ROOT = 2, } +/** + * Bit layout for vapor `createIf` flags. + * + * - bits 0-1: true branch VaporBlockShape + * - bits 2-3: false branch VaporBlockShape + * - bit 4: v-once + * - bits 5+: branch index + 1 for keyed dynamic fragments + * + * Examples: + * - v-once, true single-root, no false branch: 1 | ONCE = 17 + * - keyed index 0, true/false single-root: 1 | (1 << 2) | (1 << 5) = 37 + */ +export enum VaporIfFlags { + /** + * Documents the packed true/false branch shape bits. Runtime decode shifts + * to the selected branch first, then masks with 0b11 for one VaporBlockShape. + */ + BLOCK_SHAPE = 0b1111, + /** + * Marks a branch that is created once and never updated. + */ + ONCE = 1 << 4, + /** + * Shift for keyed branch index. The encoded value is index + 1, so decoded + * zero means "not keyed" and source index 0 still round-trips. + */ + INDEX_SHIFT = 5, +} + /** * Flags used by vapor template factories, shared between the compiler and the * runtime.