fix(formatter_json): support JSON5/JSON6 value in json/jsonc/json5 (#23193)

I wouldn't be surprised by any value that can be formatted as JSON...
This commit is contained in:
leaysgur committed 2026-06-10 05:41:02 +00:00
1 parent 8cc82c4cdb
commit b0b5d399df
5 files changed
+111 -4

No files matched your search

+21 -4
View File
@@ -101,14 +101,31 @@ impl<'a> Format<'a, JsonFormatContext<'a>> for FmtJsonValue<'a, '_> {
Expression::ObjectExpression(obj) => {
object::FmtJsonObject { object: obj }.fmt(f);
}
// `-9876.54321`, `+123`, `-Infinity`, etc. Prettier's `json` parser routes
// through the JS estree printer, which keeps both `+` and `-` operators
// while recursing into the argument so the inner number is normalized
// (`-1.0e+2` → `-1.0e2`).
// `-9876.54321`, `+123`, `-Infinity`, etc.
// Prettier's `json` parser routes through the JS estree printer,
// which keeps both `+` and `-` operators while recursing into the argument
// so the inner number is normalized (`-1.0e+2` → `-1.0e2`).
Expression::UnaryExpression(unary) => {
write!(f, unary.operator.as_str());
FmtJsonValue { expression: &unary.argument }.fmt(f);
}
// JSON5 `Infinity` / `NaN`, JSON6 `undefined`
// Prettier accepts these identifiers for every JSON variant and prints them verbatim.
// Other identifiers stay invalid (Prettier rejects them at parse time, we report at format time).
Expression::Identifier(ident)
if matches!(ident.name.as_str(), "Infinity" | "NaN" | "undefined") =>
{
write!(f, text(ident.name.as_str()));
}
// A substitution-free template literal is kept verbatim, backticks included
// (Prettier's shared `estree` printer emits the quasi raw;
// only `json-stringify` converts it to a double-quoted string).
// `raw` is safe for `text()`: the lexer normalizes `\r\n` / `\r` to `\n` (spec TRV).
Expression::TemplateLiteral(template)
if template.expressions.is_empty() && template.quasis.len() == 1 =>
{
write!(f, [text("`"), text(template.quasis[0].value.raw.as_str()), text("`")]);
}
_ => write!(f, FormatInvalidJson(span)),
}
}
@@ -0,0 +1,4 @@
[
Infinity, -Infinity, NaN, -NaN, undefined,
{ Infinity: NaN, NaN: -Infinity, undefined: undefined }
]
@@ -0,0 +1,35 @@
---
source: crates/oxc_formatter_json/tests/fixtures/mod.rs
---
==================== Input ====================
[
Infinity, -Infinity, NaN, -NaN, undefined,
{ Infinity: NaN, NaN: -Infinity, undefined: undefined }
]
==================== Output ====================
------------------
{ printWidth: 80 }
------------------
[
Infinity,
-Infinity,
NaN,
-NaN,
undefined,
{ "Infinity": NaN, "NaN": -Infinity, "undefined": undefined }
]
-------------------
{ printWidth: 100 }
-------------------
[
Infinity,
-Infinity,
NaN,
-NaN,
undefined,
{ "Infinity": NaN, "NaN": -Infinity, "undefined": undefined }
]
===================== End =====================
@@ -0,0 +1,9 @@
[
``,
`foo`,
`
multiple-line
`,
`\u{1F409}\`'"\${}`,
{ "as-object-value": `foo` }
]
@@ -0,0 +1,42 @@
---
source: crates/oxc_formatter_json/tests/fixtures/mod.rs
---
==================== Input ====================
[
``,
`foo`,
`
multiple-line
`,
`\u{1F409}\`'"\${}`,
{ "as-object-value": `foo` }
]
==================== Output ====================
------------------
{ printWidth: 80 }
------------------
[
``,
`foo`,
`
multiple-line
`,
`\u{1F409}\`'"\${}`,
{ "as-object-value": `foo` }
]
-------------------
{ printWidth: 100 }
-------------------
[
``,
`foo`,
`
multiple-line
`,
`\u{1F409}\`'"\${}`,
{ "as-object-value": `foo` }
]
===================== End =====================