boa_ast/function/
parameters.rs1use crate::{
2 declaration::{Binding, Variable},
3 expression::Expression,
4 operations::bound_names,
5 visitor::{VisitWith, Visitor, VisitorMut},
6};
7use bitflags::bitflags;
8use boa_interner::{Interner, Sym, ToInternedString};
9use core::ops::ControlFlow;
10use rustc_hash::FxHashSet;
11
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16#[derive(Clone, Debug, Default, PartialEq)]
17pub struct FormalParameterList {
18 parameters: Box<[FormalParameter]>,
19 flags: FormalParameterListFlags,
20 length: u32,
21}
22
23impl FormalParameterList {
24 #[must_use]
26 pub fn new() -> Self {
27 Self {
28 parameters: Box::new([]),
29 flags: FormalParameterListFlags::default(),
30 length: 0,
31 }
32 }
33
34 #[must_use]
36 pub fn from_parameters(parameters: Vec<FormalParameter>) -> Self {
37 let mut flags = FormalParameterListFlags::default();
38 let mut length = 0;
39 let mut names = FxHashSet::default();
40
41 for parameter in ¶meters {
42 let parameter_names = bound_names(parameter);
43
44 for name in parameter_names {
45 if name == Sym::ARGUMENTS {
46 flags |= FormalParameterListFlags::HAS_ARGUMENTS;
47 }
48 if names.contains(&name) {
49 flags |= FormalParameterListFlags::HAS_DUPLICATES;
50 } else {
51 names.insert(name);
52 }
53 }
54
55 if parameter.is_rest_param() {
56 flags |= FormalParameterListFlags::HAS_REST_PARAMETER;
57 }
58 if parameter.init().is_some() {
59 flags |= FormalParameterListFlags::HAS_EXPRESSIONS;
60 }
61 if parameter.is_rest_param() || parameter.init().is_some() || !parameter.is_identifier()
62 {
63 flags.remove(FormalParameterListFlags::IS_SIMPLE);
64 }
65 if !(flags.contains(FormalParameterListFlags::HAS_EXPRESSIONS)
66 || parameter.is_rest_param()
67 || parameter.init().is_some())
68 {
69 length += 1;
70 }
71 }
72
73 Self {
74 parameters: parameters.into(),
75 flags,
76 length,
77 }
78 }
79
80 #[must_use]
83 pub const fn length(&self) -> u32 {
84 self.length
85 }
86
87 #[must_use]
89 pub const fn flags(&self) -> FormalParameterListFlags {
90 self.flags
91 }
92
93 #[must_use]
95 pub const fn is_simple(&self) -> bool {
96 self.flags.contains(FormalParameterListFlags::IS_SIMPLE)
97 }
98
99 #[must_use]
101 pub const fn has_duplicates(&self) -> bool {
102 self.flags
103 .contains(FormalParameterListFlags::HAS_DUPLICATES)
104 }
105
106 #[must_use]
108 pub const fn has_rest_parameter(&self) -> bool {
109 self.flags
110 .contains(FormalParameterListFlags::HAS_REST_PARAMETER)
111 }
112
113 #[must_use]
115 pub const fn has_expressions(&self) -> bool {
116 self.flags
117 .contains(FormalParameterListFlags::HAS_EXPRESSIONS)
118 }
119
120 #[must_use]
122 pub const fn has_arguments(&self) -> bool {
123 self.flags.contains(FormalParameterListFlags::HAS_ARGUMENTS)
124 }
125}
126
127impl From<Vec<FormalParameter>> for FormalParameterList {
128 fn from(parameters: Vec<FormalParameter>) -> Self {
129 Self::from_parameters(parameters)
130 }
131}
132
133impl From<FormalParameter> for FormalParameterList {
134 fn from(parameter: FormalParameter) -> Self {
135 Self::from_parameters(vec![parameter])
136 }
137}
138
139impl AsRef<[FormalParameter]> for FormalParameterList {
140 fn as_ref(&self) -> &[FormalParameter] {
141 &self.parameters
142 }
143}
144
145impl VisitWith for FormalParameterList {
146 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
147 where
148 V: Visitor<'a>,
149 {
150 for parameter in &*self.parameters {
151 visitor.visit_formal_parameter(parameter)?;
152 }
153
154 ControlFlow::Continue(())
155 }
156
157 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
158 where
159 V: VisitorMut<'a>,
160 {
161 for parameter in &mut *self.parameters {
162 visitor.visit_formal_parameter_mut(parameter)?;
163 }
164
165 ControlFlow::Continue(())
167 }
168}
169
170#[cfg(feature = "arbitrary")]
171impl<'a> arbitrary::Arbitrary<'a> for FormalParameterList {
172 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
173 let params: Vec<FormalParameter> = u.arbitrary()?;
174 Ok(Self::from(params))
175 }
176}
177
178bitflags! {
179 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
181 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
182 pub struct FormalParameterListFlags: u8 {
183 const IS_SIMPLE = 0b0000_0001;
185 const HAS_DUPLICATES = 0b0000_0010;
187 const HAS_REST_PARAMETER = 0b0000_0100;
189 const HAS_EXPRESSIONS = 0b0000_1000;
191 const HAS_ARGUMENTS = 0b0001_0000;
193 }
194}
195
196impl Default for FormalParameterListFlags {
197 fn default() -> Self {
198 Self::empty().union(Self::IS_SIMPLE)
199 }
200}
201
202#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
218#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
219#[derive(Clone, Debug, PartialEq)]
220pub struct FormalParameter {
221 variable: Variable,
222 is_rest_param: bool,
223}
224
225impl FormalParameter {
226 pub fn new<D>(variable: D, is_rest_param: bool) -> Self
228 where
229 D: Into<Variable>,
230 {
231 Self {
232 variable: variable.into(),
233 is_rest_param,
234 }
235 }
236
237 #[must_use]
239 pub const fn variable(&self) -> &Variable {
240 &self.variable
241 }
242
243 #[must_use]
245 pub const fn init(&self) -> Option<&Expression> {
246 self.variable.init()
247 }
248
249 #[must_use]
251 pub const fn is_rest_param(&self) -> bool {
252 self.is_rest_param
253 }
254
255 #[must_use]
257 pub const fn is_identifier(&self) -> bool {
258 matches!(&self.variable.binding(), Binding::Identifier(_))
259 }
260}
261
262impl ToInternedString for FormalParameter {
263 fn to_interned_string(&self, interner: &Interner) -> String {
264 let mut buf = if self.is_rest_param {
265 "...".to_owned()
266 } else {
267 String::new()
268 };
269 buf.push_str(&self.variable.to_interned_string(interner));
270 buf
271 }
272}
273
274impl VisitWith for FormalParameter {
275 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
276 where
277 V: Visitor<'a>,
278 {
279 visitor.visit_variable(&self.variable)
280 }
281
282 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
283 where
284 V: VisitorMut<'a>,
285 {
286 visitor.visit_variable_mut(&mut self.variable)
287 }
288}