refactor(compiler-vapor): remove ir expression

This commit is contained in:
三咲智子 Kevin Deng 2024-02-08 19:54:36 +08:00
parent 55a956e87d
commit 8fb01504da
No known key found for this signature in database
GPG Key ID: 69992F2250DFD93E
13 changed files with 70 additions and 65 deletions

View File

@ -1,2 +0,0 @@
// TODO: add tests for this transform
test('baisc', () => {})

View File

@ -0,0 +1,4 @@
// TODO: add tests for this transform
describe('compiler: template ref transform', () => {
test.todo('basic')
})

View File

@ -0,0 +1,4 @@
// TODO: add tests for this transform
describe('compiler: text transform', () => {
test.todo('basic')
})

View File

@ -0,0 +1,4 @@
// TODO: add tests for this transform
describe('compiler: vModel transform', () => {
test.todo('basic')
})

View File

@ -1,15 +1,15 @@
import { import {
BindingTypes, BindingTypes,
NewlineType, NewlineType,
type SimpleExpressionNode,
type SourceLocation, type SourceLocation,
advancePositionWithClone, advancePositionWithClone,
isInDestructureAssignment, isInDestructureAssignment,
isStaticProperty, isStaticProperty,
walkIdentifiers, walkIdentifiers,
} from '@vue/compiler-dom' } 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 { Identifier } from '@babel/types'
import type { IRExpression } from '../ir'
import { import {
type CodeFragment, type CodeFragment,
type CodegenContext, type CodegenContext,
@ -18,13 +18,12 @@ import {
import type { Node } from '@babel/types' import type { Node } from '@babel/types'
export function genExpression( export function genExpression(
node: IRExpression, node: SimpleExpressionNode,
context: CodegenContext, context: CodegenContext,
): CodeFragment[] { ): CodeFragment[] {
const { const {
options: { prefixIdentifiers }, options: { prefixIdentifiers },
} = context } = context
if (isString(node)) return [node]
const { content: rawExpr, ast, isStatic, loc } = node const { content: rawExpr, ast, isStatic, loc } = node
if (isStatic) { if (isStatic) {

View File

@ -1,4 +1,4 @@
import { camelize, isString } from '@vue/shared' import { camelize } from '@vue/shared'
import { genExpression } from './expression' import { genExpression } from './expression'
import type { SetModelValueIRNode } from '../ir' import type { SetModelValueIRNode } from '../ir'
import { type CodeFragment, type CodegenContext, NEWLINE } from '../generate' import { type CodeFragment, type CodegenContext, NEWLINE } from '../generate'
@ -13,8 +13,8 @@ export function genSetModelValue(
options: { isTS }, options: { isTS },
} = context } = context
const name = isString(oper.key) const name = oper.key.isStatic
? [JSON.stringify(`update:${camelize(oper.key)}`)] ? [JSON.stringify(`update:${camelize(oper.key.content)}`)]
: ['`update:${', ...genExpression(oper.key, context), '}`'] : ['`update:${', ...genExpression(oper.key, context), '}`']
const handler = [ const handler = [
(isTS ? `($event: any)` : `$event`) + ' => ((', (isTS ? `($event: any)` : `$event`) + ' => ((',

View File

@ -64,7 +64,7 @@ export interface RootIRNode extends Omit<BlockFunctionIRNode, 'type'> {
export interface IfIRNode extends BaseIRNode { export interface IfIRNode extends BaseIRNode {
type: IRNodeTypes.IF type: IRNodeTypes.IF
id: number id: number
condition: IRExpression condition: SimpleExpressionNode
positive: BlockFunctionIRNode positive: BlockFunctionIRNode
negative?: BlockFunctionIRNode | IfIRNode negative?: BlockFunctionIRNode | IfIRNode
} }
@ -72,7 +72,7 @@ export interface IfIRNode extends BaseIRNode {
export interface ForIRNode extends BaseIRNode { export interface ForIRNode extends BaseIRNode {
type: IRNodeTypes.FOR type: IRNodeTypes.FOR
id: number id: number
source: IRExpression source: SimpleExpressionNode
value?: SimpleExpressionNode value?: SimpleExpressionNode
key?: SimpleExpressionNode key?: SimpleExpressionNode
index?: SimpleExpressionNode index?: SimpleExpressionNode
@ -111,7 +111,7 @@ export type KeyOverride = [find: string, replacement: string]
export interface SetEventIRNode extends BaseIRNode { export interface SetEventIRNode extends BaseIRNode {
type: IRNodeTypes.SET_EVENT type: IRNodeTypes.SET_EVENT
element: number element: number
key: IRExpression key: SimpleExpressionNode
value?: SimpleExpressionNode value?: SimpleExpressionNode
modifiers: { modifiers: {
// modifiers for addEventListener() options, e.g. .passive & .capture // modifiers for addEventListener() options, e.g. .passive & .capture
@ -127,20 +127,20 @@ export interface SetEventIRNode extends BaseIRNode {
export interface SetHtmlIRNode extends BaseIRNode { export interface SetHtmlIRNode extends BaseIRNode {
type: IRNodeTypes.SET_HTML type: IRNodeTypes.SET_HTML
element: number element: number
value: IRExpression value: SimpleExpressionNode
} }
export interface SetRefIRNode extends BaseIRNode { export interface SetRefIRNode extends BaseIRNode {
type: IRNodeTypes.SET_REF type: IRNodeTypes.SET_REF
element: number element: number
value: IRExpression value: SimpleExpressionNode
} }
export interface SetModelValueIRNode extends BaseIRNode { export interface SetModelValueIRNode extends BaseIRNode {
type: IRNodeTypes.SET_MODEL_VALUE type: IRNodeTypes.SET_MODEL_VALUE
element: number element: number
key: IRExpression key: SimpleExpressionNode
value: IRExpression value: SimpleExpressionNode
bindingType?: BindingTypes bindingType?: BindingTypes
isComponent: boolean isComponent: boolean
} }
@ -218,9 +218,8 @@ export interface IRDynamicInfo {
children: IRDynamicInfo[] children: IRDynamicInfo[]
} }
export type IRExpression = SimpleExpressionNode | string
export interface IREffect { export interface IREffect {
expressions: IRExpression[] expressions: SimpleExpressionNode[]
operations: OperationNode[] operations: OperationNode[]
} }

View File

@ -11,6 +11,7 @@ import {
type SimpleExpressionNode, type SimpleExpressionNode,
type TemplateChildNode, type TemplateChildNode,
type TemplateNode, type TemplateNode,
createSimpleExpression,
defaultOnError, defaultOnError,
defaultOnWarn, defaultOnWarn,
isVSlot, isVSlot,
@ -21,7 +22,6 @@ import {
DynamicFlag, DynamicFlag,
type HackOptions, type HackOptions,
type IRDynamicInfo, type IRDynamicInfo,
type IRExpression,
IRNodeTypes, IRNodeTypes,
type OperationNode, type OperationNode,
type RootIRNode, type RootIRNode,
@ -77,7 +77,7 @@ export interface TransformContext<T extends AllNode = AllNode> {
increaseId(): number increaseId(): number
registerTemplate(): number registerTemplate(): number
registerEffect( registerEffect(
expressions: Array<IRExpression | null | undefined>, expressions: SimpleExpressionNode[],
operation: OperationNode[], operation: OperationNode[],
): void ): void
registerOperation(...operations: OperationNode[]): void registerOperation(...operations: OperationNode[]): void
@ -153,35 +153,28 @@ function createRootContext(
return (this.dynamic.id = this.increaseId()) return (this.dynamic.id = this.increaseId())
}, },
registerEffect(expressions, operations) { registerEffect(expressions, operations) {
if ( expressions = expressions.filter(exp => !exp.isStatic)
this.inVOnce || if (this.inVOnce || expressions.length === 0) {
(expressions = expressions.filter(Boolean)).length === 0
) {
return this.registerOperation(...operations) return this.registerOperation(...operations)
} }
const existing = this.block.effect.find(e => const existing = this.block.effect.find(e =>
isSameExpression(e.expressions, expressions as IRExpression[]), isSameExpression(e.expressions, expressions),
) )
if (existing) { if (existing) {
existing.operations.push(...operations) existing.operations.push(...operations)
} else { } else {
this.block.effect.push({ this.block.effect.push({
expressions: expressions as IRExpression[], expressions,
operations, operations,
}) })
} }
function isSameExpression(a: IRExpression[], b: IRExpression[]) { function isSameExpression(
a = a.filter(filterStatic) a: SimpleExpressionNode[],
b = b.filter(filterStatic) b: SimpleExpressionNode[],
) {
if (a.length !== b.length) return false if (a.length !== b.length) return false
return (a as SimpleExpressionNode[]).every( return a.every((exp, i) => exp.content === b[i].content)
(exp, i) => exp.content === (b as SimpleExpressionNode[])[i].content,
)
}
function filterStatic(exp: IRExpression): exp is SimpleExpressionNode {
return !isString(exp) && !exp.isStatic
} }
}, },
@ -434,3 +427,5 @@ export function wrapTemplate(node: ElementNode, dirs: string[]): TemplateNode {
children: [extend({}, node, { props: pass } as TemplateChildNode)], children: [extend({}, node, { props: pass } as TemplateChildNode)],
} as Partial<TemplateNode>) } as Partial<TemplateNode>)
} }
export const EMPTY_EXPRESSION = createSimpleExpression('', true)

View File

@ -14,10 +14,11 @@ import {
isReservedProp, isReservedProp,
isVoidTag, isVoidTag,
} from '@vue/shared' } from '@vue/shared'
import type { import {
DirectiveTransformResult, type DirectiveTransformResult,
NodeTransform, EMPTY_EXPRESSION,
TransformContext, type NodeTransform,
type TransformContext,
} from '../transform' } from '../transform'
import { import {
IRNodeTypes, IRNodeTypes,
@ -154,11 +155,9 @@ function transformProp(
if (prop.type === NodeTypes.ATTRIBUTE) { if (prop.type === NodeTypes.ATTRIBUTE) {
return { return {
key: createSimpleExpression(prop.name, true, prop.nameLoc), key: createSimpleExpression(prop.name, true, prop.nameLoc),
value: createSimpleExpression( value: prop.value
prop.value ? prop.value.content : '', ? createSimpleExpression(prop.value.content, true, prop.value.loc)
true, : EMPTY_EXPRESSION,
prop.value && prop.value.loc,
),
} }
} }

View File

@ -1,25 +1,29 @@
import { import {
type AttributeNode,
NodeTypes, NodeTypes,
type SimpleExpressionNode, type SimpleExpressionNode,
createSimpleExpression,
findProp, findProp,
} from '@vue/compiler-dom' } from '@vue/compiler-dom'
import type { NodeTransform } from '../transform' import { EMPTY_EXPRESSION, type NodeTransform } from '../transform'
import { type IRExpression, IRNodeTypes } from '../ir' import { IRNodeTypes, type VaporDirectiveNode } from '../ir'
import { normalizeBindShorthand } from './vBind' import { normalizeBindShorthand } from './vBind'
export const transformRef: NodeTransform = (node, context) => { export const transformRef: NodeTransform = (node, context) => {
if (node.type !== NodeTypes.ELEMENT) return 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 if (!dir) return
let value: IRExpression let value: SimpleExpressionNode
if (dir.type === NodeTypes.DIRECTIVE) { if (dir.type === NodeTypes.DIRECTIVE) {
value = value = dir.exp || normalizeBindShorthand(dir.arg!, context)
(dir.exp as SimpleExpressionNode | undefined) ||
normalizeBindShorthand(dir.arg as SimpleExpressionNode, context)
} else { } else {
value = dir.value ? JSON.stringify(dir.value.content) : '""' value = dir.value
? createSimpleExpression(dir.value.content, true, dir.value.loc)
: EMPTY_EXPRESSION
} }
context.registerOperation({ context.registerOperation({

View File

@ -1,13 +1,14 @@
import { IRNodeTypes } from '../ir' import { IRNodeTypes } from '../ir'
import type { DirectiveTransform } from '../transform' import { type DirectiveTransform, EMPTY_EXPRESSION } from '../transform'
import { DOMErrorCodes, createDOMCompilerError } from '@vue/compiler-dom' import { DOMErrorCodes, createDOMCompilerError } from '@vue/compiler-dom'
export const transformVHtml: DirectiveTransform = (dir, node, context) => { export const transformVHtml: DirectiveTransform = (dir, node, context) => {
const { exp, loc } = dir let { exp, loc } = dir
if (!exp) { if (!exp) {
context.options.onError( context.options.onError(
createDOMCompilerError(DOMErrorCodes.X_V_HTML_NO_EXPRESSION, loc), createDOMCompilerError(DOMErrorCodes.X_V_HTML_NO_EXPRESSION, loc),
) )
exp = EMPTY_EXPRESSION
} }
if (node.children.length) { if (node.children.length) {
context.options.onError( context.options.onError(
@ -22,7 +23,7 @@ export const transformVHtml: DirectiveTransform = (dir, node, context) => {
{ {
type: IRNodeTypes.SET_HTML, type: IRNodeTypes.SET_HTML,
element: context.reference(), element: context.reference(),
value: exp || '""', value: exp,
}, },
], ],
) )

View File

@ -6,6 +6,7 @@ import {
NodeTypes, NodeTypes,
createCompilerError, createCompilerError,
createDOMCompilerError, createDOMCompilerError,
createSimpleExpression,
findDir, findDir,
findProp, findProp,
hasDynamicKeyVBind, hasDynamicKeyVBind,
@ -137,7 +138,7 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
context.registerOperation({ context.registerOperation({
type: IRNodeTypes.SET_MODEL_VALUE, type: IRNodeTypes.SET_MODEL_VALUE,
element: context.reference(), element: context.reference(),
key: (arg && arg.isStatic ? arg.content : arg) || 'modelValue', key: arg || createSimpleExpression('modelValue', true),
value: exp, value: exp,
isComponent, isComponent,
}) })

View File

@ -1,17 +1,14 @@
import { import { DOMErrorCodes, createDOMCompilerError } from '@vue/compiler-dom'
DOMErrorCodes, import { type DirectiveTransform, EMPTY_EXPRESSION } from '../transform'
createDOMCompilerError,
createSimpleExpression,
} from '@vue/compiler-dom'
import type { DirectiveTransform } from '../transform'
import { IRNodeTypes } from '../ir' import { IRNodeTypes } from '../ir'
export const transformVText: DirectiveTransform = (dir, node, context) => { export const transformVText: DirectiveTransform = (dir, node, context) => {
const { exp, loc } = dir let { exp, loc } = dir
if (!exp) { if (!exp) {
context.options.onError( context.options.onError(
createDOMCompilerError(DOMErrorCodes.X_V_TEXT_NO_EXPRESSION, loc), createDOMCompilerError(DOMErrorCodes.X_V_TEXT_NO_EXPRESSION, loc),
) )
exp = EMPTY_EXPRESSION
} }
if (node.children.length) { if (node.children.length) {
context.options.onError( context.options.onError(
@ -26,7 +23,7 @@ export const transformVText: DirectiveTransform = (dir, node, context) => {
{ {
type: IRNodeTypes.SET_TEXT, type: IRNodeTypes.SET_TEXT,
element: context.reference(), element: context.reference(),
values: [exp || createSimpleExpression('', true)], values: [exp],
}, },
], ],
) )