Skip to content

Commit

Permalink
refactor(compiler-vapor): re-organize
Browse files Browse the repository at this point in the history
  • Loading branch information
sxzz committed Jan 30, 2024
1 parent 38a0639 commit ccfadc1
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 112 deletions.
103 changes: 9 additions & 94 deletions packages/compiler-vapor/src/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@ import {
locStub,
} from '@vue/compiler-dom'
import {
type BlockFunctionIRNode,
DynamicFlag,
type IRDynamicInfo,
IRNodeTypes,
type OperationNode,
type RootIRNode,
type VaporHelper,
type WithDirectiveIRNode,
} from './ir'
import { SourceMapGenerator } from 'source-map-js'
import { extend, isString } from '@vue/shared'
Expand All @@ -27,18 +23,14 @@ import { genSetHtml } from './generators/html'
import { genSetRef } from './generators/ref'
import { genSetModelValue } from './generators/modelValue'
import { genAppendNode, genInsertNode, genPrependNode } from './generators/dom'
import { genWithDirective } from './generators/directive'
import { genIf } from './generators/if'
import { genTemplate } from './generators/template'
import { genBlockFunctionContent } from './generators/block'

interface CodegenOptions extends BaseCodegenOptions {
expressionPlugins?: ParserPlugin[]
}

// remove when stable
// @ts-expect-error
function checkNever(x: never): never {}

export type CodeFragment =
| string
| [code: string, newlineIndex?: number, loc?: SourceLocation, name?: string]
Expand Down Expand Up @@ -275,37 +267,13 @@ function genCodeFragment(context: CodegenContext) {
}
}

function genChildren(children: IRDynamicInfo[]) {
let code = ''
let offset = 0

for (const [index, child] of children.entries()) {
if (child.flags & DynamicFlag.NON_TEMPLATE) {
offset--
}

const idx = Number(index) + offset
const id =
child.flags & DynamicFlag.REFERENCED
? child.flags & DynamicFlag.INSERT
? child.anchor
: child.id
: null
const childrenString = genChildren(child.children)

if (id !== null || childrenString) {
code += ` ${idx}: [`
if (id !== null) code += `n${id}`
if (childrenString) code += `, ${childrenString}`
code += '],'
}
}

if (!code) return ''
return `{${code}}`
export function buildCodeFragment() {
const frag: CodeFragment[] = []
const push = frag.push.bind(frag)
return [frag, push] as const
}

function genOperation(
export function genOperation(
oper: OperationNode,
context: CodegenContext,
): CodeFragment[] {
Expand Down Expand Up @@ -343,59 +311,6 @@ function genOperation(
return []
}

export function buildCodeFragment() {
const frag: CodeFragment[] = []
const push = frag.push.bind(frag)
return [frag, push] as const
}

export function genBlockFunctionContent(
ir: BlockFunctionIRNode | RootIRNode,
ctx: CodegenContext,
): CodeFragment[] {
const { newline, withIndent, vaporHelper } = ctx
const [frag, push] = buildCodeFragment()

push(newline(), `const n${ir.dynamic.id} = t${ir.templateIndex}()`)

const children = genChildren(ir.dynamic.children)
if (children) {
push(
newline(),
`const ${children} = ${vaporHelper('children')}(n${ir.dynamic.id})`,
)
}

const directiveOps = ir.operation.filter(
(oper): oper is WithDirectiveIRNode =>
oper.type === IRNodeTypes.WITH_DIRECTIVE,
)
for (const directives of groupDirective(directiveOps)) {
push(...genWithDirective(directives, ctx))
}

for (const operation of ir.operation) {
push(...genOperation(operation, ctx))
}

for (const { operations } of ir.effect) {
push(newline(), `${vaporHelper('renderEffect')}(() => {`)
withIndent(() => {
operations.forEach(op => push(...genOperation(op, ctx)))
})
push(newline(), '})')
}

push(newline(), `return n${ir.dynamic.id}`)

return frag
}

function groupDirective(ops: WithDirectiveIRNode[]): WithDirectiveIRNode[][] {
const directiveMap: Record<number, WithDirectiveIRNode[]> = {}
for (const oper of ops) {
if (!directiveMap[oper.element]) directiveMap[oper.element] = []
directiveMap[oper.element].push(oper)
}
return Object.values(directiveMap)
}
// remove when stable
// @ts-expect-error
function checkNever(x: never): never {}
109 changes: 109 additions & 0 deletions packages/compiler-vapor/src/generators/block.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {
type BlockFunctionIRNode,
DynamicFlag,
type IRDynamicInfo,
IRNodeTypes,
type RootIRNode,
type WithDirectiveIRNode,
} from '../ir'
import {
type CodeFragment,
type CodegenContext,
buildCodeFragment,
genOperation,
} from '../generate'
import { genWithDirective } from './directive'

export function genBlockFunction(
oper: BlockFunctionIRNode,
context: CodegenContext,
): CodeFragment[] {
const { newline, withIndent } = context
return [
'() => {',
...withIndent(() => genBlockFunctionContent(oper, context)),
newline(),
'}',
]
}

export function genBlockFunctionContent(
ir: BlockFunctionIRNode | RootIRNode,
ctx: CodegenContext,
): CodeFragment[] {
const { newline, withIndent, vaporHelper } = ctx
const [frag, push] = buildCodeFragment()

push(newline(), `const n${ir.dynamic.id} = t${ir.templateIndex}()`)

const children = genChildren(ir.dynamic.children)
if (children) {
push(
newline(),
`const ${children} = ${vaporHelper('children')}(n${ir.dynamic.id})`,
)
}

const directiveOps = ir.operation.filter(
(oper): oper is WithDirectiveIRNode =>
oper.type === IRNodeTypes.WITH_DIRECTIVE,
)
for (const directives of groupDirective(directiveOps)) {
push(...genWithDirective(directives, ctx))
}

for (const operation of ir.operation) {
push(...genOperation(operation, ctx))
}

for (const { operations } of ir.effect) {
push(newline(), `${vaporHelper('renderEffect')}(() => {`)
withIndent(() => {
operations.forEach(op => push(...genOperation(op, ctx)))
})
push(newline(), '})')
}

push(newline(), `return n${ir.dynamic.id}`)

return frag
}

function genChildren(children: IRDynamicInfo[]) {
let code = ''
let offset = 0

for (const [index, child] of children.entries()) {
if (child.flags & DynamicFlag.NON_TEMPLATE) {
offset--
}

const idx = Number(index) + offset
const id =
child.flags & DynamicFlag.REFERENCED
? child.flags & DynamicFlag.INSERT
? child.anchor
: child.id
: null
const childrenString = genChildren(child.children)

if (id !== null || childrenString) {
code += ` ${idx}: [`
if (id !== null) code += `n${id}`
if (childrenString) code += `, ${childrenString}`
code += '],'
}
}

if (!code) return ''
return `{${code}}`
}

function groupDirective(ops: WithDirectiveIRNode[]): WithDirectiveIRNode[][] {
const directiveMap: Record<number, WithDirectiveIRNode[]> = {}
for (const oper of ops) {
if (!directiveMap[oper.element]) directiveMap[oper.element] = []
directiveMap[oper.element].push(oper)
}
return Object.values(directiveMap)
}
17 changes: 2 additions & 15 deletions packages/compiler-vapor/src/generators/if.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import {
type CodeFragment,
type CodegenContext,
buildCodeFragment,
genBlockFunctionContent,
} from '../generate'
import { type BlockFunctionIRNode, IRNodeTypes, type IfIRNode } from '../ir'
import { IRNodeTypes, type IfIRNode } from '../ir'
import { genBlockFunction } from './block'
import { genExpression } from './expression'

export function genIf(
Expand Down Expand Up @@ -40,16 +40,3 @@ export function genIf(

return frag
}

function genBlockFunction(
oper: BlockFunctionIRNode,
context: CodegenContext,
): CodeFragment[] {
const { newline, withIndent } = context
return [
'() => {',
...withIndent(() => genBlockFunctionContent(oper, context)),
newline(),
'}',
]
}
5 changes: 2 additions & 3 deletions packages/compiler-vapor/src/transforms/vIf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
ElementTypes,
ErrorCodes,
NodeTypes,
type RootNode,
type TemplateChildNode,
type TemplateNode,
createCompilerError,
Expand Down Expand Up @@ -32,7 +31,7 @@ export const transformVIf = createStructuralDirectiveTransform(
export function processIf(
node: ElementNode,
dir: VaporDirectiveNode,
context: TransformContext<RootNode | TemplateChildNode>,
context: TransformContext<ElementNode>,
) {
if (dir.name !== 'else' && (!dir.exp || !dir.exp.content.trim())) {
const loc = dir.exp ? dir.exp.loc : node.loc
Expand Down Expand Up @@ -144,7 +143,7 @@ export function processIf(

export function createIfBranch(
node: ElementNode,
context: TransformContext<RootNode | TemplateChildNode>,
context: TransformContext<ElementNode>,
): [BlockFunctionIRNode, () => void] {
context.node = node = wrapTemplate(node)

Expand Down

0 comments on commit ccfadc1

Please sign in to comment.