Skip to content

fix: improve code quality with type annotations and error handling#14570

Open
N3XT3R1337 wants to merge 1 commit intovuejs:mainfrom
N3XT3R1337:fix/improve-code-quality
Open

fix: improve code quality with type annotations and error handling#14570
N3XT3R1337 wants to merge 1 commit intovuejs:mainfrom
N3XT3R1337:fix/improve-code-quality

Conversation

@N3XT3R1337
Copy link
Copy Markdown

@N3XT3R1337 N3XT3R1337 commented Mar 15, 2026

Code quality improvements found during code review. Added type annotations, improved error handling, fixed edge cases.

Summary by CodeRabbit

Bug Fixes

  • Fixed an issue where watchers on nested object properties would fail when intermediate values were falsy (such as 0)
  • Enhanced style patching to robustly handle edge cases with trailing semicolons and malformed style segments

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 15, 2026

📝 Walkthrough

Walkthrough

The pull request adds defensive parsing to handle falsy intermediate values in watch path traversal and malformed style segments without colons in style patching. Each fix includes corresponding test cases to verify the corrected behavior.

Changes

Cohort / File(s) Summary
Watch Path Handling
packages/runtime-core/src/apiWatch.ts, packages/runtime-core/__tests__/apiWatch.spec.ts
Modified loop condition in createPathGetter from truthiness check to nullish check (!=), allowing traversal through falsy values. Added test verifying watchers fire correctly when intermediate properties contain falsy values like 0.
Style Patching
packages/runtime-dom/src/modules/style.ts, packages/runtime-dom/__tests__/patchStyle.spec.ts
Added defensive colon-location logic in patchStyle when parsing string styles; segments without colons are now skipped to prevent processing malformed entries. Added test verifying correct cssText output when patching string styles containing trailing semicolons.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A rabbit hops through code with care,
Falsy values? No despair!
Colons found or left behind,
Watchers fixed, styles refined!
Hop along, the bugs are gone! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title mentions 'type annotations and error handling' but the actual changes are bug fixes for falsy value handling in watchers and style parsing, with no type annotation changes detected. Update the title to accurately reflect the changes, such as 'fix: handle falsy intermediate values in watchers and improve style string parsing'.
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 (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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

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.

Tip

You can customize the high-level summary generated by CodeRabbit.

Configure the reviews.high_level_summary_instructions setting to provide custom instructions for generating the high-level summary.

Copy link
Copy Markdown

@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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/runtime-core/__tests__/apiWatch.spec.ts`:
- Around line 1449-1474: The test currently watches 'a.b' so the falsy value 0
is the terminal value; change the watched path to include an extra segment (e.g.
'a.b.c') so the falsy 0 is an intermediate segment: update the definition in the
test (Comp.data) to keep a.b = 0 as the intermediate falsy, change the
this.$watch call in created to this.$watch('a.b.c', spy), and in mounted assign
this.a.b = { c: 1 } (or set this.a.b.c = 1 after replacing b with an object) so
the watcher exercises traversal over a falsy intermediate value and the
assertions expect the new value 1 and previous undefined.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 36a289ef-bf43-4323-ac29-1f99debf10c0

📥 Commits

Reviewing files that changed from the base of the PR and between d61d803 and f714b86.

📒 Files selected for processing (4)
  • packages/runtime-core/__tests__/apiWatch.spec.ts
  • packages/runtime-core/src/apiWatch.ts
  • packages/runtime-dom/__tests__/patchStyle.spec.ts
  • packages/runtime-dom/src/modules/style.ts

Comment on lines +1449 to +1474
test('watching keypath should not stop on falsy intermediate values', async () => {
const spy = vi.fn()
const Comp = defineComponent({
render() {},
data() {
return {
a: {
b: 0 as any,
},
}
},
created(this: any) {
this.$watch('a.b', spy)
},
mounted(this: any) {
this.a.b = 1
},
})

const root = nodeOps.createElement('div')
createApp(Comp).mount(root)

await nextTick()
expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(1, 0, expect.anything())
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Test case does not exercise a falsy intermediate segment.

On Line 1449, a.b makes 0 the terminal value. This can pass even without the cur != null fix, so the regression target is under-tested.

✅ Suggested test addition to cover a true intermediate-falsy traversal
+  test('watching keypath should continue through falsy intermediate values', async () => {
+    const spy = vi.fn()
+    const Comp = defineComponent({
+      render() {},
+      data() {
+        return {
+          a: {
+            b: '' as any,
+          },
+        }
+      },
+      created(this: any) {
+        this.$watch('a.b.value', spy)
+      },
+      mounted(this: any) {
+        this.a.b = { value: 1 }
+      },
+    })
+
+    const root = nodeOps.createElement('div')
+    createApp(Comp).mount(root)
+
+    await nextTick()
+    expect(spy).toHaveBeenCalledTimes(1)
+    expect(spy).toHaveBeenCalledWith(1, undefined, expect.anything())
+  })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test('watching keypath should not stop on falsy intermediate values', async () => {
const spy = vi.fn()
const Comp = defineComponent({
render() {},
data() {
return {
a: {
b: 0 as any,
},
}
},
created(this: any) {
this.$watch('a.b', spy)
},
mounted(this: any) {
this.a.b = 1
},
})
const root = nodeOps.createElement('div')
createApp(Comp).mount(root)
await nextTick()
expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(1, 0, expect.anything())
})
test('watching keypath should not stop on falsy intermediate values', async () => {
const spy = vi.fn()
const Comp = defineComponent({
render() {},
data() {
return {
a: {
b: 0 as any,
},
}
},
created(this: any) {
this.$watch('a.b', spy)
},
mounted(this: any) {
this.a.b = 1
},
})
const root = nodeOps.createElement('div')
createApp(Comp).mount(root)
await nextTick()
expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(1, 0, expect.anything())
})
test('watching keypath should continue through falsy intermediate values', async () => {
const spy = vi.fn()
const Comp = defineComponent({
render() {},
data() {
return {
a: {
b: '' as any,
},
}
},
created(this: any) {
this.$watch('a.b.value', spy)
},
mounted(this: any) {
this.a.b = { value: 1 }
},
})
const root = nodeOps.createElement('div')
createApp(Comp).mount(root)
await nextTick()
expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(1, undefined, expect.anything())
})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/runtime-core/__tests__/apiWatch.spec.ts` around lines 1449 - 1474,
The test currently watches 'a.b' so the falsy value 0 is the terminal value;
change the watched path to include an extra segment (e.g. 'a.b.c') so the falsy
0 is an intermediate segment: update the definition in the test (Comp.data) to
keep a.b = 0 as the intermediate falsy, change the this.$watch call in created
to this.$watch('a.b.c', spy), and in mounted assign this.a.b = { c: 1 } (or set
this.a.b.c = 1 after replacing b with an object) so the watcher exercises
traversal over a falsy intermediate value and the assertions expect the new
value 1 and previous undefined.

@edison1105
Copy link
Copy Markdown
Member

edison1105 commented Mar 16, 2026

Thanks for your contribution.
Could you please split the changes into two PRs?

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants