Skip to content

Commit 3f37cf7

Browse files
committed
perf(runtime-core): improve efficiency of normalizePropsOptions
1 parent 422ef34 commit 3f37cf7

File tree

1 file changed

+30
-31
lines changed

1 file changed

+30
-31
lines changed

packages/runtime-core/src/componentProps.ts

Lines changed: 30 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,32 @@ 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 shouldCastTrue = true
567+
568+
const checkForBoolean = (
569+
type: PropConstructor | true | null | undefined,
570+
) => {
571+
const typeName = isFunction(type) && type.name
572+
573+
// If we find `String` before `Boolean`, e.g. `[String, Boolean]`, we need to handle the casting slightly
574+
// differently. Props passed as `<Comp checked="">` or `<Comp checked="checked">` will either be treated as
575+
// strings or converted to a boolean `true`, depending on the order of the types.
576+
if (typeName === 'String') {
577+
shouldCastTrue = false
576578
}
579+
580+
return typeName === 'Boolean'
581+
}
582+
583+
const shouldCast = isArray(propType)
584+
? propType.some(checkForBoolean)
585+
: checkForBoolean(propType)
586+
prop[BooleanFlags.shouldCast] = shouldCast
587+
prop[BooleanFlags.shouldCastTrue] = shouldCastTrue
588+
// if the prop needs boolean casting or default value
589+
if (shouldCast || hasOwn(prop, 'default')) {
590+
needCastKeys.push(normalizedKey)
577591
}
578592
}
579593
}
@@ -595,6 +609,7 @@ function validatePropName(key: string) {
595609
return false
596610
}
597611

612+
// dev only
598613
// use function string name to check type constructors
599614
// so that it works across vms / iframes.
600615
function getType(ctor: Prop<any>): string {
@@ -617,22 +632,6 @@ function getType(ctor: Prop<any>): string {
617632
return ''
618633
}
619634

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-
636635
/**
637636
* dev only
638637
*/

0 commit comments

Comments
 (0)