Skip to content

Commit 224196d

Browse files
committed
fix: wrong compilation result of withDirectives (#404)
1 parent cbad0e5 commit 224196d

File tree

5 files changed

+66
-58
lines changed

5 files changed

+66
-58
lines changed

packages/babel-plugin-jsx/src/buildProps.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,7 @@ const buildProps = (path: NodePath<t.JSXElement>, state: State) => {
242242
values.forEach((value, index) => {
243243
const propName = args[index];
244244
// v-model target with variable
245-
// const isIdentifierProp = t.isIdentifier(propName);
246-
const isDynamic = !t.isStringLiteral(propName) && !t.isNullLiteral(propName);
245+
const isDynamic = propName && !t.isStringLiteral(propName) && !t.isNullLiteral(propName);
247246

248247
// must be v-model or v-models and is a component
249248
if (!directive) {

packages/babel-plugin-jsx/src/parseDirectives.ts

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as t from '@babel/types';
22
import { NodePath } from '@babel/traverse';
33
import { createIdentifier } from './utils';
4-
import { State, ExcludesBoolean } from '.';
4+
import { State } from '.';
55

66
export type Tag = t.Identifier | t.MemberExpression | t.StringLiteral | t.CallExpression;
77

@@ -24,7 +24,7 @@ const getType = (path: NodePath<t.JSXOpeningElement>) => {
2424
return typePath ? typePath.get('value').node : null;
2525
};
2626

27-
const parseModifiers = (value: t.ArrayExpression): string[] => (
27+
const parseModifiers = (value: any): string[] => (
2828
t.isArrayExpression(value)
2929
? value.elements
3030
.map((el) => (t.isStringLiteral(el) ? el.value : ''))
@@ -64,37 +64,38 @@ const parseDirectives = (params: {
6464
const shouldResolve = !['html', 'text', 'model', 'models'].includes(directiveName)
6565
|| (isVModel && !isComponent);
6666

67-
if (['models', 'model'].includes(directiveName)) {
68-
if (t.isArrayExpression(value)) {
69-
const elementsList = isVModels ? value.elements! : [value];
67+
let modifiers = underscoreModifiers;
7068

71-
elementsList.forEach((element) => {
72-
if (isVModels && !t.isArrayExpression(element)) {
73-
throw new Error('You should pass a Two-dimensional Arrays to v-models');
74-
}
69+
if (t.isArrayExpression(value)) {
70+
const elementsList = isVModels ? value.elements! : [value];
7571

76-
const { elements } = element as t.ArrayExpression;
77-
const [first, second, third] = elements;
78-
let modifiers = underscoreModifiers;
72+
elementsList.forEach((element) => {
73+
if (isVModels && !t.isArrayExpression(element)) {
74+
throw new Error('You should pass a Two-dimensional Arrays to v-models');
75+
}
7976

80-
if (second && !t.isArrayExpression(second) && !t.isSpreadElement(second)) {
81-
args.push(second);
82-
modifiers = parseModifiers(third as t.ArrayExpression);
83-
} else if (t.isArrayExpression(second)) {
84-
args.push(t.nullLiteral());
85-
modifiers = parseModifiers(second);
86-
} else {
87-
// work as v-model={[value]} or v-models={[[value]]}
77+
const { elements } = element as t.ArrayExpression;
78+
const [first, second, third] = elements;
79+
80+
if (second && !t.isArrayExpression(second) && !t.isSpreadElement(second)) {
81+
args.push(second);
82+
modifiers = parseModifiers(third as t.ArrayExpression);
83+
} else if (t.isArrayExpression(second)) {
84+
if (!shouldResolve) {
8885
args.push(t.nullLiteral());
8986
}
90-
modifiersSet.push(new Set(modifiers));
91-
vals.push(first as t.Expression);
92-
});
93-
} else if (isVModel) {
94-
// work as v-model={value}
95-
args.push(t.nullLiteral());
96-
modifiersSet.push(new Set(underscoreModifiers));
97-
}
87+
modifiers = parseModifiers(second);
88+
} else if (!shouldResolve) {
89+
// work as v-model={[value]} or v-models={[[value]]}
90+
args.push(t.nullLiteral());
91+
}
92+
modifiersSet.push(new Set(modifiers));
93+
vals.push(first as t.Expression);
94+
});
95+
} else if (isVModel && !shouldResolve) {
96+
// work as v-model={value}
97+
args.push(t.nullLiteral());
98+
modifiersSet.push(new Set(underscoreModifiers));
9899
} else {
99100
modifiersSet.push(new Set(underscoreModifiers));
100101
}
@@ -107,7 +108,9 @@ const parseDirectives = (params: {
107108
directive: shouldResolve ? [
108109
resolveDirective(path, state, tag, directiveName),
109110
vals[0] || value,
110-
!!modifiersSet[0]?.size && t.unaryExpression('void', t.numericLiteral(0), true),
111+
modifiersSet[0]?.size
112+
? args[0] || t.unaryExpression('void', t.numericLiteral(0), true)
113+
: args[0],
111114
!!modifiersSet[0]?.size && t.objectExpression(
112115
[...modifiersSet[0]].map(
113116
(modifier) => t.objectProperty(
@@ -116,7 +119,7 @@ const parseDirectives = (params: {
116119
),
117120
),
118121
),
119-
].filter(Boolean as any as ExcludesBoolean) : undefined,
122+
].filter(Boolean) as t.Expression[] : undefined,
120123
};
121124
};
122125

packages/babel-plugin-jsx/test/__snapshots__/snapshot.test.ts.snap

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,24 @@ exports[`custom directive: custom directive 1`] = `
3636
_withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"cus\\"), x]]);"
3737
`;
3838

39+
exports[`custom directive: custom directive 2`] = `
40+
"import { withDirectives as _withDirectives, createVNode as _createVNode, resolveDirective as _resolveDirective, resolveComponent as _resolveComponent, Fragment as _Fragment } from \\"vue\\";
41+
42+
_createVNode(_Fragment, null, [_withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x]]), _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x]]), _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x, 'y']]), _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x, 'y', {
43+
a: true,
44+
b: true
45+
}]]), _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x, void 0, {
46+
a: true,
47+
b: true
48+
}]]), _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x, y, {
49+
a: true,
50+
b: true
51+
}]]), _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x, y, {
52+
a: true,
53+
b: true
54+
}]])]);"
55+
`;
56+
3957
exports[`disable object slot syntax with defaultSlot: defaultSlot 1`] = `
4058
"import { createVNode as _createVNode, resolveComponent as _resolveComponent } from \\"vue\\";
4159

packages/babel-plugin-jsx/test/index.test.tsx

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -257,32 +257,6 @@ describe('Transform JSX', () => {
257257
});
258258

259259
describe('directive', () => {
260-
test('custom', () => {
261-
const calls: number[] = [];
262-
const customDirective = {
263-
mounted() {
264-
calls.push(1);
265-
},
266-
};
267-
const wrapper = shallowMount({
268-
directives: { custom: customDirective },
269-
setup() {
270-
return () => (
271-
<a
272-
v-custom={{
273-
value: 123,
274-
modifiers: { modifier: true },
275-
arg: 'arg',
276-
}}
277-
/>
278-
);
279-
},
280-
});
281-
const node = wrapper.vm.$.subTree;
282-
expect(calls).toEqual(expect.arrayContaining([1]));
283-
expect(node.dirs).toHaveLength(1);
284-
});
285-
286260
test('vHtml', () => {
287261
const wrapper = shallowMount({
288262
setup() {

packages/babel-plugin-jsx/test/snapshot.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,20 @@ const transpile = (
139139
a = <A>{a}</A>;
140140
`,
141141
},
142+
{
143+
name: 'custom directive',
144+
from: `
145+
<>
146+
<A v-xxx={x} />
147+
<A v-xxx={[x]} />
148+
<A v-xxx={[x, 'y']} />
149+
<A v-xxx={[x, 'y', ['a', 'b']]} />
150+
<A v-xxx={[x, ['a', 'b']]} />
151+
<A v-xxx={[x, y, ['a', 'b']]} />
152+
<A v-xxx={[x, y, ['a', 'b']]} />
153+
</>
154+
`,
155+
},
142156
{
143157
name: 'vModels',
144158
from: '<C v-models={[[foo, ["modifier"]], [bar, "bar", ["modifier1", "modifier2"]]]} />',

0 commit comments

Comments
 (0)