refactor(compiler): use symbols for runtime helpers

This commit is contained in:
Evan You
2019-10-05 17:18:25 -04:00
parent 7c4eea6048
commit bfecf2cdce
26 changed files with 420 additions and 231 deletions

View File

@@ -7,7 +7,7 @@ import {
ElementTypes
} from '../ast'
import { TransformContext } from '../transform'
import { APPLY_DIRECTIVES } from '../runtimeConstants'
import { APPLY_DIRECTIVES } from '../runtimeHelpers'
import { PropsExpression } from './transformElement'
import { PatchFlags } from '@vue/shared'
@@ -41,7 +41,7 @@ function walk(
flag === PatchFlags.TEXT
) {
let codegenNode = child.codegenNode as CallExpression
if (codegenNode.callee.includes(APPLY_DIRECTIVES)) {
if (codegenNode.callee === APPLY_DIRECTIVES) {
codegenNode = codegenNode.arguments[0] as CallExpression
}
const props = codegenNode.arguments[1] as
@@ -68,7 +68,7 @@ function walk(
function getPatchFlag(node: ElementNode): number | undefined {
let codegenNode = node.codegenNode as CallExpression
if (codegenNode.callee.includes(APPLY_DIRECTIVES)) {
if (codegenNode.callee === APPLY_DIRECTIVES) {
codegenNode = codegenNode.arguments[0] as CallExpression
}
const flag = codegenNode.arguments[3]

View File

@@ -25,12 +25,10 @@ import {
RESOLVE_COMPONENT,
MERGE_PROPS,
TO_HANDLERS
} from '../runtimeConstants'
import { getInnerRange, isVSlot } from '../utils'
} from '../runtimeHelpers'
import { getInnerRange, isVSlot, toValidAssetId } from '../utils'
import { buildSlots } from './vSlot'
const toValidId = (str: string): string => str.replace(/[^\w]/g, '')
// generate a JavaScript AST for this element's codegen
export const transformElement: NodeTransform = (node, context) => {
if (node.type === NodeTypes.ELEMENT) {
@@ -50,19 +48,14 @@ export const transformElement: NodeTransform = (node, context) => {
let patchFlag: number = 0
let runtimeDirectives: DirectiveNode[] | undefined
let dynamicPropNames: string[] | undefined
let componentIdentifier: string | undefined
if (isComponent) {
componentIdentifier = `_component_${toValidId(node.tag)}`
context.statements.add(
`const ${componentIdentifier} = ${context.helper(
RESOLVE_COMPONENT
)}(${JSON.stringify(node.tag)})`
)
context.helper(RESOLVE_COMPONENT)
context.components.add(node.tag)
}
const args: CallExpression['arguments'] = [
isComponent ? componentIdentifier! : `"${node.tag}"`
isComponent ? toValidAssetId(node.tag, `component`) : `"${node.tag}"`
]
// props
if (hasProps) {
@@ -402,13 +395,11 @@ function createDirectiveArgs(
context: TransformContext
): ArrayExpression {
// inject statement for resolving directive
const dirIdentifier = `_directive_${toValidId(dir.name)}`
context.statements.add(
`const ${dirIdentifier} = ${context.helper(
RESOLVE_DIRECTIVE
)}(${JSON.stringify(dir.name)})`
)
const dirArgs: ArrayExpression['elements'] = [dirIdentifier]
context.helper(RESOLVE_DIRECTIVE)
context.directives.add(dir.name)
const dirArgs: ArrayExpression['elements'] = [
toValidAssetId(dir.name, `directive`)
]
const { loc } = dir
if (dir.exp) dirArgs.push(dir.exp)
if (dir.arg) dirArgs.push(dir.arg)

View File

@@ -8,7 +8,7 @@ import {
import { isSlotOutlet } from '../utils'
import { buildProps } from './transformElement'
import { createCompilerError, ErrorCodes } from '../errors'
import { RENDER_SLOT } from '../runtimeConstants'
import { RENDER_SLOT } from '../runtimeHelpers'
export const transformSlotOutlet: NodeTransform = (node, context) => {
if (isSlotOutlet(node)) {

View File

@@ -2,7 +2,7 @@ import { DirectiveTransform } from '../transform'
import { createObjectProperty, createSimpleExpression, NodeTypes } from '../ast'
import { createCompilerError, ErrorCodes } from '../errors'
import { camelize } from '@vue/shared'
import { CAMELIZE } from '../runtimeConstants'
import { CAMELIZE } from '../runtimeHelpers'
// v-bind 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-bind
@@ -20,10 +20,10 @@ export const transformBind: DirectiveTransform = (dir, context) => {
if (arg.isStatic) {
arg.content = camelize(arg.content)
} else {
arg.content = `${context.helper(CAMELIZE)}(${arg.content})`
arg.content = `${context.helperString(CAMELIZE)}(${arg.content})`
}
} else {
arg.children.unshift(`${context.helper(CAMELIZE)}(`)
arg.children.unshift(`${context.helperString(CAMELIZE)}(`)
arg.children.push(`)`)
}
}

View File

@@ -30,7 +30,7 @@ import {
OPEN_BLOCK,
CREATE_BLOCK,
FRAGMENT
} from '../runtimeConstants'
} from '../runtimeHelpers'
import { processExpression } from './transformExpression'
import { PatchFlags, PatchFlagNames } from '@vue/shared'
import { PropsExpression } from './transformElement'

View File

@@ -29,7 +29,7 @@ import {
APPLY_DIRECTIVES,
CREATE_VNODE,
RENDER_SLOT
} from '../runtimeConstants'
} from '../runtimeHelpers'
import { injectProp } from '../utils'
import { PropsExpression } from './transformElement'
@@ -184,18 +184,18 @@ function createChildrenCodegenNode(
const childCodegen = (child as ElementNode).codegenNode as CallExpression
let vnodeCall = childCodegen
// Element with custom directives. Locate the actual createVNode() call.
if (vnodeCall.callee.includes(APPLY_DIRECTIVES)) {
if (vnodeCall.callee === APPLY_DIRECTIVES) {
vnodeCall = vnodeCall.arguments[0] as CallExpression
}
// Change createVNode to createBlock.
if (vnodeCall.callee.includes(CREATE_VNODE)) {
if (vnodeCall.callee === CREATE_VNODE) {
vnodeCall.callee = helper(CREATE_BLOCK)
}
// It's possible to have renderSlot() here as well - which already produces
// a block, so no need to change the callee. However it accepts props at
// a different arg index so make sure to check for so that the key injection
// logic below works for it too.
const propsIndex = vnodeCall.callee.includes(RENDER_SLOT) ? 2 : 1
const propsIndex = vnodeCall.callee === RENDER_SLOT ? 2 : 1
// inject branch key
const existingProps = vnodeCall.arguments[propsIndex] as
| PropsExpression

View File

@@ -24,7 +24,7 @@ import {
import { TransformContext, NodeTransform } from '../transform'
import { createCompilerError, ErrorCodes } from '../errors'
import { findDir, isTemplateNode, assert, isVSlot } from '../utils'
import { CREATE_SLOTS, RENDER_LIST } from '../runtimeConstants'
import { CREATE_SLOTS, RENDER_LIST } from '../runtimeHelpers'
import { parseForExpression, createForLoopParams } from './vFor'
const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>