diff --git a/packages/runtime-dom/src/modules/attrs.ts b/packages/runtime-dom/src/modules/attrs.ts index d7188aa9a1f..1e75e5343e9 100644 --- a/packages/runtime-dom/src/modules/attrs.ts +++ b/packages/runtime-dom/src/modules/attrs.ts @@ -59,11 +59,11 @@ export function compatCoerceAttr( ): boolean { if (isEnumeratedAttr(key)) { const v2CoercedValue = - value === null - ? 'false' - : typeof value !== 'boolean' && value !== undefined - ? 'true' - : null + value === undefined + ? null + : value === null || value === false || value === 'false' + ? 'false' + : 'true' if ( v2CoercedValue && compatUtils.softAssertCompatEnabled( diff --git a/packages/vue-compat/__tests__/misc.spec.ts b/packages/vue-compat/__tests__/misc.spec.ts index 17fddd94c4a..3cb120d06fa 100644 --- a/packages/vue-compat/__tests__/misc.spec.ts +++ b/packages/vue-compat/__tests__/misc.spec.ts @@ -275,3 +275,24 @@ test('ATTR_ENUMERATED_COERCION', () => { )('contenteditable', 'foo', 'true'), ).toHaveBeenWarned() }) + +test('ATTR_ENUMERATED_COERCION, coercing "false"', () => { + const vm = new Vue({ + template: `
hello
`, + }).$mount() + expect(vm.$el.innerHTML).toBe( + `
hello
`, + ) + expect( + ( + deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION] + .message as Function + )('draggable', 'false', 'false'), + ).toHaveBeenWarned() + expect( + ( + deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION] + .message as Function + )('spellcheck', 'false', 'false'), + ).toHaveBeenWarned() +})