Skip to content

fix(runtime-core): preserve nullish event handlers in mergeProps#14550

Open
zhiyuanzmj wants to merge 2 commits intovuejs:mainfrom
zhiyuanzmj:null-event-merge
Open

fix(runtime-core): preserve nullish event handlers in mergeProps#14550
zhiyuanzmj wants to merge 2 commits intovuejs:mainfrom
zhiyuanzmj:null-event-merge

Conversation

@zhiyuanzmj
Copy link
Member

@zhiyuanzmj zhiyuanzmj commented Mar 10, 2026

Ensure event listeners that are explicitly null or undefined are preserved during prop merging instead of being dropped.

Summary by CodeRabbit

  • Bug Fixes

    • Prop and event handler merging now preserves explicitly set null values instead of omitting them, preventing unexpected removal of null-assigned handlers or props.
  • Tests

    • Added test coverage validating null value handling in prop/event merging scenarios to ensure consistent behavior.

mergeProps

Ensure event listeners that are explicitly null or undefined are
preserved during prop merging instead of being dropped.
Copilot AI review requested due to automatic review settings March 10, 2026 13:56
@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

Added tests and a small runtime change: mergeProps now explicitly preserves falsy (including null) event handler values when both incoming and existing props are falsy; tests were added to verify onClick: undefined and onClick: null are preserved after merging.

Changes

Cohort / File(s) Summary
Tests
packages/runtime-core/__tests__/vnode.spec.ts
Added tests verifying mergeProps preserves onClick: undefined and onClick: null from input props.
mergeProps Logic
packages/runtime-core/src/vnode.ts
Added conditional branch to assign ret[key] = incoming when both incoming and existing handler are falsy, ensuring falsy event handlers are not omitted during merge.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Suggested labels

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

Poem

🐰 I nudge a prop with gentle paw,

Null and undefined are kept in awe,
Two falsy friends now share the trail,
Merged together without fail. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: preserving nullish (null/undefined) event handlers in mergeProps, which aligns with the PR objectives and the code changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

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

@github-actions
Copy link

github-actions bot commented Mar 10, 2026

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 105 kB (+24 B) 39.7 kB (+12 B) 35.7 kB (+32 B)
vue.global.prod.js 163 kB (+24 B) 59.7 kB (+10 B) 53.2 kB (+99 B)

Usages

Name Size Gzip Brotli
createApp (CAPI only) 48.2 kB (+24 B) 18.8 kB (+10 B) 17.2 kB (+5 B)
createApp 56.3 kB (+24 B) 21.8 kB (+8 B) 19.9 kB (+9 B)
createSSRApp 60.6 kB (+24 B) 23.5 kB (+10 B) 21.5 kB (-2 B)
defineCustomElement 62.5 kB (+24 B) 23.7 kB (+10 B) 21.6 kB (+10 B)
overall 70.7 kB (+24 B) 27.1 kB (+8 B) 24.7 kB (+53 B)

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 10, 2026

Open in StackBlitz

@vue/compiler-core

pnpm add https://pkg.pr.new/@vue/compiler-core@14550
npm i https://pkg.pr.new/@vue/compiler-core@14550
yarn add https://pkg.pr.new/@vue/compiler-core@14550.tgz

@vue/compiler-dom

pnpm add https://pkg.pr.new/@vue/compiler-dom@14550
npm i https://pkg.pr.new/@vue/compiler-dom@14550
yarn add https://pkg.pr.new/@vue/compiler-dom@14550.tgz

@vue/compiler-sfc

pnpm add https://pkg.pr.new/@vue/compiler-sfc@14550
npm i https://pkg.pr.new/@vue/compiler-sfc@14550
yarn add https://pkg.pr.new/@vue/compiler-sfc@14550.tgz

@vue/compiler-ssr

pnpm add https://pkg.pr.new/@vue/compiler-ssr@14550
npm i https://pkg.pr.new/@vue/compiler-ssr@14550
yarn add https://pkg.pr.new/@vue/compiler-ssr@14550.tgz

@vue/reactivity

pnpm add https://pkg.pr.new/@vue/reactivity@14550
npm i https://pkg.pr.new/@vue/reactivity@14550
yarn add https://pkg.pr.new/@vue/reactivity@14550.tgz

@vue/runtime-core

pnpm add https://pkg.pr.new/@vue/runtime-core@14550
npm i https://pkg.pr.new/@vue/runtime-core@14550
yarn add https://pkg.pr.new/@vue/runtime-core@14550.tgz

@vue/runtime-dom

pnpm add https://pkg.pr.new/@vue/runtime-dom@14550
npm i https://pkg.pr.new/@vue/runtime-dom@14550
yarn add https://pkg.pr.new/@vue/runtime-dom@14550.tgz

@vue/server-renderer

pnpm add https://pkg.pr.new/@vue/server-renderer@14550
npm i https://pkg.pr.new/@vue/server-renderer@14550
yarn add https://pkg.pr.new/@vue/server-renderer@14550.tgz

@vue/shared

pnpm add https://pkg.pr.new/@vue/shared@14550
npm i https://pkg.pr.new/@vue/shared@14550
yarn add https://pkg.pr.new/@vue/shared@14550.tgz

vue

pnpm add https://pkg.pr.new/vue@14550
npm i https://pkg.pr.new/vue@14550
yarn add https://pkg.pr.new/vue@14550.tgz

@vue/compat

pnpm add https://pkg.pr.new/@vue/compat@14550
npm i https://pkg.pr.new/@vue/compat@14550
yarn add https://pkg.pr.new/@vue/compat@14550.tgz

commit: bf30447

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/runtime-core/__tests__/vnode.spec.ts (1)

475-478: Good basic test coverage for the new functionality.

The test correctly verifies that mergeProps({ onClick: null }) preserves onClick: null in the result.

Consider adding a few more edge case tests to strengthen coverage:

🧪 Optional: Additional test cases
       expect(mergeProps({ onClick: null })).toMatchObject({
         onClick: null,
       })
+      // undefined is also preserved
+      expect(mergeProps({ onClick: undefined })).toMatchObject({
+        onClick: undefined,
+      })
+      // existing handler is preserved when merging with null
+      expect(mergeProps({ onClick: clickHandler1 }, { onClick: null })).toMatchObject({
+        onClick: clickHandler1,
+      })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/runtime-core/__tests__/vnode.spec.ts` around lines 475 - 478, Add a
few edge-case unit tests for mergeProps in
packages/runtime-core/__tests__/vnode.spec.ts: cover merging event handlers
(e.g., onClick functions concatenation/override behavior), merging when a prop
is undefined versus null (ensure null is preserved and undefined skipped/merged
correctly), merging array/value props (arrays are concatenated or replaced per
implementation), and merging objects like style/class to verify deep merge
semantics; create concise test cases that call mergeProps with these inputs and
assert the expected outputs using expect(...).toMatchObject or toEqual,
referencing mergeProps directly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/runtime-core/__tests__/vnode.spec.ts`:
- Around line 475-478: Add a few edge-case unit tests for mergeProps in
packages/runtime-core/__tests__/vnode.spec.ts: cover merging event handlers
(e.g., onClick functions concatenation/override behavior), merging when a prop
is undefined versus null (ensure null is preserved and undefined skipped/merged
correctly), merging array/value props (arrays are concatenated or replaced per
implementation), and merging objects like style/class to verify deep merge
semantics; create concise test cases that call mergeProps with these inputs and
assert the expected outputs using expect(...).toMatchObject or toEqual,
referencing mergeProps directly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7ea8780f-dcb5-47cb-91f7-249399eb4c0d

📥 Commits

Reviewing files that changed from the base of the PR and between fdd863f and a04385c.

📒 Files selected for processing (2)
  • packages/runtime-core/__tests__/vnode.spec.ts
  • packages/runtime-core/src/vnode.ts

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts mergeProps in runtime-core to ensure event listener props that are explicitly set to null/undefined are retained in the merged output rather than being omitted, and adds a regression test in the vnode suite.

Changes:

  • Update mergeProps event-handler merging to preserve explicitly falsy (nullish) incoming handlers when there is no existing handler.
  • Add a vnode unit test covering the onClick: null merge behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
packages/runtime-core/src/vnode.ts Updates mergeProps handler merging behavior to keep nullish handlers from being dropped.
packages/runtime-core/tests/vnode.spec.ts Adds a regression assertion for preserving onClick: null during merge.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@edison1105 edison1105 changed the title fix(runtime-core): prevent removing undefined event handlers in mergeProps fix(runtime-core): preserve only nullish event handlers in mergeProps Mar 13, 2026
@edison1105 edison1105 changed the title fix(runtime-core): preserve only nullish event handlers in mergeProps fix(runtime-core): preserve nullish event handlers in mergeProps Mar 13, 2026
@edison1105 edison1105 added ready to merge The PR is ready to be merged. 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. labels Mar 13, 2026
@edison1105
Copy link
Member

/ecosystem-ci run

@vue-bot
Copy link
Contributor

vue-bot commented Mar 13, 2026

📝 Ran ecosystem CI: Open

suite result latest scheduled
primevue success success
radix-vue success success
pinia success success
test-utils success success
language-tools failure failure
vant success success
quasar success success
nuxt success success
vue-simple-compiler success success
vite-plugin-vue success success
vitepress success success
vuetify failure success
router success success
vueuse success success
vue-i18n failure success
vue-macros success success

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. ready to merge The PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants