feat(codegen): minify string with backtick when needed (#8095)

This commit is contained in:
Boshen 2024-12-24 13:39:31 +00:00
parent ad2a620d61
commit 0562830549
3 changed files with 39 additions and 20 deletions

View file

@ -1375,31 +1375,27 @@ fn print_unquoted_str(s: &str, quote: u8, p: &mut Codegen) {
}
'\'' => {
if quote == b'\'' {
p.print_str("\\'");
} else {
p.print_str("'");
p.print_ascii_byte(b'\\');
}
p.print_ascii_byte(b'\'');
}
'\"' => {
if quote == b'"' {
p.print_str("\\\"");
} else {
p.print_str("\"");
p.print_ascii_byte(b'\\');
}
p.print_ascii_byte(b'"');
}
'`' => {
if quote == b'`' {
p.print_str("\\`");
} else {
p.print_str("`");
p.print_ascii_byte(b'\\');
}
p.print_ascii_byte(b'`');
}
'$' => {
if chars.peek().is_some_and(|&next| next == '{') {
p.print_str("\\$");
} else {
p.print_str("$");
if chars.peek() == Some(&'{') {
p.print_ascii_byte(b'\\');
}
p.print_ascii_byte(b'$');
}
// Allow `U+2028` and `U+2029` in string literals
// <https://tc39.es/proposal-json-superset>
@ -1424,22 +1420,40 @@ impl Gen for StringLiteral<'_> {
let quote = if p.options.minify {
let mut single_cost: u32 = 0;
let mut double_cost: u32 = 0;
for b in s.as_bytes() {
let mut backtick_cost: u32 = 0;
let mut bytes = s.as_bytes().iter().peekable();
while let Some(b) = bytes.next() {
match b {
b'\n' if p.options.minify => {
backtick_cost = backtick_cost.saturating_sub(1);
}
b'\'' => {
single_cost += 1;
}
b'"' => {
double_cost += 1;
}
b'`' => {
backtick_cost += 1;
}
b'$' => {
if bytes.peek() == Some(&&b'{') {
backtick_cost += 1;
}
}
_ => {}
}
}
let mut quote = b'"';
if double_cost > single_cost {
b'\''
} else {
b'"'
quote = b'\'';
if single_cost > backtick_cost {
quote = b'`';
}
} else if double_cost > backtick_cost {
quote = b'`';
}
quote
} else {
p.quote
};

View file

@ -38,6 +38,11 @@ fn expr() {
test("delete 2e308", "delete (0, Infinity);\n");
test_minify("delete 2e308", "delete(1/0);");
test_minify(
r#";'eval("\'\\vstr\\ving\\v\'") === "\\vstr\\ving\\v"'"#,
r#";`eval("'\\vstr\\ving\\v'") === "\\vstr\\ving\\v"`;"#,
);
}
#[test]

View file

@ -5,7 +5,7 @@ Original | minified | minified | gzip | gzip | Fixture
173.90 kB | 61.55 kB | 59.82 kB | 19.54 kB | 19.33 kB | moment.js
287.63 kB | 92.60 kB | 90.07 kB | 32.27 kB | 31.95 kB | jquery.js
287.63 kB | 92.59 kB | 90.07 kB | 32.28 kB | 31.95 kB | jquery.js
342.15 kB | 121.55 kB | 118.14 kB | 44.64 kB | 44.37 kB | vue.js
@ -21,7 +21,7 @@ Original | minified | minified | gzip | gzip | Fixture
3.20 MB | 1.02 MB | 1.01 MB | 332.00 kB | 331.56 kB | echarts.js
6.69 MB | 2.39 MB | 2.31 MB | 495.63 kB | 488.28 kB | antd.js
6.69 MB | 2.39 MB | 2.31 MB | 495.62 kB | 488.28 kB | antd.js
10.95 MB | 3.54 MB | 3.49 MB | 909.72 kB | 915.50 kB | typescript.js
10.95 MB | 3.54 MB | 3.49 MB | 909.73 kB | 915.50 kB | typescript.js