Skip to content

fix(reactivity): preserve watch callback return value when wrapped for once: true#14902

Merged
edison1105 merged 1 commit into
vuejs:mainfrom
ackwell:reactivity-watch-once-async-error-handling
Jun 11, 2026
Merged

fix(reactivity): preserve watch callback return value when wrapped for once: true#14902
edison1105 merged 1 commit into
vuejs:mainfrom
ackwell:reactivity-watch-once-async-error-handling

Conversation

@ackwell

@ackwell ackwell commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

watch callbacks are executed via callWithAsyncErrorHandling, which inspects the return value of the callback to determine if promise rejection handling is required.

when passing once: true to watch's options, the callback is wrapped to add the watchHandle call after the first execution - in the process, silently dropping any returned promises.

this pr is just a small tweak + test to preserve the original callback's result, returning it from the new wrapped method.

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Fixed watch() function to properly return callback values when the once option is used
    • Improved error handling for async callbacks in watchers to correctly surface errors through the error handler

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e0b3acc1-79db-4fd9-a620-6d9c1f9c69c2

📥 Commits

Reviewing files that changed from the base of the PR and between 86ad076 and 022d790.

📒 Files selected for processing (2)
  • packages/reactivity/__tests__/watch.spec.ts
  • packages/reactivity/src/watch.ts

📝 Walkthrough

Walkthrough

The PR fixes the watch function to return the original callback's result when once mode is enabled. It adds comprehensive tests validating that async callbacks throw errors properly via the onError handler in both standard and once: true scenarios.

Changes

Watch callback behavior with once mode

Layer / File(s) Summary
Callback return value capture in once mode
packages/reactivity/src/watch.ts, packages/reactivity/__tests__/watch.spec.ts
When once && cb are both enabled, the internal wrapper now stores the callback's result and returns it instead of discarding the value. Tests verify that async callbacks correctly invoke onError when they throw, for both standard and once: true watch modes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Suggested labels

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

Poem

A rabbit hops through watch's flow,
Callbacks return what they should show,
Once mode keeps its promise bright,
Async errors see the light,
All caught and handled, smooth and right! 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: fixing watch callback return value preservation when once: true is used, which is the core issue addressed in the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@edison1105 edison1105 added ready to merge The PR is ready to be merged. scope: reactivity 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. labels Jun 4, 2026
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 106 kB (+15 B) 40.1 kB (+6 B) 36 kB (-21 B)
vue.global.prod.js 164 kB (+15 B) 60.1 kB (+6 B) 53.4 kB (-64 B)

Usages

Name Size Gzip Brotli
createApp (CAPI only) 48.8 kB 19 kB 17.4 kB
createApp 56.9 kB (+15 B) 22 kB (+5 B) 20.1 kB (+6 B)
createSSRApp 61.2 kB (+15 B) 23.8 kB (+6 B) 21.7 kB (+7 B)
defineCustomElement 63.1 kB (+15 B) 23.9 kB (+5 B) 21.8 kB (+3 B)
overall 71.7 kB (+15 B) 27.4 kB (+5 B) 25 kB (+3 B)

@pkg-pr-new

pkg-pr-new Bot commented Jun 4, 2026

Copy link
Copy Markdown

Open in StackBlitz

@vue/compiler-core

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

@vue/compiler-dom

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

@vue/compiler-sfc

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

@vue/compiler-ssr

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

@vue/reactivity

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

@vue/runtime-core

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

@vue/runtime-dom

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

@vue/server-renderer

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

@vue/shared

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

vue

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

@vue/compat

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

commit: 022d790

@edison1105

Copy link
Copy Markdown
Member

/ecosystem-ci run

@vue-bot

vue-bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

📝 Ran ecosystem CI: Open

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

@edison1105 edison1105 merged commit 450a8a8 into vuejs:main Jun 11, 2026
14 checks passed
@ackwell ackwell deleted the reactivity-watch-once-async-error-handling branch June 11, 2026 02:40
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. scope: reactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants