Skip to content

Commit fa1d14c

Browse files
authoredApr 13, 2022
fix(runtime-dom): catch more cases of DOM property setting error (#5552)
close #5545
1 parent 74d239c commit fa1d14c

File tree

2 files changed

+48
-33
lines changed

2 files changed

+48
-33
lines changed
 

‎packages/runtime-dom/__tests__/patchProps.spec.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -234,12 +234,29 @@ describe('runtime-dom: props patching', () => {
234234
expect(el.getAttribute('x')).toBe('2')
235235
})
236236

237-
test('input with size', () => {
237+
test('input with size (number property)', () => {
238238
const el = document.createElement('input')
239239
patchProp(el, 'size', null, 100)
240240
expect(el.size).toBe(100)
241241
patchProp(el, 'size', 100, null)
242242
expect(el.getAttribute('size')).toBe(null)
243+
expect('Failed setting prop "size" on <input>').toHaveBeenWarnedLast()
244+
})
245+
246+
test('select with type (string property)', () => {
247+
const el = document.createElement('select')
248+
patchProp(el, 'type', null, 'test')
249+
expect(el.type).toBe('select-one')
250+
expect('Failed setting prop "type" on <select>').toHaveBeenWarnedLast()
251+
})
252+
253+
test('select with willValidate (boolean property)', () => {
254+
const el = document.createElement('select')
255+
patchProp(el, 'willValidate', true, null)
256+
expect(el.willValidate).toBe(true)
257+
expect(
258+
'Failed setting prop "willValidate" on <select>'
259+
).toHaveBeenWarnedLast()
243260
})
244261

245262
test('patch value for select', () => {

‎packages/runtime-dom/src/modules/props.ts

+30-32
Original file line numberDiff line numberDiff line change
@@ -51,51 +51,48 @@ export function patchDOMProp(
5151
return
5252
}
5353

54+
let needRemove = false
5455
if (value === '' || value == null) {
5556
const type = typeof el[key]
5657
if (type === 'boolean') {
5758
// e.g. <select multiple> compiles to { multiple: '' }
58-
el[key] = includeBooleanAttr(value)
59-
return
59+
value = includeBooleanAttr(value)
6060
} else if (value == null && type === 'string') {
6161
// e.g. <div :id="null">
62-
el[key] = ''
63-
el.removeAttribute(key)
64-
return
62+
value = ''
63+
needRemove = true
6564
} else if (type === 'number') {
6665
// e.g. <img :width="null">
6766
// the value of some IDL attr must be greater than 0, e.g. input.size = 0 -> error
68-
try {
69-
el[key] = 0
70-
} catch {}
71-
el.removeAttribute(key)
72-
return
67+
value = 0
68+
needRemove = true
7369
}
74-
}
75-
76-
if (
77-
__COMPAT__ &&
78-
value === false &&
79-
compatUtils.isCompatEnabled(
80-
DeprecationTypes.ATTR_FALSE_VALUE,
81-
parentComponent
82-
)
83-
) {
84-
const type = typeof el[key]
85-
if (type === 'string' || type === 'number') {
86-
__DEV__ &&
87-
compatUtils.warnDeprecation(
88-
DeprecationTypes.ATTR_FALSE_VALUE,
89-
parentComponent,
90-
key
91-
)
92-
el[key] = type === 'number' ? 0 : ''
93-
el.removeAttribute(key)
94-
return
70+
} else {
71+
if (
72+
__COMPAT__ &&
73+
value === false &&
74+
compatUtils.isCompatEnabled(
75+
DeprecationTypes.ATTR_FALSE_VALUE,
76+
parentComponent
77+
)
78+
) {
79+
const type = typeof el[key]
80+
if (type === 'string' || type === 'number') {
81+
__DEV__ &&
82+
compatUtils.warnDeprecation(
83+
DeprecationTypes.ATTR_FALSE_VALUE,
84+
parentComponent,
85+
key
86+
)
87+
value = type === 'number' ? 0 : ''
88+
needRemove = true
89+
}
9590
}
9691
}
9792

98-
// some properties perform value validation and throw
93+
// some properties perform value validation and throw,
94+
// some properties has getter, no setter, will error in 'use strict'
95+
// eg. <select :type="null"></select> <select :willValidate="null"></select>
9996
try {
10097
el[key] = value
10198
} catch (e: any) {
@@ -107,4 +104,5 @@ export function patchDOMProp(
107104
)
108105
}
109106
}
107+
needRemove && el.removeAttribute(key)
110108
}

0 commit comments

Comments
 (0)
Please sign in to comment.