Skip to content

Commit 597ada3

Browse files
committed
test: tests for v-bind transform
1 parent 6ad8461 commit 597ada3

File tree

6 files changed

+143
-23
lines changed

6 files changed

+143
-23
lines changed
Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,120 @@
1-
test.todo('v-bind')
1+
import {
2+
parse,
3+
transform,
4+
ElementNode,
5+
ObjectExpression,
6+
CompilerOptions,
7+
ErrorCodes
8+
} from '../../src'
9+
import { transformBind } from '../../src/transforms/vBind'
10+
import { transformElement } from '../../src/transforms/transformElement'
11+
12+
function parseWithVBind(
13+
template: string,
14+
options: CompilerOptions = {}
15+
): ElementNode {
16+
const ast = parse(template)
17+
transform(ast, {
18+
nodeTransforms: [transformElement],
19+
directiveTransforms: {
20+
bind: transformBind
21+
},
22+
...options
23+
})
24+
return ast.children[0] as ElementNode
25+
}
26+
27+
describe('compiler: transform v-bind', () => {
28+
test('basic', () => {
29+
const node = parseWithVBind(`<div v-bind:id="id"/>`)
30+
const props = node.codegenNode!.arguments[1] as ObjectExpression
31+
expect(props.properties[0]).toMatchObject({
32+
key: {
33+
content: `id`,
34+
isStatic: true,
35+
loc: {
36+
start: {
37+
line: 1,
38+
column: 13
39+
},
40+
end: {
41+
line: 1,
42+
column: 15
43+
}
44+
}
45+
},
46+
value: {
47+
content: `id`,
48+
isStatic: false,
49+
loc: {
50+
start: {
51+
line: 1,
52+
column: 16
53+
},
54+
end: {
55+
line: 1,
56+
column: 20
57+
}
58+
}
59+
},
60+
loc: {
61+
start: {
62+
line: 1,
63+
column: 6
64+
},
65+
end: {
66+
line: 1,
67+
column: 20
68+
}
69+
}
70+
})
71+
})
72+
73+
test('dynamic arg', () => {
74+
const node = parseWithVBind(`<div v-bind:[id]="id"/>`)
75+
const props = node.codegenNode!.arguments[1] as ObjectExpression
76+
expect(props.properties[0]).toMatchObject({
77+
key: {
78+
content: `id`,
79+
isStatic: false
80+
},
81+
value: {
82+
content: `id`,
83+
isStatic: false
84+
}
85+
})
86+
})
87+
88+
test('should error if no expression', () => {
89+
const onError = jest.fn()
90+
parseWithVBind(`<div v-bind />`, { onError })
91+
expect(onError.mock.calls[0][0]).toMatchObject({
92+
code: ErrorCodes.X_V_BIND_NO_EXPRESSION,
93+
loc: {
94+
start: {
95+
line: 1,
96+
column: 6
97+
},
98+
end: {
99+
line: 1,
100+
column: 12
101+
}
102+
}
103+
})
104+
})
105+
106+
test('.camel modifier', () => {
107+
const node = parseWithVBind(`<div v-bind:foo-bar.camel="id"/>`)
108+
const props = node.codegenNode!.arguments[1] as ObjectExpression
109+
expect(props.properties[0]).toMatchObject({
110+
key: {
111+
content: `fooBar`,
112+
isStatic: true
113+
},
114+
value: {
115+
content: `id`,
116+
isStatic: false
117+
}
118+
})
119+
})
120+
})

packages/compiler-core/src/runtimeConstants.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export const RESOLVE_COMPONENT = `resolveComponent`
1010
export const RESOLVE_DIRECTIVE = `resolveDirective`
1111
export const APPLY_DIRECTIVES = `applyDirectives`
1212
export const RENDER_LIST = `renderList`
13-
export const CAPITALIZE = `capitalize`
1413
export const TO_STRING = `toString`
1514
export const MERGE_PROPS = `mergeProps`
1615
export const TO_HANDLERS = `toHandlers`

packages/compiler-core/src/transforms/transformExpression.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export function processExpression(
8686
enter(node: Node & PrefixMeta, parent) {
8787
if (node.type === 'Identifier') {
8888
if (
89-
ids.indexOf(node) === -1 &&
89+
!ids.includes(node) &&
9090
!knownIds[node.name] &&
9191
shouldPrefix(node, parent)
9292
) {
@@ -177,7 +177,7 @@ function shouldPrefix(identifier: Identifier, parent: Node) {
177177
// not id of a FunctionDeclaration
178178
((parent as any).id === identifier ||
179179
// not a params of a function
180-
parent.params.indexOf(identifier) > -1)
180+
parent.params.includes(identifier))
181181
) &&
182182
// not a key of Property
183183
!(

packages/compiler-core/src/transforms/vBind.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
import { DirectiveTransform } from '../transform'
22
import { createObjectProperty, createExpression } from '../ast'
33
import { createCompilerError, ErrorCodes } from '../errors'
4+
import { camelize } from '@vue/shared'
45

56
// v-bind without arg is handled directly in ./element.ts due to it affecting
67
// codegen for the entire props object. This transform here is only for v-bind
78
// *with* args.
8-
export const transformBind: DirectiveTransform = (dir, context) => {
9-
if (!dir.exp) {
10-
context.onError(
11-
createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, dir.loc)
12-
)
9+
export const transformBind: DirectiveTransform = (
10+
{ exp, arg, modifiers, loc },
11+
context
12+
) => {
13+
if (!exp) {
14+
context.onError(createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc))
15+
}
16+
// .prop is no longer necessary due to new patch behavior
17+
// .sync is replced by v-model:arg
18+
if (modifiers.includes('camel')) {
19+
arg!.content = camelize(arg!.content)
1320
}
14-
// TODO handle .prop modifier
15-
// TODO handle .camel modifier
1621
return {
1722
props: createObjectProperty(
18-
dir.arg!,
19-
dir.exp || createExpression('', true, dir.loc),
20-
dir.loc
23+
arg!,
24+
exp || createExpression('', true, loc),
25+
loc
2126
),
2227
needRuntime: false
2328
}

packages/compiler-core/src/transforms/vOn.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
11
import { DirectiveTransform } from '../transform'
22
import { createObjectProperty, createExpression } from '../ast'
33
import { capitalize } from '@vue/shared'
4-
import { CAPITALIZE } from '../runtimeConstants'
54

65
// v-on without arg is handled directly in ./element.ts due to it affecting
76
// codegen for the entire props object. This transform here is only for v-on
87
// *with* args.
9-
export const transformOn: DirectiveTransform = (dir, context) => {
10-
const arg = dir.arg!
11-
const eventName = arg.isStatic
12-
? createExpression(`on${capitalize(arg.content)}`, true, arg.loc)
13-
: createExpression(`'on' + ${CAPITALIZE}(${arg.content})`, false, arg.loc)
8+
export const transformOn: DirectiveTransform = ({ arg, exp, loc }) => {
9+
const eventName = arg!.isStatic
10+
? createExpression(`on${capitalize(arg!.content)}`, true, arg!.loc)
11+
: createExpression(`'on' + (${arg!.content})`, false, arg!.loc)
1412
// TODO .once modifier handling since it is platform agnostic
1513
// other modifiers are handled in compiler-dom
1614
return {
1715
props: createObjectProperty(
1816
eventName,
19-
dir.exp || createExpression(`() => {}`, false, dir.loc),
20-
dir.loc
17+
exp || createExpression(`() => {}`, false, loc),
18+
loc
2119
),
2220
needRuntime: false
2321
}

packages/runtime-core/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ export { resolveComponent, resolveDirective } from './helpers/resolveAssets'
4242
export { renderList } from './helpers/renderList'
4343
export { toString } from './helpers/toString'
4444
export { toHandlers } from './helpers/toHandlers'
45-
export { capitalize } from '@vue/shared'
4645

4746
// Internal, for integration with runtime compiler
4847
export { registerRuntimeCompiler } from './component'

0 commit comments

Comments
 (0)