Skip to content

Commit 5680142

Browse files
perf(runtime-core): improve efficiency of normalizePropsOptions (#11409)
close #9739
1 parent 87923f6 commit 5680142

File tree

1 file changed

+34
-31
lines changed

1 file changed

+34
-31
lines changed

packages/runtime-core/src/componentProps.ts

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -174,12 +174,10 @@ export type ExtractDefaultPropTypes<O> = O extends object
174174
{ [K in keyof Pick<O, DefaultKeys<O>>]: InferPropType<O[K]> }
175175
: {}
176176

177-
type NormalizedProp =
178-
| null
179-
| (PropOptions & {
180-
[BooleanFlags.shouldCast]?: boolean
181-
[BooleanFlags.shouldCastTrue]?: boolean
182-
})
177+
type NormalizedProp = PropOptions & {
178+
[BooleanFlags.shouldCast]?: boolean
179+
[BooleanFlags.shouldCastTrue]?: boolean
180+
}
183181

184182
// normalized value is a tuple of the actual normalized options
185183
// and an array of prop keys that need value casting (booleans and defaults)
@@ -564,16 +562,36 @@ export function normalizePropsOptions(
564562
const opt = raw[key]
565563
const prop: NormalizedProp = (normalized[normalizedKey] =
566564
isArray(opt) || isFunction(opt) ? { type: opt } : extend({}, opt))
567-
if (prop) {
568-
const booleanIndex = getTypeIndex(Boolean, prop.type)
569-
const stringIndex = getTypeIndex(String, prop.type)
570-
prop[BooleanFlags.shouldCast] = booleanIndex > -1
571-
prop[BooleanFlags.shouldCastTrue] =
572-
stringIndex < 0 || booleanIndex < stringIndex
573-
// if the prop needs boolean casting or default value
574-
if (booleanIndex > -1 || hasOwn(prop, 'default')) {
575-
needCastKeys.push(normalizedKey)
565+
const propType = prop.type
566+
let shouldCast = false
567+
let shouldCastTrue = true
568+
569+
if (isArray(propType)) {
570+
for (let index = 0; index < propType.length; ++index) {
571+
const type = propType[index]
572+
const typeName = isFunction(type) && type.name
573+
574+
if (typeName === 'Boolean') {
575+
shouldCast = true
576+
break
577+
} else if (typeName === 'String') {
578+
// If we find `String` before `Boolean`, e.g. `[String, Boolean]`,
579+
// we need to handle the casting slightly differently. Props
580+
// passed as `<Comp checked="">` or `<Comp checked="checked">`
581+
// will either be treated as strings or converted to a boolean
582+
// `true`, depending on the order of the types.
583+
shouldCastTrue = false
584+
}
576585
}
586+
} else {
587+
shouldCast = isFunction(propType) && propType.name === 'Boolean'
588+
}
589+
590+
prop[BooleanFlags.shouldCast] = shouldCast
591+
prop[BooleanFlags.shouldCastTrue] = shouldCastTrue
592+
// if the prop needs boolean casting or default value
593+
if (shouldCast || hasOwn(prop, 'default')) {
594+
needCastKeys.push(normalizedKey)
577595
}
578596
}
579597
}
@@ -595,6 +613,7 @@ function validatePropName(key: string) {
595613
return false
596614
}
597615

616+
// dev only
598617
// use function string name to check type constructors
599618
// so that it works across vms / iframes.
600619
function getType(ctor: Prop<any>): string {
@@ -617,22 +636,6 @@ function getType(ctor: Prop<any>): string {
617636
return ''
618637
}
619638

620-
function isSameType(a: Prop<any>, b: Prop<any>): boolean {
621-
return getType(a) === getType(b)
622-
}
623-
624-
function getTypeIndex(
625-
type: Prop<any>,
626-
expectedTypes: PropType<any> | void | null | true,
627-
): number {
628-
if (isArray(expectedTypes)) {
629-
return expectedTypes.findIndex(t => isSameType(t, type))
630-
} else if (isFunction(expectedTypes)) {
631-
return isSameType(expectedTypes, type) ? 0 : -1
632-
}
633-
return -1
634-
}
635-
636639
/**
637640
* dev only
638641
*/

0 commit comments

Comments
 (0)