feat(compiler): support v-for on named slots
This commit is contained in:
@@ -14,9 +14,7 @@ return function render() {
|
||||
_toString(world.burn()),
|
||||
(_openBlock(), ok
|
||||
? _createBlock(\\"div\\", { key: 0 }, \\"yes\\")
|
||||
: _createBlock(_Fragment, { key: 1 }, [
|
||||
\\"no\\"
|
||||
])),
|
||||
: _createBlock(_Fragment, { key: 1 }, [\\"no\\"])),
|
||||
(_openBlock(), _createBlock(_Fragment, null, _renderList(list, (value, index) => {
|
||||
return (_openBlock(), _createBlock(\\"div\\", null, [
|
||||
_createVNode(\\"span\\", null, _toString(value + index), 1 /* TEXT */)
|
||||
@@ -39,9 +37,7 @@ return function render() {
|
||||
toString(_ctx.world.burn()),
|
||||
(openBlock(), (_ctx.ok)
|
||||
? createBlock(\\"div\\", { key: 0 }, \\"yes\\")
|
||||
: createBlock(Fragment, { key: 1 }, [
|
||||
\\"no\\"
|
||||
])),
|
||||
: createBlock(Fragment, { key: 1 }, [\\"no\\"])),
|
||||
(openBlock(), createBlock(Fragment, null, renderList(_ctx.list, (value, index) => {
|
||||
return (openBlock(), createBlock(\\"div\\", null, [
|
||||
createVNode(\\"span\\", null, toString(value + index), 1 /* TEXT */)
|
||||
@@ -63,9 +59,7 @@ export default function render() {
|
||||
_toString(_ctx.world.burn()),
|
||||
(openBlock(), (_ctx.ok)
|
||||
? createBlock(\\"div\\", { key: 0 }, \\"yes\\")
|
||||
: createBlock(Fragment, { key: 1 }, [
|
||||
\\"no\\"
|
||||
])),
|
||||
: createBlock(Fragment, { key: 1 }, [\\"no\\"])),
|
||||
(openBlock(), createBlock(Fragment, null, renderList(_ctx.list, (value, index) => {
|
||||
return (openBlock(), createBlock(\\"div\\", null, [
|
||||
createVNode(\\"span\\", null, _toString(value + index), 1 /* TEXT */)
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
ElementTypes
|
||||
} from '../src'
|
||||
import { CREATE_VNODE } from '../src/runtimeConstants'
|
||||
import { isString } from '@vue/shared'
|
||||
|
||||
const leadingBracketRE = /^\[/
|
||||
const bracketsRE = /^\[|\]$/g
|
||||
@@ -26,11 +27,13 @@ export function createObjectMatcher(obj: any) {
|
||||
content: key.replace(bracketsRE, ''),
|
||||
isStatic: !leadingBracketRE.test(key)
|
||||
},
|
||||
value: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: obj[key].replace(bracketsRE, ''),
|
||||
isStatic: !leadingBracketRE.test(obj[key])
|
||||
}
|
||||
value: isString(obj[key])
|
||||
? {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: obj[key].replace(bracketsRE, ''),
|
||||
isStatic: !leadingBracketRE.test(obj[key])
|
||||
}
|
||||
: obj[key]
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,9 +71,7 @@ return function render() {
|
||||
? _createBlock(\\"div\\", { key: 0 })
|
||||
: orNot
|
||||
? _createBlock(\\"p\\", { key: 1 })
|
||||
: _createBlock(_Fragment, { key: 2 }, [
|
||||
\\"fine\\"
|
||||
]))
|
||||
: _createBlock(_Fragment, { key: 2 }, [\\"fine\\"]))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
@@ -8,14 +8,8 @@ return function render() {
|
||||
const _component_Comp = resolveComponent(\\"Comp\\")
|
||||
|
||||
return (openBlock(), createBlock(_component_Comp, null, {
|
||||
[_ctx.one]: ({ foo }) => [
|
||||
toString(foo),
|
||||
toString(_ctx.bar)
|
||||
],
|
||||
[_ctx.two]: ({ bar }) => [
|
||||
toString(_ctx.foo),
|
||||
toString(bar)
|
||||
]
|
||||
[_ctx.one]: ({ foo }) => [toString(foo), toString(_ctx.bar)],
|
||||
[_ctx.two]: ({ bar }) => [toString(_ctx.foo), toString(bar)]
|
||||
}, 256 /* DYNAMIC_SLOTS */))
|
||||
}"
|
||||
`;
|
||||
@@ -28,10 +22,7 @@ return function render() {
|
||||
const _component_Comp = resolveComponent(\\"Comp\\")
|
||||
|
||||
return (openBlock(), createBlock(_component_Comp, null, {
|
||||
default: ({ foo }) => [
|
||||
toString(foo),
|
||||
toString(_ctx.bar)
|
||||
]
|
||||
default: ({ foo }) => [toString(foo), toString(_ctx.bar)]
|
||||
}))
|
||||
}"
|
||||
`;
|
||||
@@ -51,6 +42,92 @@ 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
|
||||
|
||||
return function render() {
|
||||
const _ctx = this
|
||||
const _component_Comp = resolveComponent(\\"Comp\\")
|
||||
|
||||
return (openBlock(), createBlock(_component_Comp, null, createSlots({}, [
|
||||
renderList(_ctx.list, (name) => {
|
||||
return {
|
||||
name: name,
|
||||
fn: () => [toString(name)]
|
||||
}
|
||||
})
|
||||
]), 256 /* DYNAMIC_SLOTS */))
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: transform component slots named slot with v-if + prefixIdentifiers: true 1`] = `
|
||||
"const { toString, resolveComponent, createSlots, createVNode, openBlock, createBlock } = Vue
|
||||
|
||||
return function render() {
|
||||
const _ctx = this
|
||||
const _component_Comp = resolveComponent(\\"Comp\\")
|
||||
|
||||
return (openBlock(), createBlock(_component_Comp, null, createSlots({}, [
|
||||
(_ctx.ok)
|
||||
? {
|
||||
name: \\"one\\",
|
||||
fn: (props) => [toString(props)]
|
||||
}
|
||||
: undefined
|
||||
]), 256 /* DYNAMIC_SLOTS */))
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: transform component slots named slot with v-if + v-else-if + v-else 1`] = `
|
||||
"const _Vue = Vue
|
||||
|
||||
return function render() {
|
||||
with (this) {
|
||||
const { resolveComponent: _resolveComponent, createSlots: _createSlots, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
|
||||
|
||||
const _component_Comp = _resolveComponent(\\"Comp\\")
|
||||
|
||||
return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({}, [
|
||||
ok
|
||||
? {
|
||||
name: \\"one\\",
|
||||
fn: () => [\\"foo\\"]
|
||||
}
|
||||
: orNot
|
||||
? {
|
||||
name: \\"two\\",
|
||||
fn: (props) => [\\"bar\\"]
|
||||
}
|
||||
: {
|
||||
name: \\"one\\",
|
||||
fn: () => [\\"baz\\"]
|
||||
}
|
||||
]), 256 /* DYNAMIC_SLOTS */))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: transform component slots named slot with v-if 1`] = `
|
||||
"const _Vue = Vue
|
||||
|
||||
return function render() {
|
||||
with (this) {
|
||||
const { resolveComponent: _resolveComponent, createSlots: _createSlots, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
|
||||
|
||||
const _component_Comp = _resolveComponent(\\"Comp\\")
|
||||
|
||||
return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({}, [
|
||||
ok
|
||||
? {
|
||||
name: \\"one\\",
|
||||
fn: () => [\\"hello\\"]
|
||||
}
|
||||
: undefined
|
||||
]), 256 /* DYNAMIC_SLOTS */))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: transform component slots named slots 1`] = `
|
||||
"const { toString, resolveComponent, createVNode, openBlock, createBlock } = Vue
|
||||
|
||||
@@ -59,14 +136,8 @@ return function render() {
|
||||
const _component_Comp = resolveComponent(\\"Comp\\")
|
||||
|
||||
return (openBlock(), createBlock(_component_Comp, null, {
|
||||
one: ({ foo }) => [
|
||||
toString(foo),
|
||||
toString(_ctx.bar)
|
||||
],
|
||||
two: ({ bar }) => [
|
||||
toString(_ctx.foo),
|
||||
toString(bar)
|
||||
]
|
||||
one: ({ foo }) => [toString(foo), toString(_ctx.bar)],
|
||||
two: ({ bar }) => [toString(_ctx.foo), toString(bar)]
|
||||
}))
|
||||
}"
|
||||
`;
|
||||
@@ -82,11 +153,7 @@ return function render() {
|
||||
return (openBlock(), createBlock(_component_Comp, null, {
|
||||
default: ({ foo }) => [
|
||||
createVNode(_component_Inner, null, {
|
||||
default: ({ bar }) => [
|
||||
toString(foo),
|
||||
toString(bar),
|
||||
toString(_ctx.baz)
|
||||
]
|
||||
default: ({ bar }) => [toString(foo), toString(bar), toString(_ctx.baz)]
|
||||
}),
|
||||
toString(foo),
|
||||
toString(_ctx.bar),
|
||||
|
||||
@@ -11,14 +11,20 @@ import { transformElement } from '../../src/transforms/transformElement'
|
||||
import { transformOn } from '../../src/transforms/vOn'
|
||||
import { transformBind } from '../../src/transforms/vBind'
|
||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||
import { trackSlotScopes } from '../../src/transforms/vSlot'
|
||||
import {
|
||||
trackSlotScopes,
|
||||
trackVForSlotScopes
|
||||
} from '../../src/transforms/vSlot'
|
||||
import { CREATE_SLOTS, RENDER_LIST } from '../../src/runtimeConstants'
|
||||
import { createObjectMatcher } from '../testUtils'
|
||||
import { PatchFlags } from '@vue/shared'
|
||||
|
||||
function parseWithSlots(template: string, options: CompilerOptions = {}) {
|
||||
const ast = parse(template)
|
||||
transform(ast, {
|
||||
nodeTransforms: [
|
||||
...(options.prefixIdentifiers
|
||||
? [transformExpression, trackSlotScopes]
|
||||
? [trackVForSlotScopes, transformExpression, trackSlotScopes]
|
||||
: []),
|
||||
transformElement
|
||||
],
|
||||
@@ -314,118 +320,311 @@ describe('compiler: transform component slots', () => {
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('error on extraneous children w/ named slots', () => {
|
||||
const onError = jest.fn()
|
||||
const source = `<Comp><template #default>foo</template>bar</Comp>`
|
||||
parseWithSlots(source, { onError })
|
||||
const index = source.indexOf('bar')
|
||||
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||
code: ErrorCodes.X_EXTRANEOUS_NON_SLOT_CHILDREN,
|
||||
loc: {
|
||||
source: `bar`,
|
||||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
},
|
||||
end: {
|
||||
offset: index + 3,
|
||||
line: 1,
|
||||
column: index + 4
|
||||
test('named slot with v-if', () => {
|
||||
const { root, slots } = parseWithSlots(
|
||||
`<Comp>
|
||||
<template #one v-if="ok">hello</template>
|
||||
</Comp>`
|
||||
)
|
||||
expect(slots).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_SLOTS}`,
|
||||
arguments: [
|
||||
createObjectMatcher({}),
|
||||
{
|
||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||
elements: [
|
||||
{
|
||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||
test: { content: `ok` },
|
||||
consequent: createObjectMatcher({
|
||||
name: `one`,
|
||||
fn: {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
returns: [{ type: NodeTypes.TEXT, content: `hello` }]
|
||||
}
|
||||
}),
|
||||
alternate: {
|
||||
content: `undefined`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
expect((root as any).children[0].codegenNode.arguments[3]).toMatch(
|
||||
PatchFlags.DYNAMIC_SLOTS + ''
|
||||
)
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('error on duplicated slot names', () => {
|
||||
const onError = jest.fn()
|
||||
const source = `<Comp><template #foo></template><template #foo></template></Comp>`
|
||||
parseWithSlots(source, { onError })
|
||||
const index = source.lastIndexOf('#foo')
|
||||
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||
code: ErrorCodes.X_DUPLICATE_SLOT_NAMES,
|
||||
loc: {
|
||||
source: `#foo`,
|
||||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
},
|
||||
end: {
|
||||
offset: index + 4,
|
||||
line: 1,
|
||||
column: index + 5
|
||||
test('named slot with v-if + prefixIdentifiers: true', () => {
|
||||
const { root, slots } = parseWithSlots(
|
||||
`<Comp>
|
||||
<template #one="props" v-if="ok">{{ props }}</template>
|
||||
</Comp>`,
|
||||
{ prefixIdentifiers: true }
|
||||
)
|
||||
expect(slots).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: CREATE_SLOTS,
|
||||
arguments: [
|
||||
createObjectMatcher({}),
|
||||
{
|
||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||
elements: [
|
||||
{
|
||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||
test: { content: `_ctx.ok` },
|
||||
consequent: createObjectMatcher({
|
||||
name: `one`,
|
||||
fn: {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: { content: `props` },
|
||||
returns: [
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: { content: `props` }
|
||||
}
|
||||
]
|
||||
}
|
||||
}),
|
||||
alternate: {
|
||||
content: `undefined`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
expect((root as any).children[0].codegenNode.arguments[3]).toMatch(
|
||||
PatchFlags.DYNAMIC_SLOTS + ''
|
||||
)
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('error on invalid mixed slot usage', () => {
|
||||
const onError = jest.fn()
|
||||
const source = `<Comp v-slot="foo"><template #foo></template></Comp>`
|
||||
parseWithSlots(source, { onError })
|
||||
const index = source.lastIndexOf('#foo')
|
||||
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||
code: ErrorCodes.X_MIXED_SLOT_USAGE,
|
||||
loc: {
|
||||
source: `#foo`,
|
||||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
},
|
||||
end: {
|
||||
offset: index + 4,
|
||||
line: 1,
|
||||
column: index + 5
|
||||
test('named slot with v-if + v-else-if + v-else', () => {
|
||||
const { root, slots } = parseWithSlots(
|
||||
`<Comp>
|
||||
<template #one v-if="ok">foo</template>
|
||||
<template #two="props" v-else-if="orNot">bar</template>
|
||||
<template #one v-else>baz</template>
|
||||
</Comp>`
|
||||
)
|
||||
expect(slots).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_SLOTS}`,
|
||||
arguments: [
|
||||
createObjectMatcher({}),
|
||||
{
|
||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||
elements: [
|
||||
{
|
||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||
test: { content: `ok` },
|
||||
consequent: createObjectMatcher({
|
||||
name: `one`,
|
||||
fn: {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: undefined,
|
||||
returns: [{ type: NodeTypes.TEXT, content: `foo` }]
|
||||
}
|
||||
}),
|
||||
alternate: {
|
||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||
test: { content: `orNot` },
|
||||
consequent: createObjectMatcher({
|
||||
name: `two`,
|
||||
fn: {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: { content: `props` },
|
||||
returns: [{ type: NodeTypes.TEXT, content: `bar` }]
|
||||
}
|
||||
}),
|
||||
alternate: createObjectMatcher({
|
||||
name: `one`,
|
||||
fn: {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: undefined,
|
||||
returns: [{ type: NodeTypes.TEXT, content: `baz` }]
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
expect((root as any).children[0].codegenNode.arguments[3]).toMatch(
|
||||
PatchFlags.DYNAMIC_SLOTS + ''
|
||||
)
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('error on v-slot usage on plain elements', () => {
|
||||
const onError = jest.fn()
|
||||
const source = `<div v-slot/>`
|
||||
parseWithSlots(source, { onError })
|
||||
const index = source.indexOf('v-slot')
|
||||
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||
code: ErrorCodes.X_MISPLACED_V_SLOT,
|
||||
loc: {
|
||||
source: `v-slot`,
|
||||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
},
|
||||
end: {
|
||||
offset: index + 6,
|
||||
line: 1,
|
||||
column: index + 7
|
||||
test('named slot with v-for w/ prefixIdentifiers: true', () => {
|
||||
const { root, slots } = parseWithSlots(
|
||||
`<Comp>
|
||||
<template v-for="name in list" #[name]>{{ name }}</template>
|
||||
</Comp>`,
|
||||
{ prefixIdentifiers: true }
|
||||
)
|
||||
expect(slots).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: CREATE_SLOTS,
|
||||
arguments: [
|
||||
createObjectMatcher({}),
|
||||
{
|
||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||
elements: [
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: RENDER_LIST,
|
||||
arguments: [
|
||||
{ content: `_ctx.list` },
|
||||
{
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: [{ content: `name` }],
|
||||
returns: createObjectMatcher({
|
||||
name: `[name]`,
|
||||
fn: {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
returns: [
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: { content: `name`, isStatic: false }
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
expect((root as any).children[0].codegenNode.arguments[3]).toMatch(
|
||||
PatchFlags.DYNAMIC_SLOTS + ''
|
||||
)
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('error on named slot on component', () => {
|
||||
const onError = jest.fn()
|
||||
const source = `<Comp v-slot:foo>foo</Comp>`
|
||||
parseWithSlots(source, { onError })
|
||||
const index = source.indexOf('v-slot')
|
||||
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||
code: ErrorCodes.X_NAMED_SLOT_ON_COMPONENT,
|
||||
loc: {
|
||||
source: `v-slot:foo`,
|
||||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
},
|
||||
end: {
|
||||
offset: index + 10,
|
||||
line: 1,
|
||||
column: index + 11
|
||||
describe('errors', () => {
|
||||
test('error on extraneous children w/ named slots', () => {
|
||||
const onError = jest.fn()
|
||||
const source = `<Comp><template #default>foo</template>bar</Comp>`
|
||||
parseWithSlots(source, { onError })
|
||||
const index = source.indexOf('bar')
|
||||
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||
code: ErrorCodes.X_EXTRANEOUS_NON_SLOT_CHILDREN,
|
||||
loc: {
|
||||
source: `bar`,
|
||||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
},
|
||||
end: {
|
||||
offset: index + 3,
|
||||
line: 1,
|
||||
column: index + 4
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('error on duplicated slot names', () => {
|
||||
const onError = jest.fn()
|
||||
const source = `<Comp><template #foo></template><template #foo></template></Comp>`
|
||||
parseWithSlots(source, { onError })
|
||||
const index = source.lastIndexOf('#foo')
|
||||
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||
code: ErrorCodes.X_DUPLICATE_SLOT_NAMES,
|
||||
loc: {
|
||||
source: `#foo`,
|
||||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
},
|
||||
end: {
|
||||
offset: index + 4,
|
||||
line: 1,
|
||||
column: index + 5
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('error on invalid mixed slot usage', () => {
|
||||
const onError = jest.fn()
|
||||
const source = `<Comp v-slot="foo"><template #foo></template></Comp>`
|
||||
parseWithSlots(source, { onError })
|
||||
const index = source.lastIndexOf('#foo')
|
||||
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||
code: ErrorCodes.X_MIXED_SLOT_USAGE,
|
||||
loc: {
|
||||
source: `#foo`,
|
||||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
},
|
||||
end: {
|
||||
offset: index + 4,
|
||||
line: 1,
|
||||
column: index + 5
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('error on v-slot usage on plain elements', () => {
|
||||
const onError = jest.fn()
|
||||
const source = `<div v-slot/>`
|
||||
parseWithSlots(source, { onError })
|
||||
const index = source.indexOf('v-slot')
|
||||
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||
code: ErrorCodes.X_MISPLACED_V_SLOT,
|
||||
loc: {
|
||||
source: `v-slot`,
|
||||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
},
|
||||
end: {
|
||||
offset: index + 6,
|
||||
line: 1,
|
||||
column: index + 7
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('error on named slot on component', () => {
|
||||
const onError = jest.fn()
|
||||
const source = `<Comp v-slot:foo>foo</Comp>`
|
||||
parseWithSlots(source, { onError })
|
||||
const index = source.indexOf('v-slot')
|
||||
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||
code: ErrorCodes.X_NAMED_SLOT_ON_COMPONENT,
|
||||
loc: {
|
||||
source: `v-slot:foo`,
|
||||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
},
|
||||
end: {
|
||||
offset: index + 10,
|
||||
line: 1,
|
||||
column: index + 11
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user