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::{HirFunction, InstructionValue, is_props_type};
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 =
37 std::mem::replace(&mut instr.value, InstructionValue::Debugger { loc: None });
38 match old {
39 InstructionValue::MethodCall {
40 property,
41 args,
42 loc,
43 ..
44 } => {
45 instr.value = InstructionValue::CallExpression {
46 callee: property,
47 args,
48 loc,
49 };
50 }
51 _ => unreachable!(),
52 }
53 }
54 }
55 }
56}