Skip to content

Commit 32849a7

Browse files
committed
fix(compiler): missing modifiers
1 parent dce2e83 commit 32849a7

File tree

5 files changed

+329
-220
lines changed

5 files changed

+329
-220
lines changed

packages/compiler/src/utils.ts

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -253,17 +253,27 @@ export function resolveNode(
253253
const props = node.openingElement.attributes.reduce(
254254
(result, attr) => {
255255
if (attr.type === 'JSXAttribute') {
256-
if (tagType === ElementTypes.COMPONENT) {
257-
result.push(resolveDirectiveNode(attr, context))
258-
} else {
259-
result.push({
260-
type: NodeTypes.ATTRIBUTE,
261-
name: String(attr.name.name),
262-
nameLoc: resolveLocation(attr.name.loc, context),
263-
value: resolveValue(attr.value, context),
264-
loc: resolveLocation(attr.loc, context),
265-
})
266-
}
256+
result.push(
257+
attr.value?.type === 'StringLiteral'
258+
? {
259+
type: NodeTypes.ATTRIBUTE,
260+
name: String(attr.name.name),
261+
nameLoc: resolveLocation(attr.name.loc, context),
262+
value: resolveValue(attr.value, context),
263+
loc: resolveLocation(attr.loc, context),
264+
}
265+
: resolveDirectiveNode(attr, context),
266+
)
267+
} else if (attr.type === 'JSXSpreadAttribute') {
268+
result.push({
269+
type: NodeTypes.DIRECTIVE,
270+
name: 'bind',
271+
rawName: getText(attr, context),
272+
exp: resolveExpression(attr.argument, context),
273+
arg: undefined,
274+
loc: resolveLocation(node.loc, context),
275+
modifiers: [],
276+
})
267277
}
268278
return result
269279
},
@@ -296,33 +306,34 @@ export function resolveDirectiveNode(
296306
: name.type === 'JSXIdentifier'
297307
? name.name
298308
: ''
299-
let argString = name.type === 'JSXNamespacedName' ? name.name.name : ''
300-
if (name.type !== 'JSXNamespacedName' && !argString) {
301-
const [newName, modifiers] = nameString.split('_')
302-
nameString = newName
303-
modifiers && (argString = `_${modifiers}`)
304-
}
305-
309+
const isDirective = nameString.startsWith('v-')
306310
let modifiers: string[] = []
307311
let isStatic = true
308-
const result = argString.match(namespaceRE)
309-
if (result) {
310-
let modifierString = ''
311-
;[, argString, modifierString] = result
312-
if (argString) {
313-
argString = argString.replaceAll('_', '.')
314-
isStatic = false
315-
if (modifierString && modifierString.startsWith('_'))
316-
modifiers = modifierString.slice(1).split('_')
317-
} else if (modifierString) {
318-
;[argString, ...modifiers] = modifierString.split('_')
312+
let argString = name.type === 'JSXNamespacedName' ? name.name.name : ''
313+
if (name.type !== 'JSXNamespacedName' && !argString) {
314+
;[nameString, ...modifiers] = nameString.split('_')
315+
} else {
316+
const result = argString.match(namespaceRE)
317+
if (result) {
318+
let modifierString = ''
319+
;[, argString, modifierString] = result
320+
if (argString) {
321+
argString = argString.replaceAll('_', '.')
322+
isStatic = false
323+
if (modifierString && modifierString.startsWith('_'))
324+
modifiers = modifierString.slice(1).split('_')
325+
} else if (modifierString) {
326+
;[argString, ...modifiers] = modifierString.split('_')
327+
}
319328
}
320329
}
321330

322-
const arg =
323-
argString && name.type === 'JSXNamespacedName'
331+
const arg = isDirective
332+
? argString && name.type === 'JSXNamespacedName'
324333
? resolveSimpleExpression(argString, isStatic, name.name.loc)
325334
: undefined
335+
: resolveSimpleExpression(nameString, true, name.loc)
336+
326337
const exp = value
327338
? withFn && value.type === 'JSXExpressionContainer'
328339
? resolveExpressionWithFn(value.expression, context)
@@ -331,8 +342,8 @@ export function resolveDirectiveNode(
331342

332343
return {
333344
type: NodeTypes.DIRECTIVE,
334-
name: nameString.slice(2),
335-
rawName: `${nameString}:${argString}`,
345+
name: isDirective ? nameString.slice(2) : 'bind',
346+
rawName: getText(name, context),
336347
exp,
337348
arg,
338349
loc: resolveLocation(node.loc, context),

packages/compiler/test/transforms/__snapshots__/vModel.spec.ts.snap

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,68 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3+
exports[`compiler: vModel transform > component > v-model for component should generate modelModifiers 1`] = `
4+
"
5+
const n0 = _createComponent(Comp, { modelValue: () => (foo),
6+
"onUpdate:modelValue": () => _value => (foo = _value),
7+
modelModifiers: () => ({ trim: true, "bar-baz": true }) })
8+
return n0
9+
"
10+
`;
11+
12+
exports[`compiler: vModel transform > component > v-model for component should work 1`] = `
13+
"
14+
const n0 = _createComponent(Comp, { modelValue: () => (foo),
15+
"onUpdate:modelValue": () => _value => (foo = _value) })
16+
return n0
17+
"
18+
`;
19+
20+
exports[`compiler: vModel transform > component > v-model with arguments for component should generate modelModifiers 1`] = `
21+
"
22+
const n0 = _createComponent(Comp, {
23+
foo: () => (foo),
24+
"onUpdate:foo": () => _value => (foo = _value),
25+
fooModifiers: () => ({ trim: true }),
26+
bar: () => (bar),
27+
"onUpdate:bar": () => _value => (bar = _value),
28+
barModifiers: () => ({ number: true })
29+
})
30+
return n0
31+
"
32+
`;
33+
34+
exports[`compiler: vModel transform > component > v-model with arguments for component should work 1`] = `
35+
"
36+
const n0 = _createComponent(Comp, { bar: () => (foo),
37+
"onUpdate:bar": () => _value => (foo = _value) })
38+
return n0
39+
"
40+
`;
41+
42+
exports[`compiler: vModel transform > component > v-model with dynamic arguments for component should generate modelModifiers 1`] = `
43+
"
44+
const n0 = _createComponent(Comp, { $: [
45+
() => ({ [foo]: foo,
46+
["onUpdate:" + foo]: () => _value => (foo = _value),
47+
[foo + "Modifiers"]: () => ({ trim: true }) }),
48+
() => ({ [bar.value]: bar,
49+
["onUpdate:" + bar.value]: () => _value => (bar = _value),
50+
[bar.value + "Modifiers"]: () => ({ number: true }) })
51+
] })
52+
return n0
53+
"
54+
`;
55+
56+
exports[`compiler: vModel transform > component > v-model with dynamic arguments for component should work 1`] = `
57+
"
58+
const n0 = _createComponent(Comp, { $: [
59+
() => ({ [arg]: foo,
60+
["onUpdate:" + arg]: () => _value => (foo = _value) })
61+
] })
62+
return n0
63+
"
64+
`;
65+
366
exports[`compiler: vModel transform > modifiers > .lazy 1`] = `
467
"
568
const n0 = t0()
@@ -24,10 +87,91 @@ exports[`compiler: vModel transform > modifiers > .trim 1`] = `
2487
"
2588
`;
2689

90+
exports[`compiler: vModel transform > should support input (checkbox) 1`] = `
91+
"
92+
const n0 = t0()
93+
_applyCheckboxModel(n0, () => (model), _value => (model = _value))
94+
return n0
95+
"
96+
`;
97+
98+
exports[`compiler: vModel transform > should support input (dynamic type) 1`] = `
99+
"
100+
const n0 = t0()
101+
_applyDynamicModel(n0, () => (model), _value => (model = _value))
102+
return n0
103+
"
104+
`;
105+
106+
exports[`compiler: vModel transform > should support input (radio) 1`] = `
107+
"
108+
const n0 = t0()
109+
_applyRadioModel(n0, () => (model), _value => (model = _value))
110+
return n0
111+
"
112+
`;
113+
114+
exports[`compiler: vModel transform > should support input (text) 1`] = `
115+
"
116+
const n0 = t0()
117+
_applyTextModel(n0, () => (model), _value => (model = _value))
118+
return n0
119+
"
120+
`;
121+
122+
exports[`compiler: vModel transform > should support member expression 1`] = `
123+
"
124+
const n0 = t0()
125+
const n1 = t0()
126+
const n2 = t0()
127+
_applyTextModel(n0, () => (setupRef.child), _value => (setupRef.child = _value))
128+
_applyTextModel(n1, () => (setupLet.child), _value => (setupLet.child = _value))
129+
_applyTextModel(n2, () => (setupMaybeRef.child), _value => (setupMaybeRef.child = _value))
130+
return [n0, n1, n2]
131+
"
132+
`;
133+
134+
exports[`compiler: vModel transform > should support member expression w/ inline 1`] = `
135+
"
136+
const n0 = t0()
137+
const n1 = t0()
138+
const n2 = t0()
139+
_applyTextModel(n0, () => (setupRef.child), _value => (setupRef.child = _value))
140+
_applyTextModel(n1, () => (setupLet.child), _value => (setupLet.child = _value))
141+
_applyTextModel(n2, () => (setupMaybeRef.child), _value => (setupMaybeRef.child = _value))
142+
return [n0, n1, n2]
143+
"
144+
`;
145+
146+
exports[`compiler: vModel transform > should support select 1`] = `
147+
"
148+
const n0 = t0()
149+
_applySelectModel(n0, () => (model), _value => (model = _value))
150+
return n0
151+
"
152+
`;
153+
27154
exports[`compiler: vModel transform > should support simple expression 1`] = `
28155
"
29156
const n0 = t0()
30157
_applyTextModel(n0, () => (model), _value => (model = _value))
31158
return n0
32159
"
33160
`;
161+
162+
exports[`compiler: vModel transform > should support textarea 1`] = `
163+
"
164+
const n0 = t0()
165+
_applyTextModel(n0, () => (model), _value => (model = _value))
166+
return n0
167+
"
168+
`;
169+
170+
exports[`compiler: vModel transform > should support w/ dynamic v-bind 1`] = `
171+
"
172+
const n0 = t0()
173+
_applyDynamicModel(n0, () => (model), _value => (model = _value))
174+
_renderEffect(() => _setDynamicProps(n0, [obj], true))
175+
return n0
176+
"
177+
`;

packages/compiler/test/transforms/vHtml.spec.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,7 @@ const compileWithVHtml = makeCompile({
1818
describe('v-html', () => {
1919
test('should convert v-html to innerHTML', () => {
2020
const { code, ir, helpers } = compileWithVHtml(
21-
`<div v-html={code}></div>`,
22-
{
23-
bindingMetadata: {
24-
code: BindingTypes.SETUP_REF,
25-
},
26-
},
21+
`<div v-html={code.value}></div>`,
2722
)
2823

2924
expect(helpers).contains('setHtml')
@@ -34,7 +29,7 @@ describe('v-html', () => {
3429
expressions: [
3530
{
3631
type: NodeTypes.SIMPLE_EXPRESSION,
37-
content: 'code',
32+
content: 'code.value',
3833
isStatic: false,
3934
},
4035
],
@@ -44,7 +39,7 @@ describe('v-html', () => {
4439
element: 0,
4540
value: {
4641
type: NodeTypes.SIMPLE_EXPRESSION,
47-
content: 'code',
42+
content: 'code.value',
4843
isStatic: false,
4944
},
5045
},
@@ -58,7 +53,7 @@ describe('v-html', () => {
5853
test('should raise error and ignore children when v-html is present', () => {
5954
const onError = vi.fn()
6055
const { ir, helpers, preamble } = compileWithVHtml(
61-
`<div v-html={test}>hello</div>`,
56+
`<div v-html={test.value}>hello</div>`,
6257
{
6358
onError,
6459
},
@@ -75,7 +70,7 @@ describe('v-html', () => {
7570
expressions: [
7671
{
7772
type: NodeTypes.SIMPLE_EXPRESSION,
78-
content: 'test',
73+
content: 'test.value',
7974
isStatic: false,
8075
},
8176
],
@@ -85,7 +80,7 @@ describe('v-html', () => {
8580
element: 0,
8681
value: {
8782
type: NodeTypes.SIMPLE_EXPRESSION,
88-
content: 'test',
83+
content: 'test.value',
8984
isStatic: false,
9085
},
9186
},

0 commit comments

Comments
 (0)