From: 三咲智子 Kevin Deng Date: Mon, 29 Jan 2024 14:08:57 +0000 (+0800) Subject: refactor(compiler-vapor): dynamicFlag X-Git-Tag: v3.6.0-alpha.1~16^2~641 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=79636ddc5b16ce29b78f53cb8ebcabbedffc006a;p=thirdparty%2Fvuejs%2Fcore.git refactor(compiler-vapor): dynamicFlag --- 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 a251ec008d..bc726ca126 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 9629a9274e..da02641c9d 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 7d6cd38a1d..7f43dc1266 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', () => {

+ `) 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 6e1b75beca..1f2b04624a 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 7c0872a1bd..40b79cf6e7 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 b8b3adf254..073b4ad6a7 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( template: '', childrenTemplate: [], - dynamic: { - id: null, - referenced: false, - ghost: false, - placeholder: null, - children: {}, - }, - }) + dynamic: genDefaultDynamic(), + } satisfies Partial>) return ctx } @@ -243,13 +243,9 @@ export function transform( loc: root.loc, template: [], templateIndex: -1, - dynamic: { - id: null, - referenced: true, - ghost: true, - placeholder: null, - children: {}, - }, + dynamic: extend(genDefaultDynamic(), { + dynamicFlags: DynamicFlag.REFERENCED | DynamicFlag.INSERT, + } satisfies Partial), effect: [], operation: [], } @@ -287,6 +283,7 @@ function transformNode( node = context.node } } + switch (node.type) { case NodeTypes.ROOT: case NodeTypes.ELEMENT: { @@ -322,14 +319,7 @@ function transformChildren(ctx: TransformContext) { const childContext = createContext(child, ctx, i) transformNode(childContext) ctx.childrenTemplate.push(childContext.template) - if ( - childContext.dynamic.ghost || - childContext.dynamic.referenced || - childContext.dynamic.placeholder || - Object.keys(childContext.dynamic.children).length - ) { - ctx.dynamic.children[i] = childContext.dynamic - } + ctx.dynamic.children[i] = childContext.dynamic } processDynamicChildren(ctx) @@ -344,7 +334,7 @@ function processDynamicChildren(ctx: TransformContext) { for (let index = 0; index < node.children.length; index++) { const child = ctx.dynamic.children[index] - if (!child || !child.ghost) { + if (!child || !(child.dynamicFlags & DynamicFlag.INSERT)) { if (prevChildren.length) { if (hasStatic) { ctx.childrenTemplate[index - prevChildren.length] = `` diff --git a/packages/compiler-vapor/src/transforms/transformInterpolation.ts b/packages/compiler-vapor/src/transforms/transformInterpolation.ts index ac1a714208..27f6a2b74b 100644 --- a/packages/compiler-vapor/src/transforms/transformInterpolation.ts +++ b/packages/compiler-vapor/src/transforms/transformInterpolation.ts @@ -1,6 +1,6 @@ import { NodeTypes, type SimpleExpressionNode } from '@vue/compiler-dom' import type { NodeTransform } from '../transform' -import { IRNodeTypes } from '../ir' +import { DynamicFlag, IRNodeTypes } from '../ir' export const transformInterpolation: NodeTransform = (node, ctx) => { if (node.type !== NodeTypes.INTERPOLATION) return @@ -27,7 +27,7 @@ export const transformInterpolation: NodeTransform = (node, ctx) => { ) } else { const id = ctx.reference() - ctx.dynamic.ghost = true + ctx.dynamic.dynamicFlags |= DynamicFlag.INSERT ctx.registerOperation({ type: IRNodeTypes.CREATE_TEXT_NODE, loc: node.loc, diff --git a/packages/compiler-vapor/src/transforms/vIf.ts b/packages/compiler-vapor/src/transforms/vIf.ts index 25e1c4de8b..70e4523154 100644 --- a/packages/compiler-vapor/src/transforms/vIf.ts +++ b/packages/compiler-vapor/src/transforms/vIf.ts @@ -12,9 +12,12 @@ import { import { type TransformContext, createStructuralDirectiveTransform, + genDefaultDynamic, } from '../transform' import { type BlockFunctionIRNode, + DynamicFlag, + type IRDynamicInfo, IRNodeTypes, type OperationNode, type VaporDirectiveNode, @@ -41,7 +44,7 @@ export function processIf( if (dir.name === 'if') { const id = context.reference() - context.dynamic.ghost = true + context.dynamic.dynamicFlags |= DynamicFlag.INSERT const [branch, onExit] = createIfBranch(node, context) return () => { @@ -55,10 +58,13 @@ export function processIf( }) } } else { + context.dynamic.dynamicFlags |= DynamicFlag.NON_TEMPLATE + // check the adjacent v-if const parent = context.parent! const siblings = parent.node.children const templates = parent.childrenTemplate + const siblingsDynamic = parent.dynamic.children const comments = [] let sibling: TemplateChildNode | undefined @@ -66,20 +72,18 @@ export function processIf( while (i-- >= -1) { sibling = siblings[i] - if (sibling) { - if (sibling.type === NodeTypes.COMMENT) { - __DEV__ && comments.unshift(sibling) - templates[i] = null - continue - } else if ( - sibling.type === NodeTypes.TEXT && - !sibling.content.trim().length - ) { - templates[i] = null - continue - } + if ( + sibling && + (sibling.type === NodeTypes.COMMENT || + (sibling.type === NodeTypes.TEXT && !sibling.content.trim().length)) + ) { + if (__DEV__ && sibling.type === NodeTypes.COMMENT) + comments.unshift(sibling) + siblingsDynamic[i].dynamicFlags |= DynamicFlag.NON_TEMPLATE + templates[i] = null + } else { + break } - break } const { operation } = context.block @@ -150,13 +154,9 @@ export function createIfBranch( loc: node.loc, node, templateIndex: -1, - dynamic: { - id: null, - referenced: true, - ghost: true, - placeholder: null, - children: {}, - }, + dynamic: extend(genDefaultDynamic(), { + dynamicFlags: DynamicFlag.REFERENCED | DynamicFlag.INSERT, + } satisfies Partial), effect: [], operation: [], } @@ -164,7 +164,7 @@ export function createIfBranch( const exitBlock = context.enterBlock(branch) context.reference() const onExit = () => { - context.template += context.childrenTemplate.join('') + context.template += context.childrenTemplate.filter(Boolean).join('') context.registerTemplate() exitBlock() }