refactor(compiler-vapor): extract segments of `genMulti`

This commit is contained in:
三咲智子 Kevin Deng 2024-04-28 03:34:21 +09:00
parent 17d598f743
commit aa5d87b394
No known key found for this signature in database
15 changed files with 128 additions and 58 deletions

View File

@ -0,0 +1,51 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: template ref transform > dynamic ref 1`] = `
"import { setRef as _setRef, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setRef(n0, _ctx.foo)
return n0
}"
`;
exports[`compiler: template ref transform > ref + v-for 1`] = `
"import { setRef as _setRef, createFor as _createFor, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = _createFor(() => ([1,2,3]), (_block) => {
const n2 = t0()
_setRef(n2, "foo", true)
return [n2, () => {}]
})
return n0
}"
`;
exports[`compiler: template ref transform > ref + v-if 1`] = `
"import { setRef as _setRef, createIf as _createIf, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = _createIf(() => (true), () => {
const n2 = t0()
_setRef(n2, "foo")
return n2
})
return n0
}"
`;
exports[`compiler: template ref transform > static ref 1`] = `
"import { setRef as _setRef, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setRef(n0, "foo")
return n0
}"
`;

View File

@ -5,7 +5,7 @@ import {
type IfIRNode,
transformChildren,
transformElement,
transformRef,
transformTemplateRef,
transformVFor,
transformVIf,
} from '../../src'
@ -15,7 +15,7 @@ const compileWithTransformRef = makeCompile({
nodeTransforms: [
transformVIf,
transformVFor,
transformRef,
transformTemplateRef,
transformElement,
transformChildren,
],
@ -32,7 +32,7 @@ describe('compiler: template ref transform', () => {
expect(ir.template).toEqual(['<div></div>'])
expect(ir.block.operation).lengthOf(1)
expect(ir.block.operation[0]).toMatchObject({
type: IRNodeTypes.SET_REF,
type: IRNodeTypes.SET_TEMPLATE_REF,
element: 0,
value: {
content: 'foo',
@ -58,7 +58,7 @@ describe('compiler: template ref transform', () => {
expect(ir.template).toEqual(['<div></div>'])
expect(ir.block.operation).lengthOf(1)
expect(ir.block.operation[0]).toMatchObject({
type: IRNodeTypes.SET_REF,
type: IRNodeTypes.SET_TEMPLATE_REF,
element: 0,
value: {
content: 'foo',
@ -85,7 +85,7 @@ describe('compiler: template ref transform', () => {
expect(positive.operation).lengthOf(1)
expect(positive.operation[0]).toMatchObject({
type: IRNodeTypes.SET_REF,
type: IRNodeTypes.SET_TEMPLATE_REF,
element: 2,
value: {
content: 'foo',
@ -109,7 +109,7 @@ describe('compiler: template ref transform', () => {
const { render } = ir.block.operation[0] as ForIRNode
expect(render.operation).lengthOf(1)
expect(render.operation[0]).toMatchObject({
type: IRNodeTypes.SET_REF,
type: IRNodeTypes.SET_TEMPLATE_REF,
element: 2,
value: {
content: 'foo',

View File

@ -21,7 +21,7 @@ import { transformVText } from './transforms/vText'
import { transformVBind } from './transforms/vBind'
import { transformVOn } from './transforms/vOn'
import { transformVShow } from './transforms/vShow'
import { transformRef } from './transforms/transformRef'
import { transformTemplateRef } from './transforms/transformTemplateRef'
import { transformText } from './transforms/transformText'
import { transformVModel } from './transforms/vModel'
import { transformVIf } from './transforms/vIf'
@ -103,7 +103,7 @@ export function getBaseTransformPreset(
transformOnce,
transformVIf,
transformVFor,
transformRef,
transformTemplateRef,
transformText,
transformElement,
transformComment,

View File

@ -4,13 +4,14 @@ import {
INDENT_END,
INDENT_START,
NEWLINE,
SEGMENTS_ARRAY,
buildCodeFragment,
genCall,
genMulti,
} from './utils'
import type { CodegenContext } from '../generate'
import { genEffects, genOperations } from './operation'
import { genChildren } from './template'
import { genMulti } from './utils'
export function genBlock(
oper: BlockIRNode,
@ -68,7 +69,7 @@ export function genBlockContent(
const returnsCode: CodeFragment[] =
returns.length > 1
? genMulti(['[', ']', ', '], ...returns.map(n => `n${n}`))
? genMulti(SEGMENTS_ARRAY, ...returns.map(n => `n${n}`))
: [`n${returns[0]}`]
push(...(customReturns ? customReturns(returnsCode) : returnsCode))

View File

@ -3,9 +3,9 @@ import type { CodegenContext } from '../generate'
import type { CreateComponentIRNode, IRProp } from '../ir'
import {
type CodeFragment,
INDENT_END,
INDENT_START,
NEWLINE,
SEGMENTS_ARRAY,
SEGMENTS_OBJECT_NEWLINE,
genCall,
genMulti,
} from './utils'
@ -64,17 +64,13 @@ export function genCreateComponent(
})
.filter(Boolean)
if (props.length) {
return genMulti(['[', ']', ', '], ...props)
return genMulti(SEGMENTS_ARRAY, ...props)
}
}
function genStaticProps(props: IRProp[]) {
return genMulti(
[
['{', INDENT_START, NEWLINE],
[INDENT_END, NEWLINE, '}'],
[', ', NEWLINE],
],
SEGMENTS_OBJECT_NEWLINE,
...props.map(prop => {
return [
...genPropKey(prop, context),

View File

@ -2,7 +2,13 @@ import { createSimpleExpression, isSimpleIdentifier } from '@vue/compiler-dom'
import { camelize } from '@vue/shared'
import { genExpression } from './expression'
import type { CodegenContext } from '../generate'
import { type CodeFragment, NEWLINE, genCall, genMulti } from './utils'
import {
type CodeFragment,
NEWLINE,
SEGMENTS_ARRAY,
genCall,
genMulti,
} from './utils'
import {
IRNodeTypes,
type OperationNode,
@ -22,7 +28,7 @@ export function genWithDirective(
const element = `n${opers[0].element}`
const directiveItems = opers.map(genDirective)
const directives = genMulti(['[', ']', ', '], ...directiveItems)
const directives = genMulti(SEGMENTS_ARRAY, ...directiveItems)
return [
NEWLINE,
@ -47,7 +53,7 @@ export function genWithDirective(
? ['{ ', genDirectiveModifiers(dir.modifiers), ' }']
: false
return genMulti(['[', ']', ', '], directive, value, argument, modifiers)
return genMulti(SEGMENTS_ARRAY, directive, value, argument, modifiers)
function genDirective() {
const {

View File

@ -8,9 +8,8 @@ import type { SetDynamicEventsIRNode, SetEventIRNode } from '../ir'
import { genExpression } from './expression'
import {
type CodeFragment,
INDENT_END,
INDENT_START,
NEWLINE,
SEGMENTS_OBJECT_NEWLINE,
genCall,
genMulti,
} from './utils'
@ -60,11 +59,7 @@ export function genSetEvent(
if (!options.length && !nonKeys.length && !keys.length && !effect) return
return genMulti(
[
['{', INDENT_START, NEWLINE],
[INDENT_END, NEWLINE, '}'],
[', ', NEWLINE],
],
SEGMENTS_OBJECT_NEWLINE,
!!nonKeys.length && ['modifiers: ', genArrayExpression(nonKeys)],
!!keys.length && ['keys: ', genArrayExpression(keys)],
effect && ['effect: true'],

View File

@ -7,7 +7,7 @@ import { genSetHtml } from './html'
import { genIf } from './if'
import { genSetModelValue } from './modelValue'
import { genDynamicProps, genSetProp } from './prop'
import { genSetRef } from './ref'
import { genSetTemplateRef } from './templateRef'
import { genCreateTextNode, genSetText } from './text'
import {
type CodeFragment,
@ -43,8 +43,8 @@ export function genOperation(
return genSetDynamicEvents(oper, context)
case IRNodeTypes.SET_HTML:
return genSetHtml(oper, context)
case IRNodeTypes.SET_REF:
return genSetRef(oper, context)
case IRNodeTypes.SET_TEMPLATE_REF:
return genSetTemplateRef(oper, context)
case IRNodeTypes.SET_MODEL_VALUE:
return genSetModelValue(oper, context)
case IRNodeTypes.CREATE_TEXT_NODE:

View File

@ -11,7 +11,14 @@ import type {
VaporHelper,
} from '../ir'
import { genExpression } from './expression'
import { type CodeFragment, NEWLINE, genCall, genMulti } from './utils'
import {
type CodeFragment,
NEWLINE,
SEGMENTS_ARRAY,
SEGMENTS_OBJECT,
genCall,
genMulti,
} from './utils'
import { toHandlerKey } from '@vue/shared'
// only the static key prop will reach here
@ -77,7 +84,7 @@ function genLiteralObjectProps(
context: CodegenContext,
): CodeFragment[] {
return genMulti(
['{ ', ' }', ', '],
SEGMENTS_OBJECT,
...props.map(prop => [
...genPropKey(prop, context),
`: `,
@ -120,7 +127,7 @@ function genPropValue(values: SimpleExpressionNode[], context: CodegenContext) {
return genExpression(values[0], context)
}
return genMulti(
['[', ']', ', '],
SEGMENTS_ARRAY,
...values.map(expr => genExpression(expr, context)),
)
}

View File

@ -1,10 +1,10 @@
import { genExpression } from './expression'
import type { CodegenContext } from '../generate'
import type { SetRefIRNode } from '../ir'
import type { SetTemplateRefIRNode } from '../ir'
import { type CodeFragment, NEWLINE, genCall } from './utils'
export function genSetRef(
oper: SetRefIRNode,
export function genSetTemplateRef(
oper: SetTemplateRefIRNode,
context: CodegenContext,
): CodeFragment[] {
const { vaporHelper } = context
@ -12,7 +12,7 @@ export function genSetRef(
NEWLINE,
...genCall(
vaporHelper('setRef'),
[`n${oper.element}`],
`n${oper.element}`,
genExpression(oper.value, context),
oper.refFor && 'true',
),

View File

@ -1,7 +1,13 @@
import type { CodegenContext } from '../generate'
import type { CreateTextNodeIRNode, SetTextIRNode } from '../ir'
import { genExpression } from './expression'
import { type CodeFragment, NEWLINE, genCall, genMulti } from './utils'
import {
type CodeFragment,
NEWLINE,
SEGMENTS_ARRAY,
genCall,
genMulti,
} from './utils'
export function genSetText(
oper: SetTextIRNode,
@ -31,7 +37,7 @@ export function genCreateTextNode(
...genCall(vaporHelper('createTextNode'), [
effect && '() => ',
...genMulti(
['[', ']', ', '],
SEGMENTS_ARRAY,
...values.map(value => genExpression(value, context)),
),
]),

View File

@ -30,22 +30,23 @@ export function buildCodeFragment(...frag: CodeFragment[]) {
return [frag, push] as const
}
export function genMulti(
[left, right, seg]: [
type Segments = [
left: CodeFragments,
right: CodeFragments,
segment: CodeFragments,
],
...fns: CodeFragments[]
]
export function genMulti(
[left, right, seg]: Segments,
...frags: CodeFragments[]
): CodeFragment[] {
const frag: CodeFragment[] = []
fns = fns.filter(Boolean)
frags = frags.filter(Boolean)
push(left)
for (let [i, fn] of (
fns as Array<Exclude<CodeFragments, FalsyValue>>
frags as Array<Exclude<CodeFragments, FalsyValue>>
).entries()) {
push(fn)
if (i < fns.length - 1) push(seg)
if (i < frags.length - 1) push(seg)
}
push(right)
return frag
@ -55,12 +56,19 @@ export function genMulti(
frag.push(...fn)
}
}
export const SEGMENTS_ARRAY: Segments = ['[', ']', ', ']
export const SEGMENTS_OBJECT: Segments = ['{ ', ' }', ', ']
export const SEGMENTS_OBJECT_NEWLINE: Segments = [
['{', INDENT_START, NEWLINE],
[INDENT_END, NEWLINE, '}'],
[', ', NEWLINE],
]
export function genCall(
name: string,
...args: CodeFragments[]
...frags: CodeFragments[]
): CodeFragment[] {
return [name, ...genMulti(['(', ')', ', '], ...args)]
return [name, ...genMulti(['(', ')', ', '], ...frags)]
}
export function genCodeFragment(context: CodegenContext) {

View File

@ -36,7 +36,7 @@ export {
export { transformElement } from './transforms/transformElement'
export { transformChildren } from './transforms/transformChildren'
export { transformRef } from './transforms/transformRef'
export { transformTemplateRef } from './transforms/transformTemplateRef'
export { transformText } from './transforms/transformText'
export { transformVBind } from './transforms/vBind'
export { transformVHtml } from './transforms/vHtml'

View File

@ -23,7 +23,7 @@ export enum IRNodeTypes {
SET_EVENT,
SET_DYNAMIC_EVENTS,
SET_HTML,
SET_REF,
SET_TEMPLATE_REF,
SET_MODEL_VALUE,
INSERT_NODE,
@ -140,8 +140,8 @@ export interface SetHtmlIRNode extends BaseIRNode {
value: SimpleExpressionNode
}
export interface SetRefIRNode extends BaseIRNode {
type: IRNodeTypes.SET_REF
export interface SetTemplateRefIRNode extends BaseIRNode {
type: IRNodeTypes.SET_TEMPLATE_REF
element: number
value: SimpleExpressionNode
refFor: boolean
@ -202,7 +202,7 @@ export type OperationNode =
| SetEventIRNode
| SetDynamicEventsIRNode
| SetHtmlIRNode
| SetRefIRNode
| SetTemplateRefIRNode
| SetModelValueIRNode
| CreateTextNodeIRNode
| InsertNodeIRNode

View File

@ -9,7 +9,7 @@ import { normalizeBindShorthand } from './vBind'
import { findProp } from '../utils'
import { EMPTY_EXPRESSION } from './utils'
export const transformRef: NodeTransform = (node, context) => {
export const transformTemplateRef: NodeTransform = (node, context) => {
if (node.type !== NodeTypes.ELEMENT) return
const dir = findProp(node, 'ref', false, true)
@ -26,7 +26,7 @@ export const transformRef: NodeTransform = (node, context) => {
return () =>
context.registerOperation({
type: IRNodeTypes.SET_REF,
type: IRNodeTypes.SET_TEMPLATE_REF,
element: context.reference(),
value,
refFor: !!context.inVFor,