wip(compiler): codegen node w/ block optimization for v-for

This commit is contained in:
Evan You
2019-10-01 16:48:20 -04:00
parent aa134e7a4f
commit e5bc17967d
9 changed files with 353 additions and 409 deletions

View File

@@ -2,8 +2,6 @@ import {
RootNode,
TemplateChildNode,
ElementNode,
IfNode,
ForNode,
TextNode,
CommentNode,
ExpressionNode,
@@ -18,7 +16,7 @@ import {
CompoundExpressionNode,
SimpleExpressionNode,
ElementTypes,
SlotFunctionExpression,
FunctionExpression,
SequenceExpression,
ConditionalExpression
} from './ast'
@@ -29,12 +27,7 @@ import {
isSimpleIdentifier
} from './utils'
import { isString, isArray } from '@vue/shared'
import {
RENDER_LIST,
TO_STRING,
CREATE_VNODE,
COMMENT
} from './runtimeConstants'
import { TO_STRING, CREATE_VNODE, COMMENT } from './runtimeConstants'
type CodegenNode = TemplateChildNode | JSChildNode
@@ -342,7 +335,15 @@ function genNodeList(
function genNode(node: CodegenNode, context: CodegenContext) {
switch (node.type) {
case NodeTypes.ELEMENT:
genElement(node, context)
case NodeTypes.IF:
case NodeTypes.FOR:
__DEV__ &&
assert(
node.codegenNode != null,
`Codegen node is missing for element/if/for node. ` +
`Apply appropriate transforms first.`
)
genNode(node.codegenNode!, context)
break
case NodeTypes.TEXT:
genText(node, context)
@@ -359,12 +360,6 @@ function genNode(node: CodegenNode, context: CodegenContext) {
case NodeTypes.COMMENT:
genComment(node, context)
break
case NodeTypes.IF:
genIf(node, context)
break
case NodeTypes.FOR:
genFor(node, context)
break
case NodeTypes.JS_CALL_EXPRESSION:
genCallExpression(node, context)
break
@@ -374,8 +369,8 @@ function genNode(node: CodegenNode, context: CodegenContext) {
case NodeTypes.JS_ARRAY_EXPRESSION:
genArrayExpression(node, context)
break
case NodeTypes.JS_SLOT_FUNCTION:
genSlotFunction(node, context)
case NodeTypes.JS_FUNCTION_EXPRESSION:
genFunctionExpression(node, context)
break
case NodeTypes.JS_SEQUENCE_EXPRESSION:
genSequenceExpression(node, context)
@@ -394,16 +389,6 @@ function genNode(node: CodegenNode, context: CodegenContext) {
}
}
function genElement(node: ElementNode, context: CodegenContext) {
__DEV__ &&
assert(
node.codegenNode != null,
`AST is not transformed for codegen. ` +
`Apply appropriate transforms first.`
)
genCallExpression(node.codegenNode!, context, false)
}
function genText(
node: TextNode | SimpleExpressionNode,
context: CodegenContext
@@ -469,56 +454,10 @@ function genComment(node: CommentNode, context: CodegenContext) {
}
}
// control flow
function genIf(node: IfNode, context: CodegenContext) {
genNode(node.codegenNode, context)
}
function genFor(node: ForNode, context: CodegenContext) {
const { push, helper, indent, deindent } = context
const { source, keyAlias, valueAlias, objectIndexAlias, children } = node
push(`${helper(RENDER_LIST)}(`, node, true)
genNode(source, context)
push(`, (`)
if (valueAlias) {
genNode(valueAlias, context)
}
if (keyAlias) {
if (!valueAlias) {
push(`__value`)
}
push(`, `)
genNode(keyAlias, context)
}
if (objectIndexAlias) {
if (!keyAlias) {
if (!valueAlias) {
push(`__value, __key`)
} else {
push(`, __key`)
}
}
push(`, `)
genNode(objectIndexAlias, context)
}
push(`) => {`)
indent()
push(`return `)
genChildren(children, context, true)
deindent()
push(`})`)
}
// JavaScript
function genCallExpression(
node: CallExpression,
context: CodegenContext,
multilines = false
) {
function genCallExpression(node: CallExpression, context: CodegenContext) {
context.push(node.callee + `(`, node, true)
multilines && context.indent()
genNodeList(node.arguments, context, multilines)
multilines && context.deindent()
genNodeList(node.arguments, context)
context.push(`)`)
}
@@ -554,15 +493,33 @@ function genArrayExpression(node: ArrayExpression, context: CodegenContext) {
genNodeListAsArray(node.elements, context)
}
function genSlotFunction(
node: SlotFunctionExpression,
function genFunctionExpression(
node: FunctionExpression,
context: CodegenContext
) {
context.push(`(`, node)
if (node.params) genNode(node.params, context)
context.push(`) => `)
// pre-normalized slots should always return arrays
genNodeListAsArray(node.returns, context)
const { push, indent, deindent } = context
const { params, returns, newline } = node
push(`(`, node)
if (isArray(params)) {
genNodeList(params, context)
} else if (params) {
genNode(params, context)
}
push(`) => `)
if (newline) {
push(`{`)
indent()
push(`return `)
}
if (isArray(returns)) {
genNodeListAsArray(returns, context)
} else {
genNode(returns, context)
}
if (newline) {
deindent()
push(`}`)
}
}
function genConditionalExpression(