Skip to content

fix(reactivity): avoid triggering effects when set fails#14964

Open
ifer47 wants to merge 1 commit into
vuejs:mainfrom
ifer47:fix/reactivity-set-failed-trigger
Open

fix(reactivity): avoid triggering effects when set fails#14964
ifer47 wants to merge 1 commit into
vuejs:mainfrom
ifer47:fix/reactivity-set-failed-trigger

Conversation

@ifer47

@ifer47 ifer47 commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

This fixes a small reactivity edge case where MutableReactiveHandler.set triggered effects even when the underlying Reflect.set operation failed.

For example, assigning to a non-writable property through a reactive proxy throws and leaves the value unchanged, but the dependent effect was still re-run.

The handler now only triggers ADD / SET notifications when Reflect.set succeeds.

Tests added:

  • failed set operation should not trigger effects

Validation:

  • pnpm exec vitest run packages/reactivity/__tests__/reactive.spec.ts -t "failed set operation should not trigger effects"
  • pnpm exec vitest run packages/reactivity
  • pnpm exec prettier --check packages/reactivity/src/baseHandlers.ts packages/reactivity/__tests__/reactive.spec.ts
  • pnpm exec eslint packages/reactivity/src/baseHandlers.ts packages/reactivity/__tests__/reactive.spec.ts
  • pnpm check

Summary by CodeRabbit

  • Bug Fixes

    • Fixed the reactivity system to prevent triggering updates when property assignments fail on protected or read-only properties, ensuring correct state management.
  • Tests

    • Added test coverage to verify that failed property assignments do not trigger dependent updates and that cached values remain unchanged.

@coderabbitai

coderabbitai Bot commented Jun 15, 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: 98fb573c-8aa2-40f5-943d-3c881b8e2f75

📥 Commits

Reviewing files that changed from the base of the PR and between 478e3e8 and 4c93505.

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

📝 Walkthrough

Walkthrough

MutableReactiveHandler.set in baseHandlers.ts now checks that Reflect.set returned a truthy result before calling trigger. A new test in reactive.spec.ts covers the non-writable property case, asserting that a failed assignment throws TypeError and does not cause dependent effects to re-run.

Changes

Reactive trigger guard fix

Layer / File(s) Summary
Guard trigger on Reflect.set success + non-writable test
packages/reactivity/src/baseHandlers.ts, packages/reactivity/__tests__/reactive.spec.ts
The trigger call in MutableReactiveHandler.set is now gated on result being truthy, so ADD/SET triggers are suppressed when the underlying property write fails. The new test defines a writable: false property on a reactive object, asserts the assignment throws TypeError, and confirms the effect's observed value and run count remain unchanged.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~5 minutes

Suggested labels

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

Suggested reviewers

  • edison1105

Poem

🐇 A property locked, non-writable, tight,
The effect stayed calm, didn't trigger that night.
One result check added, so small, yet so true,
No phantom re-runs when the write falls through.
Hop hop, little fix — the reactive holds right! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preventing effects from being triggered when a set operation fails on a reactive object.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

@github-actions

Copy link
Copy Markdown

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 106 kB (+3 B) 40.2 kB (+2 B) 36.1 kB (+1 B)
vue.global.prod.js 164 kB (+3 B) 60.2 kB (+4 B) 53.5 kB (+27 B)

Usages

Name Size Gzip Brotli
createApp (CAPI only) 48.8 kB (+3 B) 19 kB 17.4 kB (+3 B)
createApp 56.9 kB (+3 B) 22 kB (-1 B) 20.1 kB (+4 B)
createSSRApp 61.2 kB (+3 B) 23.8 kB 21.7 kB
defineCustomElement 63.1 kB (+3 B) 23.9 kB (-1 B) 21.8 kB (+9 B)
overall 71.7 kB (+3 B) 27.4 kB 25 kB (+57 B)

@pkg-pr-new

pkg-pr-new Bot commented Jun 15, 2026

Copy link
Copy Markdown

Open in StackBlitz

@vue/compiler-core

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

@vue/compiler-dom

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

@vue/compiler-sfc

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

@vue/compiler-ssr

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

@vue/reactivity

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

@vue/runtime-core

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

@vue/runtime-dom

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

@vue/server-renderer

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

@vue/shared

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

vue

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

@vue/compat

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

commit: 4c93505

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant