diff --git a/crates/compiler/src/evaluate/css_tree.rs b/crates/compiler/src/evaluate/css_tree.rs index bcf0e5d..98ec097 100644 --- a/crates/compiler/src/evaluate/css_tree.rs +++ b/crates/compiler/src/evaluate/css_tree.rs @@ -78,28 +78,27 @@ impl CssTree { } fn add_child_to_parent(&self, child: CssStmt, parent_idx: CssTreeIdx) { - let mut parent = self.stmts[parent_idx.0].borrow_mut().take(); - match &mut parent { - Some(CssStmt::RuleSet { body, .. }) => body.push(child), - Some(CssStmt::Style(..) | CssStmt::Comment(..) | CssStmt::Import(..)) | None => { - unreachable!() - } - Some(CssStmt::Media(media, ..)) => { - media.body.push(child); - } - Some(CssStmt::UnknownAtRule(at_rule, ..)) => { - at_rule.body.push(child); - } - Some(CssStmt::Supports(supports, ..)) => { - supports.body.push(child); - } - Some(CssStmt::KeyframesRuleSet(keyframes)) => { - keyframes.body.push(child); - } - } - self.stmts[parent_idx.0] - .borrow_mut() - .replace(parent.unwrap()); + RefMut::map(self.stmts[parent_idx.0].borrow_mut(), |parent| { + match parent { + Some(CssStmt::RuleSet { body, .. }) => body.push(child), + Some(CssStmt::Style(..) | CssStmt::Comment(..) | CssStmt::Import(..)) | None => { + unreachable!() + } + Some(CssStmt::Media(media, ..)) => { + media.body.push(child); + } + Some(CssStmt::UnknownAtRule(at_rule, ..)) => { + at_rule.body.push(child); + } + Some(CssStmt::Supports(supports, ..)) => { + supports.body.push(child); + } + Some(CssStmt::KeyframesRuleSet(keyframes)) => { + keyframes.body.push(child); + } + }; + parent + }); } pub fn add_child(&mut self, child: CssStmt, parent_idx: CssTreeIdx) -> CssTreeIdx { diff --git a/crates/compiler/src/evaluate/visitor.rs b/crates/compiler/src/evaluate/visitor.rs index 9f7b9e2..81b5991 100644 --- a/crates/compiler/src/evaluate/visitor.rs +++ b/crates/compiler/src/evaluate/visitor.rs @@ -2125,26 +2125,25 @@ impl<'a> Visitor<'a> { evaluated.span, )?; - // todo: superfluous clone - let declared_arguments = func.arguments().args.clone(); + let declared_arguments = &func.arguments().args; let min_len = evaluated.positional.len().min(declared_arguments.len()); + let positional_len = evaluated.positional.len(); + #[allow(clippy::needless_range_loop)] - for i in 0..min_len { - // todo: superfluous clone + for i in (0..min_len).rev() { visitor.env.scopes_mut().insert_var_last( declared_arguments[i].name, - evaluated.positional[i].clone(), + evaluated.positional.remove(i), ); } // todo: better name for var - let additional_declared_args = - if declared_arguments.len() > evaluated.positional.len() { - &declared_arguments[evaluated.positional.len()..declared_arguments.len()] - } else { - &[] - }; + let additional_declared_args = if declared_arguments.len() > positional_len { + &declared_arguments[positional_len..declared_arguments.len()] + } else { + &[] + }; for argument in additional_declared_args { let name = argument.name; @@ -2161,17 +2160,19 @@ impl<'a> Visitor<'a> { let were_keywords_accessed = Arc::new(Cell::new(false)); - let argument_list = if let Some(rest_arg) = func.arguments().rest { - let rest = if evaluated.positional.len() > declared_arguments.len() { - &evaluated.positional[declared_arguments.len()..] + let num_named_args = evaluated.named.len(); + + let has_arg_list = if let Some(rest_arg) = func.arguments().rest { + let rest = if evaluated.positional.len() > 0 { + evaluated.positional } else { - &[] + Vec::new() }; let arg_list = Value::ArgList(ArgList::new( - rest.to_vec(), - // todo: superfluous clone + rest, Arc::clone(&were_keywords_accessed), + // todo: superfluous clone evaluated.named.clone(), if evaluated.separator == ListSeparator::Undecided { ListSeparator::Comma @@ -2180,20 +2181,16 @@ impl<'a> Visitor<'a> { }, )); - visitor - .env - .scopes_mut() - // todo: superfluous clone - .insert_var_last(rest_arg, arg_list.clone()); + visitor.env.scopes_mut().insert_var_last(rest_arg, arg_list); - Some(arg_list) + true } else { - None + false }; let val = run(func, visitor)?; - if argument_list.is_none() || evaluated.named.is_empty() { + if !has_arg_list || num_named_args == 0 { return Ok(val); } @@ -2201,7 +2198,7 @@ impl<'a> Visitor<'a> { return Ok(val); } - let argument_word = if evaluated.named.len() == 1 { + let argument_word = if num_named_args == 1 { "argument" } else { "arguments" diff --git a/crates/compiler/src/serializer.rs b/crates/compiler/src/serializer.rs index eccd3c4..72f4855 100644 --- a/crates/compiler/src/serializer.rs +++ b/crates/compiler/src/serializer.rs @@ -13,8 +13,8 @@ use crate::{ }, utils::hex_char_for, value::{ - fuzzy_equals, ArgList, CalculationArg, SassCalculation, SassFunction, SassMap, SassNumber, - Value, + fuzzy_equals, ArgList, CalculationArg, CalculationName, SassCalculation, SassFunction, + SassMap, SassNumber, Value, }, Options, }; @@ -299,10 +299,17 @@ impl<'a> Serializer<'a> { self.write_optional_space(); } + fn write_calculation_name(&mut self, name: CalculationName) { + match name { + CalculationName::Calc => self.buffer.extend_from_slice(b"calc"), + CalculationName::Min => self.buffer.extend_from_slice(b"min"), + CalculationName::Max => self.buffer.extend_from_slice(b"max"), + CalculationName::Clamp => self.buffer.extend_from_slice(b"clamp"), + } + } + fn visit_calculation(&mut self, calculation: &SassCalculation) -> SassResult<()> { - // todo: superfluous allocation - self.buffer - .extend_from_slice(calculation.name.to_string().as_bytes()); + self.write_calculation_name(calculation.name); self.buffer.push(b'('); if let Some((last, slice)) = calculation.args.split_last() {