diff --git a/crates/oxc_formatter/src/print/object_like.rs b/crates/oxc_formatter/src/print/object_like.rs index 7d4f972d978c8..49cb96e2fcdc3 100644 --- a/crates/oxc_formatter/src/print/object_like.rs +++ b/crates/oxc_formatter/src/print/object_like.rs @@ -72,6 +72,18 @@ impl<'a> ObjectLike<'a, '_> { } } + /// Check if the object is inside a JSX spread attribute or JSX spread child. + /// In these contexts, empty objects with comments should use soft line breaks + /// so they can stay on one line if they fit. + fn is_inside_jsx_spread(&self) -> bool { + match self { + Self::ObjectExpression(o) => { + matches!(o.parent, AstNodes::JSXSpreadAttribute(_) | AstNodes::JSXSpreadChild(_)) + } + Self::TSTypeLiteral(_) => false, + } + } + fn write_members(&self, f: &mut Formatter<'_, 'a>) { match self { Self::ObjectExpression(o) => o.properties().fmt(f), @@ -87,7 +99,15 @@ impl<'a> Format<'a> for ObjectLike<'a, '_> { write!(f, "{"); if self.members_are_empty() { - write!(f, format_dangling_comments(self.span()).with_block_indent()); + // In JSX spread attributes/children, use soft indent so the object + // can stay on one line if it fits (e.g., `
`). + // In other contexts like variable declarations, use block indent to + // expand the object (e.g., `var a = {\n /* comment */\n};`). + if self.is_inside_jsx_spread() { + write!(f, format_dangling_comments(self.span()).with_soft_block_indent()); + } else { + write!(f, format_dangling_comments(self.span()).with_block_indent()); + } } else { let should_insert_space_around_brackets = f.options().bracket_spacing.value(); let should_expand = diff --git a/tasks/prettier_conformance/snapshots/prettier.js.snap.md b/tasks/prettier_conformance/snapshots/prettier.js.snap.md index c96f28effc66a..e8e9660b29a70 100644 --- a/tasks/prettier_conformance/snapshots/prettier.js.snap.md +++ b/tasks/prettier_conformance/snapshots/prettier.js.snap.md @@ -1,4 +1,4 @@ -js compatibility: 743/761 (97.63%) +js compatibility: 744/761 (97.77%) # Failed @@ -20,5 +20,4 @@ js compatibility: 743/761 (97.63%) | js/sequence-expression/ignored.js | 💥 | 25.00% | | js/strings/template-literals.js | 💥💥 | 98.01% | | jsx/fbt/test.js | 💥 | 84.06% | -| jsx/ignore/spread.js | 💥 | 83.33% | | jsx/jsx/quotes.js | 💥💥💥💥 | 79.41% | diff --git a/tasks/prettier_conformance/snapshots/prettier.ts.snap.md b/tasks/prettier_conformance/snapshots/prettier.ts.snap.md index 7187748f251ab..e691b7567f13d 100644 --- a/tasks/prettier_conformance/snapshots/prettier.ts.snap.md +++ b/tasks/prettier_conformance/snapshots/prettier.ts.snap.md @@ -1,11 +1,10 @@ -ts compatibility: 579/606 (95.54%) +ts compatibility: 580/606 (95.71%) # Failed | Spec path | Failed or Passed | Match ratio | | :-------- | :--------------: | :---------: | | jsx/fbt/test.js | 💥 | 84.06% | -| jsx/ignore/spread.js | 💥 | 83.33% | | jsx/jsx/quotes.js | 💥💥💥💥 | 79.41% | | typescript/arrow/comments.ts | 💥✨ | 44.44% | | typescript/arrow/comments/issue-11100.ts | 💥 | 84.00% |