fix(transform_react): downgrade nonfatal compiler diagnostics (#25418)

Expose nonfatal React Compiler diagnostics as warnings while preserving
fatal errors.

AI-assisted.

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
This commit is contained in:
Boshen authored and GitHub committed 2026-08-09 11:18:13 +08:00
1 parent 937825c6a6
commit 9d19ab3080
3 files changed
+17 -6

No files matched your search

+4 -3
View File
@@ -34,9 +34,10 @@ if (result.fatal) {
```
`errors` contains every diagnostic reported by parsing, the React Compiler, and
the downstream transform. Some React Compiler bail-outs have error severity but
are nonfatal under the default `panicThreshold`; check `fatal` to decide whether
the transform emitted usable code.
the downstream transform. Recoverable React Compiler bail-outs are warnings;
compiler diagnostics retain error severity when `panicThreshold` makes the
transform fatal. Check `fatal` to decide whether the transform emitted usable
code.
`reactCompiler` defaults to `true`. Set it to `false` to skip React Compiler,
or pass an options object using the same names as
+9 -2
View File
@@ -23,7 +23,7 @@ use napi_derive::napi;
use oxc::{
allocator::Allocator,
codegen::{Codegen, CodegenOptions},
diagnostics::Diagnostics,
diagnostics::{Diagnostics, Severity},
parser::Parser,
semantic::{SemanticBuilder, SemanticBuilderReturn},
transformer::Transformer,
@@ -98,13 +98,20 @@ fn transform_impl(
return error_result(filename, source_text, diagnostics);
}
let (react_output, react_diagnostics, react_fatal) = match react_compiler_options {
let (react_output, mut react_diagnostics, react_fatal) = match react_compiler_options {
None => (None, Diagnostics::new(), false),
Some(options) => match react_compiler_compile(&program, &semantic, &allocator, options) {
CompileResult::Success { output, diagnostics } => (output, diagnostics, false),
CompileResult::Fatal { diagnostics } => (None, diagnostics, true),
},
};
if !react_fatal {
for diagnostic in react_diagnostics.iter_mut() {
if diagnostic.severity == Severity::Error {
diagnostic.severity = Severity::Warning;
}
}
}
diagnostics.extend(react_diagnostics);
if react_fatal {
return error_result(filename, source_text, diagnostics);
+4 -1
View File
@@ -200,6 +200,7 @@ describe("transformSync", () => {
expect(result.fatal).toBe(false);
expect(result.errors).toHaveLength(1);
expect(result.errors[0].severity).toBe("Warning");
expect(result.errors[0].message).toContain("[ReactCompiler] Suppression:");
expect(result.code).not.toContain("react/compiler-runtime");
});
@@ -224,7 +225,7 @@ describe("transformSync", () => {
expect(result.fatal).toBe(false);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toMatchObject({
severity: "Error",
severity: "Warning",
message: expect.stringContaining("[ReactCompiler] Suppression:"),
});
expect(result.code).not.toBe("");
@@ -298,6 +299,7 @@ describe("transformSync", () => {
expect(result.fatal).toBe(false);
expect(result.errors).toHaveLength(1);
expect(result.errors[0].severity).toBe("Warning");
expect(result.errors[0].message).toContain("[ReactCompiler] Suppression:");
expect(result.code).toContain("react/compiler-runtime");
expect(result.code).not.toContain("props: { text: string }");
@@ -327,6 +329,7 @@ describe("transformSync", () => {
expect(result.fatal).toBe(true);
expect(result.code).toBe("");
expect(result.errors).toHaveLength(1);
expect(result.errors[0].severity).toBe("Error");
expect(result.errors[0].message).toContain("[ReactCompiler] Suppression:");
},
);