Skip to content

Commit

Permalink
fix(es/minifier): Fix handling of template literals (#4563)
Browse files Browse the repository at this point in the history
  • Loading branch information
kdy1 committed May 7, 2022
1 parent 20ce370 commit 920d9a7
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 21 deletions.
4 changes: 2 additions & 2 deletions crates/swc_ecma_minifier/src/compress/pure/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use swc_ecma_utils::ident::IdentLike;

use super::Pure;
use crate::compress::{
pure::strings::convert_str_value_to_tpl_cooked,
pure::strings::{convert_str_value_to_tpl_cooked, convert_str_value_to_tpl_raw},
util::{is_global_var, is_pure_undefined},
};

Expand Down Expand Up @@ -404,7 +404,7 @@ impl Pure<'_> {
}
Expr::Lit(Lit::Str(s)) => {
cur_cooked.push_str(&convert_str_value_to_tpl_cooked(&s.value));
cur_raw.push_str(&s.value);
cur_raw.push_str(&convert_str_value_to_tpl_raw(&s.value));
}
_ => {
unreachable!()
Expand Down
39 changes: 30 additions & 9 deletions crates/swc_ecma_minifier/src/compress/pure/strings.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::mem::take;
use std::{borrow::Cow, mem::take};

use swc_atoms::{js_word, JsWord};
use swc_common::{util::take::Take, DUMMY_SP};
Expand Down Expand Up @@ -196,6 +196,7 @@ impl Pure<'_> {
'\n' | '\r' => self.config.force_str_for_tpl,
_ => false,
}) && (self.config.force_str_for_tpl
|| c.contains("\\`")
|| (!c.contains("\\n") && !c.contains("\\r")))
&& !c.contains("\\0")
&& !c.contains("\\x")
Expand Down Expand Up @@ -238,26 +239,31 @@ impl Pure<'_> {
let mut quasis = vec![];
let mut exprs = vec![];
let mut cur_raw = String::new();
let mut cur_cooked = String::new();

for i in 0..(tpl.exprs.len() + tpl.quasis.len()) {
if i % 2 == 0 {
let i = i / 2;
let q = tpl.quasis[i].take();

cur_raw.push_str(&q.raw);
if let Some(cooked) = q.cooked {
cur_cooked.push_str(&cooked);
}
} else {
let i = i / 2;
let e = tpl.exprs[i].take();

match *e {
Expr::Lit(Lit::Str(s)) => {
cur_raw.push_str(&s.value);
cur_raw.push_str(&convert_str_value_to_tpl_raw(&s.value));
cur_cooked.push_str(&convert_str_value_to_tpl_cooked(&s.value));
}
_ => {
quasis.push(TplElement {
span: DUMMY_SP,
tail: true,
cooked: None,
cooked: Some(JsWord::from(&*cur_cooked)),
raw: take(&mut cur_raw).into(),
});

Expand All @@ -267,6 +273,8 @@ impl Pure<'_> {
}
}

report_change!("compressing template literals");

quasis.push(TplElement {
span: DUMMY_SP,
tail: true,
Expand Down Expand Up @@ -294,11 +302,13 @@ impl Pure<'_> {
);

if let Some(cooked) = &mut l_last.cooked {
*cooked = format!("{}{}", cooked, rs.value.replace('\\', "\\\\")).into()
*cooked =
format!("{}{}", cooked, convert_str_value_to_tpl_cooked(&rs.value))
.into();
}

let new: JsWord =
format!("{}{}", l_last.raw, rs.value.replace('\\', "\\\\")).into();
format!("{}{}", l_last.raw, convert_str_value_to_tpl_raw(&rs.value)).into();
l_last.raw = new;

r.take();
Expand All @@ -316,11 +326,14 @@ impl Pure<'_> {
);

if let Some(cooked) = &mut r_first.cooked {
*cooked = format!("{}{}", ls.value.replace('\\', "\\\\"), cooked).into()
*cooked =
format!("{}{}", convert_str_value_to_tpl_cooked(&ls.value), cooked)
.into()
}

let new: JsWord =
format!("{}{}", ls.value.replace('\\', "\\\\"), r_first.raw).into();
format!("{}{}", convert_str_value_to_tpl_raw(&ls.value), r_first.raw)
.into();
r_first.raw = new;

l.take();
Expand Down Expand Up @@ -449,12 +462,20 @@ impl Pure<'_> {
}
}

pub(super) fn convert_str_value_to_tpl_cooked(value: &JsWord) -> JsWord {
pub(super) fn convert_str_value_to_tpl_cooked(value: &JsWord) -> Cow<str> {
value
.replace('\\', "\\\\")
.replace('`', "\\`")
.replace('$', "\\$")
.into()
}

pub(super) fn convert_str_value_to_tpl_raw(value: &JsWord) -> Cow<str> {
value
.replace('\\', "\\\\")
.replace('`', "\\`")
.replace('$', "\\$")
.replace('\n', "\\n")
.replace('\r', "\\r")
.replace('\\', "\\\\")
.into()
}
2 changes: 0 additions & 2 deletions crates/swc_ecma_minifier/tests/TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -143,5 +143,3 @@ sequences/delete_seq_5/input.js
sequences/for_sequences/input.js
sequences/issue_1758/input.js
sequences/lift_sequences_5/input.js
template_string/special_chars_in_string/input.js
transform/if_else_empty/input.js
2 changes: 2 additions & 0 deletions crates/swc_ecma_minifier/tests/golden.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1338,6 +1338,7 @@ template_string/semicolons/input.js
template_string/sequence_1/input.js
template_string/sequence_2/input.js
template_string/simple_string/input.js
template_string/special_chars_in_string/input.js
template_string/tagged_call_with_invalid_escape/input.js
template_string/tagged_call_with_invalid_escape_2/input.js
template_string/tagged_template_function_inline_1/input.js
Expand Down Expand Up @@ -1368,6 +1369,7 @@ template_string/template_with_newline/input.js
transform/booleans_evaluate/input.js
transform/booleans_global_defs/input.js
transform/condition_evaluate/input.js
transform/if_else_empty/input.js
transform/if_return/input.js
transform/while_if_break/input.js
try_catch/broken_safari_catch_scope/input.js
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a;
18 changes: 10 additions & 8 deletions crates/swc_html_parser/tests/fixture.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#![deny(warnings)]
#![allow(clippy::needless_update)]
#![allow(clippy::redundant_clone)]
#![allow(clippy::while_let_on_iterator)]

use std::{fs, mem::take, path::PathBuf};

Expand Down Expand Up @@ -788,19 +790,19 @@ impl VisitMut for DomVisualizer<'_> {
document_type.push_str("<!DOCTYPE ");

if let Some(name) = &n.name {
document_type.push_str(&name);
document_type.push_str(name);
}

if let Some(public_id) = &n.public_id {
document_type.push(' ');
document_type.push('"');
document_type.push_str(&public_id);
document_type.push_str(public_id);
document_type.push('"');

if let Some(system_id) = &n.system_id {
document_type.push(' ');
document_type.push('"');
document_type.push_str(&system_id);
document_type.push_str(system_id);
document_type.push('"');
} else {
document_type.push(' ');
Expand All @@ -813,7 +815,7 @@ impl VisitMut for DomVisualizer<'_> {
document_type.push('"');
document_type.push(' ');
document_type.push('"');
document_type.push_str(&system_id);
document_type.push_str(system_id);
document_type.push('"');
}

Expand Down Expand Up @@ -865,7 +867,7 @@ impl VisitMut for DomVisualizer<'_> {
attribute.push_str(&self.get_ident());

if let Some(prefix) = &n.prefix {
attribute.push_str(&prefix);
attribute.push_str(prefix);
attribute.push(' ');
}

Expand All @@ -874,7 +876,7 @@ impl VisitMut for DomVisualizer<'_> {
attribute.push('"');

if let Some(value) = &n.value {
attribute.push_str(&value);
attribute.push_str(value);
}

attribute.push('"');
Expand Down Expand Up @@ -961,9 +963,9 @@ fn html5lib_test_tree_construction(input: PathBuf) {
.find("#errors\n")
.expect("failed to get errors in test");
let mut data = &test[data_start..data_end];
if data.ends_with("\n") {
if data.ends_with('\n') {
data = data
.strip_suffix("\n")
.strip_suffix('\n')
.expect("failed to strip last line in test");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(unused_variables)]
#[cfg(feature = "plugin-mode")]
use swc_common::{source_map::FileLinesResult, BytePos, FileName, Loc, SourceMapper, Span};

Expand Down

1 comment on commit 920d9a7

@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: 920d9a7 Previous: f9b6016 Ratio
es/full/minify/libraries/antd 2033441629 ns/iter (± 95068366) 1787754351 ns/iter (± 54808489) 1.14
es/full/minify/libraries/d3 604781315 ns/iter (± 37752837) 413290041 ns/iter (± 7186290) 1.46
es/full/minify/libraries/echarts 2363777965 ns/iter (± 19527488) 2069599622 ns/iter (± 11570055) 1.14
es/full/minify/libraries/jquery 114971857 ns/iter (± 2268150) 94875908 ns/iter (± 710650) 1.21
es/full/minify/libraries/lodash 150523194 ns/iter (± 6494047) 112914874 ns/iter (± 2158263) 1.33
es/full/minify/libraries/moment 64949658 ns/iter (± 807060) 54566712 ns/iter (± 218839) 1.19
es/full/minify/libraries/react 20357734 ns/iter (± 331453) 16999619 ns/iter (± 49621) 1.20
es/full/minify/libraries/terser 729059372 ns/iter (± 24742989) 564272953 ns/iter (± 7944464) 1.29
es/full/minify/libraries/three 759719446 ns/iter (± 19959500) 572615406 ns/iter (± 11251570) 1.33
es/full/minify/libraries/typescript 4432760295 ns/iter (± 45386408) 4026188600 ns/iter (± 17136182) 1.10
es/full/minify/libraries/victory 936510447 ns/iter (± 29059268) 773683952 ns/iter (± 10686327) 1.21
es/full/minify/libraries/vue 179863931 ns/iter (± 7762155) 133153516 ns/iter (± 934595) 1.35
es/full/codegen/es3 33924 ns/iter (± 1772) 29391 ns/iter (± 134) 1.15
es/full/codegen/es5 33675 ns/iter (± 381) 29442 ns/iter (± 137) 1.14
es/full/codegen/es2015 33773 ns/iter (± 331) 29499 ns/iter (± 128) 1.14
es/full/codegen/es2016 36981 ns/iter (± 1928) 29442 ns/iter (± 147) 1.26
es/full/codegen/es2017 33922 ns/iter (± 183) 29390 ns/iter (± 172) 1.15
es/full/codegen/es2018 33945 ns/iter (± 297) 29481 ns/iter (± 150) 1.15
es/full/codegen/es2019 33944 ns/iter (± 184) 29494 ns/iter (± 141) 1.15
es/full/codegen/es2020 33925 ns/iter (± 171) 29385 ns/iter (± 121) 1.15
es/full/all/es3 209741948 ns/iter (± 5697887) 180860224 ns/iter (± 826135) 1.16
es/full/all/es5 199101148 ns/iter (± 6347051) 171660801 ns/iter (± 1044016) 1.16
es/full/all/es2015 157858526 ns/iter (± 6292783) 136977212 ns/iter (± 1178534) 1.15
es/full/all/es2016 155552028 ns/iter (± 5386480) 136061165 ns/iter (± 870463) 1.14
es/full/all/es2017 156591014 ns/iter (± 4043011) 136071674 ns/iter (± 1246036) 1.15
es/full/all/es2018 154292649 ns/iter (± 5544008) 135105523 ns/iter (± 1438956) 1.14
es/full/all/es2019 152941833 ns/iter (± 8617515) 131998394 ns/iter (± 1218523) 1.16
es/full/all/es2020 146966410 ns/iter (± 6650484) 117675828 ns/iter (± 524515) 1.25
es/full/parser 673030 ns/iter (± 15855) 577258 ns/iter (± 24194) 1.17
es/full/base/fixer 26127 ns/iter (± 388) 22353 ns/iter (± 169) 1.17
es/full/base/resolver_and_hygiene 108260 ns/iter (± 2824) 91769 ns/iter (± 1391) 1.18
serialization of ast node 165 ns/iter (± 5) 136 ns/iter (± 0) 1.21
serialization of serde 167 ns/iter (± 1) 137 ns/iter (± 0) 1.22
es/codegen/colors 67611 ns/iter (± 5292) 68364 ns/iter (± 453) 0.99
es/codegen/large 379813 ns/iter (± 3990) 352031 ns/iter (± 2344) 1.08
es/codegen/with-parser/colors 62087 ns/iter (± 998) 53048 ns/iter (± 515) 1.17
es/codegen/with-parser/large 659374 ns/iter (± 9144) 570655 ns/iter (± 14414) 1.16
es/minify/libraries/antd 1902218768 ns/iter (± 12589563) 1759610540 ns/iter (± 50223615) 1.08
es/minify/libraries/d3 541701569 ns/iter (± 14146505) 417439397 ns/iter (± 5836347) 1.30
es/minify/libraries/echarts 2318252004 ns/iter (± 11463940) 2052397779 ns/iter (± 12003476) 1.13
es/minify/libraries/jquery 116564712 ns/iter (± 4337804) 90865243 ns/iter (± 561032) 1.28
es/minify/libraries/lodash 139650854 ns/iter (± 1581348) 109078304 ns/iter (± 488466) 1.28
es/minify/libraries/moment 66994223 ns/iter (± 1427188) 52996847 ns/iter (± 319334) 1.26
es/minify/libraries/react 20140089 ns/iter (± 379416) 16316685 ns/iter (± 69428) 1.23
es/minify/libraries/terser 705378103 ns/iter (± 14675440) 553319540 ns/iter (± 16724039) 1.27
es/minify/libraries/three 697965371 ns/iter (± 12915792) 541860594 ns/iter (± 12274985) 1.29
es/minify/libraries/typescript 4286576425 ns/iter (± 19728726) 3917570609 ns/iter (± 14145230) 1.09
es/minify/libraries/victory 885129781 ns/iter (± 27965618) 737974701 ns/iter (± 13695707) 1.20
es/minify/libraries/vue 168128139 ns/iter (± 4394484) 128823973 ns/iter (± 889050) 1.31
es/visitor/compare/clone 3092383 ns/iter (± 190563) 2320505 ns/iter (± 31409) 1.33
es/visitor/compare/visit_mut_span 4099349 ns/iter (± 221573) 2911086 ns/iter (± 208498) 1.41
es/visitor/compare/visit_mut_span_panic 4097729 ns/iter (± 287076) 2906479 ns/iter (± 38799) 1.41
es/visitor/compare/fold_span 5396408 ns/iter (± 335473) 3944305 ns/iter (± 67457) 1.37
es/visitor/compare/fold_span_panic 5950223 ns/iter (± 358977) 4111994 ns/iter (± 62723) 1.45
es/lexer/colors 24657 ns/iter (± 127) 20649 ns/iter (± 71) 1.19
es/lexer/angular 12451316 ns/iter (± 565785) 10076458 ns/iter (± 13267) 1.24
es/lexer/backbone 1673472 ns/iter (± 145117) 1351543 ns/iter (± 1429) 1.24
es/lexer/jquery 8583357 ns/iter (± 81007) 7260935 ns/iter (± 5439) 1.18
es/lexer/jquery mobile 14036615 ns/iter (± 127926) 11767414 ns/iter (± 11611) 1.19
es/lexer/mootools 6635921 ns/iter (± 63300) 5595316 ns/iter (± 6012) 1.19
es/lexer/underscore 1343021 ns/iter (± 11226) 1128462 ns/iter (± 1371) 1.19
es/lexer/three 39818754 ns/iter (± 328531) 33389469 ns/iter (± 40263) 1.19
es/lexer/yui 7313055 ns/iter (± 68353) 6159537 ns/iter (± 6493) 1.19
es/parser/colors 41279 ns/iter (± 713) 35997 ns/iter (± 244) 1.15
es/parser/angular 21512535 ns/iter (± 646133) 17702054 ns/iter (± 376484) 1.22
es/parser/backbone 2963190 ns/iter (± 47093) 2548828 ns/iter (± 14385) 1.16
es/parser/jquery 16723755 ns/iter (± 468117) 14092618 ns/iter (± 337099) 1.19
es/parser/jquery mobile 27326241 ns/iter (± 628362) 22825936 ns/iter (± 671320) 1.20
es/parser/mootools 12864691 ns/iter (± 422480) 10954554 ns/iter (± 193418) 1.17
es/parser/underscore 2514585 ns/iter (± 43320) 2193864 ns/iter (± 11403) 1.15
es/parser/three 77276596 ns/iter (± 923236) 68994598 ns/iter (± 770660) 1.12
es/parser/yui 12956483 ns/iter (± 302494) 11080844 ns/iter (± 112728) 1.17
es/preset-env/usage/builtin_type 150106 ns/iter (± 8116) 125702 ns/iter (± 3786) 1.19
es/preset-env/usage/property 33522 ns/iter (± 668) 29616 ns/iter (± 782) 1.13
es/transforms/base/resolver 161780 ns/iter (± 2931) 135568 ns/iter (± 1540) 1.19
es/transforms/base/fixer 151498 ns/iter (± 2239) 128450 ns/iter (± 900) 1.18
es/transforms/base/hygiene 381921 ns/iter (± 4889) 324047 ns/iter (± 1237) 1.18
es/transforms/base/resolver_with_hygiene 452410 ns/iter (± 4574) 379385 ns/iter (± 1962) 1.19
es/visitor/base-perf/module_clone 111783 ns/iter (± 3077) 96481 ns/iter (± 2183) 1.16
es/visitor/base-perf/fold_empty 126620 ns/iter (± 2868) 108975 ns/iter (± 2024) 1.16
es/visitor/base-perf/fold_noop_impl_all 126866 ns/iter (± 2860) 109153 ns/iter (± 2276) 1.16
es/visitor/base-perf/fold_noop_impl_vec 126008 ns/iter (± 2519) 109358 ns/iter (± 1916) 1.15
es/visitor/base-perf/boxing_boxed_clone 81 ns/iter (± 1) 71 ns/iter (± 0) 1.14
es/visitor/base-perf/boxing_unboxed_clone 124 ns/iter (± 1) 106 ns/iter (± 0) 1.17
es/visitor/base-perf/boxing_boxed 158 ns/iter (± 1) 143 ns/iter (± 0) 1.10
es/visitor/base-perf/boxing_unboxed 191 ns/iter (± 2) 164 ns/iter (± 0) 1.16
es/visitor/base-perf/visit_contains_this 4417 ns/iter (± 153) 3716 ns/iter (± 112) 1.19
misc/visitors/time-complexity/time 5 120 ns/iter (± 1) 103 ns/iter (± 0) 1.17
misc/visitors/time-complexity/time 10 397 ns/iter (± 6) 338 ns/iter (± 4) 1.17
misc/visitors/time-complexity/time 15 843 ns/iter (± 9) 707 ns/iter (± 6) 1.19
misc/visitors/time-complexity/time 20 1493 ns/iter (± 16) 1345 ns/iter (± 3) 1.11
misc/visitors/time-complexity/time 40 5087 ns/iter (± 63) 7021 ns/iter (± 12) 0.72
misc/visitors/time-complexity/time 60 10974 ns/iter (± 149) 17920 ns/iter (± 31) 0.61
es/full-target/es2016 302173 ns/iter (± 15355) 252777 ns/iter (± 6023) 1.20
es/full-target/es2017 285207 ns/iter (± 2218) 237962 ns/iter (± 1737) 1.20
es/full-target/es2018 269476 ns/iter (± 1736) 226767 ns/iter (± 1183) 1.19
es2020_nullish_coalescing 139241 ns/iter (± 1238) 117084 ns/iter (± 806) 1.19
es2020_optional_chaining 173244 ns/iter (± 1130) 145296 ns/iter (± 794) 1.19
es2022_class_properties 174894 ns/iter (± 1360) 146734 ns/iter (± 1167) 1.19
es2018_object_rest_spread 128400 ns/iter (± 2555) 107299 ns/iter (± 1930) 1.20
es2019_optional_catch_binding 113233 ns/iter (± 2334) 94401 ns/iter (± 1732) 1.20
es2017_async_to_generator 113402 ns/iter (± 2181) 94621 ns/iter (± 1842) 1.20
es2016_exponentiation 137232 ns/iter (± 1267) 115619 ns/iter (± 480) 1.19
es2015_arrow 140132 ns/iter (± 1430) 117320 ns/iter (± 634) 1.19
es2015_block_scoped_fn 139674 ns/iter (± 874) 116939 ns/iter (± 575) 1.19
es2015_block_scoping 235238 ns/iter (± 2207) 197322 ns/iter (± 1253) 1.19
es2015_classes 198788 ns/iter (± 1868) 166078 ns/iter (± 1846) 1.20
es2015_computed_props 113116 ns/iter (± 2966) 95988 ns/iter (± 2222) 1.18
es2015_destructuring 208981 ns/iter (± 2337) 175718 ns/iter (± 926) 1.19
es2015_duplicate_keys 116627 ns/iter (± 2756) 97709 ns/iter (± 1893) 1.19
es2015_parameters 148300 ns/iter (± 866) 125073 ns/iter (± 519) 1.19
es2015_fn_name 118139 ns/iter (± 2461) 98523 ns/iter (± 1912) 1.20
es2015_for_of 135957 ns/iter (± 957) 114087 ns/iter (± 512) 1.19
es2015_instanceof 126258 ns/iter (± 1252) 106224 ns/iter (± 582) 1.19
es2015_shorthand_property 113124 ns/iter (± 2538) 95226 ns/iter (± 1717) 1.19
es2015_spread 114019 ns/iter (± 2512) 94787 ns/iter (± 1902) 1.20
es2015_sticky_regex 115721 ns/iter (± 2416) 95823 ns/iter (± 1744) 1.21
es2015_typeof_symbol 116742 ns/iter (± 2716) 96954 ns/iter (± 1681) 1.20
es/transform/baseline/base 99825 ns/iter (± 2524) 83495 ns/iter (± 1853) 1.20
es/transform/baseline/common_reserved_word 117514 ns/iter (± 2252) 98028 ns/iter (± 1712) 1.20
es/transform/baseline/common_typescript 246163 ns/iter (± 1824) 206405 ns/iter (± 725) 1.19
es/target/es3 303175 ns/iter (± 1972) 255230 ns/iter (± 1092) 1.19
es/target/es2015 884819 ns/iter (± 3098) 742692 ns/iter (± 1429) 1.19
es/target/es2016 138463 ns/iter (± 989) 115849 ns/iter (± 565) 1.20
es/target/es2017 114120 ns/iter (± 2498) 94466 ns/iter (± 1827) 1.21
es/target/es2018 143729 ns/iter (± 2328) 119610 ns/iter (± 1816) 1.20
es/target/es2020 216357 ns/iter (± 1914) 180749 ns/iter (± 1313) 1.20
babelify-only 828441 ns/iter (± 221511) 686761 ns/iter (± 3856) 1.21
parse_and_babelify_angular 81579385 ns/iter (± 3640911) 70844977 ns/iter (± 941669) 1.15
parse_and_babelify_backbone 9344765 ns/iter (± 681897) 6883095 ns/iter (± 99238) 1.36
parse_and_babelify_jquery 57681568 ns/iter (± 3219908) 48813302 ns/iter (± 723601) 1.18
parse_and_babelify_jquery_mobile 101079768 ns/iter (± 4971523) 86117379 ns/iter (± 785954) 1.17
parse_and_babelify_mootools 45760808 ns/iter (± 2393296) 36057130 ns/iter (± 710479) 1.27
parse_and_babelify_underscore 7416100 ns/iter (± 300569) 5755533 ns/iter (± 43290) 1.29
parse_and_babelify_yui 43875173 ns/iter (± 2641346) 35464199 ns/iter (± 748135) 1.24

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

Please sign in to comment.