feat(compiler): handle runtime helper injection

This commit is contained in:
Evan You
2019-09-22 23:07:36 -04:00
parent 914087edea
commit 8076ce1f28
10 changed files with 272 additions and 30 deletions

View File

@@ -16,6 +16,14 @@ import {
} from '../ast'
import { isArray } from '@vue/shared'
import { createCompilerError, ErrorCodes } from '../errors'
import {
CREATE_ELEMENT,
APPLY_DIRECTIVES,
RESOLVE_DIRECTIVE,
RESOLVE_COMPONENT
} from '../runtimeConstants'
const toValidId = (str: string): string => str.replace(/[^\w]/g, '')
// generate a JavaScript AST for this element's codegen
export const prepareElementForCodegen: NodeTransform = (node, context) => {
@@ -28,15 +36,20 @@ export const prepareElementForCodegen: NodeTransform = (node, context) => {
const hasProps = node.props.length > 0
const hasChildren = node.children.length > 0
let runtimeDirectives: DirectiveNode[] | undefined
let componentIdentifier: string | undefined
if (isComponent) {
// TODO inject import for `resolveComponent`
// TODO inject statement for resolving component
context.imports.add(RESOLVE_COMPONENT)
componentIdentifier = `_component_${toValidId(node.tag)}`
context.statements.push(
`const ${componentIdentifier} = ${RESOLVE_COMPONENT}(${JSON.stringify(
node.tag
)})`
)
}
const args: CallExpression['arguments'] = [
// TODO inject resolveComponent dep to root
isComponent ? node.tag : `"${node.tag}"`
isComponent ? componentIdentifier! : `"${node.tag}"`
]
// props
if (hasProps) {
@@ -54,13 +67,13 @@ export const prepareElementForCodegen: NodeTransform = (node, context) => {
}
const { loc } = node
// TODO inject import for `h`
const vnode = createCallExpression(`h`, args, loc)
context.imports.add(CREATE_ELEMENT)
const vnode = createCallExpression(CREATE_ELEMENT, args, loc)
if (runtimeDirectives && runtimeDirectives.length) {
// TODO inject import for `applyDirectives`
context.imports.add(APPLY_DIRECTIVES)
node.codegenNode = createCallExpression(
`applyDirectives`,
APPLY_DIRECTIVES,
[
vnode,
createArrayExpression(
@@ -174,9 +187,16 @@ function createDirectiveArgs(
dir: DirectiveNode,
context: TransformContext
): ArrayExpression {
// TODO inject import for `resolveDirective`
// TODO inject statement for resolving directive
const dirArgs: ArrayExpression['elements'] = [dir.name]
// inject import for `resolveDirective`
context.imports.add(RESOLVE_DIRECTIVE)
// inject statement for resolving directive
const dirIdentifier = `_directive_${toValidId(dir.name)}`
context.statements.push(
`const ${dirIdentifier} = _${RESOLVE_DIRECTIVE}(${JSON.stringify(
dir.name
)})`
)
const dirArgs: ArrayExpression['elements'] = [dirIdentifier]
const { loc } = dir
if (dir.exp) dirArgs.push(dir.exp)
if (dir.arg) dirArgs.push(dir.arg)

View File

@@ -2,18 +2,17 @@ import { createStructuralDirectiveTransform } from '../transform'
import { NodeTypes, ExpressionNode, createExpression } from '../ast'
import { createCompilerError, ErrorCodes } from '../errors'
import { getInnerRange } from '../utils'
import { RENDER_LIST } from '../runtimeConstants'
const forAliasRE = /([\s\S]*?)(?:(?<=\))|\s+)(?:in|of)\s+([\s\S]*)/
const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
const stripParensRE = /^\(|\)$/g
export const RENDER_LIST_HELPER = `renderList`
export const transformFor = createStructuralDirectiveTransform(
'for',
(node, dir, context) => {
if (dir.exp) {
// TODO inject helper import
context.imports.add(RENDER_LIST)
const aliases = parseAliasExpressions(dir.exp.content)
if (aliases) {

View File

@@ -1,6 +1,7 @@
import { DirectiveTransform } from '../transform'
import { createObjectProperty, createExpression } from '../ast'
import { capitalize } from '@vue/shared'
import { CAPITALIZE } from '../runtimeConstants'
// v-on without arg is handled directly in ./element.ts due to it affecting
// codegen for the entire props object. This transform here is only for v-on
@@ -9,8 +10,7 @@ export const transformOn: DirectiveTransform = (dir, context) => {
const arg = dir.arg!
const eventName = arg.isStatic
? createExpression(`on${capitalize(arg.content)}`, true, arg.loc)
: // TODO inject capitalize helper
createExpression(`'on' + capitalize(${arg.content})`, false, arg.loc)
: createExpression(`'on' + ${CAPITALIZE}(${arg.content})`, false, arg.loc)
// TODO .once modifier handling since it is platform agnostic
// other modifiers are handled in compiler-dom
return {