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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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