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 a251ec008..bc726ca12 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vIf.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vIf.spec.ts.snap @@ -21,14 +21,15 @@ export function render(_ctx) { `; exports[`compiler: v-if > comment between branches 1`] = ` -"import { template as _template, fragment as _fragment, createIf as _createIf, prepend as _prepend } from 'vue/vapor'; +"import { template as _template, children as _children, createIf as _createIf, prepend as _prepend, renderEffect as _renderEffect, setText as _setText } from 'vue/vapor'; export function render(_ctx) { const t0 = _template("
") const t1 = _template("") const t2 = _template("fine") - const t3 = _fragment() + const t3 = _template("") const n0 = t3() + const { 0: [n5],} = _children(n0) const n1 = _createIf(() => (_ctx.ok), () => { const n2 = t0() return n2 @@ -40,6 +41,9 @@ export function render(_ctx) { return n4 })) _prepend(n0, n1) + _renderEffect(() => { + _setText(n5, _ctx.text) + }) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts b/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts index 9629a9274..da02641c9 100644 --- a/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts @@ -1,5 +1,10 @@ import { ErrorCodes, NodeTypes } from '@vue/compiler-dom' -import { IRNodeTypes, transformElement, transformVBind } from '../../src' +import { + DynamicFlag, + IRNodeTypes, + transformElement, + transformVBind, +} from '../../src' import { makeCompile } from './_utils' const compileWithVBind = makeCompile({ @@ -15,7 +20,7 @@ describe('compiler v-bind', () => { expect(ir.dynamic.children[0]).toMatchObject({ id: 1, - referenced: true, + dynamicFlags: DynamicFlag.REFERENCED, }) expect(ir.template[0]).toMatchObject({ type: IRNodeTypes.TEMPLATE_FACTORY, diff --git a/packages/compiler-vapor/__tests__/transforms/vIf.spec.ts b/packages/compiler-vapor/__tests__/transforms/vIf.spec.ts index 7d6cd38a1..7f43dc126 100644 --- a/packages/compiler-vapor/__tests__/transforms/vIf.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vIf.spec.ts @@ -276,6 +276,7 @@ describe('compiler: v-if', () => { fine + `) expect(code).matchSnapshot() expect(ir.template).lengthOf(4) @@ -292,7 +293,10 @@ describe('compiler: v-if', () => { template: 'fine', type: IRNodeTypes.TEMPLATE_FACTORY, }, - { type: IRNodeTypes.FRAGMENT_FACTORY }, + { + type: IRNodeTypes.TEMPLATE_FACTORY, + template: '', + }, ]) }) diff --git a/packages/compiler-vapor/src/generate.ts b/packages/compiler-vapor/src/generate.ts index 6e1b75bec..1f2b04624 100644 --- a/packages/compiler-vapor/src/generate.ts +++ b/packages/compiler-vapor/src/generate.ts @@ -9,6 +9,7 @@ import { } from '@vue/compiler-dom' import { type BlockFunctionIRNode, + DynamicFlag, type IRDynamicChildren, IRNodeTypes, type OperationNode, @@ -317,20 +318,27 @@ function genChildren(children: IRDynamicChildren) { let offset = 0 for (const [index, child] of Object.entries(children)) { const childrenLength = Object.keys(child.children).length - if (child.ghost && child.placeholder === null && childrenLength === 0) { + if ( + child.dynamicFlags & DynamicFlag.NON_TEMPLATE || + (child.dynamicFlags & DynamicFlag.INSERT && + child.placeholder === null && + childrenLength === 0) + ) { offset-- continue } - code += ` ${Number(index) + offset}: [` - - const id = child.ghost ? child.placeholder : child.id - if (id !== null) code += `n${id}` - + const idx = Number(index) + offset + const id = + child.dynamicFlags & DynamicFlag.INSERT ? child.placeholder : child.id const childrenString = childrenLength && genChildren(child.children) - if (childrenString) code += `, ${childrenString}` - code += '],' + if (id !== null || childrenString) { + code += ` ${idx}: [` + if (id !== null) code += `n${id}` + if (childrenString) code += `, ${childrenString}` + code += '],' + } } if (!code) return '' diff --git a/packages/compiler-vapor/src/ir.ts b/packages/compiler-vapor/src/ir.ts index 7c0872a1b..40b79cf6e 100644 --- a/packages/compiler-vapor/src/ir.ts +++ b/packages/compiler-vapor/src/ir.ts @@ -180,11 +180,25 @@ export type OperationNode = export type BlockIRNode = RootIRNode | BlockFunctionIRNode +export enum DynamicFlag { + NONE = 0, + /** + * This node is referenced and needs to be saved as a variable. + */ + REFERENCED = 1, + /** + * This node is not generated from template, but is generated dynamically. + */ + NON_TEMPLATE = 1 << 1, + /** + * This node needs to be inserted back into the template. + */ + INSERT = 1 << 2, +} + export interface IRDynamicInfo { id: number | null - referenced: boolean - /** created by DOM API */ - ghost: boolean + dynamicFlags: DynamicFlag placeholder: number | null children: IRDynamicChildren } diff --git a/packages/compiler-vapor/src/transform.ts b/packages/compiler-vapor/src/transform.ts index b8b3adf25..073b4ad6a 100644 --- a/packages/compiler-vapor/src/transform.ts +++ b/packages/compiler-vapor/src/transform.ts @@ -14,18 +14,17 @@ import { } from '@vue/compiler-dom' import { EMPTY_OBJ, NOOP, extend, isArray, isString } from '@vue/shared' import { + type BlockIRNode, + DynamicFlag, + type FragmentFactoryIRNode, + type HackOptions, type IRDynamicInfo, type IRExpression, IRNodeTypes, type OperationNode, type RootIRNode, -} from './ir' -import type { - BlockIRNode, - FragmentFactoryIRNode, - HackOptions, - TemplateFactoryIRNode, - VaporDirectiveNode, + type TemplateFactoryIRNode, + type VaporDirectiveNode, } from './ir' export type NodeTransform = ( @@ -100,6 +99,13 @@ const defaultOptions = { onWarn: defaultOnWarn, } +export const genDefaultDynamic = (): IRDynamicInfo => ({ + id: null, + dynamicFlags: 0, + placeholder: null, + children: {}, +}) + // TODO use class for better perf function createRootContext( root: RootIRNode, @@ -135,7 +141,7 @@ function createRootContext( increaseId: () => globalId++, reference() { if (this.dynamic.id !== null) return this.dynamic.id - this.dynamic.referenced = true + this.dynamic.dynamicFlags |= DynamicFlag.REFERENCED return (this.dynamic.id = this.increaseId()) }, registerEffect(expressions, operations) { @@ -220,14 +226,8 @@ function createContext