fix(compiler): handle block nodes with custom directives + improve ast types
This commit is contained in:
parent
1393ee52ca
commit
16da9ae89f
@ -34,7 +34,7 @@ function createRoot(options: Partial<RootNode> = {}): RootNode {
|
|||||||
components: [],
|
components: [],
|
||||||
directives: [],
|
directives: [],
|
||||||
hoists: [],
|
hoists: [],
|
||||||
codegenNode: undefined,
|
codegenNode: createSimpleExpression(`null`, false),
|
||||||
loc: locStub,
|
loc: locStub,
|
||||||
...options
|
...options
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import {
|
|||||||
locStub,
|
locStub,
|
||||||
Namespaces,
|
Namespaces,
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
ElementCodegenNode
|
PlainElementCodegenNode
|
||||||
} from '../src'
|
} from '../src'
|
||||||
import { CREATE_VNODE } from '../src/runtimeHelpers'
|
import { CREATE_VNODE } from '../src/runtimeHelpers'
|
||||||
import { isString, PatchFlags, PatchFlagNames, isArray } from '@vue/shared'
|
import { isString, PatchFlags, PatchFlagNames, isArray } from '@vue/shared'
|
||||||
@ -39,7 +39,7 @@ export function createObjectMatcher(obj: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createElementWithCodegen(
|
export function createElementWithCodegen(
|
||||||
args: ElementCodegenNode['arguments']
|
args: PlainElementCodegenNode['arguments']
|
||||||
): ElementNode {
|
): ElementNode {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
|
@ -14,7 +14,8 @@ import {
|
|||||||
OPEN_BLOCK,
|
OPEN_BLOCK,
|
||||||
CREATE_BLOCK,
|
CREATE_BLOCK,
|
||||||
FRAGMENT,
|
FRAGMENT,
|
||||||
RENDER_SLOT
|
RENDER_SLOT,
|
||||||
|
APPLY_DIRECTIVES
|
||||||
} from '../src/runtimeHelpers'
|
} from '../src/runtimeHelpers'
|
||||||
import { transformIf } from '../src/transforms/vIf'
|
import { transformIf } from '../src/transforms/vIf'
|
||||||
import { transformFor } from '../src/transforms/vFor'
|
import { transformFor } from '../src/transforms/vFor'
|
||||||
@ -301,6 +302,28 @@ describe('compiler: transform', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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', () => {
|
test('single text', () => {
|
||||||
const ast = transformWithCodegen(`hello`)
|
const ast = transformWithCodegen(`hello`)
|
||||||
expect(ast.codegenNode).toMatchObject({
|
expect(ast.codegenNode).toMatchObject({
|
||||||
|
@ -11,7 +11,7 @@ const _hoisted_1 = _createVNode(\\"p\\", null, [
|
|||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
with (this) {
|
||||||
const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
|
const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
|
||||||
|
|
||||||
return (_openBlock(), _createBlock(\\"div\\", null, [
|
return (_openBlock(), _createBlock(\\"div\\", null, [
|
||||||
_hoisted_1
|
_hoisted_1
|
||||||
@ -29,7 +29,7 @@ const _hoisted_2 = _createVNode(\\"div\\")
|
|||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
with (this) {
|
||||||
const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
|
const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
|
||||||
|
|
||||||
return (_openBlock(), _createBlock(\\"div\\", null, [
|
return (_openBlock(), _createBlock(\\"div\\", null, [
|
||||||
_hoisted_1,
|
_hoisted_1,
|
||||||
@ -47,7 +47,7 @@ const _hoisted_1 = _createVNode(\\"span\\", { class: \\"inline\\" }, \\"hello\\"
|
|||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
with (this) {
|
||||||
const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
|
const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
|
||||||
|
|
||||||
return (_openBlock(), _createBlock(\\"div\\", null, [
|
return (_openBlock(), _createBlock(\\"div\\", null, [
|
||||||
_hoisted_1
|
_hoisted_1
|
||||||
@ -64,7 +64,7 @@ const _hoisted_1 = { id: \\"foo\\" }
|
|||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
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\\")
|
const _directive_foo = _resolveDirective(\\"foo\\")
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ const _hoisted_1 = { id: \\"foo\\" }
|
|||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
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, [
|
return (_openBlock(), _createBlock(\\"div\\", null, [
|
||||||
_createVNode(\\"div\\", _hoisted_1, _toString(hello), 1 /* TEXT */)
|
_createVNode(\\"div\\", _hoisted_1, _toString(hello), 1 /* TEXT */)
|
||||||
@ -102,7 +102,7 @@ const _hoisted_1 = { id: \\"foo\\" }
|
|||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
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\\")
|
const _component_Comp = _resolveComponent(\\"Comp\\")
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ exports[`compiler: hositStatic transform should NOT hoist components 1`] = `
|
|||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
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\\")
|
const _component_Comp = _resolveComponent(\\"Comp\\")
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ exports[`compiler: hositStatic transform should NOT hoist element with dynamic p
|
|||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
with (this) {
|
||||||
const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
|
const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
|
||||||
|
|
||||||
return (_openBlock(), _createBlock(\\"div\\", null, [
|
return (_openBlock(), _createBlock(\\"div\\", null, [
|
||||||
_createVNode(\\"div\\", { id: foo }, null, 8 /* PROPS */, [\\"id\\"])
|
_createVNode(\\"div\\", { id: foo }, null, 8 /* PROPS */, [\\"id\\"])
|
||||||
@ -150,7 +150,7 @@ exports[`compiler: hositStatic transform should NOT hoist root node 1`] = `
|
|||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
with (this) {
|
||||||
const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
|
const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
|
||||||
|
|
||||||
return (_openBlock(), _createBlock(\\"div\\"))
|
return (_openBlock(), _createBlock(\\"div\\"))
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ exports[`compiler: optimize interpolation consecutive text between elements 1`]
|
|||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
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, [
|
return (_openBlock(), _createBlock(_Fragment, null, [
|
||||||
_createVNode(\\"div\\"),
|
_createVNode(\\"div\\"),
|
||||||
@ -33,7 +33,7 @@ exports[`compiler: optimize interpolation consecutive text mixed with elements 1
|
|||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
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, [
|
return (_openBlock(), _createBlock(_Fragment, null, [
|
||||||
_createVNode(\\"div\\"),
|
_createVNode(\\"div\\"),
|
||||||
|
@ -132,6 +132,24 @@ return function render() {
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
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`] = `
|
exports[`compiler: v-for codegen v-if + v-for 1`] = `
|
||||||
"const _Vue = Vue
|
"const _Vue = Vue
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`compiler: transform component slots dynamically named slots 1`] = `
|
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() {
|
return function render() {
|
||||||
const _ctx = this
|
const _ctx = this
|
||||||
@ -16,7 +16,7 @@ return function render() {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compiler: transform component slots explicit default slot 1`] = `
|
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() {
|
return function render() {
|
||||||
const _ctx = this
|
const _ctx = this
|
||||||
@ -30,7 +30,7 @@ return function render() {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compiler: transform component slots implicit default slot 1`] = `
|
exports[`compiler: transform component slots implicit default slot 1`] = `
|
||||||
"const { createVNode, resolveComponent, openBlock, createBlock } = Vue
|
"const { createVNode, resolveComponent, createBlock, openBlock } = Vue
|
||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
const _ctx = this
|
const _ctx = this
|
||||||
@ -46,7 +46,7 @@ return function render() {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compiler: transform component slots named slot with v-for w/ prefixIdentifiers: true 1`] = `
|
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() {
|
return function render() {
|
||||||
const _ctx = this
|
const _ctx = this
|
||||||
@ -64,7 +64,7 @@ return function render() {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compiler: transform component slots named slot with v-if + prefixIdentifiers: true 1`] = `
|
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() {
|
return function render() {
|
||||||
const _ctx = this
|
const _ctx = this
|
||||||
@ -86,7 +86,7 @@ exports[`compiler: transform component slots named slot with v-if + v-else-if +
|
|||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
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\\")
|
const _component_Comp = _resolveComponent(\\"Comp\\")
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ exports[`compiler: transform component slots named slot with v-if 1`] = `
|
|||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
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\\")
|
const _component_Comp = _resolveComponent(\\"Comp\\")
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ return function render() {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compiler: transform component slots named slots 1`] = `
|
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() {
|
return function render() {
|
||||||
const _ctx = this
|
const _ctx = this
|
||||||
@ -147,7 +147,7 @@ return function render() {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compiler: transform component slots nested slots scoping 1`] = `
|
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() {
|
return function render() {
|
||||||
const _ctx = this
|
const _ctx = this
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
import {
|
import { CompilerOptions, parse, transform, ErrorCodes } from '../../src'
|
||||||
ElementNode,
|
|
||||||
CompilerOptions,
|
|
||||||
parse,
|
|
||||||
transform,
|
|
||||||
ErrorCodes
|
|
||||||
} from '../../src'
|
|
||||||
import {
|
import {
|
||||||
RESOLVE_COMPONENT,
|
RESOLVE_COMPONENT,
|
||||||
CREATE_VNODE,
|
CREATE_VNODE,
|
||||||
@ -35,12 +29,14 @@ function parseWithElementTransform(
|
|||||||
root: RootNode
|
root: RootNode
|
||||||
node: CallExpression
|
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, {
|
transform(ast, {
|
||||||
nodeTransforms: [optimizeText, transformElement],
|
nodeTransforms: [optimizeText, transformElement],
|
||||||
...options
|
...options
|
||||||
})
|
})
|
||||||
const codegenNode = (ast.children[0] as ElementNode)
|
const codegenNode = (ast as any).children[0].children[0]
|
||||||
.codegenNode as CallExpression
|
.codegenNode as CallExpression
|
||||||
expect(codegenNode.type).toBe(NodeTypes.JS_CALL_EXPRESSION)
|
expect(codegenNode.type).toBe(NodeTypes.JS_CALL_EXPRESSION)
|
||||||
return {
|
return {
|
||||||
|
@ -22,7 +22,8 @@ import {
|
|||||||
CREATE_BLOCK,
|
CREATE_BLOCK,
|
||||||
FRAGMENT,
|
FRAGMENT,
|
||||||
RENDER_LIST,
|
RENDER_LIST,
|
||||||
RENDER_SLOT
|
RENDER_SLOT,
|
||||||
|
APPLY_DIRECTIVES
|
||||||
} from '../../src/runtimeHelpers'
|
} from '../../src/runtimeHelpers'
|
||||||
import { PatchFlags } from '@vue/runtime-dom'
|
import { PatchFlags } from '@vue/runtime-dom'
|
||||||
import { createObjectMatcher, genFlagText } from '../testUtils'
|
import { createObjectMatcher, genFlagText } from '../testUtils'
|
||||||
@ -845,5 +846,28 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
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()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -114,19 +114,12 @@ export interface BaseElementNode extends Node {
|
|||||||
|
|
||||||
export interface PlainElementNode extends BaseElementNode {
|
export interface PlainElementNode extends BaseElementNode {
|
||||||
tagType: ElementTypes.ELEMENT
|
tagType: ElementTypes.ELEMENT
|
||||||
codegenNode:
|
codegenNode: ElementCodegenNode | undefined | SimpleExpressionNode // only when hoisted
|
||||||
| ElementCodegenNode
|
|
||||||
| CodegenNodeWithDirective<ElementCodegenNode>
|
|
||||||
| undefined
|
|
||||||
// | SimpleExpressionNode (only when hoisted)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ComponentNode extends BaseElementNode {
|
export interface ComponentNode extends BaseElementNode {
|
||||||
tagType: ElementTypes.COMPONENT
|
tagType: ElementTypes.COMPONENT
|
||||||
codegenNode:
|
codegenNode: ComponentCodegenNode | undefined
|
||||||
| ComponentCodegenNode
|
|
||||||
| CodegenNodeWithDirective<ComponentCodegenNode>
|
|
||||||
| undefined
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SlotOutletNode extends BaseElementNode {
|
export interface SlotOutletNode extends BaseElementNode {
|
||||||
@ -280,8 +273,8 @@ export interface ConditionalExpression extends Node {
|
|||||||
// Codegen Node Types ----------------------------------------------------------
|
// Codegen Node Types ----------------------------------------------------------
|
||||||
|
|
||||||
// createVNode(...)
|
// createVNode(...)
|
||||||
export interface ElementCodegenNode extends CallExpression {
|
export interface PlainElementCodegenNode extends CallExpression {
|
||||||
callee: typeof CREATE_VNODE
|
callee: typeof CREATE_VNODE | typeof CREATE_BLOCK
|
||||||
arguments: // tag, props, children, patchFlag, dynamicProps
|
arguments: // tag, props, children, patchFlag, dynamicProps
|
||||||
| [string | RuntimeHelper]
|
| [string | RuntimeHelper]
|
||||||
| [string | RuntimeHelper, PropsExpression]
|
| [string | RuntimeHelper, PropsExpression]
|
||||||
@ -301,13 +294,13 @@ export interface ElementCodegenNode extends CallExpression {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ElementCodegenNodeWithDirective = CodegenNodeWithDirective<
|
export type ElementCodegenNode =
|
||||||
ElementCodegenNode
|
| PlainElementCodegenNode
|
||||||
>
|
| CodegenNodeWithDirective<PlainElementCodegenNode>
|
||||||
|
|
||||||
// createVNode(...)
|
// createVNode(...)
|
||||||
export interface ComponentCodegenNode extends CallExpression {
|
export interface PlainComponentCodegenNode extends CallExpression {
|
||||||
callee: typeof CREATE_VNODE
|
callee: typeof CREATE_VNODE | typeof CREATE_BLOCK
|
||||||
arguments: // Comp, props, slots, patchFlag, dynamicProps
|
arguments: // Comp, props, slots, patchFlag, dynamicProps
|
||||||
| [string | RuntimeHelper]
|
| [string | RuntimeHelper]
|
||||||
| [string | RuntimeHelper, PropsExpression]
|
| [string | RuntimeHelper, PropsExpression]
|
||||||
@ -327,9 +320,9 @@ export interface ComponentCodegenNode extends CallExpression {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CompoenntCodegenNodeWithDirective = CodegenNodeWithDirective<
|
export type ComponentCodegenNode =
|
||||||
ComponentCodegenNode
|
| PlainComponentCodegenNode
|
||||||
>
|
| CodegenNodeWithDirective<PlainComponentCodegenNode>
|
||||||
|
|
||||||
export type SlotsExpression = SlotsObjectExpression | DynamicSlotsExpression
|
export type SlotsExpression = SlotsObjectExpression | DynamicSlotsExpression
|
||||||
|
|
||||||
@ -417,6 +410,11 @@ export interface SlotOutletCodegenNode extends CallExpression {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type BlockCodegenNode =
|
||||||
|
| ElementCodegenNode
|
||||||
|
| ComponentCodegenNode
|
||||||
|
| SlotOutletCodegenNode
|
||||||
|
|
||||||
export interface IfCodegenNode extends SequenceExpression {
|
export interface IfCodegenNode extends SequenceExpression {
|
||||||
expressions: [OpenBlockExpression, IfConditionalExpression]
|
expressions: [OpenBlockExpression, IfConditionalExpression]
|
||||||
}
|
}
|
||||||
@ -449,28 +447,6 @@ export interface OpenBlockExpression extends CallExpression {
|
|||||||
arguments: []
|
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 ---------------------------------------------------------------
|
// AST Utilities ---------------------------------------------------------------
|
||||||
|
|
||||||
// Some expressions, e.g. sequence and conditional expressions, are never
|
// Some expressions, e.g. sequence and conditional expressions, are never
|
||||||
@ -552,13 +528,15 @@ export function createCompoundExpression(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type InferCodegenNodeType<T> = T extends typeof CREATE_VNODE
|
type InferCodegenNodeType<T> = T extends
|
||||||
? ElementCodegenNode | ComponentCodegenNode
|
| typeof CREATE_VNODE
|
||||||
: T extends typeof CREATE_BLOCK
|
| typeof CREATE_BLOCK
|
||||||
? BlockElementCodegenNode | BlockComponentCodegenNode
|
? PlainElementCodegenNode | PlainComponentCodegenNode
|
||||||
: T extends typeof APPLY_DIRECTIVES
|
: T extends typeof APPLY_DIRECTIVES
|
||||||
? ElementCodegenNodeWithDirective | CompoenntCodegenNodeWithDirective
|
?
|
||||||
: T extends typeof RENDER_SLOT ? SlotOutletCodegenNode : CallExpression
|
| CodegenNodeWithDirective<PlainElementCodegenNode>
|
||||||
|
| CodegenNodeWithDirective<PlainComponentCodegenNode>
|
||||||
|
: T extends typeof RENDER_SLOT ? SlotOutletCodegenNode : CallExpression
|
||||||
|
|
||||||
export function createCallExpression<T extends CallExpression['callee']>(
|
export function createCallExpression<T extends CallExpression['callee']>(
|
||||||
callee: T,
|
callee: T,
|
||||||
|
@ -10,7 +10,10 @@ import {
|
|||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
JSChildNode,
|
JSChildNode,
|
||||||
SimpleExpressionNode,
|
SimpleExpressionNode,
|
||||||
ElementTypes
|
ElementTypes,
|
||||||
|
ElementCodegenNode,
|
||||||
|
ComponentCodegenNode,
|
||||||
|
createCallExpression
|
||||||
} from './ast'
|
} from './ast'
|
||||||
import { isString, isArray } from '@vue/shared'
|
import { isString, isArray } from '@vue/shared'
|
||||||
import { CompilerError, defaultOnError } from './errors'
|
import { CompilerError, defaultOnError } from './errors'
|
||||||
@ -20,7 +23,9 @@ import {
|
|||||||
CREATE_VNODE,
|
CREATE_VNODE,
|
||||||
FRAGMENT,
|
FRAGMENT,
|
||||||
RuntimeHelper,
|
RuntimeHelper,
|
||||||
helperNameMap
|
helperNameMap,
|
||||||
|
APPLY_DIRECTIVES,
|
||||||
|
CREATE_BLOCK
|
||||||
} from './runtimeHelpers'
|
} from './runtimeHelpers'
|
||||||
import { isVSlot, createBlockExpression } from './utils'
|
import { isVSlot, createBlockExpression } from './utils'
|
||||||
import { hoistStatic, isSingleElementRoot } from './transforms/hoistStatic'
|
import { hoistStatic, isSingleElementRoot } from './transforms/hoistStatic'
|
||||||
@ -147,7 +152,7 @@ function createTransformContext(
|
|||||||
}
|
}
|
||||||
const list = context.parent!.children
|
const list = context.parent!.children
|
||||||
const removalIndex = node
|
const removalIndex = node
|
||||||
? list.indexOf(node as any)
|
? list.indexOf(node)
|
||||||
: context.currentNode
|
: context.currentNode
|
||||||
? context.childIndex
|
? context.childIndex
|
||||||
: -1
|
: -1
|
||||||
@ -230,24 +235,38 @@ function finalizeRoot(root: RootNode, context: TransformContext) {
|
|||||||
const { helper } = context
|
const { helper } = context
|
||||||
const { children } = root
|
const { children } = root
|
||||||
const child = children[0]
|
const child = children[0]
|
||||||
if (isSingleElementRoot(root, child) && child.codegenNode) {
|
if (children.length === 1) {
|
||||||
// turn root element into a block
|
// if the single child is an element, turn it into a block.
|
||||||
root.codegenNode = createBlockExpression(
|
if (isSingleElementRoot(root, child) && child.codegenNode) {
|
||||||
child.codegenNode.arguments,
|
// single element root is never hoisted so codegenNode will never be
|
||||||
context
|
// SimpleExpressionNode
|
||||||
)
|
const codegenNode = child.codegenNode as
|
||||||
} else if (children.length === 1) {
|
| ElementCodegenNode
|
||||||
// - single <slot/>, IfNode, ForNode: already blocks.
|
| ComponentCodegenNode
|
||||||
// - single text node: always patched.
|
if (codegenNode.callee === APPLY_DIRECTIVES) {
|
||||||
// - transform calls without transformElement (only during tests)
|
codegenNode.arguments[0].callee = helper(CREATE_BLOCK)
|
||||||
// Just generate the node as-is
|
} else {
|
||||||
root.codegenNode = child
|
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) {
|
} else if (children.length > 1) {
|
||||||
// root has multiple nodes - return a fragment block.
|
// root has multiple nodes - return a fragment block.
|
||||||
root.codegenNode = createBlockExpression(
|
root.codegenNode = createBlockExpression(
|
||||||
[helper(FRAGMENT), `null`, root.children],
|
createCallExpression(helper(CREATE_BLOCK), [
|
||||||
|
helper(FRAGMENT),
|
||||||
|
`null`,
|
||||||
|
root.children
|
||||||
|
]),
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
// no children = noop. codegen will return null.
|
||||||
}
|
}
|
||||||
// finalize meta information
|
// finalize meta information
|
||||||
root.helpers = [...context.helpers]
|
root.helpers = [...context.helpers]
|
||||||
|
@ -2,10 +2,8 @@ import {
|
|||||||
RootNode,
|
RootNode,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
TemplateChildNode,
|
TemplateChildNode,
|
||||||
ElementNode,
|
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
ElementCodegenNode,
|
ElementCodegenNode,
|
||||||
ElementCodegenNodeWithDirective,
|
|
||||||
PlainElementNode,
|
PlainElementNode,
|
||||||
ComponentNode,
|
ComponentNode,
|
||||||
TemplateNode
|
TemplateNode
|
||||||
@ -51,7 +49,7 @@ function walk(
|
|||||||
) {
|
) {
|
||||||
if (!doNotHoistNode && isStaticNode(child, resultCache)) {
|
if (!doNotHoistNode && isStaticNode(child, resultCache)) {
|
||||||
// whole tree is static
|
// whole tree is static
|
||||||
;(child as any).codegenNode = context.hoist(child.codegenNode!)
|
child.codegenNode = context.hoist(child.codegenNode!)
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
// node may contain dynamic children, but its props may be eligible for
|
// node may contain dynamic children, but its props may be eligible for
|
||||||
@ -62,7 +60,7 @@ function walk(
|
|||||||
flag === PatchFlags.NEED_PATCH ||
|
flag === PatchFlags.NEED_PATCH ||
|
||||||
flag === PatchFlags.TEXT
|
flag === PatchFlags.TEXT
|
||||||
) {
|
) {
|
||||||
let codegenNode = child.codegenNode!
|
let codegenNode = child.codegenNode as ElementCodegenNode
|
||||||
if (codegenNode.callee === APPLY_DIRECTIVES) {
|
if (codegenNode.callee === APPLY_DIRECTIVES) {
|
||||||
codegenNode = codegenNode.arguments[0]
|
codegenNode = codegenNode.arguments[0]
|
||||||
}
|
}
|
||||||
@ -88,10 +86,8 @@ function walk(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPatchFlag(node: ElementNode): number | undefined {
|
function getPatchFlag(node: PlainElementNode): number | undefined {
|
||||||
let codegenNode = node.codegenNode as
|
let codegenNode = node.codegenNode as ElementCodegenNode
|
||||||
| ElementCodegenNode
|
|
||||||
| ElementCodegenNodeWithDirective
|
|
||||||
if (codegenNode.callee === APPLY_DIRECTIVES) {
|
if (codegenNode.callee === APPLY_DIRECTIVES) {
|
||||||
codegenNode = codegenNode.arguments[0]
|
codegenNode = codegenNode.arguments[0]
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import {
|
|||||||
createObjectExpression,
|
createObjectExpression,
|
||||||
createObjectProperty,
|
createObjectProperty,
|
||||||
ForCodegenNode,
|
ForCodegenNode,
|
||||||
PlainElementNode
|
ElementCodegenNode
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { createCompilerError, ErrorCodes } from '../errors'
|
||||||
import {
|
import {
|
||||||
@ -30,11 +30,11 @@ import {
|
|||||||
RENDER_LIST,
|
RENDER_LIST,
|
||||||
OPEN_BLOCK,
|
OPEN_BLOCK,
|
||||||
CREATE_BLOCK,
|
CREATE_BLOCK,
|
||||||
FRAGMENT
|
FRAGMENT,
|
||||||
|
APPLY_DIRECTIVES
|
||||||
} from '../runtimeHelpers'
|
} from '../runtimeHelpers'
|
||||||
import { processExpression } from './transformExpression'
|
import { processExpression } from './transformExpression'
|
||||||
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
||||||
import { PropsExpression } from './transformElement'
|
|
||||||
|
|
||||||
export const transformFor = createStructuralDirectiveTransform(
|
export const transformFor = createStructuralDirectiveTransform(
|
||||||
'for',
|
'for',
|
||||||
@ -124,34 +124,29 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||||||
// <template v-for="..." :key="..."><slot/></template>
|
// <template v-for="..." :key="..."><slot/></template>
|
||||||
// we need to inject the key to the renderSlot() call.
|
// we need to inject the key to the renderSlot() call.
|
||||||
// the props for renderSlot is passed as the 3rd argument.
|
// the props for renderSlot is passed as the 3rd argument.
|
||||||
const existingProps = childBlock.arguments[2] as
|
injectProp(childBlock, keyProperty, context)
|
||||||
| PropsExpression
|
|
||||||
| undefined
|
|
||||||
| 'null'
|
|
||||||
childBlock.arguments[2] = injectProp(
|
|
||||||
existingProps,
|
|
||||||
keyProperty,
|
|
||||||
context
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else if (isTemplate) {
|
} else if (isTemplate) {
|
||||||
// <template v-for="...">
|
// <template v-for="...">
|
||||||
// should generate a fragment block for each loop
|
// should generate a fragment block for each loop
|
||||||
childBlock = createBlockExpression(
|
childBlock = createBlockExpression(
|
||||||
[
|
createCallExpression(helper(CREATE_BLOCK), [
|
||||||
helper(FRAGMENT),
|
helper(FRAGMENT),
|
||||||
keyProperty ? createObjectExpression([keyProperty]) : `null`,
|
keyProperty ? createObjectExpression([keyProperty]) : `null`,
|
||||||
node.children
|
node.children
|
||||||
],
|
]),
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// Normal element v-for. Directly use the child's codegenNode
|
// Normal element v-for. Directly use the child's codegenNode
|
||||||
// arguments, but replace createVNode() with createBlock()
|
// arguments, but replace createVNode() with createBlock()
|
||||||
childBlock = createBlockExpression(
|
let codegenNode = node.codegenNode as ElementCodegenNode
|
||||||
(node as PlainElementNode).codegenNode!.arguments,
|
if (codegenNode.callee === APPLY_DIRECTIVES) {
|
||||||
context
|
codegenNode.arguments[0].callee = helper(CREATE_BLOCK)
|
||||||
)
|
} else {
|
||||||
|
codegenNode.callee = helper(CREATE_BLOCK)
|
||||||
|
}
|
||||||
|
childBlock = createBlockExpression(codegenNode, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderExp.arguments.push(
|
renderExp.arguments.push(
|
||||||
|
@ -23,9 +23,7 @@ import {
|
|||||||
BlockCodegenNode,
|
BlockCodegenNode,
|
||||||
SlotOutletCodegenNode,
|
SlotOutletCodegenNode,
|
||||||
ElementCodegenNode,
|
ElementCodegenNode,
|
||||||
ComponentCodegenNode,
|
ComponentCodegenNode
|
||||||
ElementCodegenNodeWithDirective,
|
|
||||||
CompoenntCodegenNodeWithDirective
|
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { createCompilerError, ErrorCodes } from '../errors'
|
||||||
import { processExpression } from './transformExpression'
|
import { processExpression } from './transformExpression'
|
||||||
@ -35,8 +33,7 @@ import {
|
|||||||
EMPTY,
|
EMPTY,
|
||||||
FRAGMENT,
|
FRAGMENT,
|
||||||
APPLY_DIRECTIVES,
|
APPLY_DIRECTIVES,
|
||||||
CREATE_VNODE,
|
CREATE_VNODE
|
||||||
RENDER_SLOT
|
|
||||||
} from '../runtimeHelpers'
|
} from '../runtimeHelpers'
|
||||||
import { injectProp } from '../utils'
|
import { injectProp } from '../utils'
|
||||||
|
|
||||||
@ -196,8 +193,6 @@ function createChildrenCodegenNode(
|
|||||||
const childCodegen = (child as ElementNode).codegenNode as
|
const childCodegen = (child as ElementNode).codegenNode as
|
||||||
| ElementCodegenNode
|
| ElementCodegenNode
|
||||||
| ComponentCodegenNode
|
| ComponentCodegenNode
|
||||||
| ElementCodegenNodeWithDirective
|
|
||||||
| CompoenntCodegenNodeWithDirective
|
|
||||||
| SlotOutletCodegenNode
|
| SlotOutletCodegenNode
|
||||||
let vnodeCall = childCodegen
|
let vnodeCall = childCodegen
|
||||||
// Element with custom directives. Locate the actual createVNode() call.
|
// Element with custom directives. Locate the actual createVNode() call.
|
||||||
@ -206,22 +201,10 @@ function createChildrenCodegenNode(
|
|||||||
}
|
}
|
||||||
// Change createVNode to createBlock.
|
// Change createVNode to createBlock.
|
||||||
if (vnodeCall.callee === CREATE_VNODE) {
|
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
|
// inject branch key
|
||||||
const existingProps = vnodeCall.arguments[
|
injectProp(vnodeCall, keyProperty, context)
|
||||||
propsIndex
|
|
||||||
] as ElementCodegenNode['arguments'][1]
|
|
||||||
vnodeCall.arguments[propsIndex] = injectProp(
|
|
||||||
existingProps,
|
|
||||||
keyProperty,
|
|
||||||
context
|
|
||||||
)
|
|
||||||
return childCodegen
|
return childCodegen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,17 @@ import {
|
|||||||
JSChildNode,
|
JSChildNode,
|
||||||
createObjectExpression,
|
createObjectExpression,
|
||||||
SlotOutletNode,
|
SlotOutletNode,
|
||||||
TemplateNode
|
TemplateNode,
|
||||||
|
BlockCodegenNode,
|
||||||
|
ElementCodegenNode,
|
||||||
|
SlotOutletCodegenNode,
|
||||||
|
ComponentCodegenNode
|
||||||
} from './ast'
|
} from './ast'
|
||||||
import { parse } from 'acorn'
|
import { parse } from 'acorn'
|
||||||
import { walk } from 'estree-walker'
|
import { walk } from 'estree-walker'
|
||||||
import { TransformContext } from './transform'
|
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 { isString, isFunction } from '@vue/shared'
|
||||||
import { PropsExpression } from './transforms/transformElement'
|
|
||||||
|
|
||||||
// cache node requires
|
// cache node requires
|
||||||
// lazy require dependencies so that they don't end up in rollup's dep graph
|
// lazy require dependencies so that they don't end up in rollup's dep graph
|
||||||
@ -168,12 +171,12 @@ export function findProp(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createBlockExpression(
|
export function createBlockExpression(
|
||||||
args: CallExpression['arguments'],
|
blockExp: BlockCodegenNode,
|
||||||
context: TransformContext
|
context: TransformContext
|
||||||
): SequenceExpression {
|
): SequenceExpression {
|
||||||
return createSequenceExpression([
|
return createSequenceExpression([
|
||||||
createCallExpression(context.helper(OPEN_BLOCK)),
|
createCallExpression(context.helper(OPEN_BLOCK)),
|
||||||
createCallExpression(context.helper(CREATE_BLOCK), args)
|
blockExp
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,12 +194,15 @@ export const isSlotOutlet = (
|
|||||||
node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT
|
node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT
|
||||||
|
|
||||||
export function injectProp(
|
export function injectProp(
|
||||||
props: PropsExpression | undefined | 'null',
|
node: ElementCodegenNode | ComponentCodegenNode | SlotOutletCodegenNode,
|
||||||
prop: Property,
|
prop: Property,
|
||||||
context: TransformContext
|
context: TransformContext
|
||||||
): ObjectExpression | CallExpression {
|
) {
|
||||||
if (props == null || props === `null`) {
|
let propsWithInjection: ObjectExpression | CallExpression
|
||||||
return createObjectExpression([prop])
|
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) {
|
} else if (props.type === NodeTypes.JS_CALL_EXPRESSION) {
|
||||||
// merged props... add ours
|
// merged props... add ours
|
||||||
// only inject key to object literal if it's the first argument so that
|
// only inject key to object literal if it's the first argument so that
|
||||||
@ -207,17 +213,22 @@ export function injectProp(
|
|||||||
} else {
|
} else {
|
||||||
props.arguments.unshift(createObjectExpression([prop]))
|
props.arguments.unshift(createObjectExpression([prop]))
|
||||||
}
|
}
|
||||||
return props
|
propsWithInjection = props
|
||||||
} else if (props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
|
} else if (props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
|
||||||
props.properties.unshift(prop)
|
props.properties.unshift(prop)
|
||||||
return props
|
propsWithInjection = props
|
||||||
} else {
|
} else {
|
||||||
// single v-bind with expression, return a merged replacement
|
// single v-bind with expression, return a merged replacement
|
||||||
return createCallExpression(context.helper(MERGE_PROPS), [
|
propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [
|
||||||
createObjectExpression([prop]),
|
createObjectExpression([prop]),
|
||||||
props
|
props
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
if (node.callee === RENDER_SLOT) {
|
||||||
|
node.arguments[2] = propsWithInjection
|
||||||
|
} else {
|
||||||
|
node.arguments[1] = propsWithInjection
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toValidAssetId(
|
export function toValidAssetId(
|
||||||
|
Loading…
Reference in New Issue
Block a user