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 {
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) {

View File

@ -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`) + ' => ((',

View File

@ -64,7 +64,7 @@ export interface RootIRNode extends Omit<BlockFunctionIRNode, 'type'> {
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[]
}

View File

@ -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<T extends AllNode = AllNode> {
increaseId(): number
registerTemplate(): number
registerEffect(
expressions: Array<IRExpression | null | undefined>,
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<TemplateNode>)
}
export const EMPTY_EXPRESSION = createSimpleExpression('', true)

View File

@ -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,
}
}

View File

@ -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({

View File

@ -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,
},
],
)

View File

@ -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,
})

View File

@ -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],
},
],
)