fix(jsx): render async children of document metadata tags instead of [object Promise] - #5204
Merged
Merged
Conversation
Codecov Report❌ Patch coverage is
❌ Your patch check has failed because the patch coverage (0.00%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #5204 +/- ##
==========================================
+ Coverage 79.68% 79.70% +0.01%
==========================================
Files 155 155
Lines 10894 10894
Branches 2281 2281
==========================================
+ Hits 8681 8683 +2
+ Misses 2213 2211 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Member
|
Thank you! |
yusukebe
approved these changes
Aug 9, 2026
1 task
BlankParticle
pushed a commit
to BlankParticle/hono
that referenced
this pull request
Sep 6, 2026
…[object Promise] (honojs#5204)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
When a document metadata tag (
<title>,<script>,<style>,<link>,<meta>) has async children (an async component or a promise as a child), the rendered HTML contains the literal string[object Promise]instead of the tag's content.Two symptoms, same cause:
<head>in the tree: the tag's content is lost and[object Promise]is rendered in its place.<head>in the tree: the tag is hoisted into<head>correctly, but[object Promise]is left behind in the body, becauseinsertIntoHeadtries toreplaceAll(tag, '')with the resolved string while the buffer contains[object Promise], so the removal silently no-ops.The cause
In
src/jsx/intrinsic-element/components.ts,documentMetadataTag, async branch (line 111):raw()doesnew String(value), andnew String(Promise.resolve('x')).toString()is"[object Promise]". The sync branch right below correctly passes the resolved string; the async branch wraps the unresolvedstring(the Promise) instead ofresString.The existing test only covers an async component that returns
[<title>Hello</title>]— there the promise resolves beforedocumentMetadataTagruns, so it takes the sync branch. The async branch had no coverage.Reproduction
On
main(cf78528, v4.13.1), afterresolveCallback(...):The fix
One token — pass the resolved string to
raw():The sync branch is untouched (it already uses
stringcorrectly).Tests
Two tests added in
src/jsx/intrinsic-element/components.test.tsx, mirroring the existing "async component array" test:should hoist a title with async children— with<head>: asserts the exact HTML, title hoisted, body clean.should render a title with async children without a head element— without<head>: asserts the content is preserved and[object Promise]does not appear.Red→green verified: both tests fail on
mainwithout the fix ([object Promise]in the received HTML), both pass with it.Verification
Run on Windows, Node v24.14.1, Bun 1.3.14, clone at
~/repos/hono:vitest --run src/jsx— 37 files, 1945 passed, 9 skipped (full jsx suite green).bun run test(tsc+ whole Vitest suite): 4751 passed; 11 failures insrc/helper/dev,src/middleware/loggerandsrc/utils/color.test.ts, all ANSI/color-detection related and identical on pristinemainon this Windows machine — pre-existing environment failures, unrelated to this change.tsc -p tsconfig.spec.json— clean.eslinton both touched files — clean.prettier --checkon both touched files — clean.Not verified: Deno/Bun-native runtime tests (
test:deno,test:bun) — the change is runtime-agnostic (pure string handling), but I only ran the Vitest suite under Node.The author should do the following, if applicable
bun run format:fix && bun run lint:fixto format the code