|
@@ -15,7 +15,7 @@ import {
|
|
|
createObjectExpression,
|
|
createObjectExpression,
|
|
|
Property
|
|
Property
|
|
|
} from '../ast'
|
|
} from '../ast'
|
|
|
-import { isArray, PatchFlags, PatchFlagNames } from '@vue/shared'
|
|
|
|
|
|
|
+import { PatchFlags, PatchFlagNames, isSymbol } from '@vue/shared'
|
|
|
import { createCompilerError, ErrorCodes } from '../errors'
|
|
import { createCompilerError, ErrorCodes } from '../errors'
|
|
|
import {
|
|
import {
|
|
|
CREATE_VNODE,
|
|
CREATE_VNODE,
|
|
@@ -28,6 +28,10 @@ import {
|
|
|
import { getInnerRange, isVSlot, toValidAssetId } from '../utils'
|
|
import { getInnerRange, isVSlot, toValidAssetId } from '../utils'
|
|
|
import { buildSlots } from './vSlot'
|
|
import { buildSlots } from './vSlot'
|
|
|
|
|
|
|
|
|
|
+// some directive transforms (e.g. v-model) may return a symbol for runtime
|
|
|
|
|
+// import, which should be used instead of a resolveDirective call.
|
|
|
|
|
+const directiveImportMap = new WeakMap<DirectiveNode, symbol>()
|
|
|
|
|
+
|
|
|
// generate a JavaScript AST for this element's codegen
|
|
// generate a JavaScript AST for this element's codegen
|
|
|
export const transformElement: NodeTransform = (node, context) => {
|
|
export const transformElement: NodeTransform = (node, context) => {
|
|
|
if (node.type === NodeTypes.ELEMENT) {
|
|
if (node.type === NodeTypes.ELEMENT) {
|
|
@@ -137,9 +141,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
|
|
[
|
|
[
|
|
|
vnode,
|
|
vnode,
|
|
|
createArrayExpression(
|
|
createArrayExpression(
|
|
|
- runtimeDirectives.map(dir => {
|
|
|
|
|
- return createDirectiveArgs(dir, context)
|
|
|
|
|
- }),
|
|
|
|
|
|
|
+ runtimeDirectives.map(dir => createDirectiveArgs(dir, context)),
|
|
|
loc
|
|
loc
|
|
|
)
|
|
)
|
|
|
],
|
|
],
|
|
@@ -274,15 +276,13 @@ export function buildProps(
|
|
|
if (directiveTransform) {
|
|
if (directiveTransform) {
|
|
|
// has built-in directive transform.
|
|
// has built-in directive transform.
|
|
|
const { props, needRuntime } = directiveTransform(prop, node, context)
|
|
const { props, needRuntime } = directiveTransform(prop, node, context)
|
|
|
- if (isArray(props)) {
|
|
|
|
|
- properties.push(...props)
|
|
|
|
|
- properties.forEach(analyzePatchFlag)
|
|
|
|
|
- } else {
|
|
|
|
|
- properties.push(props)
|
|
|
|
|
- analyzePatchFlag(props)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ props.forEach(analyzePatchFlag)
|
|
|
|
|
+ properties.push(...props)
|
|
|
if (needRuntime) {
|
|
if (needRuntime) {
|
|
|
runtimeDirectives.push(prop)
|
|
runtimeDirectives.push(prop)
|
|
|
|
|
+ if (isSymbol(needRuntime)) {
|
|
|
|
|
+ directiveImportMap.set(prop, needRuntime)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
// no built-in transform, this is a user custom directive.
|
|
// no built-in transform, this is a user custom directive.
|
|
@@ -362,7 +362,12 @@ function dedupeProperties(properties: Property[]): Property[] {
|
|
|
const name = prop.key.content
|
|
const name = prop.key.content
|
|
|
const existing = knownProps[name]
|
|
const existing = knownProps[name]
|
|
|
if (existing) {
|
|
if (existing) {
|
|
|
- if (name.startsWith('on') || name === 'style' || name === 'class') {
|
|
|
|
|
|
|
+ if (
|
|
|
|
|
+ name === 'style' ||
|
|
|
|
|
+ name === 'class' ||
|
|
|
|
|
+ name.startsWith('on') ||
|
|
|
|
|
+ name.startsWith('vnode')
|
|
|
|
|
+ ) {
|
|
|
mergeAsArray(existing, prop)
|
|
mergeAsArray(existing, prop)
|
|
|
}
|
|
}
|
|
|
// unexpected duplicate, should have emitted error during parse
|
|
// unexpected duplicate, should have emitted error during parse
|
|
@@ -389,12 +394,17 @@ function createDirectiveArgs(
|
|
|
dir: DirectiveNode,
|
|
dir: DirectiveNode,
|
|
|
context: TransformContext
|
|
context: TransformContext
|
|
|
): ArrayExpression {
|
|
): ArrayExpression {
|
|
|
- // inject statement for resolving directive
|
|
|
|
|
- context.helper(RESOLVE_DIRECTIVE)
|
|
|
|
|
- context.directives.add(dir.name)
|
|
|
|
|
- const dirArgs: ArrayExpression['elements'] = [
|
|
|
|
|
- toValidAssetId(dir.name, `directive`)
|
|
|
|
|
- ]
|
|
|
|
|
|
|
+ const dirArgs: ArrayExpression['elements'] = []
|
|
|
|
|
+ const runtime = directiveImportMap.get(dir)
|
|
|
|
|
+ if (runtime) {
|
|
|
|
|
+ context.helper(runtime)
|
|
|
|
|
+ dirArgs.push(context.helperString(runtime))
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // inject statement for resolving directive
|
|
|
|
|
+ context.helper(RESOLVE_DIRECTIVE)
|
|
|
|
|
+ context.directives.add(dir.name)
|
|
|
|
|
+ dirArgs.push(toValidAssetId(dir.name, `directive`))
|
|
|
|
|
+ }
|
|
|
const { loc } = dir
|
|
const { loc } = dir
|
|
|
if (dir.exp) dirArgs.push(dir.exp)
|
|
if (dir.exp) dirArgs.push(dir.exp)
|
|
|
if (dir.arg) dirArgs.push(dir.arg)
|
|
if (dir.arg) dirArgs.push(dir.arg)
|