Skip to content

fix(reactivity): preserve effect options (fix #16100) - #16103

Closed
JoaoMarcos44 wants to merge 3 commits into
vuejs:minorfrom
JoaoMarcos44:fix/preserve-shared-effect-options
Closed

JoaoMarcos44 wants to merge 3 commits into
vuejs:minorfrom
JoaoMarcos44:fix/preserve-shared-effect-options

Conversation

@JoaoMarcos44

@JoaoMarcos44 JoaoMarcos44 commented Nov 2, 2026 •

Copy link
Copy Markdown

Closes #16100.

Cause and consequence

effect() changed the caller's scheduler and onStop options to undefined. Reusing the options could lose scheduling and cleanup callbacks, and frozen options could throw in ESM. Reading the remaining options before installing cleanup also let a debug-hook getter stop the effect's scope or throw before onStop was attached.

Solution

Read scheduler and onStop once and install their behavior first. Then copy the other own enumerable option properties to the effect, including symbol keys, without changing the caller's object. Property reads keep their original receiver.

Why this approach

It preserves the callback setup order while supporting shared, frozen, readonly and getter-based options. If an onTrack or onTrigger getter stops the scope, or throws before the caller stops it, cleanup is already installed. Inherited and non-enumerable debug-hook behavior follows the existing option-copying rules.

Pros and cons

  • Pros: shared options retain callbacks; frozen options work; getters are read once; cleanup survives reentrant debug getters; own enumerable symbols are preserved.
  • Cons: option creation enumerates own keys and checks enumerability. No performance benchmark was run. The existing repeated-stop callback behavior is outside this fix.

The PR targets minor because the original mutation regression is in the 3.6 line; stable 3.5.44 and main retain the non-mutating implementation.

Validation

  • Four durable getter-cleanup tests failed before the initialization-order fix, then passed. Controls cover frozen single-read getters, inherited/non-enumerable hooks and own enumerable symbols with the original receiver.
  • effect.spec.ts: 84/84. Reactivity tests including unit-gc and supplementary review cases: 500 passed, 2 existing todo tests.
  • Coverage of effect.ts: 90.26% statements, 88.33% branches, 90.47% functions, 90.90% lines.
  • Full project TypeScript, targeted Vite+ lint/format and reactivity esm-browser development/production builds passed.
  • The original frozen/shared-options reproduction and the additional scope/getter cases were exercised in isolated snapshots.
  • RED/GREEN evidence is preserved in the branch commits.

Original reproduction · PR preview

A dragon conductor shares an intact score with two musical spirits.

AI-generated conceptual illustration: reactive effects can reuse the caller-owned options while scheduling and cleanup callbacks are installed first. This is not execution or test evidence.

@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2fa68919-8922-497d-b249-990883387d84

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-02T19:07:39.512091Z d6b8219 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

RED: four scoped getter cleanup tests fail on 7a65ab8 with zero onStop calls; three controls pass for frozen single-read getters and inherited/non-enumerable callbacks. Tests ran in an isolated snapshot with one worker.
Install onStop and scheduler before evaluating other option getters. Copy own enumerable keys, including symbols, without mutating options or rereading callback getters. Preserve getter receivers and inherited/non-enumerable behavior.

GREEN: 84 effect tests and 500 reactivity tests including review probes pass, with 2 existing todo tests. Full TypeScript, targeted lint/format and development/production esm-browser builds pass in the isolated snapshot.
@edison1105

Copy link
Copy Markdown
Member

Closing in favor of #16105

@edison1105 edison1105 closed this Nov 3, 2026
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.

2 participants