-
-
Notifications
You must be signed in to change notification settings - Fork 8.7k
fix(compat): watch arrays as deep: 1 #13377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
# Conflicts: # packages/reactivity/src/watch.ts
WalkthroughCompatibility logic for array watching was added and refactored across the reactivity and runtime-core modules. The watch callback triggering conditions were extended to support legacy array semantics under a compatibility flag. The watcher getter logic was centralized and reused, and the test suite for the Changes
Sequence Diagram(s)sequenceDiagram
participant Component
participant Watcher
participant CompatGetter
participant Callback
Component->>Watcher: Register watch on array property (compat mode)
Watcher->>CompatGetter: Get value (array)
CompatGetter->>Watcher: Return deeply traversed array (depth 1)
Watcher->>Callback: Invoke callback if compatWatchArray flag and array detected
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
@vue/compiler-core
@vue/compiler-dom
@vue/compiler-ssr
@vue/compiler-sfc
@vue/reactivity
@vue/runtime-core
@vue/runtime-dom
@vue/server-renderer
@vue/shared
vue
@vue/compat
commit: |
Size ReportBundles
Usages
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/runtime-core/src/apiWatch.ts (1)
289-299
: Address static analysis suggestion for optional chaining.The compatibility logic is correct, but there's an opportunity to improve code quality by using optional chaining as suggested by the static analysis tool.
Apply this diff to use optional chaining:
- const deep = options && options.deep + const deep = options?.deep🧰 Tools
🪛 Biome (1.9.4)
[error] 294-294: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
packages/reactivity/src/watch.ts
(1 hunks)packages/runtime-core/src/apiWatch.ts
(5 hunks)packages/runtime-core/src/componentOptions.ts
(5 hunks)packages/vue-compat/__tests__/misc.spec.ts
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
packages/reactivity/src/watch.ts (1)
packages/shared/src/general.ts (2)
hasChanged
(143-144)isArray
(39-39)
packages/runtime-core/src/componentOptions.ts (3)
packages/runtime-core/src/index.ts (1)
DeprecationTypes
(479-481)packages/shared/src/general.ts (3)
isObject
(53-54)isArray
(39-39)isFunction
(49-50)packages/runtime-core/src/apiWatch.ts (1)
createCompatWatchGetter
(252-266)
🪛 Biome (1.9.4)
packages/runtime-core/src/apiWatch.ts
[error] 294-294: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: Redirect rules
- GitHub Check: Header rules
- GitHub Check: Pages changed
🔇 Additional comments (5)
packages/reactivity/src/watch.ts (1)
248-249
: LGTM: Correctly implements array watching compatibility.The additional condition properly bypasses normal change detection for arrays under compatibility mode, ensuring Vue 2-like behavior where array mutations trigger watchers even when the array reference hasn't changed.
packages/runtime-core/src/apiWatch.ts (1)
252-266
: LGTM: Well-designed compatibility wrapper function.The
createCompatWatchGetter
function correctly wraps the base getter and conditionally traverses arrays with depth 1 when theWATCH_ARRAY
compatibility flag is enabled. This approach is clean and reusable.packages/vue-compat/__tests__/misc.spec.ts (1)
50-421
: Excellent comprehensive test coverage.The expanded test suite thoroughly covers the
WATCH_ARRAY
compatibility feature with well-structured scenarios for both thewatch
option and$watch()
method. The tests appropriately verify:
- Basic array watching behavior and deprecation warnings
- Dynamic depth behavior when switching between objects and arrays
- Proper handling of the
deep: true
option- Component-level
compatConfig
overrides- Various option combinations (immediate, etc.)
- Function getter behavior
This comprehensive coverage will help prevent regressions and ensure the compatibility feature works as expected.
packages/runtime-core/src/componentOptions.ts (2)
1-35
: Clean import organization with proper type imports.The import changes properly use
import type
for type-only imports and remove unused imports (traverse
,getCurrentScope
). The addition ofcreateCompatWatchGetter
aligns with the new compatibility approach.
857-866
: Improved compatibility logic using centralized approach.The refactored compatibility logic is cleaner and more maintainable than the previous approach. Instead of forcing
deep: true
, it now:
- Properly checks if
deep
is already explicitly set- Uses the
compatWatchArray
flag to signal compatibility mode- Leverages the reusable
createCompatWatchGetter
wrapperThis approach provides better separation of concerns and consistency across the codebase.
/ecosystem-ci run |
📝 Ran ecosystem CI: Open
|
@skirtles-code |
This PR builds on the work done in #12236 to try to make the compat build more accurately emulate Vue 2.
Watching arrays in Vue 2 behaved like
deep: 1
, rather thandeep: true
, so mutating nested objects should not trigger the watcher. Support for a numeric depth was added in 3.5 and wasn't available when the compat build was first implemented.But there are several other inconsistencies in the compat build. Some of these seem to have been introduced by #9927, and worked correctly prior to 3.5:
null
while data is loading.this.$watch()
, not just thewatch
option.deep: true
has been set.There were relatively few tests for
WATCH_ARRAY
, so it's understandable that these regressions were introduced. I've added a lot of extra tests to try to avoid future problems.I've introduced a
compatWatchArray
flag to the internal watcher options as a way to tell@vue/reactivity
that we want the special handling of arrays. This only impacts the equality check, which needs to behave like a deep watcher only if the current value is an array. I didn't want to add this flag to the public types, so there's a bit ofas any
hackery to access it.Summary by CodeRabbit
New Features
Bug Fixes
Tests