From 5586cdafd6b3d885df116d20cab36a1d9d11f424 Mon Sep 17 00:00:00 2001 From: Codex CLI Date: Fri, 31 Oct 2025 11:29:34 +0800 Subject: [PATCH 1/2] fix(runtime-core): guard prop validator to avoid instanceof crash --- packages/runtime-core/src/componentProps.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts index 775eb8b6728..07a6722e385 100644 --- a/packages/runtime-core/src/componentProps.ts +++ b/packages/runtime-core/src/componentProps.ts @@ -737,14 +737,19 @@ function assertType( valid = t === expectedType.toLowerCase() // for primitive wrapper objects if (!valid && t === 'object') { - valid = value instanceof (type as PropConstructor) + // Guard against invalid prop type definitions (e.g. 'object', {}, etc.) + // Only attempt instanceof when the provided type is a function/constructor. + valid = isFunction(type) && value instanceof (type as PropConstructor) } } else if (expectedType === 'Object') { valid = isObject(value) } else if (expectedType === 'Array') { valid = isArray(value) } else { - valid = value instanceof (type as PropConstructor) + // Fallback to constructor check only when type is a function. + // This avoids errors like "Right-hand side of 'instanceof' is not an object" + // when users mistakenly pass invalid values (e.g. strings) in prop type. + valid = isFunction(type) && value instanceof (type as PropConstructor) } return { valid, From 5603acadee88df254e37807fa646fd26ee5518ba Mon Sep 17 00:00:00 2001 From: Zhaokun Date: Tue, 4 Nov 2025 13:16:48 +0800 Subject: [PATCH 2/2] refactor(runtime-core): handle null type check before assertType Move null type validation logic to the caller side (validateProp) before calling assertType, instead of handling it inside assertType. This provides: - Better separation of concerns - Avoids unnecessary function calls for null types - Clearer code flow and intent - Simplifies assertType and getType implementations All existing tests pass, including support for `type: [Function,null]`. --- packages/runtime-core/src/componentProps.ts | 35 +++++++++++---------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts index 07a6722e385..b28f5edff8f 100644 --- a/packages/runtime-core/src/componentProps.ts +++ b/packages/runtime-core/src/componentProps.ts @@ -626,12 +626,7 @@ function validatePropName(key: string) { // dev only // use function string name to check type constructors // so that it works across vms / iframes. -function getType(ctor: Prop | null): string { - // Early return for null to avoid unnecessary computations - if (ctor === null) { - return 'null' - } - +function getType(ctor: Prop): string { // Avoid using regex for common cases by checking the type directly if (typeof ctor === 'function') { // Using name property to avoid converting function to string @@ -697,9 +692,22 @@ function validateProp( const expectedTypes = [] // value is valid as long as one of the specified types match for (let i = 0; i < types.length && !isValid; i++) { - const { valid, expectedType } = assertType(value, types[i]) - expectedTypes.push(expectedType || '') - isValid = valid + // Handle null type directly without calling assertType + if (types[i] === null) { + if (value === null) { + expectedTypes.push('null') + isValid = true + } else { + expectedTypes.push('null') + } + } else if (types[i] !== undefined) { + // TypeScript doesn't narrow the type after the checks above, + // so we use a const to help it understand types[i] is not null/undefined here + const type = types[i] as PropConstructor + const { valid, expectedType } = assertType(value, type) + expectedTypes.push(expectedType || '') + isValid = valid + } } if (!isValid) { warn(getInvalidTypeMessage(name, value, expectedTypes)) @@ -724,15 +732,10 @@ type AssertionResult = { /** * dev only */ -function assertType( - value: unknown, - type: PropConstructor | null, -): AssertionResult { +function assertType(value: unknown, type: PropConstructor): AssertionResult { let valid const expectedType = getType(type) - if (expectedType === 'null') { - valid = value === null - } else if (isSimpleType(expectedType)) { + if (isSimpleType(expectedType)) { const t = typeof value valid = t === expectedType.toLowerCase() // for primitive wrapper objects