]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-core): generate TS-cast safe assignment code for v-model
authorEvan You <yyx990803@gmail.com>
Wed, 22 Sep 2021 20:54:59 +0000 (16:54 -0400)
committerEvan You <yyx990803@gmail.com>
Wed, 22 Sep 2021 20:55:06 +0000 (16:55 -0400)
fix #4655

packages/compiler-core/__tests__/transforms/__snapshots__/vModel.spec.ts.snap
packages/compiler-core/__tests__/transforms/vModel.spec.ts
packages/compiler-core/src/transforms/vModel.ts
packages/compiler-dom/__tests__/transforms/__snapshots__/vModel.spec.ts.snap
packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
packages/compiler-sfc/__tests__/compileScript.spec.ts

index 877561f95318d888cc8a44945c6274e2e0aac718..42974581f604bad767fe17e9bb601b72013cfab5 100644 (file)
@@ -6,7 +6,7 @@ exports[`compiler: transform v-model compound expression (with prefixIdentifiers
 export function render(_ctx, _cache) {
   return (_openBlock(), _createElementBlock(\\"input\\", {
     modelValue: _ctx.model[_ctx.index],
-    \\"onUpdate:modelValue\\": $event => (_ctx.model[_ctx.index] = $event)
+    \\"onUpdate:modelValue\\": $event => ((_ctx.model[_ctx.index]) = $event)
   }, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]))
 }"
 `;
@@ -20,7 +20,7 @@ return function render(_ctx, _cache) {
 
     return (_openBlock(), _createElementBlock(\\"input\\", {
       modelValue: model[index],
-      \\"onUpdate:modelValue\\": $event => (model[index] = $event)
+      \\"onUpdate:modelValue\\": $event => ((model[index]) = $event)
     }, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]))
   }
 }"
@@ -39,11 +39,11 @@ return function render(_ctx, _cache) {
 .
 foo 
 ,
-      \\"onUpdate:modelValue\\": $event => (
+      \\"onUpdate:modelValue\\": $event => ((
  model
 .
 foo 
- = $event)
+) = $event)
     }, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]))
   }
 }"
@@ -55,7 +55,7 @@ exports[`compiler: transform v-model simple expression (with prefixIdentifiers)
 export function render(_ctx, _cache) {
   return (_openBlock(), _createElementBlock(\\"input\\", {
     modelValue: _ctx.model,
-    \\"onUpdate:modelValue\\": $event => (_ctx.model = $event)
+    \\"onUpdate:modelValue\\": $event => ((_ctx.model) = $event)
   }, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]))
 }"
 `;
@@ -69,7 +69,7 @@ return function render(_ctx, _cache) {
 
     return (_openBlock(), _createElementBlock(\\"input\\", {
       modelValue: model,
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]))
   }
 }"
@@ -84,7 +84,7 @@ return function render(_ctx, _cache) {
 
     return (_openBlock(), _createElementBlock(\\"input\\", {
       value: model,
-      \\"onUpdate:value\\": $event => (model = $event)
+      \\"onUpdate:value\\": $event => ((model) = $event)
     }, null, 40 /* PROPS, HYDRATE_EVENTS */, [\\"value\\", \\"onUpdate:value\\"]))
   }
 }"
@@ -96,7 +96,7 @@ exports[`compiler: transform v-model with dynamic argument (with prefixIdentifie
 export function render(_ctx, _cache) {
   return (_openBlock(), _createElementBlock(\\"input\\", _normalizeProps({
     [_ctx.value]: _ctx.model,
-    [\\"onUpdate:\\" + _ctx.value]: $event => (_ctx.model = $event)
+    [\\"onUpdate:\\" + _ctx.value]: $event => ((_ctx.model) = $event)
   }), null, 16 /* FULL_PROPS */))
 }"
 `;
@@ -110,7 +110,7 @@ return function render(_ctx, _cache) {
 
     return (_openBlock(), _createElementBlock(\\"input\\", _normalizeProps({
       [value]: model,
-      [\\"onUpdate:\\" + value]: $event => (model = $event)
+      [\\"onUpdate:\\" + value]: $event => ((model) = $event)
     }), null, 16 /* FULL_PROPS */))
   }
 }"
index 92051b7671786bdaef965cb3d0350b01d09ba17e..96dbe2cb5fb98d3195b8cb4c8a8e7b07a5624538 100644 (file)
@@ -65,12 +65,12 @@ describe('compiler: transform v-model', () => {
       },
       value: {
         children: [
-          '$event => (',
+          '$event => ((',
           {
             content: 'model',
             isStatic: false
           },
-          ' = $event)'
+          ') = $event)'
         ]
       }
     })
@@ -104,12 +104,12 @@ describe('compiler: transform v-model', () => {
       },
       value: {
         children: [
-          '$event => (',
+          '$event => ((',
           {
             content: '_ctx.model',
             isStatic: false
           },
-          ' = $event)'
+          ') = $event)'
         ]
       }
     })
@@ -142,12 +142,12 @@ describe('compiler: transform v-model', () => {
       },
       value: {
         children: [
-          '$event => (',
+          '$event => ((',
           {
             content: '\n model\n.\nfoo \n',
             isStatic: false
           },
-          ' = $event)'
+          ') = $event)'
         ]
       }
     })
@@ -179,12 +179,12 @@ describe('compiler: transform v-model', () => {
       },
       value: {
         children: [
-          '$event => (',
+          '$event => ((',
           {
             content: 'model[index]',
             isStatic: false
           },
-          ' = $event)'
+          ') = $event)'
         ]
       }
     })
@@ -228,7 +228,7 @@ describe('compiler: transform v-model', () => {
       },
       value: {
         children: [
-          '$event => (',
+          '$event => ((',
           {
             children: [
               {
@@ -243,7 +243,7 @@ describe('compiler: transform v-model', () => {
               ']'
             ]
           },
-          ' = $event)'
+          ') = $event)'
         ]
       }
     })
@@ -274,12 +274,12 @@ describe('compiler: transform v-model', () => {
       },
       value: {
         children: [
-          '$event => (',
+          '$event => ((',
           {
             content: 'model',
             isStatic: false
           },
-          ' = $event)'
+          ') = $event)'
         ]
       }
     })
@@ -322,12 +322,12 @@ describe('compiler: transform v-model', () => {
               },
               value: {
                 children: [
-                  '$event => (',
+                  '$event => ((',
                   {
                     content: 'model',
                     isStatic: false
                   },
-                  ' = $event)'
+                  ') = $event)'
                 ]
               }
             }
@@ -376,12 +376,12 @@ describe('compiler: transform v-model', () => {
               },
               value: {
                 children: [
-                  '$event => (',
+                  '$event => ((',
                   {
                     content: '_ctx.model',
                     isStatic: false
                   },
-                  ' = $event)'
+                  ') = $event)'
                 ]
               }
             }
index bfd51c604063a269112001381877ad955e97ddc0..bcf3749bdfe81e622c4586f758bbc1e56e3ae5e9 100644 (file)
@@ -76,9 +76,9 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
     if (bindingType === BindingTypes.SETUP_REF) {
       // v-model used on known ref.
       assignmentExp = createCompoundExpression([
-        `${eventArg} => (`,
+        `${eventArg} => ((`,
         createSimpleExpression(rawExp, false, exp.loc),
-        `.value = $event)`
+        `).value = $event)`
       ])
     } else {
       // v-model used on a potentially ref binding in <script setup> inline mode.
@@ -86,16 +86,16 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
       const altAssignment =
         bindingType === BindingTypes.SETUP_LET ? `${rawExp} = $event` : `null`
       assignmentExp = createCompoundExpression([
-        `${eventArg} => (${context.helperString(IS_REF)}(${rawExp}) ? `,
+        `${eventArg} => (${context.helperString(IS_REF)}(${rawExp}) ? (`,
         createSimpleExpression(rawExp, false, exp.loc),
-        `.value = $event : ${altAssignment})`
+        `).value = $event : ${altAssignment})`
       ])
     }
   } else {
     assignmentExp = createCompoundExpression([
-      `${eventArg} => (`,
+      `${eventArg} => ((`,
       exp,
-      ` = $event)`
+      `) = $event)`
     ])
   }
 
index f92b6768515c0f1890babd77084e3ad3876a8f65..1a4ce5e66c7a1abe4dcf02417e5dd17ccaabce85 100644 (file)
@@ -8,7 +8,7 @@ return function render(_ctx, _cache) {
     const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 
     return _withDirectives((_openBlock(), _createElementBlock(\\"my-input\\", {
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
       [_vModelText, model]
     ])
@@ -24,7 +24,7 @@ return function render(_ctx, _cache) {
     const { vModelDynamic: _vModelDynamic, mergeProps: _mergeProps, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 
     return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", _mergeProps(obj, {
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }), null, 16 /* FULL_PROPS */, [\\"onUpdate:modelValue\\"])), [
       [_vModelDynamic, model]
     ])
@@ -42,7 +42,7 @@ return function render(_ctx, _cache) {
     const _directive_bind = _resolveDirective(\\"bind\\")
 
     return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
       [_directive_bind, val, key],
       [_vModelDynamic, model]
@@ -59,7 +59,7 @@ return function render(_ctx, _cache) {
     const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 
     return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
       [
         _vModelText,
@@ -80,7 +80,7 @@ return function render(_ctx, _cache) {
     const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 
     return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
       [
         _vModelText,
@@ -101,7 +101,7 @@ return function render(_ctx, _cache) {
     const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 
     return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
       [
         _vModelText,
@@ -122,7 +122,7 @@ return function render(_ctx, _cache) {
     const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 
     return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
       [_vModelText, model]
     ])
@@ -139,7 +139,7 @@ return function render(_ctx, _cache) {
 
     return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
       type: \\"checkbox\\",
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
       [_vModelCheckbox, model]
     ])
@@ -157,7 +157,7 @@ return function render(_ctx, _cache) {
     const _directive_bind = _resolveDirective(\\"bind\\")
 
     return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
       [_directive_bind, foo, \\"type\\"],
       [_vModelDynamic, model]
@@ -175,7 +175,7 @@ return function render(_ctx, _cache) {
 
     return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
       type: \\"radio\\",
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
       [_vModelRadio, model]
     ])
@@ -192,7 +192,7 @@ return function render(_ctx, _cache) {
 
     return _withDirectives((_openBlock(), _createElementBlock(\\"input\\", {
       type: \\"text\\",
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
       [_vModelText, model]
     ])
@@ -208,7 +208,7 @@ return function render(_ctx, _cache) {
     const { vModelSelect: _vModelSelect, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 
     return _withDirectives((_openBlock(), _createElementBlock(\\"select\\", {
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
       [_vModelSelect, model]
     ])
@@ -224,7 +224,7 @@ return function render(_ctx, _cache) {
     const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 
     return _withDirectives((_openBlock(), _createElementBlock(\\"textarea\\", {
-      \\"onUpdate:modelValue\\": $event => (model = $event)
+      \\"onUpdate:modelValue\\": $event => ((model) = $event)
     }, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
       [_vModelText, model]
     ])
index b60687d97c47cf8388d2ec5c76eff2d83149c8df..c60aef7af22999bbf6871cc8b20004a5154bce70 100644 (file)
@@ -924,17 +924,17 @@ export default {
 return (_ctx, _cache) => {
   return (_openBlock(), _createElementBlock(_Fragment, null, [
     _withDirectives(_createElementVNode(\\"input\\", {
-      \\"onUpdate:modelValue\\": _cache[0] || (_cache[0] = $event => (count.value = $event))
+      \\"onUpdate:modelValue\\": _cache[0] || (_cache[0] = $event => ((count).value = $event))
     }, null, 512 /* NEED_PATCH */), [
       [_vModelText, count.value]
     ]),
     _withDirectives(_createElementVNode(\\"input\\", {
-      \\"onUpdate:modelValue\\": _cache[1] || (_cache[1] = $event => (_isRef(maybe) ? maybe.value = $event : null))
+      \\"onUpdate:modelValue\\": _cache[1] || (_cache[1] = $event => (_isRef(maybe) ? (maybe).value = $event : null))
     }, null, 512 /* NEED_PATCH */), [
       [_vModelText, _unref(maybe)]
     ]),
     _withDirectives(_createElementVNode(\\"input\\", {
-      \\"onUpdate:modelValue\\": _cache[2] || (_cache[2] = $event => (_isRef(lett) ? lett.value = $event : lett = $event))
+      \\"onUpdate:modelValue\\": _cache[2] || (_cache[2] = $event => (_isRef(lett) ? (lett).value = $event : lett = $event))
     }, null, 512 /* NEED_PATCH */), [
       [_vModelText, _unref(lett)]
     ])
index 20ce70a97e8c10c6962298be12f8c5c87c7438d8..ff4279ecd632aecde2ce6656990ad2ec22b4725c 100644 (file)
@@ -523,13 +523,12 @@ defineExpose({ foo: 123 })
         { inlineTemplate: true }
       )
       // known const ref: set value
-      expect(content).toMatch(`count.value = $event`)
-      // const but maybe ref: also assign .value directly since non-ref
-      // won't work
-      expect(content).toMatch(`maybe.value = $event`)
+      expect(content).toMatch(`(count).value = $event`)
+      // const but maybe ref: assign if ref, otherwise do nothing
+      expect(content).toMatch(`_isRef(maybe) ? (maybe).value = $event : null`)
       // let: handle both cases
       expect(content).toMatch(
-        `_isRef(lett) ? lett.value = $event : lett = $event`
+        `_isRef(lett) ? (lett).value = $event : lett = $event`
       )
       assertCode(content)
     })