1use react_compiler_ast::File;2use react_compiler_ast::expressions::Identifier as AstIdentifier;3use react_compiler_ast::patterns::PatternLike;4use react_compiler_ast::statements::BlockStatement;5use react_compiler_diagnostics::SourceLocation;6use react_compiler_hir::ReactFunctionType;7use serde::Serialize;89use crate::timing::TimingEntry;1011/// Source location with index and filename fields for logger event serialization.12/// Matches the Babel SourceLocation format that the TS compiler emits in logger events.13#[derive(Debug, Clone, Serialize)]14pub struct LoggerSourceLocation {15 pub start: LoggerPosition,16 pub end: LoggerPosition,17 #[serde(skip_serializing_if = "Option::is_none")]18 pub filename: Option<String>,19 #[serde(rename = "identifierName", skip_serializing_if = "Option::is_none")]20 pub identifier_name: Option<String>,21}2223#[derive(Debug, Clone, Serialize)]24pub struct LoggerPosition {25 pub line: u32,26 pub column: u32,27 #[serde(skip_serializing_if = "Option::is_none")]28 pub index: Option<u32>,29}3031impl LoggerSourceLocation {32 /// Create from a diagnostics SourceLocation, adding index and filename.33 pub fn from_loc(34 loc: &SourceLocation,35 filename: Option<&str>,36 start_index: Option<u32>,37 end_index: Option<u32>,38 ) -> Self {39 Self {40 start: LoggerPosition {41 line: loc.start.line,42 column: loc.start.column,43 index: start_index,44 },45 end: LoggerPosition {46 line: loc.end.line,47 column: loc.end.column,48 index: end_index,49 },50 filename: filename.map(|s| s.to_string()),51 identifier_name: None,52 }53 }5455 /// Create from a diagnostics SourceLocation without index or filename.56 pub fn from_loc_simple(loc: &SourceLocation) -> Self {57 Self {58 start: LoggerPosition {59 line: loc.start.line,60 column: loc.start.column,61 index: None,62 },63 end: LoggerPosition {64 line: loc.end.line,65 column: loc.end.column,66 index: None,67 },68 filename: None,69 identifier_name: None,70 }71 }72}7374/// A variable rename from lowering, serialized for the JS shim.75#[derive(Debug, Clone, Serialize)]76pub struct BindingRenameInfo {77 pub original: String,78 pub renamed: String,79 #[serde(rename = "declarationStart")]80 pub declaration_start: u32,81}8283/// Main result type returned by the compile function.84/// Serialized to JSON and returned to the JS shim.85#[derive(Debug, Serialize)]86#[serde(tag = "kind", rename_all = "lowercase")]87pub enum CompileResult {88 /// Compilation succeeded (or no functions needed compilation).89 /// `ast` is None if no changes were made to the program.90 /// The compiled Babel AST is returned by value so in-process Rust consumers91 /// (the oxc/swc frontends) use it directly instead of round-tripping through92 /// JSON. CompileResult still derives Serialize, so the napi consumer93 /// serializes the whole result (inlining the File) as before.94 Success {95 ast: Option<File>,96 events: Vec<LoggerEvent>,97 /// Unified ordered log interleaving events and debug entries.98 /// Items appear in the order they were emitted during compilation.99 /// The JS side uses this as the single source of truth (preferred over100 /// separate events/debugLogs arrays).101 #[serde(rename = "orderedLog", skip_serializing_if = "Vec::is_empty")]102 ordered_log: Vec<OrderedLogItem>,103 /// Variable renames from lowering, for applying back to the Babel AST.104 /// Each entry maps an original binding name to its renamed version,105 /// identified by the binding's declaration start position in the source.106 #[serde(skip_serializing_if = "Vec::is_empty")]107 renames: Vec<BindingRenameInfo>,108 /// Timing data for profiling. Only populated when __profiling is enabled.109 #[serde(skip_serializing_if = "Vec::is_empty")]110 timing: Vec<TimingEntry>,111 },112 /// A fatal error occurred and panicThreshold dictates it should throw.113 Error {114 error: CompilerErrorInfo,115 events: Vec<LoggerEvent>,116 #[serde(rename = "orderedLog", skip_serializing_if = "Vec::is_empty")]117 ordered_log: Vec<OrderedLogItem>,118 /// Timing data for profiling. Only populated when __profiling is enabled.119 #[serde(skip_serializing_if = "Vec::is_empty")]120 timing: Vec<TimingEntry>,121 },122}123124/// An item in the ordered log, which can be either a logger event or a debug entry.125#[derive(Debug, Clone, Serialize)]126#[serde(tag = "type", rename_all = "camelCase")]127pub enum OrderedLogItem {128 Event { event: LoggerEvent },129 Debug { entry: DebugLogEntry },130}131132/// Structured error information for the JS shim.133#[derive(Debug, Clone, Serialize)]134pub struct CompilerErrorInfo {135 pub reason: String,136 #[serde(skip_serializing_if = "Option::is_none")]137 pub description: Option<String>,138 pub details: Vec<CompilerErrorDetailInfo>,139 /// When set, the JS shim should throw an Error with this exact message140 /// instead of formatting through formatCompilerError(). This is used141 /// for simulated unknown exceptions (throwUnknownException__testonly)142 /// which in the TS compiler are plain Error objects, not CompilerErrors.143 #[serde(rename = "rawMessage", skip_serializing_if = "Option::is_none")]144 pub raw_message: Option<String>,145 /// Pre-formatted error message produced by Rust, matching the JS146 /// formatCompilerError() output. When present, the JS shim uses this147 /// directly instead of calling formatCompilerError() on the JS side.148 #[serde(rename = "formattedMessage", skip_serializing_if = "Option::is_none")]149 pub formatted_message: Option<String>,150}151152/// Serializable error detail — flat plain object matching the TS153/// `formatDetailForLogging()` output. All fields are direct properties.154#[derive(Debug, Clone, Serialize)]155pub struct CompilerErrorDetailInfo {156 pub category: String,157 pub reason: String,158 pub description: Option<String>,159 pub severity: String,160 pub suggestions: Option<Vec<LoggerSuggestionInfo>>,161 #[serde(skip_serializing_if = "Option::is_none")]162 pub details: Option<Vec<CompilerErrorItemInfo>>,163 #[serde(skip_serializing_if = "Option::is_none")]164 pub loc: Option<LoggerSourceLocation>,165}166167/// Serializable suggestion info for logger events.168#[derive(Debug, Clone, Serialize)]169pub struct LoggerSuggestionInfo {170 pub description: String,171 pub op: LoggerSuggestionOp,172 pub range: (usize, usize),173 #[serde(skip_serializing_if = "Option::is_none")]174 pub text: Option<String>,175}176177/// Numeric enum matching TS `CompilerSuggestionOperation`.178#[derive(Debug, Clone, Copy)]179pub enum LoggerSuggestionOp {180 InsertBefore = 0,181 InsertAfter = 1,182 Remove = 2,183 Replace = 3,184}185186impl serde::Serialize for LoggerSuggestionOp {187 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {188 serializer.serialize_u8(*self as u8)189 }190}191192/// Individual error or hint item within a CompilerErrorDetailInfo.193#[derive(Debug, Clone, Serialize)]194pub struct CompilerErrorItemInfo {195 pub kind: String,196 pub loc: Option<LoggerSourceLocation>,197 /// Serialized as `null` when None (not omitted), matching TS behavior.198 pub message: Option<String>,199}200201/// Debug log entry for debugLogIRs support.202/// Currently only supports the 'debug' variant (string values).203#[derive(Debug, Clone, Serialize)]204pub struct DebugLogEntry {205 pub kind: &'static str,206 pub name: String,207 pub value: String,208}209210impl DebugLogEntry {211 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {212 Self {213 kind: "debug",214 name: name.into(),215 value: value.into(),216 }217 }218}219220/// Codegen output for a single compiled function.221/// Carries the generated AST fields needed to replace the original function.222#[derive(Debug, Clone)]223pub struct CodegenFunction {224 pub loc: Option<SourceLocation>,225 pub id: Option<AstIdentifier>,226 pub name_hint: Option<String>,227 pub params: Vec<PatternLike>,228 pub body: BlockStatement,229 pub generator: bool,230 pub is_async: bool,231 pub memo_slots_used: u32,232 pub memo_blocks: u32,233 pub memo_values: u32,234 pub pruned_memo_blocks: u32,235 pub pruned_memo_values: u32,236 pub outlined: Vec<OutlinedFunction>,237}238239/// An outlined function extracted during compilation.240#[derive(Debug, Clone)]241pub struct OutlinedFunction {242 pub func: CodegenFunction,243 pub fn_type: Option<ReactFunctionType>,244}245246/// Logger events emitted during compilation.247/// These are returned to JS for the logger callback.248#[derive(Debug, Clone, Serialize)]249#[serde(tag = "kind")]250pub enum LoggerEvent {251 CompileSuccess {252 #[serde(rename = "fnLoc")]253 fn_loc: Option<LoggerSourceLocation>,254 #[serde(rename = "fnName")]255 fn_name: Option<String>,256 #[serde(rename = "memoSlots")]257 memo_slots: u32,258 #[serde(rename = "memoBlocks")]259 memo_blocks: u32,260 #[serde(rename = "memoValues")]261 memo_values: u32,262 #[serde(rename = "prunedMemoBlocks")]263 pruned_memo_blocks: u32,264 #[serde(rename = "prunedMemoValues")]265 pruned_memo_values: u32,266 },267 CompileError {268 detail: CompilerErrorDetailInfo,269 #[serde(rename = "fnLoc")]270 fn_loc: Option<LoggerSourceLocation>,271 },272 /// Same as CompileError but serializes fnLoc before detail (matching TS program.ts output)273 #[serde(rename = "CompileError")]274 CompileErrorWithLoc {275 #[serde(rename = "fnLoc")]276 fn_loc: LoggerSourceLocation,277 detail: CompilerErrorDetailInfo,278 },279 CompileSkip {280 #[serde(rename = "fnLoc")]281 fn_loc: Option<LoggerSourceLocation>,282 reason: String,283 #[serde(skip_serializing_if = "Option::is_none")]284 loc: Option<LoggerSourceLocation>,285 },286 CompileUnexpectedThrow {287 #[serde(rename = "fnLoc")]288 fn_loc: Option<LoggerSourceLocation>,289 data: String,290 },291 PipelineError {292 #[serde(rename = "fnLoc")]293 fn_loc: Option<LoggerSourceLocation>,294 data: String,295 },296}
Findings
✓ No findings reported for this file.