Skip to content

Commit

Permalink
feat(css/minifier): Handle nested calc() (#6153)
Browse files Browse the repository at this point in the history
  • Loading branch information
ghostd committed Oct 17, 2022
1 parent 30f3de2 commit d4a733d
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 130 deletions.
58 changes: 28 additions & 30 deletions crates/swc_css_minifier/src/compressor/calc_sum.rs
Expand Up @@ -184,6 +184,20 @@ impl CalcSumContext {
let mut sum = s.clone();
self.nested_fold(operator, &mut sum);
}
CalcValueOrOperator::Value(CalcValue::Function(Function {
name, value, ..
})) if is_calc_function_name(name) && value.len() == 1 => {
match &value[0] {
ComponentValue::CalcSum(calc_sum) => {
let mut sum = calc_sum.clone();
self.nested_fold(operator, &mut sum);
}
_ => {
// Other cases (constant, function...), just push the data
self.push(operator, operand);
}
}
}
_ => {
// Other cases (constant, function...), just push the data
self.push(operator, operand);
Expand Down Expand Up @@ -970,39 +984,23 @@ impl Compressor {
ComponentValue::CalcSum(CalcSum {
expressions: calc_sum_expressions,
..
}) if calc_sum_expressions.len() == 1 => {
match &calc_sum_expressions[0] {
CalcProductOrOperator::Product(CalcProduct {
expressions: calc_product_expressions,
..
}) if calc_product_expressions.len() == 1 => {
match &calc_product_expressions[0] {
CalcValueOrOperator::Value(CalcValue::Sum(_)) => {
// Do nothing, we cannot transform a
// CalcSum into a ComponentValue
}
CalcValueOrOperator::Value(CalcValue::Constant(_)) => {
// https://www.w3.org/TR/css-values-4/#calc-constants
// "These keywords are only usable
// within a calculation"
// "If used outside of a calculation,
// they’re treated like any other
// keyword"
}
// `calc` and other math functions can be used in `@supports` to
// check availability, we should leave them as is
CalcValueOrOperator::Value(calc_value)
if !self.in_supports_conidition =>
{
*component_value =
transform_calc_value_into_component_value(calc_value);
}
_ => {}
}) if calc_sum_expressions.len() == 1 => match &calc_sum_expressions[0] {
CalcProductOrOperator::Product(CalcProduct {
expressions: calc_product_expressions,
..
}) if calc_product_expressions.len() == 1 => {
if let CalcValueOrOperator::Value(calc_value) =
&calc_product_expressions[0]
{
if let Some(cv) =
transform_calc_value_into_component_value(calc_value)
{
*component_value = cv;
}
}
_ => {}
}
}
_ => {}
},
_ => {}
}
}
Expand Down
50 changes: 17 additions & 33 deletions crates/swc_css_minifier/src/compressor/container.rs
Expand Up @@ -13,46 +13,30 @@ impl Compressor {
ComponentValue::CalcSum(CalcSum {
expressions: calc_sum_expressions,
..
}) if calc_sum_expressions.len() == 1 => {
match &calc_sum_expressions[0] {
CalcProductOrOperator::Product(CalcProduct {
expressions: calc_product_expressions,
..
}) if calc_product_expressions.len() == 1 => {
match &calc_product_expressions[0] {
CalcValueOrOperator::Value(CalcValue::Sum(_)) => {
// Do nothing, we cannot transform a
// CalcSum into a ComponentValue
}) if calc_sum_expressions.len() == 1 => match &calc_sum_expressions[0] {
CalcProductOrOperator::Product(CalcProduct {
expressions: calc_product_expressions,
..
}) if calc_product_expressions.len() == 1 => {
if let CalcValueOrOperator::Value(calc_value) =
&calc_product_expressions[0]
{
match transform_calc_value_into_component_value(calc_value) {
Some(ComponentValue::Function(function)) => {
*n = SizeFeatureValue::Function(function);
}
CalcValueOrOperator::Value(CalcValue::Constant(_)) => {
// https://www.w3.org/TR/css-values-4/#calc-constants
// "These keywords are only usable
// within a calculation"
// "If used outside of a calculation,
// they’re treated like any other
// keyword"
Some(ComponentValue::Dimension(dimension)) => {
*n = SizeFeatureValue::Dimension(dimension);
}
CalcValueOrOperator::Value(calc_value) => {
match transform_calc_value_into_component_value(calc_value)
{
ComponentValue::Function(function) => {
*n = SizeFeatureValue::Function(function);
}
ComponentValue::Dimension(dimension) => {
*n = SizeFeatureValue::Dimension(dimension);
}
ComponentValue::Number(number) => {
*n = SizeFeatureValue::Number(number);
}
_ => {}
}
Some(ComponentValue::Number(number)) => {
*n = SizeFeatureValue::Number(number);
}
_ => {}
}
}
_ => {}
}
}
_ => {}
},
_ => {}
}
}
Expand Down
56 changes: 30 additions & 26 deletions crates/swc_css_minifier/src/compressor/math/mod.rs
Expand Up @@ -7,72 +7,76 @@ pub fn is_calc_function_name(ident: &Ident) -> bool {
|| ident.value.to_ascii_lowercase() == js_word!("-moz-calc")
}

pub fn transform_calc_value_into_component_value(calc_value: &CalcValue) -> ComponentValue {
pub fn transform_calc_value_into_component_value(calc_value: &CalcValue) -> Option<ComponentValue> {
match &calc_value {
CalcValue::Number(n) => ComponentValue::Number(n.clone()),
CalcValue::Number(n) => Some(ComponentValue::Number(n.clone())),
CalcValue::Dimension(Dimension::Length(l)) => {
ComponentValue::Dimension(Dimension::Length(Length {
Some(ComponentValue::Dimension(Dimension::Length(Length {
span: l.span,
value: l.value.clone(),
unit: l.unit.clone(),
}))
})))
}
CalcValue::Dimension(Dimension::Angle(a)) => {
ComponentValue::Dimension(Dimension::Angle(Angle {
Some(ComponentValue::Dimension(Dimension::Angle(Angle {
span: a.span,
value: a.value.clone(),
unit: a.unit.clone(),
}))
})))
}
CalcValue::Dimension(Dimension::Time(t)) => {
ComponentValue::Dimension(Dimension::Time(Time {
Some(ComponentValue::Dimension(Dimension::Time(Time {
span: t.span,
value: t.value.clone(),
unit: t.unit.clone(),
}))
})))
}
CalcValue::Dimension(Dimension::Frequency(f)) => {
ComponentValue::Dimension(Dimension::Frequency(Frequency {
Some(ComponentValue::Dimension(Dimension::Frequency(Frequency {
span: f.span,
value: f.value.clone(),
unit: f.unit.clone(),
}))
})))
}
CalcValue::Dimension(Dimension::Resolution(r)) => {
ComponentValue::Dimension(Dimension::Resolution(Resolution {
CalcValue::Dimension(Dimension::Resolution(r)) => Some(ComponentValue::Dimension(
Dimension::Resolution(Resolution {
span: r.span,
value: r.value.clone(),
unit: r.unit.clone(),
}))
}
}),
)),
CalcValue::Dimension(Dimension::Flex(f)) => {
ComponentValue::Dimension(Dimension::Flex(Flex {
Some(ComponentValue::Dimension(Dimension::Flex(Flex {
span: f.span,
value: f.value.clone(),
unit: f.unit.clone(),
}))
})))
}
CalcValue::Dimension(Dimension::UnknownDimension(u)) => {
ComponentValue::Dimension(Dimension::UnknownDimension(UnknownDimension {
CalcValue::Dimension(Dimension::UnknownDimension(u)) => Some(ComponentValue::Dimension(
Dimension::UnknownDimension(UnknownDimension {
span: u.span,
value: u.value.clone(),
unit: u.unit.clone(),
}))
}
CalcValue::Percentage(p) => ComponentValue::Percentage(Percentage {
}),
)),
CalcValue::Percentage(p) => Some(ComponentValue::Percentage(Percentage {
span: p.span,
value: p.value.clone(),
}),
CalcValue::Function(f) => ComponentValue::Function(Function {
})),
CalcValue::Function(f) => Some(ComponentValue::Function(Function {
span: f.span,
name: f.name.clone(),
value: f.value.to_vec(),
}),
})),
CalcValue::Constant(_) => {
unreachable!("CalcValue::Constant cannot be transformed into a ComponentValue per spec")
// https://www.w3.org/TR/css-values-4/#calc-constants
// "These keywords are only usable within a calculation"
// "If used outside of a calculation, they’re treated like any other keyword"
None
}
CalcValue::Sum(_) => {
unreachable!("CalcValue::Sum cannot be transformed into a ComponentValue")
// Do nothing, we cannot transform a CalcSum into a ComponentValue
None
}
}
}
50 changes: 17 additions & 33 deletions crates/swc_css_minifier/src/compressor/media.rs
Expand Up @@ -339,46 +339,30 @@ impl Compressor {
ComponentValue::CalcSum(CalcSum {
expressions: calc_sum_expressions,
..
}) if calc_sum_expressions.len() == 1 => {
match &calc_sum_expressions[0] {
CalcProductOrOperator::Product(CalcProduct {
expressions: calc_product_expressions,
..
}) if calc_product_expressions.len() == 1 => {
match &calc_product_expressions[0] {
CalcValueOrOperator::Value(CalcValue::Sum(_)) => {
// Do nothing, we cannot transform a
// CalcSum into a ComponentValue
}) if calc_sum_expressions.len() == 1 => match &calc_sum_expressions[0] {
CalcProductOrOperator::Product(CalcProduct {
expressions: calc_product_expressions,
..
}) if calc_product_expressions.len() == 1 => {
if let CalcValueOrOperator::Value(calc_value) =
&calc_product_expressions[0]
{
match transform_calc_value_into_component_value(calc_value) {
Some(ComponentValue::Function(function)) => {
*n = MediaFeatureValue::Function(function);
}
CalcValueOrOperator::Value(CalcValue::Constant(_)) => {
// https://www.w3.org/TR/css-values-4/#calc-constants
// "These keywords are only usable
// within a calculation"
// "If used outside of a calculation,
// they’re treated like any other
// keyword"
Some(ComponentValue::Dimension(dimension)) => {
*n = MediaFeatureValue::Dimension(dimension);
}
CalcValueOrOperator::Value(calc_value) => {
match transform_calc_value_into_component_value(calc_value)
{
ComponentValue::Function(function) => {
*n = MediaFeatureValue::Function(function);
}
ComponentValue::Dimension(dimension) => {
*n = MediaFeatureValue::Dimension(dimension);
}
ComponentValue::Number(number) => {
*n = MediaFeatureValue::Number(number);
}
_ => {}
}
Some(ComponentValue::Number(number)) => {
*n = MediaFeatureValue::Number(number);
}
_ => {}
}
}
_ => {}
}
}
_ => {}
},
_ => {}
}
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 comment on commit d4a733d

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: d4a733d Previous: ea4ae3d Ratio
es/full/minify/libraries/antd 1948312900 ns/iter (± 55587654) 1956461219 ns/iter (± 117590375) 1.00
es/full/minify/libraries/d3 451194529 ns/iter (± 27518322) 459575785 ns/iter (± 13290191) 0.98
es/full/minify/libraries/echarts 1631970074 ns/iter (± 155478946) 1683915389 ns/iter (± 59182978) 0.97
es/full/minify/libraries/jquery 125248562 ns/iter (± 10443973) 113134427 ns/iter (± 4385062) 1.11
es/full/minify/libraries/lodash 136136662 ns/iter (± 7438137) 134906115 ns/iter (± 6860213) 1.01
es/full/minify/libraries/moment 75300997 ns/iter (± 6765838) 63738703 ns/iter (± 6889052) 1.18
es/full/minify/libraries/react 30185866 ns/iter (± 15827278) 20762882 ns/iter (± 524492) 1.45
es/full/minify/libraries/terser 412431577 ns/iter (± 21139102) 387076223 ns/iter (± 48375430) 1.07
es/full/minify/libraries/three 756644996 ns/iter (± 114680812) 609578064 ns/iter (± 17516983) 1.24
es/full/minify/libraries/typescript 4217164183 ns/iter (± 277853843) 4032025416 ns/iter (± 383853971) 1.05
es/full/minify/libraries/victory 967423936 ns/iter (± 84020217) 956209419 ns/iter (± 83648026) 1.01
es/full/minify/libraries/vue 198111721 ns/iter (± 30205419) 191921360 ns/iter (± 13895654) 1.03
es/full/codegen/es3 36116 ns/iter (± 3526) 34648 ns/iter (± 2672) 1.04
es/full/codegen/es5 35017 ns/iter (± 2650) 34044 ns/iter (± 3973) 1.03
es/full/codegen/es2015 35781 ns/iter (± 4396) 33737 ns/iter (± 1782) 1.06
es/full/codegen/es2016 34798 ns/iter (± 2255) 34044 ns/iter (± 966) 1.02
es/full/codegen/es2017 46452 ns/iter (± 26296) 33896 ns/iter (± 2119) 1.37
es/full/codegen/es2018 35200 ns/iter (± 3169) 110641 ns/iter (± 2098222) 0.32
es/full/codegen/es2019 35464 ns/iter (± 5451) 34401 ns/iter (± 12020) 1.03
es/full/codegen/es2020 35526 ns/iter (± 2494) 34283 ns/iter (± 2758) 1.04
es/full/all/es3 299051875 ns/iter (± 119545602) 219507176 ns/iter (± 25166291) 1.36
es/full/all/es5 272207182 ns/iter (± 86506413) 246171905 ns/iter (± 50351384) 1.11
es/full/all/es2015 156521306 ns/iter (± 26821526) 183158764 ns/iter (± 19885735) 0.85
es/full/all/es2016 214759228 ns/iter (± 21076519) 174158603 ns/iter (± 13854519) 1.23
es/full/all/es2017 224515970 ns/iter (± 26972682) 159257150 ns/iter (± 20734383) 1.41
es/full/all/es2018 194888486 ns/iter (± 20419326) 153788495 ns/iter (± 17896821) 1.27
es/full/all/es2019 199450236 ns/iter (± 26156647) 156880720 ns/iter (± 24904761) 1.27
es/full/all/es2020 177148780 ns/iter (± 19240166) 154856270 ns/iter (± 19580178) 1.14
es/full/parser 789872 ns/iter (± 92710) 739620 ns/iter (± 55627) 1.07
es/full/base/fixer 27572 ns/iter (± 2347) 26419 ns/iter (± 1266) 1.04
es/full/base/resolver_and_hygiene 97912 ns/iter (± 6015) 93966 ns/iter (± 5037) 1.04
serialization of ast node 213 ns/iter (± 14) 208 ns/iter (± 8) 1.02
serialization of serde 213 ns/iter (± 15) 211 ns/iter (± 8) 1.01

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.