Skip to main content

react_compiler_optimization/
optimize_props_method_calls.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//! Converts `MethodCall` instructions on props objects into `CallExpression`
7//! instructions.
8//!
9//! When the receiver of a method call is typed as the component's props object,
10//! we can safely convert the method call `props.foo(args)` into a direct call
11//! `foo(args)` using the property as the callee. This simplifies downstream
12//! analysis by removing the receiver dependency.
13//!
14//! Analogous to TS `Optimization/OptimizePropsMethodCalls.ts`.
15
16use react_compiler_hir::environment::Environment;
17use react_compiler_hir::{is_props_type, HirFunction, InstructionValue};
18
19pub fn optimize_props_method_calls(func: &mut HirFunction, env: &Environment) {
20    for (_block_id, block) in &func.body.blocks {
21        let instruction_ids: Vec<_> = block.instructions.clone();
22        for instr_id in instruction_ids {
23            let instr = &mut func.instructions[instr_id.0 as usize];
24            let should_replace = matches!(
25                &instr.value,
26                InstructionValue::MethodCall { receiver, .. }
27                    if {
28                        let identifier = &env.identifiers[receiver.identifier.0 as usize];
29                        let ty = &env.types[identifier.type_.0 as usize];
30                        is_props_type(ty)
31                    }
32            );
33            if should_replace {
34                // Take the old value out, replacing with a temporary.
35                // The if-let is guaranteed to match since we checked above.
36                let old = std::mem::replace(
37                    &mut instr.value,
38                    InstructionValue::Debugger { loc: None },
39                );
40                match old {
41                    InstructionValue::MethodCall {
42                        property,
43                        args,
44                        loc,
45                        ..
46                    } => {
47                        instr.value = InstructionValue::CallExpression {
48                            callee: property,
49                            args,
50                            loc,
51                        };
52                    }
53                    _ => unreachable!(),
54                }
55            }
56        }
57    }
58}