From 718f2371b94d09aa8a8fdbd8e98e01594cb9d41f Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 9 Mar 2018 14:46:00 -0500 Subject: [PATCH] fix: respect type order when boolean casting multi-typed props fix #7485 --- src/core/util/props.js | 33 +++++++++++++++--------- test/unit/features/options/props.spec.js | 17 ++++++++++++ 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/core/util/props.js b/src/core/util/props.js index 4d55b877c40..a92643f9d2a 100644 --- a/src/core/util/props.js +++ b/src/core/util/props.js @@ -27,12 +27,18 @@ export function validateProp ( const prop = propOptions[key] const absent = !hasOwn(propsData, key) let value = propsData[key] - // handle boolean props - if (isType(Boolean, prop.type)) { + // boolean casting + const booleanIndex = getTypeIndex(Boolean, prop.type) + if (booleanIndex > -1) { if (absent && !hasOwn(prop, 'default')) { value = false - } else if (!isType(String, prop.type) && (value === '' || value === hyphenate(key))) { - value = true + } else if (value === '' || value === hyphenate(key)) { + // only cast empty string / same name to boolean if + // boolean has higher priority + const stringIndex = getTypeIndex(String, prop.type) + if (stringIndex < 0 || booleanIndex < stringIndex) { + value = true + } } } // check default value @@ -179,15 +185,18 @@ function getType (fn) { return match ? match[1] : '' } -function isType (type, fn) { - if (!Array.isArray(fn)) { - return getType(fn) === getType(type) +function isSameType (a, b) { + return getType(a) === getType(b) +} + +function getTypeIndex (type, expectedTypes): number { + if (!Array.isArray(expectedTypes)) { + return isSameType(expectedTypes, type) ? 0 : -1 } - for (let i = 0, len = fn.length; i < len; i++) { - if (getType(fn[i]) === getType(type)) { - return true + for (let i = 0, len = expectedTypes.length; i < len; i++) { + if (isSameType(expectedTypes[i], type)) { + return i } } - /* istanbul ignore next */ - return false + return -1 } diff --git a/test/unit/features/options/props.spec.js b/test/unit/features/options/props.spec.js index ae2baefff99..bdb6cdaa8f5 100644 --- a/test/unit/features/options/props.spec.js +++ b/test/unit/features/options/props.spec.js @@ -512,4 +512,21 @@ describe('Options props', () => { expect(`"${attr}" is a reserved attribute`).toHaveBeenWarned() }) }) + + it('should consider order when casting [Boolean, String] multi-type props', () => { + const vm = new Vue({ + template: '', + components: { + test: { + template: '
', + props: { + booleanOrString: [Boolean, String], + stringOrBoolean: [String, Boolean] + } + } + } + }).$mount() + expect(vm.$refs.test.$props.booleanOrString).toBe(true) + expect(vm.$refs.test.$props.stringOrBoolean).toBe('') + }) })