compiler/crates/react_compiler/src/entrypoint/compile_result.rs RUST 297 lines View on github.com → Search inside
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.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.