fix(runtime-dom): catch more cases of DOM property setting error (#5552)

close #5545
This commit is contained in:
zscumt123 2022-04-13 17:25:11 +08:00 committed by GitHub
parent 74d239caf7
commit fa1d14c2c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 34 deletions

View File

@ -234,12 +234,29 @@ describe('runtime-dom: props patching', () => {
expect(el.getAttribute('x')).toBe('2') expect(el.getAttribute('x')).toBe('2')
}) })
test('input with size', () => { test('input with size (number property)', () => {
const el = document.createElement('input') const el = document.createElement('input')
patchProp(el, 'size', null, 100) patchProp(el, 'size', null, 100)
expect(el.size).toBe(100) expect(el.size).toBe(100)
patchProp(el, 'size', 100, null) patchProp(el, 'size', 100, null)
expect(el.getAttribute('size')).toBe(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', () => { test('patch value for select', () => {

View File

@ -51,28 +51,23 @@ export function patchDOMProp(
return return
} }
let needRemove = false
if (value === '' || value == null) { if (value === '' || value == null) {
const type = typeof el[key] const type = typeof el[key]
if (type === 'boolean') { if (type === 'boolean') {
// e.g. <select multiple> compiles to { multiple: '' } // e.g. <select multiple> compiles to { multiple: '' }
el[key] = includeBooleanAttr(value) value = includeBooleanAttr(value)
return
} else if (value == null && type === 'string') { } else if (value == null && type === 'string') {
// e.g. <div :id="null"> // e.g. <div :id="null">
el[key] = '' value = ''
el.removeAttribute(key) needRemove = true
return
} else if (type === 'number') { } else if (type === 'number') {
// e.g. <img :width="null"> // e.g. <img :width="null">
// the value of some IDL attr must be greater than 0, e.g. input.size = 0 -> error // the value of some IDL attr must be greater than 0, e.g. input.size = 0 -> error
try { value = 0
el[key] = 0 needRemove = true
} catch {}
el.removeAttribute(key)
return
} }
} } else {
if ( if (
__COMPAT__ && __COMPAT__ &&
value === false && value === false &&
@ -89,13 +84,15 @@ export function patchDOMProp(
parentComponent, parentComponent,
key key
) )
el[key] = type === 'number' ? 0 : '' value = type === 'number' ? 0 : ''
el.removeAttribute(key) needRemove = true
return }
} }
} }
// 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 { try {
el[key] = value el[key] = value
} catch (e: any) { } catch (e: any) {
@ -107,4 +104,5 @@ export function patchDOMProp(
) )
} }
} }
needRemove && el.removeAttribute(key)
} }