From 8fb01504da82b1251bfb88958b82c147b770fe91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Thu, 8 Feb 2024 19:54:36 +0800 Subject: [PATCH] refactor(compiler-vapor): remove ir expression --- .../transforms/transformInterpolation.spec.ts | 2 -- .../__tests__/transforms/transformRef.spec.ts | 4 +++ .../transforms/transformText.spec.ts | 4 +++ .../__tests__/transforms/vModel.spec.ts | 4 +++ .../src/generators/expression.ts | 7 ++--- .../src/generators/modelValue.ts | 6 ++-- packages/compiler-vapor/src/ir.ts | 17 +++++----- packages/compiler-vapor/src/transform.ts | 31 ++++++++----------- .../src/transforms/transformElement.ts | 17 +++++----- .../src/transforms/transformRef.ts | 20 +++++++----- .../compiler-vapor/src/transforms/vHtml.ts | 7 +++-- .../compiler-vapor/src/transforms/vModel.ts | 3 +- .../compiler-vapor/src/transforms/vText.ts | 13 +++----- 13 files changed, 70 insertions(+), 65 deletions(-) delete mode 100644 packages/compiler-vapor/__tests__/transforms/transformInterpolation.spec.ts create mode 100644 packages/compiler-vapor/__tests__/transforms/transformRef.spec.ts create mode 100644 packages/compiler-vapor/__tests__/transforms/transformText.spec.ts create mode 100644 packages/compiler-vapor/__tests__/transforms/vModel.spec.ts diff --git a/packages/compiler-vapor/__tests__/transforms/transformInterpolation.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformInterpolation.spec.ts deleted file mode 100644 index 42c304f46..000000000 --- a/packages/compiler-vapor/__tests__/transforms/transformInterpolation.spec.ts +++ /dev/null @@ -1,2 +0,0 @@ -// TODO: add tests for this transform -test('baisc', () => {}) diff --git a/packages/compiler-vapor/__tests__/transforms/transformRef.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformRef.spec.ts new file mode 100644 index 000000000..a5221255e --- /dev/null +++ b/packages/compiler-vapor/__tests__/transforms/transformRef.spec.ts @@ -0,0 +1,4 @@ +// TODO: add tests for this transform +describe('compiler: template ref transform', () => { + test.todo('basic') +}) diff --git a/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts new file mode 100644 index 000000000..7f9965930 --- /dev/null +++ b/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts @@ -0,0 +1,4 @@ +// TODO: add tests for this transform +describe('compiler: text transform', () => { + test.todo('basic') +}) diff --git a/packages/compiler-vapor/__tests__/transforms/vModel.spec.ts b/packages/compiler-vapor/__tests__/transforms/vModel.spec.ts new file mode 100644 index 000000000..52fe1a038 --- /dev/null +++ b/packages/compiler-vapor/__tests__/transforms/vModel.spec.ts @@ -0,0 +1,4 @@ +// TODO: add tests for this transform +describe('compiler: vModel transform', () => { + test.todo('basic') +}) diff --git a/packages/compiler-vapor/src/generators/expression.ts b/packages/compiler-vapor/src/generators/expression.ts index e1675a274..a9b97e35f 100644 --- a/packages/compiler-vapor/src/generators/expression.ts +++ b/packages/compiler-vapor/src/generators/expression.ts @@ -1,15 +1,15 @@ import { BindingTypes, NewlineType, + type SimpleExpressionNode, type SourceLocation, advancePositionWithClone, isInDestructureAssignment, isStaticProperty, walkIdentifiers, } from '@vue/compiler-dom' -import { isGloballyAllowed, isString, makeMap } from '@vue/shared' +import { isGloballyAllowed, makeMap } from '@vue/shared' import type { Identifier } from '@babel/types' -import type { IRExpression } from '../ir' import { type CodeFragment, type CodegenContext, @@ -18,13 +18,12 @@ import { import type { Node } from '@babel/types' export function genExpression( - node: IRExpression, + node: SimpleExpressionNode, context: CodegenContext, ): CodeFragment[] { const { options: { prefixIdentifiers }, } = context - if (isString(node)) return [node] const { content: rawExpr, ast, isStatic, loc } = node if (isStatic) { diff --git a/packages/compiler-vapor/src/generators/modelValue.ts b/packages/compiler-vapor/src/generators/modelValue.ts index 7912195f4..99c242853 100644 --- a/packages/compiler-vapor/src/generators/modelValue.ts +++ b/packages/compiler-vapor/src/generators/modelValue.ts @@ -1,4 +1,4 @@ -import { camelize, isString } from '@vue/shared' +import { camelize } from '@vue/shared' import { genExpression } from './expression' import type { SetModelValueIRNode } from '../ir' import { type CodeFragment, type CodegenContext, NEWLINE } from '../generate' @@ -13,8 +13,8 @@ export function genSetModelValue( options: { isTS }, } = context - const name = isString(oper.key) - ? [JSON.stringify(`update:${camelize(oper.key)}`)] + const name = oper.key.isStatic + ? [JSON.stringify(`update:${camelize(oper.key.content)}`)] : ['`update:${', ...genExpression(oper.key, context), '}`'] const handler = [ (isTS ? `($event: any)` : `$event`) + ' => ((', diff --git a/packages/compiler-vapor/src/ir.ts b/packages/compiler-vapor/src/ir.ts index a4838f18a..d020613d8 100644 --- a/packages/compiler-vapor/src/ir.ts +++ b/packages/compiler-vapor/src/ir.ts @@ -64,7 +64,7 @@ export interface RootIRNode extends Omit { export interface IfIRNode extends BaseIRNode { type: IRNodeTypes.IF id: number - condition: IRExpression + condition: SimpleExpressionNode positive: BlockFunctionIRNode negative?: BlockFunctionIRNode | IfIRNode } @@ -72,7 +72,7 @@ export interface IfIRNode extends BaseIRNode { export interface ForIRNode extends BaseIRNode { type: IRNodeTypes.FOR id: number - source: IRExpression + source: SimpleExpressionNode value?: SimpleExpressionNode key?: SimpleExpressionNode index?: SimpleExpressionNode @@ -111,7 +111,7 @@ export type KeyOverride = [find: string, replacement: string] export interface SetEventIRNode extends BaseIRNode { type: IRNodeTypes.SET_EVENT element: number - key: IRExpression + key: SimpleExpressionNode value?: SimpleExpressionNode modifiers: { // modifiers for addEventListener() options, e.g. .passive & .capture @@ -127,20 +127,20 @@ export interface SetEventIRNode extends BaseIRNode { export interface SetHtmlIRNode extends BaseIRNode { type: IRNodeTypes.SET_HTML element: number - value: IRExpression + value: SimpleExpressionNode } export interface SetRefIRNode extends BaseIRNode { type: IRNodeTypes.SET_REF element: number - value: IRExpression + value: SimpleExpressionNode } export interface SetModelValueIRNode extends BaseIRNode { type: IRNodeTypes.SET_MODEL_VALUE element: number - key: IRExpression - value: IRExpression + key: SimpleExpressionNode + value: SimpleExpressionNode bindingType?: BindingTypes isComponent: boolean } @@ -218,9 +218,8 @@ export interface IRDynamicInfo { children: IRDynamicInfo[] } -export type IRExpression = SimpleExpressionNode | string export interface IREffect { - expressions: IRExpression[] + expressions: SimpleExpressionNode[] operations: OperationNode[] } diff --git a/packages/compiler-vapor/src/transform.ts b/packages/compiler-vapor/src/transform.ts index f5995378d..4aa7fd771 100644 --- a/packages/compiler-vapor/src/transform.ts +++ b/packages/compiler-vapor/src/transform.ts @@ -11,6 +11,7 @@ import { type SimpleExpressionNode, type TemplateChildNode, type TemplateNode, + createSimpleExpression, defaultOnError, defaultOnWarn, isVSlot, @@ -21,7 +22,6 @@ import { DynamicFlag, type HackOptions, type IRDynamicInfo, - type IRExpression, IRNodeTypes, type OperationNode, type RootIRNode, @@ -77,7 +77,7 @@ export interface TransformContext { increaseId(): number registerTemplate(): number registerEffect( - expressions: Array, + expressions: SimpleExpressionNode[], operation: OperationNode[], ): void registerOperation(...operations: OperationNode[]): void @@ -153,35 +153,28 @@ function createRootContext( return (this.dynamic.id = this.increaseId()) }, registerEffect(expressions, operations) { - if ( - this.inVOnce || - (expressions = expressions.filter(Boolean)).length === 0 - ) { + expressions = expressions.filter(exp => !exp.isStatic) + if (this.inVOnce || expressions.length === 0) { return this.registerOperation(...operations) } const existing = this.block.effect.find(e => - isSameExpression(e.expressions, expressions as IRExpression[]), + isSameExpression(e.expressions, expressions), ) if (existing) { existing.operations.push(...operations) } else { this.block.effect.push({ - expressions: expressions as IRExpression[], + expressions, operations, }) } - function isSameExpression(a: IRExpression[], b: IRExpression[]) { - a = a.filter(filterStatic) - b = b.filter(filterStatic) + function isSameExpression( + a: SimpleExpressionNode[], + b: SimpleExpressionNode[], + ) { if (a.length !== b.length) return false - return (a as SimpleExpressionNode[]).every( - (exp, i) => exp.content === (b as SimpleExpressionNode[])[i].content, - ) - } - - function filterStatic(exp: IRExpression): exp is SimpleExpressionNode { - return !isString(exp) && !exp.isStatic + return a.every((exp, i) => exp.content === b[i].content) } }, @@ -434,3 +427,5 @@ export function wrapTemplate(node: ElementNode, dirs: string[]): TemplateNode { children: [extend({}, node, { props: pass } as TemplateChildNode)], } as Partial) } + +export const EMPTY_EXPRESSION = createSimpleExpression('', true) diff --git a/packages/compiler-vapor/src/transforms/transformElement.ts b/packages/compiler-vapor/src/transforms/transformElement.ts index 98e589e39..044e21aca 100644 --- a/packages/compiler-vapor/src/transforms/transformElement.ts +++ b/packages/compiler-vapor/src/transforms/transformElement.ts @@ -14,10 +14,11 @@ import { isReservedProp, isVoidTag, } from '@vue/shared' -import type { - DirectiveTransformResult, - NodeTransform, - TransformContext, +import { + type DirectiveTransformResult, + EMPTY_EXPRESSION, + type NodeTransform, + type TransformContext, } from '../transform' import { IRNodeTypes, @@ -154,11 +155,9 @@ function transformProp( if (prop.type === NodeTypes.ATTRIBUTE) { return { key: createSimpleExpression(prop.name, true, prop.nameLoc), - value: createSimpleExpression( - prop.value ? prop.value.content : '', - true, - prop.value && prop.value.loc, - ), + value: prop.value + ? createSimpleExpression(prop.value.content, true, prop.value.loc) + : EMPTY_EXPRESSION, } } diff --git a/packages/compiler-vapor/src/transforms/transformRef.ts b/packages/compiler-vapor/src/transforms/transformRef.ts index 980c9fbfd..f27a7b683 100644 --- a/packages/compiler-vapor/src/transforms/transformRef.ts +++ b/packages/compiler-vapor/src/transforms/transformRef.ts @@ -1,25 +1,29 @@ import { + type AttributeNode, NodeTypes, type SimpleExpressionNode, + createSimpleExpression, findProp, } from '@vue/compiler-dom' -import type { NodeTransform } from '../transform' -import { type IRExpression, IRNodeTypes } from '../ir' +import { EMPTY_EXPRESSION, type NodeTransform } from '../transform' +import { IRNodeTypes, type VaporDirectiveNode } from '../ir' import { normalizeBindShorthand } from './vBind' export const transformRef: NodeTransform = (node, context) => { if (node.type !== NodeTypes.ELEMENT) return - const dir = findProp(node, 'ref', false, true) + const dir = findProp(node, 'ref', false, true) as + | VaporDirectiveNode + | AttributeNode if (!dir) return - let value: IRExpression + let value: SimpleExpressionNode if (dir.type === NodeTypes.DIRECTIVE) { - value = - (dir.exp as SimpleExpressionNode | undefined) || - normalizeBindShorthand(dir.arg as SimpleExpressionNode, context) + value = dir.exp || normalizeBindShorthand(dir.arg!, context) } else { - value = dir.value ? JSON.stringify(dir.value.content) : '""' + value = dir.value + ? createSimpleExpression(dir.value.content, true, dir.value.loc) + : EMPTY_EXPRESSION } context.registerOperation({ diff --git a/packages/compiler-vapor/src/transforms/vHtml.ts b/packages/compiler-vapor/src/transforms/vHtml.ts index 8b851b498..eef9bf2a0 100644 --- a/packages/compiler-vapor/src/transforms/vHtml.ts +++ b/packages/compiler-vapor/src/transforms/vHtml.ts @@ -1,13 +1,14 @@ import { IRNodeTypes } from '../ir' -import type { DirectiveTransform } from '../transform' +import { type DirectiveTransform, EMPTY_EXPRESSION } from '../transform' import { DOMErrorCodes, createDOMCompilerError } from '@vue/compiler-dom' export const transformVHtml: DirectiveTransform = (dir, node, context) => { - const { exp, loc } = dir + let { exp, loc } = dir if (!exp) { context.options.onError( createDOMCompilerError(DOMErrorCodes.X_V_HTML_NO_EXPRESSION, loc), ) + exp = EMPTY_EXPRESSION } if (node.children.length) { context.options.onError( @@ -22,7 +23,7 @@ export const transformVHtml: DirectiveTransform = (dir, node, context) => { { type: IRNodeTypes.SET_HTML, element: context.reference(), - value: exp || '""', + value: exp, }, ], ) diff --git a/packages/compiler-vapor/src/transforms/vModel.ts b/packages/compiler-vapor/src/transforms/vModel.ts index 29bccaa32..edc7137e8 100644 --- a/packages/compiler-vapor/src/transforms/vModel.ts +++ b/packages/compiler-vapor/src/transforms/vModel.ts @@ -6,6 +6,7 @@ import { NodeTypes, createCompilerError, createDOMCompilerError, + createSimpleExpression, findDir, findProp, hasDynamicKeyVBind, @@ -137,7 +138,7 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => { context.registerOperation({ type: IRNodeTypes.SET_MODEL_VALUE, element: context.reference(), - key: (arg && arg.isStatic ? arg.content : arg) || 'modelValue', + key: arg || createSimpleExpression('modelValue', true), value: exp, isComponent, }) diff --git a/packages/compiler-vapor/src/transforms/vText.ts b/packages/compiler-vapor/src/transforms/vText.ts index 11db973e1..295632ae3 100644 --- a/packages/compiler-vapor/src/transforms/vText.ts +++ b/packages/compiler-vapor/src/transforms/vText.ts @@ -1,17 +1,14 @@ -import { - DOMErrorCodes, - createDOMCompilerError, - createSimpleExpression, -} from '@vue/compiler-dom' -import type { DirectiveTransform } from '../transform' +import { DOMErrorCodes, createDOMCompilerError } from '@vue/compiler-dom' +import { type DirectiveTransform, EMPTY_EXPRESSION } from '../transform' import { IRNodeTypes } from '../ir' export const transformVText: DirectiveTransform = (dir, node, context) => { - const { exp, loc } = dir + let { exp, loc } = dir if (!exp) { context.options.onError( createDOMCompilerError(DOMErrorCodes.X_V_TEXT_NO_EXPRESSION, loc), ) + exp = EMPTY_EXPRESSION } if (node.children.length) { context.options.onError( @@ -26,7 +23,7 @@ export const transformVText: DirectiveTransform = (dir, node, context) => { { type: IRNodeTypes.SET_TEXT, element: context.reference(), - values: [exp || createSimpleExpression('', true)], + values: [exp], }, ], )