components: [],
directives: [],
hoists: [],
- codegenNode: undefined,
+ codegenNode: createSimpleExpression(`null`, false),
loc: locStub,
...options
}
locStub,
Namespaces,
ElementTypes,
- ElementCodegenNode
+ PlainElementCodegenNode
} from '../src'
import { CREATE_VNODE } from '../src/runtimeHelpers'
import { isString, PatchFlags, PatchFlagNames, isArray } from '@vue/shared'
}
export function createElementWithCodegen(
- args: ElementCodegenNode['arguments']
+ args: PlainElementCodegenNode['arguments']
): ElementNode {
return {
type: NodeTypes.ELEMENT,
OPEN_BLOCK,
CREATE_BLOCK,
FRAGMENT,
- RENDER_SLOT
+ RENDER_SLOT,
+ APPLY_DIRECTIVES
} from '../src/runtimeHelpers'
import { transformIf } from '../src/transforms/vIf'
import { transformFor } from '../src/transforms/vFor'
})
})
+ test('root element with custom directive', () => {
+ const ast = transformWithCodegen(`<div v-foo/>`)
+ expect(ast.codegenNode).toMatchObject({
+ type: NodeTypes.JS_SEQUENCE_EXPRESSION,
+ expressions: [
+ {
+ type: NodeTypes.JS_CALL_EXPRESSION,
+ callee: OPEN_BLOCK
+ },
+ {
+ type: NodeTypes.JS_CALL_EXPRESSION,
+ // should wrap applyDirectives() around createBlock()
+ callee: APPLY_DIRECTIVES,
+ arguments: [
+ { callee: CREATE_BLOCK },
+ { type: NodeTypes.JS_ARRAY_EXPRESSION }
+ ]
+ }
+ ]
+ })
+ })
+
test('single text', () => {
const ast = transformWithCodegen(`hello`)
expect(ast.codegenNode).toMatchObject({
return function render() {
with (this) {
- const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
return (_openBlock(), _createBlock(\\"div\\", null, [
_hoisted_1
return function render() {
with (this) {
- const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
return (_openBlock(), _createBlock(\\"div\\", null, [
_hoisted_1,
return function render() {
with (this) {
- const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
return (_openBlock(), _createBlock(\\"div\\", null, [
_hoisted_1
return function render() {
with (this) {
- const { createVNode: _createVNode, applyDirectives: _applyDirectives, resolveDirective: _resolveDirective, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { createVNode: _createVNode, applyDirectives: _applyDirectives, resolveDirective: _resolveDirective, createBlock: _createBlock, openBlock: _openBlock } = _Vue
const _directive_foo = _resolveDirective(\\"foo\\")
return function render() {
with (this) {
- const { toString: _toString, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { toString: _toString, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
return (_openBlock(), _createBlock(\\"div\\", null, [
_createVNode(\\"div\\", _hoisted_1, _toString(hello), 1 /* TEXT */)
return function render() {
with (this) {
- const { resolveComponent: _resolveComponent, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { resolveComponent: _resolveComponent, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
const _component_Comp = _resolveComponent(\\"Comp\\")
return function render() {
with (this) {
- const { resolveComponent: _resolveComponent, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { resolveComponent: _resolveComponent, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
const _component_Comp = _resolveComponent(\\"Comp\\")
return function render() {
with (this) {
- const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
return (_openBlock(), _createBlock(\\"div\\", null, [
_createVNode(\\"div\\", { id: foo }, null, 8 /* PROPS */, [\\"id\\"])
return function render() {
with (this) {
- const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
return (_openBlock(), _createBlock(\\"div\\"))
}
return function render() {
with (this) {
- const { createVNode: _createVNode, toString: _toString, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { createVNode: _createVNode, toString: _toString, createBlock: _createBlock, Fragment: _Fragment, openBlock: _openBlock } = _Vue
return (_openBlock(), _createBlock(_Fragment, null, [
_createVNode(\\"div\\"),
return function render() {
with (this) {
- const { createVNode: _createVNode, toString: _toString, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { createVNode: _createVNode, toString: _toString, createBlock: _createBlock, Fragment: _Fragment, openBlock: _openBlock } = _Vue
return (_openBlock(), _createBlock(_Fragment, null, [
_createVNode(\\"div\\"),
}"
`;
+exports[`compiler: v-for codegen v-for on element with custom directive 1`] = `
+"const _Vue = Vue
+
+return function render() {
+ with (this) {
+ const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, createVNode: _createVNode, applyDirectives: _applyDirectives, resolveDirective: _resolveDirective } = _Vue
+
+ const _directive_foo = _resolveDirective(\\"foo\\")
+
+ return (_openBlock(), _createBlock(_Fragment, null, _renderList(list, (i) => {
+ return (_openBlock(), _applyDirectives(_createBlock(\\"div\\", null, null, 32 /* NEED_PATCH */), [
+ [_directive_foo]
+ ]))
+ }), 128 /* UNKEYED_FRAGMENT */))
+ }
+}"
+`;
+
exports[`compiler: v-for codegen v-if + v-for 1`] = `
"const _Vue = Vue
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`compiler: transform component slots dynamically named slots 1`] = `
-"const { toString, resolveComponent, createVNode, openBlock, createBlock } = Vue
+"const { toString, resolveComponent, createVNode, createBlock, openBlock } = Vue
return function render() {
const _ctx = this
`;
exports[`compiler: transform component slots explicit default slot 1`] = `
-"const { toString, resolveComponent, createVNode, openBlock, createBlock } = Vue
+"const { toString, resolveComponent, createVNode, createBlock, openBlock } = Vue
return function render() {
const _ctx = this
`;
exports[`compiler: transform component slots implicit default slot 1`] = `
-"const { createVNode, resolveComponent, openBlock, createBlock } = Vue
+"const { createVNode, resolveComponent, createBlock, openBlock } = Vue
return function render() {
const _ctx = this
`;
exports[`compiler: transform component slots named slot with v-for w/ prefixIdentifiers: true 1`] = `
-"const { toString, resolveComponent, renderList, createSlots, createVNode, openBlock, createBlock } = Vue
+"const { toString, resolveComponent, renderList, createSlots, createVNode, createBlock, openBlock } = Vue
return function render() {
const _ctx = this
`;
exports[`compiler: transform component slots named slot with v-if + prefixIdentifiers: true 1`] = `
-"const { toString, resolveComponent, createSlots, createVNode, openBlock, createBlock } = Vue
+"const { toString, resolveComponent, createSlots, createVNode, createBlock, openBlock } = Vue
return function render() {
const _ctx = this
return function render() {
with (this) {
- const { resolveComponent: _resolveComponent, createSlots: _createSlots, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { resolveComponent: _resolveComponent, createSlots: _createSlots, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
const _component_Comp = _resolveComponent(\\"Comp\\")
return function render() {
with (this) {
- const { resolveComponent: _resolveComponent, createSlots: _createSlots, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { resolveComponent: _resolveComponent, createSlots: _createSlots, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
const _component_Comp = _resolveComponent(\\"Comp\\")
`;
exports[`compiler: transform component slots named slots 1`] = `
-"const { toString, resolveComponent, createVNode, openBlock, createBlock } = Vue
+"const { toString, resolveComponent, createVNode, createBlock, openBlock } = Vue
return function render() {
const _ctx = this
`;
exports[`compiler: transform component slots nested slots scoping 1`] = `
-"const { toString, resolveComponent, createVNode, openBlock, createBlock } = Vue
+"const { toString, resolveComponent, createVNode, createBlock, openBlock } = Vue
return function render() {
const _ctx = this
-import {
- ElementNode,
- CompilerOptions,
- parse,
- transform,
- ErrorCodes
-} from '../../src'
+import { CompilerOptions, parse, transform, ErrorCodes } from '../../src'
import {
RESOLVE_COMPONENT,
CREATE_VNODE,
root: RootNode
node: CallExpression
} {
- const ast = parse(template, options)
+ // wrap raw template in an extra div so that it doesn't get turned into a
+ // block as root node
+ const ast = parse(`<div>${template}</div>`, options)
transform(ast, {
nodeTransforms: [optimizeText, transformElement],
...options
})
- const codegenNode = (ast.children[0] as ElementNode)
+ const codegenNode = (ast as any).children[0].children[0]
.codegenNode as CallExpression
expect(codegenNode.type).toBe(NodeTypes.JS_CALL_EXPRESSION)
return {
CREATE_BLOCK,
FRAGMENT,
RENDER_LIST,
- RENDER_SLOT
+ RENDER_SLOT,
+ APPLY_DIRECTIVES
} from '../../src/runtimeHelpers'
import { PatchFlags } from '@vue/runtime-dom'
import { createObjectMatcher, genFlagText } from '../testUtils'
})
expect(generate(root).code).toMatchSnapshot()
})
+
+ test('v-for on element with custom directive', () => {
+ const {
+ root,
+ node: { codegenNode }
+ } = parseWithForTransform('<div v-for="i in list" v-foo/>')
+ const { returns } = assertSharedCodegen(codegenNode, false, true)
+ expect(returns).toMatchObject({
+ type: NodeTypes.JS_SEQUENCE_EXPRESSION,
+ expressions: [
+ { callee: OPEN_BLOCK },
+ // should wrap applyDirectives() around createBlock()
+ {
+ callee: APPLY_DIRECTIVES,
+ arguments: [
+ { callee: CREATE_BLOCK },
+ { type: NodeTypes.JS_ARRAY_EXPRESSION }
+ ]
+ }
+ ]
+ })
+ expect(generate(root).code).toMatchSnapshot()
+ })
})
})
export interface PlainElementNode extends BaseElementNode {
tagType: ElementTypes.ELEMENT
- codegenNode:
- | ElementCodegenNode
- | CodegenNodeWithDirective<ElementCodegenNode>
- | undefined
- // | SimpleExpressionNode (only when hoisted)
+ codegenNode: ElementCodegenNode | undefined | SimpleExpressionNode // only when hoisted
}
export interface ComponentNode extends BaseElementNode {
tagType: ElementTypes.COMPONENT
- codegenNode:
- | ComponentCodegenNode
- | CodegenNodeWithDirective<ComponentCodegenNode>
- | undefined
+ codegenNode: ComponentCodegenNode | undefined
}
export interface SlotOutletNode extends BaseElementNode {
// Codegen Node Types ----------------------------------------------------------
// createVNode(...)
-export interface ElementCodegenNode extends CallExpression {
- callee: typeof CREATE_VNODE
+export interface PlainElementCodegenNode extends CallExpression {
+ callee: typeof CREATE_VNODE | typeof CREATE_BLOCK
arguments: // tag, props, children, patchFlag, dynamicProps
| [string | RuntimeHelper]
| [string | RuntimeHelper, PropsExpression]
]
}
-export type ElementCodegenNodeWithDirective = CodegenNodeWithDirective<
- ElementCodegenNode
->
+export type ElementCodegenNode =
+ | PlainElementCodegenNode
+ | CodegenNodeWithDirective<PlainElementCodegenNode>
// createVNode(...)
-export interface ComponentCodegenNode extends CallExpression {
- callee: typeof CREATE_VNODE
+export interface PlainComponentCodegenNode extends CallExpression {
+ callee: typeof CREATE_VNODE | typeof CREATE_BLOCK
arguments: // Comp, props, slots, patchFlag, dynamicProps
| [string | RuntimeHelper]
| [string | RuntimeHelper, PropsExpression]
]
}
-export type CompoenntCodegenNodeWithDirective = CodegenNodeWithDirective<
- ComponentCodegenNode
->
+export type ComponentCodegenNode =
+ | PlainComponentCodegenNode
+ | CodegenNodeWithDirective<PlainComponentCodegenNode>
export type SlotsExpression = SlotsObjectExpression | DynamicSlotsExpression
]
}
+export type BlockCodegenNode =
+ | ElementCodegenNode
+ | ComponentCodegenNode
+ | SlotOutletCodegenNode
+
export interface IfCodegenNode extends SequenceExpression {
expressions: [OpenBlockExpression, IfConditionalExpression]
}
arguments: []
}
-export type BlockCodegenNode =
- | BlockElementCodegenNode
- | BlockComponentCodegenNode
- | BlockElementCodegenNodeWithDirective
- | BlockComponentCodegenNodeWithDirective
-
-export type BlockElementCodegenNode = ElementCodegenNode & {
- callee: typeof CREATE_BLOCK
-}
-
-export type BlockComponentCodegenNode = ComponentCodegenNode & {
- callee: typeof CREATE_BLOCK
-}
-
-export type BlockElementCodegenNodeWithDirective = CodegenNodeWithDirective<
- BlockElementCodegenNode
->
-
-export type BlockComponentCodegenNodeWithDirective = CodegenNodeWithDirective<
- BlockComponentCodegenNode
->
-
// AST Utilities ---------------------------------------------------------------
// Some expressions, e.g. sequence and conditional expressions, are never
}
}
-type InferCodegenNodeType<T> = T extends typeof CREATE_VNODE
- ? ElementCodegenNode | ComponentCodegenNode
- : T extends typeof CREATE_BLOCK
- ? BlockElementCodegenNode | BlockComponentCodegenNode
- : T extends typeof APPLY_DIRECTIVES
- ? ElementCodegenNodeWithDirective | CompoenntCodegenNodeWithDirective
- : T extends typeof RENDER_SLOT ? SlotOutletCodegenNode : CallExpression
+type InferCodegenNodeType<T> = T extends
+ | typeof CREATE_VNODE
+ | typeof CREATE_BLOCK
+ ? PlainElementCodegenNode | PlainComponentCodegenNode
+ : T extends typeof APPLY_DIRECTIVES
+ ?
+ | CodegenNodeWithDirective<PlainElementCodegenNode>
+ | CodegenNodeWithDirective<PlainComponentCodegenNode>
+ : T extends typeof RENDER_SLOT ? SlotOutletCodegenNode : CallExpression
export function createCallExpression<T extends CallExpression['callee']>(
callee: T,
createSimpleExpression,
JSChildNode,
SimpleExpressionNode,
- ElementTypes
+ ElementTypes,
+ ElementCodegenNode,
+ ComponentCodegenNode,
+ createCallExpression
} from './ast'
import { isString, isArray } from '@vue/shared'
import { CompilerError, defaultOnError } from './errors'
CREATE_VNODE,
FRAGMENT,
RuntimeHelper,
- helperNameMap
+ helperNameMap,
+ APPLY_DIRECTIVES,
+ CREATE_BLOCK
} from './runtimeHelpers'
import { isVSlot, createBlockExpression } from './utils'
import { hoistStatic, isSingleElementRoot } from './transforms/hoistStatic'
}
const list = context.parent!.children
const removalIndex = node
- ? list.indexOf(node as any)
+ ? list.indexOf(node)
: context.currentNode
? context.childIndex
: -1
const { helper } = context
const { children } = root
const child = children[0]
- if (isSingleElementRoot(root, child) && child.codegenNode) {
- // turn root element into a block
- root.codegenNode = createBlockExpression(
- child.codegenNode.arguments,
- context
- )
- } else if (children.length === 1) {
- // - single <slot/>, IfNode, ForNode: already blocks.
- // - single text node: always patched.
- // - transform calls without transformElement (only during tests)
- // Just generate the node as-is
- root.codegenNode = child
+ if (children.length === 1) {
+ // if the single child is an element, turn it into a block.
+ if (isSingleElementRoot(root, child) && child.codegenNode) {
+ // single element root is never hoisted so codegenNode will never be
+ // SimpleExpressionNode
+ const codegenNode = child.codegenNode as
+ | ElementCodegenNode
+ | ComponentCodegenNode
+ if (codegenNode.callee === APPLY_DIRECTIVES) {
+ codegenNode.arguments[0].callee = helper(CREATE_BLOCK)
+ } else {
+ codegenNode.callee = helper(CREATE_BLOCK)
+ }
+ root.codegenNode = createBlockExpression(codegenNode, context)
+ } else {
+ // - single <slot/>, IfNode, ForNode: already blocks.
+ // - single text node: always patched.
+ // root codegen falls through via genNode()
+ root.codegenNode = child
+ }
} else if (children.length > 1) {
// root has multiple nodes - return a fragment block.
root.codegenNode = createBlockExpression(
- [helper(FRAGMENT), `null`, root.children],
+ createCallExpression(helper(CREATE_BLOCK), [
+ helper(FRAGMENT),
+ `null`,
+ root.children
+ ]),
context
)
+ } else {
+ // no children = noop. codegen will return null.
}
// finalize meta information
root.helpers = [...context.helpers]
RootNode,
NodeTypes,
TemplateChildNode,
- ElementNode,
ElementTypes,
ElementCodegenNode,
- ElementCodegenNodeWithDirective,
PlainElementNode,
ComponentNode,
TemplateNode
) {
if (!doNotHoistNode && isStaticNode(child, resultCache)) {
// whole tree is static
- ;(child as any).codegenNode = context.hoist(child.codegenNode!)
+ child.codegenNode = context.hoist(child.codegenNode!)
continue
} else {
// node may contain dynamic children, but its props may be eligible for
flag === PatchFlags.NEED_PATCH ||
flag === PatchFlags.TEXT
) {
- let codegenNode = child.codegenNode!
+ let codegenNode = child.codegenNode as ElementCodegenNode
if (codegenNode.callee === APPLY_DIRECTIVES) {
codegenNode = codegenNode.arguments[0]
}
}
}
-function getPatchFlag(node: ElementNode): number | undefined {
- let codegenNode = node.codegenNode as
- | ElementCodegenNode
- | ElementCodegenNodeWithDirective
+function getPatchFlag(node: PlainElementNode): number | undefined {
+ let codegenNode = node.codegenNode as ElementCodegenNode
if (codegenNode.callee === APPLY_DIRECTIVES) {
codegenNode = codegenNode.arguments[0]
}
createObjectExpression,
createObjectProperty,
ForCodegenNode,
- PlainElementNode
+ ElementCodegenNode
} from '../ast'
import { createCompilerError, ErrorCodes } from '../errors'
import {
RENDER_LIST,
OPEN_BLOCK,
CREATE_BLOCK,
- FRAGMENT
+ FRAGMENT,
+ APPLY_DIRECTIVES
} from '../runtimeHelpers'
import { processExpression } from './transformExpression'
import { PatchFlags, PatchFlagNames } from '@vue/shared'
-import { PropsExpression } from './transformElement'
export const transformFor = createStructuralDirectiveTransform(
'for',
// <template v-for="..." :key="..."><slot/></template>
// we need to inject the key to the renderSlot() call.
// the props for renderSlot is passed as the 3rd argument.
- const existingProps = childBlock.arguments[2] as
- | PropsExpression
- | undefined
- | 'null'
- childBlock.arguments[2] = injectProp(
- existingProps,
- keyProperty,
- context
- )
+ injectProp(childBlock, keyProperty, context)
}
} else if (isTemplate) {
// <template v-for="...">
// should generate a fragment block for each loop
childBlock = createBlockExpression(
- [
+ createCallExpression(helper(CREATE_BLOCK), [
helper(FRAGMENT),
keyProperty ? createObjectExpression([keyProperty]) : `null`,
node.children
- ],
+ ]),
context
)
} else {
// Normal element v-for. Directly use the child's codegenNode
// arguments, but replace createVNode() with createBlock()
- childBlock = createBlockExpression(
- (node as PlainElementNode).codegenNode!.arguments,
- context
- )
+ let codegenNode = node.codegenNode as ElementCodegenNode
+ if (codegenNode.callee === APPLY_DIRECTIVES) {
+ codegenNode.arguments[0].callee = helper(CREATE_BLOCK)
+ } else {
+ codegenNode.callee = helper(CREATE_BLOCK)
+ }
+ childBlock = createBlockExpression(codegenNode, context)
}
renderExp.arguments.push(
BlockCodegenNode,
SlotOutletCodegenNode,
ElementCodegenNode,
- ComponentCodegenNode,
- ElementCodegenNodeWithDirective,
- CompoenntCodegenNodeWithDirective
+ ComponentCodegenNode
} from '../ast'
import { createCompilerError, ErrorCodes } from '../errors'
import { processExpression } from './transformExpression'
EMPTY,
FRAGMENT,
APPLY_DIRECTIVES,
- CREATE_VNODE,
- RENDER_SLOT
+ CREATE_VNODE
} from '../runtimeHelpers'
import { injectProp } from '../utils'
const childCodegen = (child as ElementNode).codegenNode as
| ElementCodegenNode
| ComponentCodegenNode
- | ElementCodegenNodeWithDirective
- | CompoenntCodegenNodeWithDirective
| SlotOutletCodegenNode
let vnodeCall = childCodegen
// Element with custom directives. Locate the actual createVNode() call.
}
// Change createVNode to createBlock.
if (vnodeCall.callee === CREATE_VNODE) {
- ;(vnodeCall as any).callee = helper(CREATE_BLOCK)
+ 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 === RENDER_SLOT ? 2 : 1
// inject branch key
- const existingProps = vnodeCall.arguments[
- propsIndex
- ] as ElementCodegenNode['arguments'][1]
- vnodeCall.arguments[propsIndex] = injectProp(
- existingProps,
- keyProperty,
- context
- )
+ injectProp(vnodeCall, keyProperty, context)
return childCodegen
}
}
JSChildNode,
createObjectExpression,
SlotOutletNode,
- TemplateNode
+ TemplateNode,
+ BlockCodegenNode,
+ ElementCodegenNode,
+ SlotOutletCodegenNode,
+ ComponentCodegenNode
} from './ast'
import { parse } from 'acorn'
import { walk } from 'estree-walker'
import { TransformContext } from './transform'
-import { OPEN_BLOCK, CREATE_BLOCK, MERGE_PROPS } from './runtimeHelpers'
+import { OPEN_BLOCK, MERGE_PROPS, RENDER_SLOT } from './runtimeHelpers'
import { isString, isFunction } from '@vue/shared'
-import { PropsExpression } from './transforms/transformElement'
// cache node requires
// lazy require dependencies so that they don't end up in rollup's dep graph
}
export function createBlockExpression(
- args: CallExpression['arguments'],
+ blockExp: BlockCodegenNode,
context: TransformContext
): SequenceExpression {
return createSequenceExpression([
createCallExpression(context.helper(OPEN_BLOCK)),
- createCallExpression(context.helper(CREATE_BLOCK), args)
+ blockExp
])
}
node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT
export function injectProp(
- props: PropsExpression | undefined | 'null',
+ node: ElementCodegenNode | ComponentCodegenNode | SlotOutletCodegenNode,
prop: Property,
context: TransformContext
-): ObjectExpression | CallExpression {
- if (props == null || props === `null`) {
- return createObjectExpression([prop])
+) {
+ let propsWithInjection: ObjectExpression | CallExpression
+ const props =
+ node.callee === RENDER_SLOT ? node.arguments[2] : node.arguments[1]
+ if (props == null || isString(props)) {
+ propsWithInjection = createObjectExpression([prop])
} else if (props.type === NodeTypes.JS_CALL_EXPRESSION) {
// merged props... add ours
// only inject key to object literal if it's the first argument so that
} else {
props.arguments.unshift(createObjectExpression([prop]))
}
- return props
+ propsWithInjection = props
} else if (props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
props.properties.unshift(prop)
- return props
+ propsWithInjection = props
} else {
// single v-bind with expression, return a merged replacement
- return createCallExpression(context.helper(MERGE_PROPS), [
+ propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [
createObjectExpression([prop]),
props
])
}
+ if (node.callee === RENDER_SLOT) {
+ node.arguments[2] = propsWithInjection
+ } else {
+ node.arguments[1] = propsWithInjection
+ }
}
export function toValidAssetId(