]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler): fix template ref codegen for setup-maybe-ref binding types (#4549)
authorygj6 <7699524+ygj6@users.noreply.github.com>
Thu, 16 Sep 2021 15:33:16 +0000 (23:33 +0800)
committerGitHub <noreply@github.com>
Thu, 16 Sep 2021 15:33:16 +0000 (11:33 -0400)
fix #4546

packages/compiler-core/__tests__/transforms/transformElement.spec.ts
packages/compiler-core/src/transforms/transformElement.ts

index 16a4c0443223e47debd5ebf193496f67a3b0bed6..eb29f346522a4c855d7fa6def2455e4957925877 100644 (file)
@@ -1004,6 +1004,81 @@ describe('compiler: element transform', () => {
       })
     })
 
+    test('the binding not exists (inline maybe ref input)', () => {
+      const { node } = parseWithElementTransform(`<input ref="input"/>`, {
+        inline: true,
+        bindingMetadata: {
+          input: BindingTypes.SETUP_MAYBE_REF
+        }
+      })
+      expect(node.props).toMatchObject({
+        type: NodeTypes.JS_OBJECT_EXPRESSION,
+        properties: [
+          {
+            type: NodeTypes.JS_PROPERTY,
+            key: {
+              type: NodeTypes.SIMPLE_EXPRESSION,
+              content: 'ref',
+              isStatic: true
+            },
+            value: {
+              type: NodeTypes.JS_FUNCTION_EXPRESSION,
+              params: ['_value', '_refs'],
+              body: {
+                type: NodeTypes.JS_BLOCK_STATEMENT,
+                body: [
+                  {
+                    content: `_refs['input'] = _value`
+                  },
+                  {
+                    content: '_isRef(input) && (input.value = _value)'
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      })
+    })
+
+    test('the binding not exists (inline let ref input)', () => {
+      const { node } = parseWithElementTransform(`<input ref="input"/>`, {
+        inline: true,
+        bindingMetadata: {
+          input: BindingTypes.SETUP_LET
+        }
+      })
+      expect(node.props).toMatchObject({
+        type: NodeTypes.JS_OBJECT_EXPRESSION,
+        properties: [
+          {
+            type: NodeTypes.JS_PROPERTY,
+            key: {
+              type: NodeTypes.SIMPLE_EXPRESSION,
+              content: 'ref',
+              isStatic: true
+            },
+            value: {
+              type: NodeTypes.JS_FUNCTION_EXPRESSION,
+              params: ['_value', '_refs'],
+              body: {
+                type: NodeTypes.JS_BLOCK_STATEMENT,
+                body: [
+                  {
+                    content: `_refs['input'] = _value`
+                  },
+                  {
+                    content:
+                      '_isRef(input) ? input.value = _value : input = _value'
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      })
+    })
+
     test('HYDRATE_EVENTS', () => {
       // ignore click events (has dedicated fast path)
       const { node } = parseWithElementTransform(`<div @click="foo" />`, {
index c471d2a4b84a569ac90e7dcebc78ec3a325ad4f3..2bc44e83980968e12eb26c07d3aded8cc00d4d57 100644 (file)
@@ -48,7 +48,8 @@ import {
   KEEP_ALIVE,
   SUSPENSE,
   UNREF,
-  GUARD_REACTIVE_PROPS
+  GUARD_REACTIVE_PROPS,
+  IS_REF
 } from '../runtimeHelpers'
 import {
   getInnerRange,
@@ -61,7 +62,7 @@ import {
 } from '../utils'
 import { buildSlots } from './vSlot'
 import { getConstantType } from './hoistStatic'
-import { BindingMetadata, BindingTypes } from '../options'
+import { BindingTypes } from '../options'
 import {
   checkCompatEnabled,
   CompilerDeprecationTypes,
@@ -475,7 +476,7 @@ export function buildProps(
         if (!__BROWSER__ && context.inline && value?.content) {
           valueNode = createFunctionExpression(['_value', '_refs'])
           valueNode.body = createBlockStatement(
-            processInlineRef(context.bindingMetadata, value.content)
+            processInlineRef(context, value.content)
           )
         }
       }
@@ -894,15 +895,28 @@ function isComponentTag(tag: string) {
 }
 
 function processInlineRef(
-  bindings: BindingMetadata,
+  context: TransformContext,
   raw: string
 ): JSChildNode[] {
   const body = [createSimpleExpression(`_refs['${raw}'] = _value`)]
-  const type = bindings[raw]
+  const { bindingMetadata, helperString } = context
+  const type = bindingMetadata[raw]
   if (type === BindingTypes.SETUP_REF) {
     body.push(createSimpleExpression(`${raw}.value = _value`))
+  } else if (type === BindingTypes.SETUP_MAYBE_REF) {
+    body.push(
+      createSimpleExpression(
+        `${helperString(IS_REF)}(${raw}) && (${raw}.value = _value)`
+      )
+    )
   } else if (type === BindingTypes.SETUP_LET) {
-    body.push(createSimpleExpression(`${raw} = _value`))
+    body.push(
+      createSimpleExpression(
+        `${helperString(
+          IS_REF
+        )}(${raw}) ? ${raw}.value = _value : ${raw} = _value`
+      )
+    )
   }
   return body
 }