Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,17 @@ export function render(_ctx) {
return n0
}"
`;

exports[`compiler: v-if > v-on with v-if 1`] = `
"import { setDynamicEvents as _setDynamicEvents, renderEffect as _renderEffect, createIf as _createIf, template as _template } from 'vue';
const t0 = _template("<button>w/ v-if</button>", true)

export function render(_ctx) {
const n0 = _createIf(() => (true), () => {
const n2 = t0()
_renderEffect(() => _setDynamicEvents(n2, { click: _ctx.clickEvent }))
return n2
}, null, true)
return n0
}"
`;
182 changes: 178 additions & 4 deletions packages/compiler-vapor/__tests__/transforms/vIf.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
transformVOnce,
transformVText,
} from '../../src'
import { NodeTypes } from '@vue/compiler-dom'
import { ErrorCodes, NodeTypes, type RootNode } from '@vue/compiler-dom'

const compileWithVIf = makeCompile({
nodeTransforms: [
Expand Down Expand Up @@ -380,7 +380,181 @@ describe('compiler: v-if', () => {
])
})

describe.todo('errors')
describe.todo('codegen')
test.todo('v-on with v-if')
test('v-on with v-if', () => {
const { code, ir } = compileWithVIf(
`<button v-on="{ click: clickEvent }" v-if="true">w/ v-if</button>`,
)
expect(code).toMatchSnapshot()
expect([...ir.template.keys()]).toEqual(['<button>w/ v-if</button>'])

expect(ir.block.returns).toEqual([0])
expect(ir.block.dynamic.children[0].operation).toMatchObject({
type: IRNodeTypes.IF,
condition: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'true',
isStatic: false,
},
positive: {
type: IRNodeTypes.BLOCK,
dynamic: {
children: [{ template: 0 }],
},
},
})
})

describe('errors', () => {
test('error on v-else missing adjacent v-if', () => {
const onError = vi.fn()

{
const { ir } = compileWithVIf(`<div v-else/>`, { onError })
expect(onError.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: ir.node.loc,
},
])
}

{
const { ir } = compileWithVIf(`<div/><div v-else/>`, {
onError,
})
expect(onError.mock.calls[1]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: (ir.block.node as RootNode).children[1].loc,
},
])
}

{
const { ir } = compileWithVIf(`<div/>foo<div v-else/>`, { onError })
expect(onError.mock.calls[2]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: (ir.block.node as RootNode).children[2].loc,
},
])
}

{
const { ir } = compileWithVIf(`<div v-if="bar"/>foo<div v-else/>`, {
onError,
})
expect(onError.mock.calls[3]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: (ir.block.node as RootNode).children[2].loc,
},
])
}

// Non-breaking space
{
const { ir } = compileWithVIf(`<div v-if="bar"/>\u00a0<div v-else/>`, {
onError,
})
expect(onError.mock.calls[4]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: (ir.block.node as RootNode).children[2].loc,
},
])
}
})

test('error on v-else-if missing adjacent v-if or v-else-if', () => {
const onError = vi.fn()
{
const { ir } = compileWithVIf(`<div v-else-if="foo"/>`, {
onError,
})
expect(onError.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: ir.node.loc,
},
])
}
{
const { ir } = compileWithVIf(`<div/><div v-else-if="foo"/>`, {
onError,
})
expect(onError.mock.calls[1]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: (ir.block.node as RootNode).children[1].loc,
},
])
}
{
const { ir } = compileWithVIf(`<div/>foo<div v-else-if="foo"/>`, {
onError,
})
expect(onError.mock.calls[2]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: (ir.block.node as RootNode).children[2].loc,
},
])
}
{
const { ir } = compileWithVIf(
`<div v-if="bar"/>foo<div v-else-if="foo"/>`,
{ onError },
)
expect(onError.mock.calls[3]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: (ir.block.node as RootNode).children[2].loc,
},
])
}
{
// Non-breaking space
const { ir } = compileWithVIf(
`<div v-if="bar"/>\u00a0<div v-else-if="foo"/>`,
{ onError },
)
expect(onError.mock.calls[4]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: (ir.block.node as RootNode).children[2].loc,
},
])
}

{
const { ir } = compileWithVIf(
`<div v-if="notOk"/><div v-else/><div v-else-if="ok"/>`,
{ onError },
)
expect(onError.mock.calls[5]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: (ir.block.node as RootNode).children[2].loc,
},
])
}
})

test('error on adjacent v-else', () => {
const onError = vi.fn()

const { ir } = compileWithVIf(
`<div v-if="false"/><div v-else/><div v-else/>`,
{ onError },
)

expect(onError.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
loc: (ir.block.node as RootNode).children[2].loc,
},
])
})
})
})
10 changes: 2 additions & 8 deletions packages/compiler-vapor/src/transforms/transformComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
type ElementNode,
NodeTypes,
type TemplateChildNode,
isCommentOrWhitespace,
} from '@vue/compiler-dom'
import type { NodeTransform, TransformContext } from '../transform'
import { DynamicFlag } from '../ir'
Expand Down Expand Up @@ -31,7 +32,7 @@ export function getSiblingIf(
let i = siblings.indexOf(context.node)
while (reverse ? --i >= 0 : ++i < siblings.length) {
sibling = siblings[i]
if (!isCommentLike(sibling)) {
if (!isCommentOrWhitespace(sibling)) {
break
}
}
Expand All @@ -48,10 +49,3 @@ export function getSiblingIf(
return sibling
}
}

function isCommentLike(node: TemplateChildNode) {
return (
node.type === NodeTypes.COMMENT ||
(node.type === NodeTypes.TEXT && !node.content.trim().length)
)
}
Loading