Skip to main content

react_compiler_hir/
environment_config.rs

1// Copyright (c) Meta Platforms, Inc. and affiliates.
2//
3// This source code is licensed under the MIT license found in the
4// LICENSE file in the root directory of this source tree.
5
6//! Environment configuration, ported from EnvironmentConfigSchema in Environment.ts.
7//!
8//! Contains feature flags and custom hook definitions that control compiler behavior.
9
10use react_compiler_utils::FxIndexMap;
11use rustc_hash::FxHashMap;
12
13use serde::Serialize;
14
15use crate::Effect;
16use crate::type_config::{TypeConfig, ValueKind};
17
18/// External function reference (source module + import name).
19/// Corresponds to TS `ExternalFunction`.
20#[derive(Debug, Clone, Serialize)]
21#[serde(rename_all = "camelCase")]
22pub struct ExternalFunctionConfig {
23    pub source: String,
24    pub import_specifier_name: String,
25}
26
27/// Instrumentation configuration.
28/// Corresponds to TS `InstrumentationSchema`.
29#[derive(Debug, Clone, Serialize)]
30#[serde(rename_all = "camelCase")]
31pub struct InstrumentationConfig {
32    #[serde(rename = "fn")]
33    pub fn_: ExternalFunctionConfig,
34    #[serde(default)]
35    pub gating: Option<ExternalFunctionConfig>,
36    #[serde(default)]
37    pub global_gating: Option<String>,
38}
39
40/// Custom hook configuration, ported from TS `HookSchema`.
41#[derive(Debug, Clone, Serialize)]
42#[serde(rename_all = "camelCase")]
43pub struct HookConfig {
44    pub effect_kind: Effect,
45    pub value_kind: ValueKind,
46    #[serde(default)]
47    pub no_alias: bool,
48    #[serde(default)]
49    pub transitive_mixed_data: bool,
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
53pub enum ExhaustiveEffectDepsMode {
54    #[serde(rename = "off")]
55    Off,
56    #[serde(rename = "all")]
57    All,
58    #[serde(rename = "missing-only")]
59    MissingOnly,
60    #[serde(rename = "extra-only")]
61    ExtraOnly,
62}
63
64impl Default for ExhaustiveEffectDepsMode {
65    fn default() -> Self {
66        Self::Off
67    }
68}
69
70/// Compiler environment configuration. Contains feature flags and settings.
71///
72/// Fields that would require passing JS functions across the JS/Rust boundary
73/// are omitted with TODO comments. The Rust port uses hardcoded defaults for
74/// these (e.g., `defaultModuleTypeProvider`).
75#[derive(Debug, Clone, Serialize)]
76#[serde(rename_all = "camelCase")]
77pub struct EnvironmentConfig {
78    /// Custom hook type definitions, keyed by hook name.
79    #[serde(default)]
80    pub custom_hooks: FxHashMap<String, HookConfig>,
81
82    /// Pre-resolved module type provider results.
83    /// Map from module name to TypeConfig, computed by the JS shim.
84    #[serde(default)]
85    pub module_type_provider: Option<FxIndexMap<String, TypeConfig>>,
86
87    /// Custom macro-like function names that should have their operands
88    /// memoized in the same scope (similar to fbt).
89    #[serde(default)]
90    pub custom_macros: Option<Vec<String>>,
91
92    /// If true, emit code to reset the memo cache on source file changes (HMR/fast refresh).
93    /// If null (None), HMR detection is conditionally enabled based on NODE_ENV/__DEV__.
94    #[serde(default)]
95    pub enable_reset_cache_on_source_file_changes: Option<bool>,
96
97    pub enable_preserve_existing_memoization_guarantees: bool,
98    pub validate_preserve_existing_memoization_guarantees: bool,
99    pub validate_exhaustive_memoization_dependencies: bool,
100    #[serde(default)]
101    pub validate_exhaustive_effect_dependencies: ExhaustiveEffectDepsMode,
102
103    // TODO: flowTypeProvider — requires JS function callback.
104    pub enable_optional_dependencies: bool,
105    #[serde(default)]
106    pub enable_name_anonymous_functions: bool,
107    pub validate_hooks_usage: bool,
108    pub validate_ref_access_during_render: bool,
109    pub validate_no_set_state_in_render: bool,
110    #[serde(default)]
111    pub enable_use_keyed_state: bool,
112    #[serde(default)]
113    pub validate_no_set_state_in_effects: bool,
114    #[serde(default)]
115    pub validate_no_derived_computations_in_effects: bool,
116    #[serde(default)]
117    #[serde(alias = "validateNoDerivedComputationsInEffects_exp")]
118    pub validate_no_derived_computations_in_effects_exp: bool,
119    #[serde(default)]
120    #[serde(alias = "validateNoJSXInTryStatements")]
121    pub validate_no_jsx_in_try_statements: bool,
122    #[serde(default)]
123    pub validate_static_components: bool,
124    #[serde(default)]
125    pub validate_no_capitalized_calls: Option<Vec<String>>,
126    #[serde(default)]
127    #[serde(alias = "restrictedImports")]
128    pub validate_blocklisted_imports: Option<Vec<String>>,
129    #[serde(default)]
130    pub validate_source_locations: bool,
131    #[serde(default)]
132    pub validate_no_impure_functions_in_render: bool,
133    #[serde(default)]
134    pub validate_no_freezing_known_mutable_functions: bool,
135    pub enable_assume_hooks_follow_rules_of_react: bool,
136    pub enable_transitively_freeze_function_expressions: bool,
137
138    /// Hook guard configuration. When set, wraps hook calls with dispatcher guard calls.
139    #[serde(default)]
140    pub enable_emit_hook_guards: Option<ExternalFunctionConfig>,
141
142    /// Instrumentation configuration. When set, emits calls to instrument functions.
143    #[serde(default)]
144    pub enable_emit_instrument_forget: Option<InstrumentationConfig>,
145
146    pub enable_function_outlining: bool,
147    #[serde(default)]
148    pub enable_jsx_outlining: bool,
149    #[serde(default)]
150    pub assert_valid_mutable_ranges: bool,
151    #[serde(default)]
152    #[serde(alias = "throwUnknownException__testonly")]
153    pub throw_unknown_exception_testonly: bool,
154    #[serde(default)]
155    pub enable_custom_type_definition_for_reanimated: bool,
156    pub enable_treat_ref_like_identifiers_as_refs: bool,
157    #[serde(default)]
158    pub enable_treat_set_identifiers_as_state_setters: bool,
159    pub validate_no_void_use_memo: bool,
160    pub enable_allow_set_state_from_refs_in_effects: bool,
161    #[serde(default)]
162    pub enable_verbose_no_set_state_in_effect: bool,
163
164    // 🌲
165    #[serde(default)]
166    pub enable_forest: bool,
167}
168
169impl Default for EnvironmentConfig {
170    fn default() -> Self {
171        Self {
172            custom_hooks: FxHashMap::default(),
173            enable_reset_cache_on_source_file_changes: None,
174            module_type_provider: None,
175            enable_preserve_existing_memoization_guarantees: true,
176            validate_preserve_existing_memoization_guarantees: true,
177            validate_exhaustive_memoization_dependencies: true,
178            validate_exhaustive_effect_dependencies: ExhaustiveEffectDepsMode::Off,
179            enable_optional_dependencies: true,
180            enable_name_anonymous_functions: false,
181            validate_hooks_usage: true,
182            validate_ref_access_during_render: true,
183            validate_no_set_state_in_render: true,
184            enable_use_keyed_state: false,
185            validate_no_set_state_in_effects: false,
186            validate_no_derived_computations_in_effects: false,
187            validate_no_derived_computations_in_effects_exp: false,
188            validate_no_jsx_in_try_statements: false,
189            validate_static_components: false,
190            validate_no_capitalized_calls: None,
191            validate_blocklisted_imports: None,
192            validate_source_locations: false,
193            validate_no_impure_functions_in_render: false,
194            validate_no_freezing_known_mutable_functions: false,
195            enable_assume_hooks_follow_rules_of_react: true,
196            enable_transitively_freeze_function_expressions: true,
197            enable_emit_hook_guards: None,
198            enable_emit_instrument_forget: None,
199            enable_function_outlining: true,
200            enable_jsx_outlining: false,
201            assert_valid_mutable_ranges: false,
202            throw_unknown_exception_testonly: false,
203            enable_custom_type_definition_for_reanimated: false,
204            enable_treat_ref_like_identifiers_as_refs: true,
205            enable_treat_set_identifiers_as_state_setters: false,
206            validate_no_void_use_memo: true,
207            enable_allow_set_state_from_refs_in_effects: true,
208            enable_verbose_no_set_state_in_effect: false,
209            enable_forest: false,
210            custom_macros: None,
211        }
212    }
213}