]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-dom): catch more cases of DOM property setting error (#5552)
authorzscumt123 <zscumt123@163.com>
Wed, 13 Apr 2022 09:25:11 +0000 (17:25 +0800)
committerGitHub <noreply@github.com>
Wed, 13 Apr 2022 09:25:11 +0000 (05:25 -0400)
close #5545

packages/runtime-dom/__tests__/patchProps.spec.ts
packages/runtime-dom/src/modules/props.ts

index 247606950407bdddf3ae14e3bc9c29e04cab881c..9a324970cc9d3c7e8d414240b03cf4d7a951e691 100644 (file)
@@ -234,12 +234,29 @@ describe('runtime-dom: props patching', () => {
     expect(el.getAttribute('x')).toBe('2')
   })
 
-  test('input with size', () => {
+  test('input with size (number property)', () => {
     const el = document.createElement('input')
     patchProp(el, 'size', null, 100)
     expect(el.size).toBe(100)
     patchProp(el, 'size', 100, null)
     expect(el.getAttribute('size')).toBe(null)
+    expect('Failed setting prop "size" on <input>').toHaveBeenWarnedLast()
+  })
+
+  test('select with type (string property)', () => {
+    const el = document.createElement('select')
+    patchProp(el, 'type', null, 'test')
+    expect(el.type).toBe('select-one')
+    expect('Failed setting prop "type" on <select>').toHaveBeenWarnedLast()
+  })
+
+  test('select with willValidate (boolean property)', () => {
+    const el = document.createElement('select')
+    patchProp(el, 'willValidate', true, null)
+    expect(el.willValidate).toBe(true)
+    expect(
+      'Failed setting prop "willValidate" on <select>'
+    ).toHaveBeenWarnedLast()
   })
 
   test('patch value for select', () => {
index 5092911e44a6dbed718b762b7d1e8c1f94da6859..591f8caa7d0a745ed550c24b72b542ac8bffbce9 100644 (file)
@@ -51,51 +51,48 @@ export function patchDOMProp(
     return
   }
 
+  let needRemove = false
   if (value === '' || value == null) {
     const type = typeof el[key]
     if (type === 'boolean') {
       // e.g. <select multiple> compiles to { multiple: '' }
-      el[key] = includeBooleanAttr(value)
-      return
+      value = includeBooleanAttr(value)
     } else if (value == null && type === 'string') {
       // e.g. <div :id="null">
-      el[key] = ''
-      el.removeAttribute(key)
-      return
+      value = ''
+      needRemove = true
     } else if (type === 'number') {
       // e.g. <img :width="null">
       // the value of some IDL attr must be greater than 0, e.g. input.size = 0 -> error
-      try {
-        el[key] = 0
-      } catch {}
-      el.removeAttribute(key)
-      return
+      value = 0
+      needRemove = true
     }
-  }
-
-  if (
-    __COMPAT__ &&
-    value === false &&
-    compatUtils.isCompatEnabled(
-      DeprecationTypes.ATTR_FALSE_VALUE,
-      parentComponent
-    )
-  ) {
-    const type = typeof el[key]
-    if (type === 'string' || type === 'number') {
-      __DEV__ &&
-        compatUtils.warnDeprecation(
-          DeprecationTypes.ATTR_FALSE_VALUE,
-          parentComponent,
-          key
-        )
-      el[key] = type === 'number' ? 0 : ''
-      el.removeAttribute(key)
-      return
+  } else {
+    if (
+      __COMPAT__ &&
+      value === false &&
+      compatUtils.isCompatEnabled(
+        DeprecationTypes.ATTR_FALSE_VALUE,
+        parentComponent
+      )
+    ) {
+      const type = typeof el[key]
+      if (type === 'string' || type === 'number') {
+        __DEV__ &&
+          compatUtils.warnDeprecation(
+            DeprecationTypes.ATTR_FALSE_VALUE,
+            parentComponent,
+            key
+          )
+        value = type === 'number' ? 0 : ''
+        needRemove = true
+      }
     }
   }
 
-  // some properties perform value validation and throw
+  // some properties perform value validation and throw,
+  // some properties has getter, no setter, will error in 'use strict'
+  // eg. <select :type="null"></select> <select :willValidate="null"></select>
   try {
     el[key] = value
   } catch (e: any) {
@@ -107,4 +104,5 @@ export function patchDOMProp(
       )
     }
   }
+  needRemove && el.removeAttribute(key)
 }