Skip to content

Conversation

@rzzf
Copy link
Contributor

@rzzf rzzf commented Dec 6, 2025

fix #14173

Summary by CodeRabbit

  • Tests

    • Added test coverage for async components with dynamic list rendering inside Suspense boundaries.
  • Bug Fixes

    • Improved placeholder handling in async component scenarios with wrapped components.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 6, 2025

Walkthrough

Fixes an issue where Suspense renders elements in the wrong order when using v-for with keys and a higher-order component wrapper. The fix propagates placeholder values through HOC host element updates and ensures placeholder host elements are updated during async setup.

Changes

Cohort / File(s) Change Summary
Test additions
packages/runtime-core/__tests__/components/Suspense.spec.ts
Adds test case for rendering multiple async components in Suspense with v-for, HOC wrapper, and array mutations to verify correct render order.
Placeholder propagation for HOC
packages/runtime-core/src/componentRenderUtils.ts
Copies root.placeholder to vnode.placeholder in updateHOCHostEl when root vnode matches current vnode, enabling placeholder propagation through HOC layers.
Async setup placeholder handling
packages/runtime-core/src/renderer.ts
Calls updateHOCHostEl after creating a placeholder vnode for unresolved async setup to propagate the host element in HOC scenarios.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Areas for attention:
    • Verify root.placeholder check and assignment logic correctly handles edge cases where placeholder may not exist
    • Ensure updateHOCHostEl call during async setup doesn't introduce timing or order dependencies
    • Confirm test covers the exact reproduction case from the issue (v-for + keys + HOC + mutations)

Possibly related PRs

Suggested labels

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

Poem

🐰 Async components wrapped in layers deep,
Now keep their order, promises to keep,
Placeholder anchors guide the way,
HOC no longer leads them astray,
For-loops dance in harmony at last!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ 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 directly describes the fix: correcting placeholder propagation for async components, which is the core objective of the linked issue.
Linked Issues check ✅ Passed The code changes implement the fix for issue #14173 by propagating placeholders for async components through HOCs and updating host elements correctly, addressing the root cause of the reverse-order rendering.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing placeholder propagation for async components in Suspense scenarios; no unrelated modifications are present.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 44ee438 and ea03d8e.

📒 Files selected for processing (3)
  • packages/runtime-core/__tests__/components/Suspense.spec.ts (1 hunks)
  • packages/runtime-core/src/componentRenderUtils.ts (1 hunks)
  • packages/runtime-core/src/renderer.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/runtime-core/__tests__/components/Suspense.spec.ts (3)
packages/runtime-core/src/components/Suspense.ts (1)
  • Suspense (131-142)
packages/runtime-core/src/vnode.ts (1)
  • Fragment (63-68)
packages/runtime-test/src/serialize.ts (1)
  • serializeInner (22-33)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: test / unit-test-windows
  • GitHub Check: test / e2e-test
🔇 Additional comments (3)
packages/runtime-core/src/componentRenderUtils.ts (1)

464-466: LGTM! Correct placeholder propagation for HOC scenarios.

The logic correctly propagates the placeholder property from root to the parent vnode during HOC host element updates. This ensures that when Suspense uses placeholders as anchors (e.g., in patchKeyedChildren), it can locate them even when components are wrapped by higher-order components.

The conditional check prevents unnecessary assignments when no placeholder exists.

packages/runtime-core/src/renderer.ts (1)

1242-1242: LGTM! Correct HOC host element update for async placeholders.

The call to updateHOCHostEl ensures that when a placeholder is created for an async component, the host element is properly propagated through any HOC wrappers. This works in tandem with the placeholder propagation logic added in componentRenderUtils.ts (lines 464-466) to maintain correct element ordering in Suspense with v-for and HOC scenarios.

The placement is correct—it's called immediately after the placeholder is created and assigned.

packages/runtime-core/__tests__/components/Suspense.spec.ts (1)

2398-2460: LGTM! Comprehensive test for issue #14173.

The test correctly reproduces the scenario from issue #14173: multiple async components rendered in Suspense with v-for, keyed items, and an HOC wrapper (CompWrapper). The test verifies both:

  1. Initial render with correct order
  2. List mutation with new items maintains correct order (not reversed)

The test structure follows existing patterns in the test suite and directly validates that the placeholder propagation fix resolves the rendering order issue.


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

github-actions bot commented Dec 6, 2025

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 103 kB (+56 B) 39 kB (+14 B) 35.1 kB (+28 B)
vue.global.prod.js 161 kB (+56 B) 59 kB (+19 B) 52.5 kB (-90 B)

Usages

Name Size Gzip Brotli
createApp (CAPI only) 47 kB (+61 B) 18.3 kB (+21 B) 16.8 kB (+26 B)
createApp 55.2 kB (+61 B) 21.4 kB (+23 B) 19.6 kB (+16 B)
createSSRApp 59.4 kB (+56 B) 23.2 kB (+18 B) 21.1 kB (+17 B)
defineCustomElement 60.8 kB (+61 B) 23.2 kB (+34 B) 21.1 kB (+33 B)
overall 69.5 kB (+56 B) 26.6 kB (+16 B) 24.3 kB (-32 B)

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 6, 2025

Open in StackBlitz

@vue/compiler-core

npm i https://pkg.pr.new/@vue/compiler-core@14177

@vue/compiler-dom

npm i https://pkg.pr.new/@vue/compiler-dom@14177

@vue/compiler-sfc

npm i https://pkg.pr.new/@vue/compiler-sfc@14177

@vue/compiler-ssr

npm i https://pkg.pr.new/@vue/compiler-ssr@14177

@vue/reactivity

npm i https://pkg.pr.new/@vue/reactivity@14177

@vue/runtime-core

npm i https://pkg.pr.new/@vue/runtime-core@14177

@vue/runtime-dom

npm i https://pkg.pr.new/@vue/runtime-dom@14177

@vue/server-renderer

npm i https://pkg.pr.new/@vue/server-renderer@14177

@vue/shared

npm i https://pkg.pr.new/@vue/shared@14177

vue

npm i https://pkg.pr.new/vue@14177

@vue/compat

npm i https://pkg.pr.new/@vue/compat@14177

commit: ea03d8e

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.

<Suspense> changes the order of elements when using v-for with a given key and a wrapper component

1 participant