feat(compiler): handle runtime helper injection
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user