Skip to content

Conversation

@ZKunZhang
Copy link

@ZKunZhang ZKunZhang commented Oct 31, 2025

Problem Description

  • When uncommenting <test-comp :modelValue="{ type: 'js' }" />, the app throws "Right-hand side of 'instanceof' is not an object" during hot-reload/render in development mode
  • The error occurs in the dev-only props type assertion path before the child component instance exists, so the parent onErrorCaptured cannot intercept it

Root Cause

  • assertType uses value instanceof type even when type is not a constructor/function (e.g., user mistakenly declares type: 'object', type: 'Object', or nested { type: String })
  • This causes a raw TypeError which bypasses Vue's error boundary

Change Summary

File: packages/runtime-core/src/componentProps.ts

  • Only execute instanceof checks when type is a function/constructor:
    // Before
    value instanceof (type as PropConstructor)
    
    // After
    isFunction(type) && value instanceof (type as PropConstructor)
  • Applied in both the "primitive wrapper objects" branch and the final fallback branch
  • Preserve existing dev warnings (warn(getInvalidTypeMessage(...))); do not crash

Behavior After Change

Development Environment

  • Invalid prop types produce an "Invalid prop" warning instead of throwing a TypeError
  • If a child later throws during render/effects, the parent onErrorCaptured can capture it (and apps can suppress overlays)

Production Environment

  • No change (prop type assertions are skipped in production)

Reproduction (Pre-fix)

  1. Parent template includes <test-comp :modelValue="{ type: 'js' }" />
  2. test-comp incorrectly declares modelValue prop type (e.g., type: 'object' or type: { type: String })
  3. Hot update or initial render throws "Right-hand side of 'instanceof' is not an object"; onErrorCaptured does not run

Validation

With the fix:

  • Uncommenting the usage no longer crashes; the page renders
  • Dev console shows a prop type warning (expected)
  • Any other runtime errors from test-comp are captured by the parent onErrorCaptured and no red overlay appears if handled

Scope and Risk

  • Scope: Dev-only prop type validation in runtime-core
  • Risk: Low; only adds an isFunction guard around instanceof
  • Performance: Negligible change

Related

Notes for App Authors

While the runtime now guards against crashes, component props should still be declared with valid constructors/PropType, e.g.:

type: Object as PropType<{ type: string }>

with an optional validator.

Summary by CodeRabbit

  • Bug Fixes
    • Improved component prop validation to safely handle null and non-function type entries, preventing runtime errors when props use unexpected or non-standard type definitions.
    • Adjusted validation flow so null-type cases are handled without causing crashes, increasing stability during component initialization and prop checks.

@coderabbitai
Copy link

coderabbitai bot commented Oct 31, 2025

Walkthrough

The prop validation logic was changed to guard instanceof checks by verifying the prop type is a function before using instanceof; null-type handling was moved to callers and validateProp now explicitly handles null entries in declared prop types.

Changes

Cohort / File(s) Change Summary
Prop type validation guard
packages/runtime-core/src/componentProps.ts
Added function-type guard before instanceof in assertType; removed null handling from getType; validateProp now explicitly handles null entries in prop types and delegates constructor checks to assertType when defined. Comments adjusted accordingly.

Sequence Diagram(s)

sequenceDiagram
  participant C as Component / caller
  participant V as validateProp
  participant A as assertType

  C->>V: validateProp(propValue, propOptions)
  V->>V: loop declared types (including null)
  alt type === null
    V-->>C: mark valid only if value === null
  else type defined
    V->>A: assertType(value, type)
    A->>A: isFunction(type)?
    alt true
      A->>A: check instanceof / primitive checks
      A-->>V: return validity + expectedType
    else false
      A-->>V: skip instanceof, perform primitive checks only
    end
  end
  V-->>C: final validation result
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Pay attention to:
    • Correct handling of null in validateProp (expectedTypes and validity).
    • All call sites of getType / assertType still behave correctly.
    • Edge cases where non-function types (e.g., objects) were previously passed as prop types.

Suggested labels

ready to merge, :hammer: p3-minor-bug

Poem

A rabbit nibbles through the prop-check glade,
Guards put in place so no errors cascade.
Instanceof sits only where constructors play,
Now props hop along, safe through the day. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: guarding the prop validator against invalid types to prevent instanceof crashes, with a direct reference to the fixed issue #14041.
Linked Issues check ✅ Passed The code changes directly address all objectives from #14041: guard instanceof checks with isFunction, prevent TypeError crashes, allow onErrorCaptured to capture subsequent errors, preserve production behavior, and emit dev warnings instead.
Out of Scope Changes check ✅ Passed All changes in componentProps.ts are directly related to fixing the instanceof crash issue and preventing invalid prop type metadata from causing runtime errors, with no extraneous modifications.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5586cda and 5603aca.

📒 Files selected for processing (1)
  • packages/runtime-core/src/componentProps.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/runtime-core/src/componentProps.ts (1)
packages/shared/src/general.ts (3)
  • isFunction (49-50)
  • isObject (53-54)
  • isArray (39-39)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Redirect rules
  • GitHub Check: Header rules
  • GitHub Check: Pages changed
🔇 Additional comments (1)
packages/runtime-core/src/componentProps.ts (1)

743-756: Guard prevents invalid instanceof crash

Great call adding isFunction(type) before the instanceof checks; this neatly sidesteps the dev-time TypeError when users supply non-constructors while keeping valid constructors untouched.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

// for primitive wrapper objects
if (!valid && t === 'object') {
valid = value instanceof (type as PropConstructor)
// Guard against invalid prop type definitions (e.g. 'object', {}, etc.)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proper fix should be to avoid calling assertType if type is a null-lish value (at line:700)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proper fix should be to avoid calling assertType if type is a null-lish value (at line:700)

Sorry, I misunderstood the meaning. I'll fix it right now

@edison1105 edison1105 added 🍰 p2-nice-to-have Priority 2: this is not breaking anything but nice to have it addressed. wait changes need test The PR has missing test cases. labels Nov 4, 2025
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]`.
@ZKunZhang ZKunZhang requested a review from edison1105 November 4, 2025 05:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🍰 p2-nice-to-have Priority 2: this is not breaking anything but nice to have it addressed. need test The PR has missing test cases. wait changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

onErrorCaptured hook fails to capture instanceof error from child component

2 participants