mirror of https://github.com/vuejs/core.git
feat: pushFnCall
This commit is contained in:
parent
0c26b0d4ed
commit
ecf7da98d7
|
@ -52,7 +52,7 @@ export interface CodegenContext extends Required<CodegenOptions> {
|
||||||
loc?: SourceLocation,
|
loc?: SourceLocation,
|
||||||
name?: string,
|
name?: string,
|
||||||
): void
|
): void
|
||||||
pushWithNewline(
|
pushNewline(
|
||||||
code: string,
|
code: string,
|
||||||
newlineIndex?: number,
|
newlineIndex?: number,
|
||||||
loc?: SourceLocation,
|
loc?: SourceLocation,
|
||||||
|
@ -60,8 +60,9 @@ export interface CodegenContext extends Required<CodegenOptions> {
|
||||||
): void
|
): void
|
||||||
pushMulti(
|
pushMulti(
|
||||||
codes: [left: string, right: string, segment?: string],
|
codes: [left: string, right: string, segment?: string],
|
||||||
...fn: Array<false | (() => void)>
|
...fn: Array<false | string | (() => void)>
|
||||||
): void
|
): void
|
||||||
|
pushFnCall(name: string, ...args: Array<false | string | (() => void)>): void
|
||||||
withIndent(fn: () => void): void
|
withIndent(fn: () => void): void
|
||||||
newline(): void
|
newline(): void
|
||||||
|
|
||||||
|
@ -169,7 +170,7 @@ function createCodegenContext(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pushWithNewline(code, newlineIndex, node) {
|
pushNewline(code, newlineIndex, node) {
|
||||||
context.newline()
|
context.newline()
|
||||||
context.push(code, newlineIndex, node)
|
context.push(code, newlineIndex, node)
|
||||||
},
|
},
|
||||||
|
@ -177,25 +178,28 @@ function createCodegenContext(
|
||||||
fns = fns.filter(Boolean)
|
fns = fns.filter(Boolean)
|
||||||
context.push(left)
|
context.push(left)
|
||||||
for (let i = 0; i < fns.length; i++) {
|
for (let i = 0; i < fns.length; i++) {
|
||||||
;(fns[i] as () => void)()
|
const fn = fns[i] as string | (() => void)
|
||||||
|
|
||||||
|
if (isString(fn)) context.push(fn)
|
||||||
|
else fn()
|
||||||
if (seg && i < fns.length - 1) context.push(seg)
|
if (seg && i < fns.length - 1) context.push(seg)
|
||||||
}
|
}
|
||||||
context.push(right)
|
context.push(right)
|
||||||
},
|
},
|
||||||
|
pushFnCall(name, ...args) {
|
||||||
|
context.push(name)
|
||||||
|
context.pushMulti(['(', ')', ', '], ...args)
|
||||||
|
},
|
||||||
withIndent(fn) {
|
withIndent(fn) {
|
||||||
++context.indentLevel
|
++context.indentLevel
|
||||||
fn()
|
fn()
|
||||||
--context.indentLevel
|
--context.indentLevel
|
||||||
},
|
},
|
||||||
newline() {
|
newline() {
|
||||||
newline(context.indentLevel)
|
context.push(`\n${` `.repeat(context.indentLevel)}`, NewlineType.Start)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function newline(n: number) {
|
|
||||||
context.push(`\n${` `.repeat(n)}`, NewlineType.Start)
|
|
||||||
}
|
|
||||||
|
|
||||||
function addMapping(loc: Position, name: string | null = null) {
|
function addMapping(loc: Position, name: string | null = null) {
|
||||||
// we use the private property to directly add the mapping
|
// we use the private property to directly add the mapping
|
||||||
// because the addMapping() implementation in source-map-js has a bunch of
|
// because the addMapping() implementation in source-map-js has a bunch of
|
||||||
|
@ -231,7 +235,7 @@ export function generate(
|
||||||
const ctx = createCodegenContext(ir, options)
|
const ctx = createCodegenContext(ir, options)
|
||||||
const {
|
const {
|
||||||
push,
|
push,
|
||||||
pushWithNewline,
|
pushNewline,
|
||||||
withIndent,
|
withIndent,
|
||||||
newline,
|
newline,
|
||||||
helpers,
|
helpers,
|
||||||
|
@ -246,21 +250,21 @@ export function generate(
|
||||||
} else {
|
} else {
|
||||||
// placeholder for preamble
|
// placeholder for preamble
|
||||||
newline()
|
newline()
|
||||||
pushWithNewline(`export function ${functionName}(_ctx) {`)
|
pushNewline(`export function ${functionName}(_ctx) {`)
|
||||||
}
|
}
|
||||||
|
|
||||||
withIndent(() => {
|
withIndent(() => {
|
||||||
ir.template.forEach((template, i) => {
|
ir.template.forEach((template, i) => {
|
||||||
if (template.type === IRNodeTypes.TEMPLATE_FACTORY) {
|
if (template.type === IRNodeTypes.TEMPLATE_FACTORY) {
|
||||||
// TODO source map?
|
// TODO source map?
|
||||||
pushWithNewline(
|
pushNewline(
|
||||||
`const t${i} = ${vaporHelper('template')}(${JSON.stringify(
|
`const t${i} = ${vaporHelper('template')}(${JSON.stringify(
|
||||||
template.template,
|
template.template,
|
||||||
)})`,
|
)})`,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// fragment
|
// fragment
|
||||||
pushWithNewline(
|
pushNewline(
|
||||||
`const t0 = ${vaporHelper('fragment')}()\n`,
|
`const t0 = ${vaporHelper('fragment')}()\n`,
|
||||||
NewlineType.End,
|
NewlineType.End,
|
||||||
)
|
)
|
||||||
|
@ -268,11 +272,11 @@ export function generate(
|
||||||
})
|
})
|
||||||
|
|
||||||
{
|
{
|
||||||
pushWithNewline(`const n${ir.dynamic.id} = t0()`)
|
pushNewline(`const n${ir.dynamic.id} = t0()`)
|
||||||
|
|
||||||
const children = genChildren(ir.dynamic.children)
|
const children = genChildren(ir.dynamic.children)
|
||||||
if (children) {
|
if (children) {
|
||||||
pushWithNewline(
|
pushNewline(
|
||||||
`const ${children} = ${vaporHelper('children')}(n${ir.dynamic.id})`,
|
`const ${children} = ${vaporHelper('children')}(n${ir.dynamic.id})`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -289,18 +293,18 @@ export function generate(
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const { operations } of ir.effect) {
|
for (const { operations } of ir.effect) {
|
||||||
pushWithNewline(`${vaporHelper('effect')}(() => {`)
|
pushNewline(`${vaporHelper('effect')}(() => {`)
|
||||||
withIndent(() => {
|
withIndent(() => {
|
||||||
for (const operation of operations) {
|
for (const operation of operations) {
|
||||||
genOperation(operation, ctx)
|
genOperation(operation, ctx)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
pushWithNewline('})')
|
pushNewline('})')
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO multiple-template
|
// TODO multiple-template
|
||||||
// TODO return statement in IR
|
// TODO return statement in IR
|
||||||
pushWithNewline(`return n${ir.dynamic.id}`)
|
pushNewline(`return n${ir.dynamic.id}`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -336,7 +340,6 @@ export function generate(
|
||||||
|
|
||||||
function genChildren(children: IRDynamicChildren) {
|
function genChildren(children: IRDynamicChildren) {
|
||||||
let code = ''
|
let code = ''
|
||||||
// TODO
|
|
||||||
let offset = 0
|
let offset = 0
|
||||||
for (const [index, child] of Object.entries(children)) {
|
for (const [index, child] of Object.entries(children)) {
|
||||||
const childrenLength = Object.keys(child.children).length
|
const childrenLength = Object.keys(child.children).length
|
||||||
|
@ -388,77 +391,93 @@ function genOperation(oper: OperationNode, context: CodegenContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function genSetProp(oper: SetPropIRNode, context: CodegenContext) {
|
function genSetProp(oper: SetPropIRNode, context: CodegenContext) {
|
||||||
const { push, pushWithNewline, vaporHelper, helper } = context
|
const { pushFnCall, newline, vaporHelper, helper } = context
|
||||||
pushWithNewline(`${vaporHelper('setAttr')}(n${oper.element}, `)
|
|
||||||
if (oper.runtimeCamelize) push(`${helper('camelize')}(`)
|
newline()
|
||||||
|
pushFnCall(
|
||||||
|
vaporHelper('setAttr'),
|
||||||
|
`n${oper.element}`,
|
||||||
|
// 2. key name
|
||||||
|
() => {
|
||||||
|
if (oper.runtimeCamelize) {
|
||||||
|
pushFnCall(helper('camelize'), () => genExpression(oper.key, context))
|
||||||
|
} else {
|
||||||
genExpression(oper.key, context)
|
genExpression(oper.key, context)
|
||||||
if (oper.runtimeCamelize) push(`)`)
|
}
|
||||||
push(`, undefined, `)
|
},
|
||||||
genExpression(oper.value, context)
|
'undefined',
|
||||||
push(')')
|
() => genExpression(oper.value, context),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function genSetText(oper: SetTextIRNode, context: CodegenContext) {
|
function genSetText(oper: SetTextIRNode, context: CodegenContext) {
|
||||||
const { push, pushWithNewline, vaporHelper } = context
|
const { pushFnCall, newline, vaporHelper } = context
|
||||||
pushWithNewline(`${vaporHelper('setText')}(n${oper.element}, undefined, `)
|
newline()
|
||||||
genExpression(oper.value, context)
|
pushFnCall(vaporHelper('setText'), `n${oper.element}`, 'undefined', () =>
|
||||||
push(')')
|
genExpression(oper.value, context),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function genSetHtml(oper: SetHtmlIRNode, context: CodegenContext) {
|
function genSetHtml(oper: SetHtmlIRNode, context: CodegenContext) {
|
||||||
const { push, pushWithNewline, vaporHelper } = context
|
const { newline, pushFnCall, vaporHelper } = context
|
||||||
pushWithNewline(`${vaporHelper('setHtml')}(n${oper.element}, undefined, `)
|
newline()
|
||||||
genExpression(oper.value, context)
|
pushFnCall(vaporHelper('setHtml'), `n${oper.element}`, 'undefined', () =>
|
||||||
push(')')
|
genExpression(oper.value, context),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function genCreateTextNode(
|
function genCreateTextNode(
|
||||||
oper: CreateTextNodeIRNode,
|
oper: CreateTextNodeIRNode,
|
||||||
context: CodegenContext,
|
context: CodegenContext,
|
||||||
) {
|
) {
|
||||||
const { push, pushWithNewline, vaporHelper } = context
|
const { pushNewline, pushFnCall, vaporHelper } = context
|
||||||
pushWithNewline(`const n${oper.id} = ${vaporHelper('createTextNode')}(`)
|
pushNewline(`const n${oper.id} = `)
|
||||||
genExpression(oper.value, context)
|
pushFnCall(vaporHelper('createTextNode'), () =>
|
||||||
push(')')
|
genExpression(oper.value, context),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function genInsertNode(oper: InsertNodeIRNode, context: CodegenContext) {
|
function genInsertNode(oper: InsertNodeIRNode, context: CodegenContext) {
|
||||||
const { pushWithNewline, vaporHelper } = context
|
const { newline, pushFnCall, vaporHelper } = context
|
||||||
const elements = ([] as number[]).concat(oper.element)
|
const elements = ([] as number[]).concat(oper.element)
|
||||||
let element = elements.map((el) => `n${el}`).join(', ')
|
let element = elements.map((el) => `n${el}`).join(', ')
|
||||||
if (elements.length > 1) element = `[${element}]`
|
if (elements.length > 1) element = `[${element}]`
|
||||||
pushWithNewline(
|
newline()
|
||||||
`${vaporHelper('insert')}(${element}, n${
|
pushFnCall(
|
||||||
oper.parent
|
vaporHelper('insert'),
|
||||||
}${`, n${oper.anchor}`})`,
|
element,
|
||||||
|
`n${oper.parent}`,
|
||||||
|
`n${oper.anchor}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function genPrependNode(oper: PrependNodeIRNode, context: CodegenContext) {
|
function genPrependNode(oper: PrependNodeIRNode, context: CodegenContext) {
|
||||||
const { pushWithNewline, vaporHelper } = context
|
const { newline, pushFnCall, vaporHelper } = context
|
||||||
pushWithNewline(
|
newline()
|
||||||
`${vaporHelper('prepend')}(n${oper.parent}, ${oper.elements
|
pushFnCall(
|
||||||
.map((el) => `n${el}`)
|
vaporHelper('prepend'),
|
||||||
.join(', ')})`,
|
`n${oper.parent}`,
|
||||||
|
oper.elements.map((el) => `n${el}`).join(', '),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function genAppendNode(oper: AppendNodeIRNode, context: CodegenContext) {
|
function genAppendNode(oper: AppendNodeIRNode, context: CodegenContext) {
|
||||||
const { pushWithNewline, vaporHelper } = context
|
const { newline, pushFnCall, vaporHelper } = context
|
||||||
pushWithNewline(
|
newline()
|
||||||
`${vaporHelper('append')}(n${oper.parent}, ${oper.elements
|
pushFnCall(
|
||||||
.map((el) => `n${el}`)
|
vaporHelper('append'),
|
||||||
.join(', ')})`,
|
`n${oper.parent}`,
|
||||||
|
oper.elements.map((el) => `n${el}`).join(', '),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function genSetEvent(oper: SetEventIRNode, context: CodegenContext) {
|
function genSetEvent(oper: SetEventIRNode, context: CodegenContext) {
|
||||||
const { vaporHelper, push, pushWithNewline, pushMulti: pushMulti } = context
|
const { vaporHelper, push, newline, pushMulti, pushFnCall } = context
|
||||||
const { keys, nonKeys, options } = oper.modifiers
|
const { keys, nonKeys, options } = oper.modifiers
|
||||||
|
|
||||||
pushWithNewline(vaporHelper('on'))
|
newline()
|
||||||
pushMulti(
|
pushFnCall(
|
||||||
['(', ')', ', '],
|
vaporHelper('on'),
|
||||||
// 1st arg: event name
|
// 1st arg: event name
|
||||||
() => push(`n${oper.element}`),
|
() => push(`n${oper.element}`),
|
||||||
// 2nd arg: event name
|
// 2nd arg: event name
|
||||||
|
@ -508,19 +527,29 @@ function genSetEvent(oper: SetEventIRNode, context: CodegenContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function genWithDirective(oper: WithDirectiveIRNode, context: CodegenContext) {
|
function genWithDirective(oper: WithDirectiveIRNode, context: CodegenContext) {
|
||||||
const { push, pushWithNewline, vaporHelper, bindingMetadata } = context
|
const { push, newline, pushFnCall, pushMulti, vaporHelper, bindingMetadata } =
|
||||||
|
context
|
||||||
const { dir } = oper
|
const { dir } = oper
|
||||||
|
|
||||||
// TODO merge directive for the same node
|
// TODO merge directive for the same node
|
||||||
pushWithNewline(`${vaporHelper('withDirectives')}(n${oper.element}, [[`)
|
newline()
|
||||||
|
pushFnCall(
|
||||||
|
vaporHelper('withDirectives'),
|
||||||
|
// 1st arg: node
|
||||||
|
`n${oper.element}`,
|
||||||
|
// 2nd arg: directives
|
||||||
|
() => {
|
||||||
|
push('[')
|
||||||
|
// directive
|
||||||
|
pushMulti(['[', ']', ', '], () => {
|
||||||
if (dir.name === 'show') {
|
if (dir.name === 'show') {
|
||||||
push(vaporHelper('vShow'))
|
push(vaporHelper('vShow'))
|
||||||
} else {
|
} else {
|
||||||
const directiveReference = camelize(`v-${dir.name}`)
|
const directiveReference = camelize(`v-${dir.name}`)
|
||||||
// TODO resolve directive
|
// TODO resolve directive
|
||||||
if (bindingMetadata[directiveReference]) {
|
if (bindingMetadata[directiveReference]) {
|
||||||
const directiveExpression = createSimpleExpression(directiveReference)
|
const directiveExpression =
|
||||||
|
createSimpleExpression(directiveReference)
|
||||||
directiveExpression.ast = null
|
directiveExpression.ast = null
|
||||||
genExpression(directiveExpression, context)
|
genExpression(directiveExpression, context)
|
||||||
}
|
}
|
||||||
|
@ -546,8 +575,10 @@ function genWithDirective(oper: WithDirectiveIRNode, context: CodegenContext) {
|
||||||
push(genDirectiveModifiers(dir.modifiers))
|
push(genDirectiveModifiers(dir.modifiers))
|
||||||
push(' }')
|
push(' }')
|
||||||
}
|
}
|
||||||
push(']])')
|
})
|
||||||
return
|
push(']')
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: other types (not only string)
|
// TODO: other types (not only string)
|
||||||
|
|
Loading…
Reference in New Issue