1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
pub trait FunctionExt {
/// This trait only considers side effects from parameters and function body.
/// Using very naive checks for side effects.
fn is_side_effect_free(&self) -> bool;
}
impl FunctionExt for oxc::ast::ast::FormalParameters<'_> {
fn is_side_effect_free(&self) -> bool {
self.items.iter().all(|param| {
// Check for default values with side effects
// Type annotations are removed at compile time and cannot have side effects
// No need to check for them
// Check for destructuring patterns that might have side effects
match ¶m.pattern.kind {
// `function foo({ x } ) {}` probably has trigger side effects if x is a getter
| oxc::ast::ast::BindingPatternKind::ObjectPattern(_)
// `function foo([x]) {}` probably has trigger side effects if x is a getter
| oxc::ast::ast::BindingPatternKind::ArrayPattern(_)
| oxc::ast::ast::BindingPatternKind::AssignmentPattern(_) => {
// `function foo(x = global()) {}`
// Default parameter values might have side effects
false
}
oxc::ast::ast::BindingPatternKind::BindingIdentifier(_) => true, // Simple identifiers are safe
}
})
}
}
impl FunctionExt for oxc::ast::ast::Function<'_> {
fn is_side_effect_free(&self) -> bool {
// Check if body is empty
let body_empty = match &self.body {
Some(body) => body.statements.is_empty(),
None => true,
};
body_empty && self.params.is_side_effect_free()
}
}
impl FunctionExt for oxc::ast::ast::ArrowFunctionExpression<'_> {
fn is_side_effect_free(&self) -> bool {
// Check if body is empty
let body_empty = self.body.is_empty();
// Check if parameters have side effects
body_empty && self.params.is_side_effect_free()
}
}