mirror of
https://github.com/swc-project/swc.git
synced 2024-11-23 09:38:16 +03:00
fix(es/minifier): Fix a bug in tpl string <-> string logic (#8510)
**Related issue:** - Closes #8496
This commit is contained in:
parent
104f604e50
commit
4946a11137
70
crates/swc/tests/fixture/issues-8xxx/8496/input/.swcrc
Normal file
70
crates/swc/tests/fixture/issues-8xxx/8496/input/.swcrc
Normal file
@ -0,0 +1,70 @@
|
||||
{
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "ecmascript",
|
||||
"jsx": false
|
||||
},
|
||||
"loose": true,
|
||||
"minify": {
|
||||
"mangle": false,
|
||||
"compress": {
|
||||
"arguments": false,
|
||||
"arrows": true,
|
||||
"booleans": true,
|
||||
"booleans_as_integers": false,
|
||||
"collapse_vars": true,
|
||||
"comparisons": true,
|
||||
"computed_props": true,
|
||||
"conditionals": true,
|
||||
"dead_code": true,
|
||||
"directives": true,
|
||||
"drop_console": false,
|
||||
"drop_debugger": true,
|
||||
"evaluate": true,
|
||||
"expression": false,
|
||||
"hoist_funs": false,
|
||||
"hoist_props": true,
|
||||
"hoist_vars": false,
|
||||
"if_return": true,
|
||||
"join_vars": true,
|
||||
"keep_classnames": false,
|
||||
"keep_fargs": true,
|
||||
"keep_fnames": false,
|
||||
"keep_infinity": false,
|
||||
"loops": true,
|
||||
"negate_iife": true,
|
||||
"properties": true,
|
||||
"reduce_funcs": false,
|
||||
"reduce_vars": false,
|
||||
"side_effects": true,
|
||||
"switches": true,
|
||||
"typeofs": true,
|
||||
"unsafe": false,
|
||||
"unsafe_arrows": false,
|
||||
"unsafe_comps": false,
|
||||
"unsafe_Function": false,
|
||||
"unsafe_math": false,
|
||||
"unsafe_symbols": false,
|
||||
"unsafe_methods": false,
|
||||
"unsafe_proto": false,
|
||||
"unsafe_regexp": false,
|
||||
"unsafe_undefined": false,
|
||||
"unused": true,
|
||||
"const_to_let": true,
|
||||
"pristine_globals": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"module": {
|
||||
"type": "es6"
|
||||
},
|
||||
"minify": true,
|
||||
"isModule": true,
|
||||
"env": {
|
||||
"targets": {
|
||||
"chrome": 109
|
||||
},
|
||||
"coreJs": "3.21",
|
||||
"mode": "usage"
|
||||
}
|
||||
}
|
3
crates/swc/tests/fixture/issues-8xxx/8496/input/1.js
Normal file
3
crates/swc/tests/fixture/issues-8xxx/8496/input/1.js
Normal file
@ -0,0 +1,3 @@
|
||||
export const strWithDollar = `$login`;
|
||||
|
||||
export const use = `${strWithDollar}`; // expected: "$login" without \\
|
3
crates/swc/tests/fixture/issues-8xxx/8496/input/2.js
Normal file
3
crates/swc/tests/fixture/issues-8xxx/8496/input/2.js
Normal file
@ -0,0 +1,3 @@
|
||||
export const strWithDollar = `$login`;
|
||||
|
||||
export const use = `${strWithDollar}${1}`; // expected: "$login" without \\
|
3
crates/swc/tests/fixture/issues-8xxx/8496/input/3.js
Normal file
3
crates/swc/tests/fixture/issues-8xxx/8496/input/3.js
Normal file
@ -0,0 +1,3 @@
|
||||
export const strWithDollar = `$login`;
|
||||
|
||||
export const use = `${1}${strWithDollar}`; // expected: "$login" without \\
|
3
crates/swc/tests/fixture/issues-8xxx/8496/input/4.js
Normal file
3
crates/swc/tests/fixture/issues-8xxx/8496/input/4.js
Normal file
@ -0,0 +1,3 @@
|
||||
export const strWithDollar = `$login`;
|
||||
|
||||
export const use = `asd${strWithDollar}`; // expected: "$login" without \\
|
3
crates/swc/tests/fixture/issues-8xxx/8496/input/5.js
Normal file
3
crates/swc/tests/fixture/issues-8xxx/8496/input/5.js
Normal file
@ -0,0 +1,3 @@
|
||||
export const strWithDollar = `$login`;
|
||||
|
||||
export const use = `$${strWithDollar}`; // expected: "$login" without \\
|
3
crates/swc/tests/fixture/issues-8xxx/8496/input/6.js
Normal file
3
crates/swc/tests/fixture/issues-8xxx/8496/input/6.js
Normal file
@ -0,0 +1,3 @@
|
||||
export const strWithDollar = `$login`;
|
||||
|
||||
export const use = `{${strWithDollar}`; // expected: "$login" without \\
|
3
crates/swc/tests/fixture/issues-8xxx/8496/input/7.js
Normal file
3
crates/swc/tests/fixture/issues-8xxx/8496/input/7.js
Normal file
@ -0,0 +1,3 @@
|
||||
export const strWithDollar = `$login`;
|
||||
|
||||
export const use = `\{${strWithDollar}`; // expected: "$login" without \\
|
1
crates/swc/tests/fixture/issues-8xxx/8496/input/8.js
Normal file
1
crates/swc/tests/fixture/issues-8xxx/8496/input/8.js
Normal file
@ -0,0 +1 @@
|
||||
export const use = `\xffathjax{$login`;
|
1
crates/swc/tests/fixture/issues-8xxx/8496/output/1.js
Normal file
1
crates/swc/tests/fixture/issues-8xxx/8496/output/1.js
Normal file
@ -0,0 +1 @@
|
||||
export const strWithDollar="$login";export const use="$login";
|
1
crates/swc/tests/fixture/issues-8xxx/8496/output/2.js
Normal file
1
crates/swc/tests/fixture/issues-8xxx/8496/output/2.js
Normal file
@ -0,0 +1 @@
|
||||
export const strWithDollar="$login";export const use="$login1";
|
1
crates/swc/tests/fixture/issues-8xxx/8496/output/3.js
Normal file
1
crates/swc/tests/fixture/issues-8xxx/8496/output/3.js
Normal file
@ -0,0 +1 @@
|
||||
export const strWithDollar="$login";export const use="1$login";
|
1
crates/swc/tests/fixture/issues-8xxx/8496/output/4.js
Normal file
1
crates/swc/tests/fixture/issues-8xxx/8496/output/4.js
Normal file
@ -0,0 +1 @@
|
||||
export const strWithDollar="$login";export const use="asd$login";
|
1
crates/swc/tests/fixture/issues-8xxx/8496/output/5.js
Normal file
1
crates/swc/tests/fixture/issues-8xxx/8496/output/5.js
Normal file
@ -0,0 +1 @@
|
||||
export const strWithDollar="$login";export const use="$$login";
|
1
crates/swc/tests/fixture/issues-8xxx/8496/output/6.js
Normal file
1
crates/swc/tests/fixture/issues-8xxx/8496/output/6.js
Normal file
@ -0,0 +1 @@
|
||||
export const strWithDollar="$login";export const use="{$login";
|
1
crates/swc/tests/fixture/issues-8xxx/8496/output/7.js
Normal file
1
crates/swc/tests/fixture/issues-8xxx/8496/output/7.js
Normal file
@ -0,0 +1 @@
|
||||
export const strWithDollar="$login";export const use="{$login";
|
1
crates/swc/tests/fixture/issues-8xxx/8496/output/8.js
Normal file
1
crates/swc/tests/fixture/issues-8xxx/8496/output/8.js
Normal file
@ -0,0 +1 @@
|
||||
export const use=`\xffathjax{$login`;
|
@ -265,6 +265,43 @@ impl Pure<'_> {
|
||||
let mut cur_raw = String::new();
|
||||
let mut cur_cooked = Some(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].clone();
|
||||
|
||||
if q.cooked.is_some() {
|
||||
if let Some(cur_cooked) = &mut cur_cooked {
|
||||
cur_cooked.push_str("");
|
||||
}
|
||||
} else {
|
||||
// If cooked is None, it means that the template literal contains invalid escape
|
||||
// sequences.
|
||||
cur_cooked = None;
|
||||
}
|
||||
} else {
|
||||
let i = i / 2;
|
||||
let e = &tpl.exprs[i];
|
||||
|
||||
match &**e {
|
||||
Expr::Lit(Lit::Str(s)) => {
|
||||
if cur_cooked.is_none() && s.raw.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(cur_cooked) = &mut cur_cooked {
|
||||
cur_cooked.push_str("");
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
cur_cooked = Some(String::new());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cur_cooked = Some(Default::default());
|
||||
|
||||
for i in 0..(tpl.exprs.len() + tpl.quasis.len()) {
|
||||
if i % 2 == 0 {
|
||||
let i = i / 2;
|
||||
@ -286,10 +323,19 @@ impl Pure<'_> {
|
||||
|
||||
match *e {
|
||||
Expr::Lit(Lit::Str(s)) => {
|
||||
cur_raw.push_str(&convert_str_value_to_tpl_raw(&s.value));
|
||||
if let Some(cur_cooked) = &mut cur_cooked {
|
||||
cur_cooked.push_str(&convert_str_value_to_tpl_cooked(&s.value));
|
||||
}
|
||||
|
||||
if let Some(raw) = &s.raw {
|
||||
if raw.len() >= 2 {
|
||||
// Exclude quotes
|
||||
cur_raw
|
||||
.push_str(&convert_str_raw_to_tpl_raw(&raw[1..raw.len() - 1]));
|
||||
}
|
||||
} else {
|
||||
cur_raw.push_str(&convert_str_value_to_tpl_raw(&s.value));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
quasis.push(TplElement {
|
||||
@ -325,6 +371,12 @@ impl Pure<'_> {
|
||||
pub(super) fn concat_tpl(&mut self, l: &mut Expr, r: &mut Expr) {
|
||||
match (&mut *l, &mut *r) {
|
||||
(Expr::Tpl(l), Expr::Lit(Lit::Str(rs))) => {
|
||||
if let Some(raw) = &rs.raw {
|
||||
if raw.len() <= 2 {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Append
|
||||
if let Some(l_last) = l.quasis.last_mut() {
|
||||
self.changed = true;
|
||||
@ -340,15 +392,27 @@ impl Pure<'_> {
|
||||
.into();
|
||||
}
|
||||
|
||||
let new: Atom =
|
||||
format!("{}{}", l_last.raw, convert_str_value_to_tpl_raw(&rs.value)).into();
|
||||
l_last.raw = new;
|
||||
l_last.raw = format!(
|
||||
"{}{}",
|
||||
l_last.raw,
|
||||
rs.raw
|
||||
.clone()
|
||||
.map(|s| convert_str_raw_to_tpl_raw(&s[1..s.len() - 1]))
|
||||
.unwrap_or_else(|| convert_str_value_to_tpl_raw(&rs.value).into())
|
||||
)
|
||||
.into();
|
||||
|
||||
r.take();
|
||||
}
|
||||
}
|
||||
|
||||
(Expr::Lit(Lit::Str(ls)), Expr::Tpl(r)) => {
|
||||
if let Some(raw) = &ls.raw {
|
||||
if raw.len() <= 2 {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Append
|
||||
if let Some(r_first) = r.quasis.first_mut() {
|
||||
self.changed = true;
|
||||
@ -364,8 +428,14 @@ impl Pure<'_> {
|
||||
.into()
|
||||
}
|
||||
|
||||
let new: Atom =
|
||||
format!("{}{}", convert_str_value_to_tpl_raw(&ls.value), r_first.raw)
|
||||
let new: Atom = format!(
|
||||
"{}{}",
|
||||
ls.raw
|
||||
.clone()
|
||||
.map(|s| convert_str_raw_to_tpl_raw(&s[1..s.len() - 1]))
|
||||
.unwrap_or_else(|| convert_str_value_to_tpl_raw(&ls.value).into()),
|
||||
r_first.raw
|
||||
)
|
||||
.into();
|
||||
r_first.raw = new;
|
||||
|
||||
@ -392,7 +462,7 @@ impl Pure<'_> {
|
||||
|
||||
debug_assert!(l.quasis.len() == l.exprs.len() + 1, "{:?} is invalid", l);
|
||||
self.changed = true;
|
||||
report_change!("strings: Merged to template literals");
|
||||
report_change!("strings: Merged two template literals");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -498,9 +568,9 @@ impl Pure<'_> {
|
||||
|
||||
pub(super) fn convert_str_value_to_tpl_cooked(value: &JsWord) -> Cow<str> {
|
||||
value
|
||||
.replace('\\', "\\\\")
|
||||
.replace('`', "\\`")
|
||||
.replace('$', "\\$")
|
||||
.replace("\\\\", "\\")
|
||||
.replace("\\`", "`")
|
||||
.replace("\\$", "$")
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -513,3 +583,7 @@ pub(super) fn convert_str_value_to_tpl_raw(value: &JsWord) -> Cow<str> {
|
||||
.replace('\r', "\\r")
|
||||
.into()
|
||||
}
|
||||
|
||||
pub(super) fn convert_str_raw_to_tpl_raw(value: &str) -> Atom {
|
||||
value.replace('`', "\\`").replace('$', "\\$").into()
|
||||
}
|
||||
|
@ -479,7 +479,7 @@ fn fixture(input: PathBuf) {
|
||||
|
||||
let expected = {
|
||||
let expected = read_to_string(dir.join("output.js")).unwrap();
|
||||
let fm = cm.new_source_file(FileName::Anon, expected);
|
||||
let fm = cm.new_source_file(FileName::Custom("expected.js".into()), expected);
|
||||
let lexer = Lexer::new(
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
|
Loading…
Reference in New Issue
Block a user