Skip to content

Commit d0b78f7

Browse files
committed
feat(codegen): minify whitespace for some expressions (#7671)
part of #7638
1 parent 6ae178e commit d0b78f7

File tree

4 files changed

+44
-26
lines changed

4 files changed

+44
-26
lines changed

crates/oxc_codegen/src/gen.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ impl Gen for ReturnStatement<'_> {
477477
p.print_space_before_identifier();
478478
p.print_str("return");
479479
if let Some(arg) = &self.argument {
480-
p.print_hard_space();
480+
p.print_soft_space();
481481
p.print_expression(arg);
482482
}
483483
p.print_semicolon_after_statement();
@@ -531,7 +531,8 @@ impl Gen for ThrowStatement<'_> {
531531
fn gen(&self, p: &mut Codegen, _ctx: Context) {
532532
p.add_source_mapping(self.span);
533533
p.print_indent();
534-
p.print_str("throw ");
534+
p.print_str("throw");
535+
p.print_soft_space();
535536
p.print_expression(&self.argument);
536537
p.print_semicolon_after_statement();
537538
}
@@ -1316,8 +1317,8 @@ impl Gen for StringLiteral<'_> {
13161317

13171318
impl Gen for ThisExpression {
13181319
fn gen(&self, p: &mut Codegen, _ctx: Context) {
1319-
p.add_source_mapping(self.span);
13201320
p.print_space_before_identifier();
1321+
p.add_source_mapping(self.span);
13211322
p.print_str("this");
13221323
}
13231324
}
@@ -1628,14 +1629,11 @@ impl GenExpr for ArrowFunctionExpression<'_> {
16281629
p.wrap(precedence >= Precedence::Assign, |p| {
16291630
p.print_annotation_comments(self.span.start);
16301631
if self.r#async {
1632+
p.print_space_before_identifier();
16311633
p.add_source_mapping(self.span);
16321634
p.print_str("async");
1635+
p.print_soft_space();
16331636
}
1634-
1635-
if self.r#async {
1636-
p.print_hard_space();
1637-
}
1638-
16391637
if let Some(type_parameters) = &self.type_parameters {
16401638
type_parameters.print(p, ctx);
16411639
}
@@ -1666,8 +1664,8 @@ impl GenExpr for ArrowFunctionExpression<'_> {
16661664
impl GenExpr for YieldExpression<'_> {
16671665
fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, _ctx: Context) {
16681666
p.wrap(precedence >= Precedence::Assign, |p| {
1669-
p.add_source_mapping(self.span);
16701667
p.print_space_before_identifier();
1668+
p.add_source_mapping(self.span);
16711669
p.print_str("yield");
16721670
if self.delegate {
16731671
p.print_ascii_byte(b'*');
@@ -1992,6 +1990,7 @@ impl GenExpr for ImportExpression<'_> {
19921990
|| self.arguments.first().is_some_and(|argument| p.has_comment(argument.span().start));
19931991

19941992
p.wrap(wrap, |p| {
1993+
p.print_space_before_identifier();
19951994
p.add_source_mapping(self.span);
19961995
p.print_str("import(");
19971996
if has_comment {
@@ -2059,6 +2058,7 @@ impl Gen for TaggedTemplateExpression<'_> {
20592058

20602059
impl Gen for Super {
20612060
fn gen(&self, p: &mut Codegen, _ctx: Context) {
2061+
p.print_space_before_identifier();
20622062
p.add_source_mapping(self.span);
20632063
p.print_str("super");
20642064
}
@@ -2067,8 +2067,10 @@ impl Gen for Super {
20672067
impl GenExpr for AwaitExpression<'_> {
20682068
fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
20692069
p.wrap(precedence >= self.precedence(), |p| {
2070+
p.print_space_before_identifier();
20702071
p.add_source_mapping(self.span);
2071-
p.print_str("await ");
2072+
p.print_str("await");
2073+
p.print_soft_space();
20722074
self.argument.print_expr(p, Precedence::Exponentiation, ctx);
20732075
});
20742076
}
@@ -2181,6 +2183,7 @@ impl GenExpr for TSTypeAssertion<'_> {
21812183

21822184
impl Gen for MetaProperty<'_> {
21832185
fn gen(&self, p: &mut Codegen, ctx: Context) {
2186+
p.print_space_before_identifier();
21842187
p.add_source_mapping(self.span);
21852188
self.meta.print(p, ctx);
21862189
p.print_ascii_byte(b'.');
@@ -2198,6 +2201,8 @@ impl Gen for Class<'_> {
21982201
decorator.print(p, ctx);
21992202
p.print_hard_space();
22002203
}
2204+
p.print_space_before_identifier();
2205+
p.add_source_mapping(self.span);
22012206
if self.declare {
22022207
p.print_str("declare ");
22032208
}

crates/oxc_codegen/tests/integration/tester.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,7 @@ pub fn test_minify(source_text: &str, expected: &str) {
2929
.code;
3030
assert_eq!(result, expected, "\nfor minify source: {source_text}");
3131
}
32+
33+
pub fn test_minify_same(source_text: &str) {
34+
test_minify(source_text, source_text);
35+
}

crates/oxc_codegen/tests/integration/unit.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::tester::{test, test_minify, test_without_source};
1+
use crate::tester::{test, test_minify, test_minify_same, test_without_source};
22

33
#[test]
44
fn module_decl() {
@@ -15,6 +15,15 @@ fn expr() {
1515

1616
test("1000000000000000128.0.toFixed(0)", "0xde0b6b3a7640080.toFixed(0);\n");
1717
test_minify("1000000000000000128.0.toFixed(0)", "0xde0b6b3a7640080.toFixed(0);");
18+
19+
test_minify("throw 'foo'", "throw\"foo\";");
20+
test_minify("return 'foo'", "return\"foo\";");
21+
test_minify("return class {}", "return class{};");
22+
test_minify("return async function foo() {}", "return async function foo(){};");
23+
test_minify_same("return super();");
24+
test_minify_same("return new.target;");
25+
test_minify_same("throw await 1;");
26+
test_minify_same("await import(\"\");");
1827
}
1928

2029
#[test]
@@ -121,7 +130,7 @@ fn assignment() {
121130
test_minify("({a,b} = (1, 2))", "({a,b}=(1,2));");
122131
test_minify("a *= yield b", "a*=yield b;");
123132
test_minify("a /= () => {}", "a/=()=>{};");
124-
test_minify("a %= async () => {}", "a%=async ()=>{};");
133+
test_minify("a %= async () => {}", "a%=async()=>{};");
125134
test_minify("a -= (1, 2)", "a-=(1,2);");
126135
test_minify("a >>= b >>= c", "a>>=b>>=c;");
127136
}
@@ -132,11 +141,11 @@ fn r#yield() {
132141
test_minify("function *foo() { yield * a ? b : c }", "function*foo(){yield*a?b:c}");
133142
test_minify("function *foo() { yield * yield * a }", "function*foo(){yield*yield*a}");
134143
test_minify("function *foo() { yield * () => {} }", "function*foo(){yield*()=>{}}");
135-
test_minify("function *foo() { yield * async () => {} }", "function*foo(){yield*async ()=>{}}");
144+
test_minify("function *foo() { yield * async () => {} }", "function*foo(){yield*async()=>{}}");
136145
test_minify("function *foo() { yield a ? b : c }", "function*foo(){yield a?b:c}");
137146
test_minify("function *foo() { yield yield a }", "function*foo(){yield yield a}");
138147
test_minify("function *foo() { yield () => {} }", "function*foo(){yield ()=>{}}");
139-
test_minify("function *foo() { yield async () => {} }", "function*foo(){yield async ()=>{}}");
148+
test_minify("function *foo() { yield async () => {} }", "function*foo(){yield async()=>{}}");
140149
test_minify(
141150
"function *foo() { yield { a } = [ b ] = c ? b : d }",
142151
"function*foo(){yield {a}=[b]=c?b:d}",

tasks/minsize/minsize.snap

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
Original | Minified | esbuild | Gzip | esbuild
22

3-
72.14 kB | 24.12 kB | 23.70 kB | 8.62 kB | 8.54 kB | react.development.js
3+
72.14 kB | 24.09 kB | 23.70 kB | 8.62 kB | 8.54 kB | react.development.js
44

5-
173.90 kB | 61.67 kB | 59.82 kB | 19.54 kB | 19.33 kB | moment.js
5+
173.90 kB | 61.61 kB | 59.82 kB | 19.55 kB | 19.33 kB | moment.js
66

7-
287.63 kB | 92.70 kB | 90.07 kB | 32.26 kB | 31.95 kB | jquery.js
7+
287.63 kB | 92.61 kB | 90.07 kB | 32.27 kB | 31.95 kB | jquery.js
88

9-
342.15 kB | 121.90 kB | 118.14 kB | 44.59 kB | 44.37 kB | vue.js
9+
342.15 kB | 121.79 kB | 118.14 kB | 44.59 kB | 44.37 kB | vue.js
1010

11-
544.10 kB | 73.48 kB | 72.48 kB | 26.12 kB | 26.20 kB | lodash.js
11+
544.10 kB | 73.37 kB | 72.48 kB | 26.13 kB | 26.20 kB | lodash.js
1212

13-
555.77 kB | 276.48 kB | 270.13 kB | 91.15 kB | 90.80 kB | d3.js
13+
555.77 kB | 276.22 kB | 270.13 kB | 91.15 kB | 90.80 kB | d3.js
1414

15-
1.01 MB | 467.59 kB | 458.89 kB | 126.73 kB | 126.71 kB | bundle.min.js
15+
1.01 MB | 467.14 kB | 458.89 kB | 126.74 kB | 126.71 kB | bundle.min.js
1616

17-
1.25 MB | 662.83 kB | 646.76 kB | 164.00 kB | 163.73 kB | three.js
17+
1.25 MB | 662.69 kB | 646.76 kB | 164.02 kB | 163.73 kB | three.js
1818

19-
2.14 MB | 741.55 kB | 724.14 kB | 181.45 kB | 181.07 kB | victory.js
19+
2.14 MB | 740.94 kB | 724.14 kB | 181.49 kB | 181.07 kB | victory.js
2020

21-
3.20 MB | 1.02 MB | 1.01 MB | 332.07 kB | 331.56 kB | echarts.js
21+
3.20 MB | 1.02 MB | 1.01 MB | 332.09 kB | 331.56 kB | echarts.js
2222

23-
6.69 MB | 2.39 MB | 2.31 MB | 496.11 kB | 488.28 kB | antd.js
23+
6.69 MB | 2.39 MB | 2.31 MB | 496.17 kB | 488.28 kB | antd.js
2424

25-
10.95 MB | 3.56 MB | 3.49 MB | 911.20 kB | 915.50 kB | typescript.js
25+
10.95 MB | 3.56 MB | 3.49 MB | 911.37 kB | 915.50 kB | typescript.js
2626

0 commit comments

Comments
 (0)