Skip to content

Commit 686d014

Browse files
committed
fix(compiler-core): generate TS-cast safe assignment code for v-model
fix #4655
1 parent 1873f0f commit 686d014

File tree

6 files changed

+51
-52
lines changed

6 files changed

+51
-52
lines changed

packages/compiler-core/__tests__/transforms/__snapshots__/vModel.spec.ts.snap

+9-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ exports[`compiler: transform v-model compound expression (with prefixIdentifiers
66
export function render(_ctx, _cache) {
77
return (_openBlock(), _createElementBlock(\\"input\\", {
88
modelValue: _ctx.model[_ctx.index],
9-
\\"onUpdate:modelValue\\": $event => (_ctx.model[_ctx.index] = $event)
9+
\\"onUpdate:modelValue\\": $event => ((_ctx.model[_ctx.index]) = $event)
1010
}, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]))
1111
}"
1212
`;
@@ -20,7 +20,7 @@ return function render(_ctx, _cache) {
2020
2121
return (_openBlock(), _createElementBlock(\\"input\\", {
2222
modelValue: model[index],
23-
\\"onUpdate:modelValue\\": $event => (model[index] = $event)
23+
\\"onUpdate:modelValue\\": $event => ((model[index]) = $event)
2424
}, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]))
2525
}
2626
}"
@@ -39,11 +39,11 @@ return function render(_ctx, _cache) {
3939
.
4040
foo
4141
,
42-
\\"onUpdate:modelValue\\": $event => (
42+
\\"onUpdate:modelValue\\": $event => ((
4343
model
4444
.
4545
foo
46-
= $event)
46+
) = $event)
4747
}, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]))
4848
}
4949
}"
@@ -55,7 +55,7 @@ exports[`compiler: transform v-model simple expression (with prefixIdentifiers)
5555
export function render(_ctx, _cache) {
5656
return (_openBlock(), _createElementBlock(\\"input\\", {
5757
modelValue: _ctx.model,
58-
\\"onUpdate:modelValue\\": $event => (_ctx.model = $event)
58+
\\"onUpdate:modelValue\\": $event => ((_ctx.model) = $event)
5959
}, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]))
6060
}"
6161
`;
@@ -69,7 +69,7 @@ return function render(_ctx, _cache) {
6969
7070
return (_openBlock(), _createElementBlock(\\"input\\", {
7171
modelValue: model,
72-
\\"onUpdate:modelValue\\": $event => (model = $event)
72+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
7373
}, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]))
7474
}
7575
}"
@@ -84,7 +84,7 @@ return function render(_ctx, _cache) {
8484
8585
return (_openBlock(), _createElementBlock(\\"input\\", {
8686
value: model,
87-
\\"onUpdate:value\\": $event => (model = $event)
87+
\\"onUpdate:value\\": $event => ((model) = $event)
8888
}, null, 40 /* PROPS, HYDRATE_EVENTS */, [\\"value\\", \\"onUpdate:value\\"]))
8989
}
9090
}"
@@ -96,7 +96,7 @@ exports[`compiler: transform v-model with dynamic argument (with prefixIdentifie
9696
export function render(_ctx, _cache) {
9797
return (_openBlock(), _createElementBlock(\\"input\\", _normalizeProps({
9898
[_ctx.value]: _ctx.model,
99-
[\\"onUpdate:\\" + _ctx.value]: $event => (_ctx.model = $event)
99+
[\\"onUpdate:\\" + _ctx.value]: $event => ((_ctx.model) = $event)
100100
}), null, 16 /* FULL_PROPS */))
101101
}"
102102
`;
@@ -110,7 +110,7 @@ return function render(_ctx, _cache) {
110110
111111
return (_openBlock(), _createElementBlock(\\"input\\", _normalizeProps({
112112
[value]: model,
113-
[\\"onUpdate:\\" + value]: $event => (model = $event)
113+
[\\"onUpdate:\\" + value]: $event => ((model) = $event)
114114
}), null, 16 /* FULL_PROPS */))
115115
}
116116
}"

packages/compiler-core/__tests__/transforms/vModel.spec.ts

+16-16
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ describe('compiler: transform v-model', () => {
6565
},
6666
value: {
6767
children: [
68-
'$event => (',
68+
'$event => ((',
6969
{
7070
content: 'model',
7171
isStatic: false
7272
},
73-
' = $event)'
73+
') = $event)'
7474
]
7575
}
7676
})
@@ -104,12 +104,12 @@ describe('compiler: transform v-model', () => {
104104
},
105105
value: {
106106
children: [
107-
'$event => (',
107+
'$event => ((',
108108
{
109109
content: '_ctx.model',
110110
isStatic: false
111111
},
112-
' = $event)'
112+
') = $event)'
113113
]
114114
}
115115
})
@@ -142,12 +142,12 @@ describe('compiler: transform v-model', () => {
142142
},
143143
value: {
144144
children: [
145-
'$event => (',
145+
'$event => ((',
146146
{
147147
content: '\n model\n.\nfoo \n',
148148
isStatic: false
149149
},
150-
' = $event)'
150+
') = $event)'
151151
]
152152
}
153153
})
@@ -179,12 +179,12 @@ describe('compiler: transform v-model', () => {
179179
},
180180
value: {
181181
children: [
182-
'$event => (',
182+
'$event => ((',
183183
{
184184
content: 'model[index]',
185185
isStatic: false
186186
},
187-
' = $event)'
187+
') = $event)'
188188
]
189189
}
190190
})
@@ -228,7 +228,7 @@ describe('compiler: transform v-model', () => {
228228
},
229229
value: {
230230
children: [
231-
'$event => (',
231+
'$event => ((',
232232
{
233233
children: [
234234
{
@@ -243,7 +243,7 @@ describe('compiler: transform v-model', () => {
243243
']'
244244
]
245245
},
246-
' = $event)'
246+
') = $event)'
247247
]
248248
}
249249
})
@@ -274,12 +274,12 @@ describe('compiler: transform v-model', () => {
274274
},
275275
value: {
276276
children: [
277-
'$event => (',
277+
'$event => ((',
278278
{
279279
content: 'model',
280280
isStatic: false
281281
},
282-
' = $event)'
282+
') = $event)'
283283
]
284284
}
285285
})
@@ -322,12 +322,12 @@ describe('compiler: transform v-model', () => {
322322
},
323323
value: {
324324
children: [
325-
'$event => (',
325+
'$event => ((',
326326
{
327327
content: 'model',
328328
isStatic: false
329329
},
330-
' = $event)'
330+
') = $event)'
331331
]
332332
}
333333
}
@@ -376,12 +376,12 @@ describe('compiler: transform v-model', () => {
376376
},
377377
value: {
378378
children: [
379-
'$event => (',
379+
'$event => ((',
380380
{
381381
content: '_ctx.model',
382382
isStatic: false
383383
},
384-
' = $event)'
384+
') = $event)'
385385
]
386386
}
387387
}

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

+6-6
Original file line numberDiff line numberDiff line change
@@ -76,26 +76,26 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
7676
if (bindingType === BindingTypes.SETUP_REF) {
7777
// v-model used on known ref.
7878
assignmentExp = createCompoundExpression([
79-
`${eventArg} => (`,
79+
`${eventArg} => ((`,
8080
createSimpleExpression(rawExp, false, exp.loc),
81-
`.value = $event)`
81+
`).value = $event)`
8282
])
8383
} else {
8484
// v-model used on a potentially ref binding in <script setup> inline mode.
8585
// the assignment needs to check whether the binding is actually a ref.
8686
const altAssignment =
8787
bindingType === BindingTypes.SETUP_LET ? `${rawExp} = $event` : `null`
8888
assignmentExp = createCompoundExpression([
89-
`${eventArg} => (${context.helperString(IS_REF)}(${rawExp}) ? `,
89+
`${eventArg} => (${context.helperString(IS_REF)}(${rawExp}) ? (`,
9090
createSimpleExpression(rawExp, false, exp.loc),
91-
`.value = $event : ${altAssignment})`
91+
`).value = $event : ${altAssignment})`
9292
])
9393
}
9494
} else {
9595
assignmentExp = createCompoundExpression([
96-
`${eventArg} => (`,
96+
`${eventArg} => ((`,
9797
exp,
98-
` = $event)`
98+
`) = $event)`
9999
])
100100
}
101101

packages/compiler-dom/__tests__/transforms/__snapshots__/vModel.spec.ts.snap

+13-13
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ return function render(_ctx, _cache) {
88
const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
99
1010
return _withDirectives((_openBlock(), _createElementBlock(\\"my-input\\", {
11-
\\"onUpdate:modelValue\\": $event => (model = $event)
11+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
1212
}, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
1313
[_vModelText, model]
1414
])
@@ -24,7 +24,7 @@ return function render(_ctx, _cache) {
2424
const { vModelDynamic: _vModelDynamic, mergeProps: _mergeProps, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
2525
2626
return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", _mergeProps(obj, {
27-
\\"onUpdate:modelValue\\": $event => (model = $event)
27+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
2828
}), null, 16 /* FULL_PROPS */, [\\"onUpdate:modelValue\\"])), [
2929
[_vModelDynamic, model]
3030
])
@@ -42,7 +42,7 @@ return function render(_ctx, _cache) {
4242
const _directive_bind = _resolveDirective(\\"bind\\")
4343
4444
return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
45-
\\"onUpdate:modelValue\\": $event => (model = $event)
45+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
4646
}, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
4747
[_directive_bind, val, key],
4848
[_vModelDynamic, model]
@@ -59,7 +59,7 @@ return function render(_ctx, _cache) {
5959
const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
6060
6161
return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
62-
\\"onUpdate:modelValue\\": $event => (model = $event)
62+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
6363
}, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
6464
[
6565
_vModelText,
@@ -80,7 +80,7 @@ return function render(_ctx, _cache) {
8080
const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
8181
8282
return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
83-
\\"onUpdate:modelValue\\": $event => (model = $event)
83+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
8484
}, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
8585
[
8686
_vModelText,
@@ -101,7 +101,7 @@ return function render(_ctx, _cache) {
101101
const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
102102
103103
return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
104-
\\"onUpdate:modelValue\\": $event => (model = $event)
104+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
105105
}, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
106106
[
107107
_vModelText,
@@ -122,7 +122,7 @@ return function render(_ctx, _cache) {
122122
const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
123123
124124
return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
125-
\\"onUpdate:modelValue\\": $event => (model = $event)
125+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
126126
}, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
127127
[_vModelText, model]
128128
])
@@ -139,7 +139,7 @@ return function render(_ctx, _cache) {
139139
140140
return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
141141
type: \\"checkbox\\",
142-
\\"onUpdate:modelValue\\": $event => (model = $event)
142+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
143143
}, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
144144
[_vModelCheckbox, model]
145145
])
@@ -157,7 +157,7 @@ return function render(_ctx, _cache) {
157157
const _directive_bind = _resolveDirective(\\"bind\\")
158158
159159
return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
160-
\\"onUpdate:modelValue\\": $event => (model = $event)
160+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
161161
}, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
162162
[_directive_bind, foo, \\"type\\"],
163163
[_vModelDynamic, model]
@@ -175,7 +175,7 @@ return function render(_ctx, _cache) {
175175
176176
return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
177177
type: \\"radio\\",
178-
\\"onUpdate:modelValue\\": $event => (model = $event)
178+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
179179
}, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
180180
[_vModelRadio, model]
181181
])
@@ -192,7 +192,7 @@ return function render(_ctx, _cache) {
192192
193193
return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
194194
type: \\"text\\",
195-
\\"onUpdate:modelValue\\": $event => (model = $event)
195+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
196196
}, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
197197
[_vModelText, model]
198198
])
@@ -208,7 +208,7 @@ return function render(_ctx, _cache) {
208208
const { vModelSelect: _vModelSelect, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
209209
210210
return _withDirectives((_openBlock(), _createElementBlock(\\"select\\", {
211-
\\"onUpdate:modelValue\\": $event => (model = $event)
211+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
212212
}, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
213213
[_vModelSelect, model]
214214
])
@@ -224,7 +224,7 @@ return function render(_ctx, _cache) {
224224
const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
225225
226226
return _withDirectives((_openBlock(), _createElementBlock(\\"textarea\\", {
227-
\\"onUpdate:modelValue\\": $event => (model = $event)
227+
\\"onUpdate:modelValue\\": $event => ((model) = $event)
228228
}, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
229229
[_vModelText, model]
230230
])

packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap

+3-3
Original file line numberDiff line numberDiff line change
@@ -924,17 +924,17 @@ export default {
924924
return (_ctx, _cache) => {
925925
return (_openBlock(), _createElementBlock(_Fragment, null, [
926926
_withDirectives(_createElementVNode(\\"input\\", {
927-
\\"onUpdate:modelValue\\": _cache[0] || (_cache[0] = $event => (count.value = $event))
927+
\\"onUpdate:modelValue\\": _cache[0] || (_cache[0] = $event => ((count).value = $event))
928928
}, null, 512 /* NEED_PATCH */), [
929929
[_vModelText, count.value]
930930
]),
931931
_withDirectives(_createElementVNode(\\"input\\", {
932-
\\"onUpdate:modelValue\\": _cache[1] || (_cache[1] = $event => (_isRef(maybe) ? maybe.value = $event : null))
932+
\\"onUpdate:modelValue\\": _cache[1] || (_cache[1] = $event => (_isRef(maybe) ? (maybe).value = $event : null))
933933
}, null, 512 /* NEED_PATCH */), [
934934
[_vModelText, _unref(maybe)]
935935
]),
936936
_withDirectives(_createElementVNode(\\"input\\", {
937-
\\"onUpdate:modelValue\\": _cache[2] || (_cache[2] = $event => (_isRef(lett) ? lett.value = $event : lett = $event))
937+
\\"onUpdate:modelValue\\": _cache[2] || (_cache[2] = $event => (_isRef(lett) ? (lett).value = $event : lett = $event))
938938
}, null, 512 /* NEED_PATCH */), [
939939
[_vModelText, _unref(lett)]
940940
])

packages/compiler-sfc/__tests__/compileScript.spec.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -523,13 +523,12 @@ defineExpose({ foo: 123 })
523523
{ inlineTemplate: true }
524524
)
525525
// known const ref: set value
526-
expect(content).toMatch(`count.value = $event`)
527-
// const but maybe ref: also assign .value directly since non-ref
528-
// won't work
529-
expect(content).toMatch(`maybe.value = $event`)
526+
expect(content).toMatch(`(count).value = $event`)
527+
// const but maybe ref: assign if ref, otherwise do nothing
528+
expect(content).toMatch(`_isRef(maybe) ? (maybe).value = $event : null`)
530529
// let: handle both cases
531530
expect(content).toMatch(
532-
`_isRef(lett) ? lett.value = $event : lett = $event`
531+
`_isRef(lett) ? (lett).value = $event : lett = $event`
533532
)
534533
assertCode(content)
535534
})

0 commit comments

Comments
 (0)