fix(compiler): handle block nodes with custom directives + improve ast types
This commit is contained in:
@@ -34,7 +34,7 @@ function createRoot(options: Partial<RootNode> = {}): RootNode {
|
||||
components: [],
|
||||
directives: [],
|
||||
hoists: [],
|
||||
codegenNode: undefined,
|
||||
codegenNode: createSimpleExpression(`null`, false),
|
||||
loc: locStub,
|
||||
...options
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
locStub,
|
||||
Namespaces,
|
||||
ElementTypes,
|
||||
ElementCodegenNode
|
||||
PlainElementCodegenNode
|
||||
} from '../src'
|
||||
import { CREATE_VNODE } from '../src/runtimeHelpers'
|
||||
import { isString, PatchFlags, PatchFlagNames, isArray } from '@vue/shared'
|
||||
@@ -39,7 +39,7 @@ export function createObjectMatcher(obj: any) {
|
||||
}
|
||||
|
||||
export function createElementWithCodegen(
|
||||
args: ElementCodegenNode['arguments']
|
||||
args: PlainElementCodegenNode['arguments']
|
||||
): ElementNode {
|
||||
return {
|
||||
type: NodeTypes.ELEMENT,
|
||||
|
||||
@@ -14,7 +14,8 @@ import {
|
||||
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'
|
||||
@@ -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', () => {
|
||||
const ast = transformWithCodegen(`hello`)
|
||||
expect(ast.codegenNode).toMatchObject({
|
||||
|
||||
@@ -11,7 +11,7 @@ const _hoisted_1 = _createVNode(\\"p\\", null, [
|
||||
|
||||
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
|
||||
@@ -29,7 +29,7 @@ const _hoisted_2 = _createVNode(\\"div\\")
|
||||
|
||||
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,
|
||||
@@ -47,7 +47,7 @@ const _hoisted_1 = _createVNode(\\"span\\", { class: \\"inline\\" }, \\"hello\\"
|
||||
|
||||
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
|
||||
@@ -64,7 +64,7 @@ const _hoisted_1 = { id: \\"foo\\" }
|
||||
|
||||
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\\")
|
||||
|
||||
@@ -85,7 +85,7 @@ const _hoisted_1 = { id: \\"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 */)
|
||||
@@ -102,7 +102,7 @@ const _hoisted_1 = { id: \\"foo\\" }
|
||||
|
||||
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\\")
|
||||
|
||||
@@ -120,7 +120,7 @@ exports[`compiler: hositStatic transform should NOT hoist components 1`] = `
|
||||
|
||||
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\\")
|
||||
|
||||
@@ -136,7 +136,7 @@ exports[`compiler: hositStatic transform should NOT hoist element with dynamic p
|
||||
|
||||
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\\"])
|
||||
@@ -150,7 +150,7 @@ exports[`compiler: hositStatic transform should NOT hoist root node 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\\"))
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ exports[`compiler: optimize interpolation consecutive text between elements 1`]
|
||||
|
||||
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\\"),
|
||||
@@ -33,7 +33,7 @@ exports[`compiler: optimize interpolation consecutive text mixed with elements 1
|
||||
|
||||
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\\"),
|
||||
|
||||
@@ -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`] = `
|
||||
"const _Vue = Vue
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// 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
|
||||
@@ -16,7 +16,7 @@ return function render() {
|
||||
`;
|
||||
|
||||
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
|
||||
@@ -30,7 +30,7 @@ return function render() {
|
||||
`;
|
||||
|
||||
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
|
||||
@@ -46,7 +46,7 @@ return function render() {
|
||||
`;
|
||||
|
||||
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
|
||||
@@ -64,7 +64,7 @@ return function render() {
|
||||
`;
|
||||
|
||||
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
|
||||
@@ -86,7 +86,7 @@ exports[`compiler: transform component slots named slot with v-if + v-else-if +
|
||||
|
||||
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\\")
|
||||
|
||||
@@ -115,7 +115,7 @@ exports[`compiler: transform component slots named slot with v-if 1`] = `
|
||||
|
||||
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\\")
|
||||
|
||||
@@ -132,7 +132,7 @@ return function render() {
|
||||
`;
|
||||
|
||||
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
|
||||
@@ -147,7 +147,7 @@ return function render() {
|
||||
`;
|
||||
|
||||
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
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
import {
|
||||
ElementNode,
|
||||
CompilerOptions,
|
||||
parse,
|
||||
transform,
|
||||
ErrorCodes
|
||||
} from '../../src'
|
||||
import { CompilerOptions, parse, transform, ErrorCodes } from '../../src'
|
||||
import {
|
||||
RESOLVE_COMPONENT,
|
||||
CREATE_VNODE,
|
||||
@@ -35,12 +29,14 @@ function parseWithElementTransform(
|
||||
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 {
|
||||
|
||||
@@ -22,7 +22,8 @@ import {
|
||||
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'
|
||||
@@ -845,5 +846,28 @@ describe('compiler: v-for', () => {
|
||||
})
|
||||
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()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user