Skip to content

Commit

Permalink
feat(codegen): balance string quotes when minify whitespace (#8072)
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Dec 23, 2024
1 parent 0b04288 commit 373279b
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 36 deletions.
30 changes: 27 additions & 3 deletions crates/oxc_codegen/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1414,9 +1414,33 @@ impl Gen for StringLiteral<'_> {
fn gen(&self, p: &mut Codegen, _ctx: Context) {
p.add_source_mapping(self.span);
let s = self.value.as_str();
p.wrap_quote(|p, quote| {
print_unquoted_str(s, quote, p);
});

let quote = if p.options.minify {
let mut single_cost: u32 = 0;
let mut double_cost: u32 = 0;
for b in s.as_bytes() {
match b {
b'\'' => {
single_cost += 1;
}
b'"' => {
double_cost += 1;
}
_ => {}
}
}
if double_cost > single_cost {
b'\''
} else {
b'"'
}
} else {
p.quote
};

p.print_ascii_byte(quote);
print_unquoted_str(s, quote, p);
p.print_ascii_byte(quote);
}
}

Expand Down
7 changes: 0 additions & 7 deletions crates/oxc_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,13 +636,6 @@ impl<'a> Codegen<'a> {
}
}

#[inline]
fn wrap_quote<F: FnMut(&mut Self, u8)>(&mut self, mut f: F) {
self.print_ascii_byte(self.quote);
f(self, self.quote);
self.print_ascii_byte(self.quote);
}

fn add_source_mapping(&mut self, span: Span) {
if span == SPAN {
return;
Expand Down
32 changes: 16 additions & 16 deletions crates/oxc_codegen/tests/integration/snapshots/minify.snap
Original file line number Diff line number Diff line change
Expand Up @@ -11,71 +11,71 @@ function foo<T extends string>(x: T, y: string, ...restOfParams: Omit<T, 'x'>):
return x;
}
----------
function foo<T extends string>(x:T,y:string,...restOfParams:Omit<T,'x'>): T{return x}
function foo<T extends string>(x:T,y:string,...restOfParams:Omit<T,"x">): T{return x}
########## 2
let x: string[] = ['abc', 'def', 'ghi'];
----------
let x:string[]=['abc','def','ghi'];
let x:string[]=["abc","def","ghi"];
########## 3
let x: Array<string> = ['abc', 'def', 'ghi',];
----------
let x:Array<string>=['abc','def','ghi'];
let x:Array<string>=["abc","def","ghi"];
########## 4
let x: [string, number] = ['abc', 123];
----------
let x:[string,number]=['abc',123];
let x:[string,number]=["abc",123];
########## 5
let x: string | number = 'abc';
----------
let x:string|number='abc';
let x:string|number="abc";
########## 6
let x: string & number = 'abc';
----------
let x:string&number='abc';
let x:string&number="abc";
########## 7
let x: typeof String = 'string';
----------
let x:typeof String='string';
let x:typeof String="string";
########## 8
let x: keyof string = 'length';
----------
let x:keyof string='length';
let x:keyof string="length";
########## 9
let x: keyof typeof String = 'length';
----------
let x:keyof typeof String='length';
let x:keyof typeof String="length";
########## 10
let x: string['length'] = 123;
----------
let x:string['length']=123;
let x:string["length"]=123;
########## 11
function isString(value: unknown): asserts value is string {
if (typeof value !== 'string') {
throw new Error('Not a string');
}
}
----------
function isString(value:unknown): asserts value is string{if(typeof value!=='string'){throw new Error('Not a string')}}
function isString(value:unknown): asserts value is string{if(typeof value!=="string"){throw new Error("Not a string")}}
########## 12
import type { Foo } from 'foo';
----------
import type{Foo}from'foo';
import type{Foo}from"foo";
########## 13
import { Foo, type Bar } from 'foo';
----------
import{Foo,type Bar}from'foo';
import{Foo,type Bar}from"foo";
########## 14
export { Foo, type Bar } from 'foo';
----------
export{Foo,type Bar}from'foo';
export{Foo,type Bar}from"foo";
########## 15
type A<T> = { [K in keyof T as K extends string ? B<K> : K ]: T[K] }
----------
type A<T>={[K in keyof T as K extends string ? B<K> : K]:T[K]};
########## 16
class A {readonly type = 'frame'}
----------
class A{readonly type='frame'}
class A{readonly type="frame"}
########## 17
let foo: { <T>(t: T): void }
----------
Expand Down Expand Up @@ -196,4 +196,4 @@ export { default, /* …, */ } from "module-name";
export { default as name16 } from "module-name";

----------
import defaultExport from'module-name';import*as name from'module-name';import{export1}from'module-name';import{export1 as alias1}from'module-name';import{default as alias}from'module-name';import{export1,export2}from'module-name';import{export1,export2 as alias2}from'module-name';import{'string name' as alias}from'module-name';import defaultExport,{export1}from'module-name';import defaultExport,*as name from'module-name';import'module-name';import{}from"mod";export let name1,name2;export const name3=1,name4=2;export function functionName(){}export class ClassName{}export function*generatorFunctionName(){}export const {name5,name2:bar}=o;export const [name6,name7]=array;export{name8,name81};export{variable1 as name9,variable2 as name10,name82};export{variable1 as 'string name'};export{name1 as default1};export*from'module-name';export*as name11 from'module-name';export{name12,nameN}from'module-name';export{import1 as name13,import2 as name14,name15}from'module-name';export{default}from'module-name';export{default as name16}from'module-name';
import defaultExport from"module-name";import*as name from"module-name";import{export1}from"module-name";import{export1 as alias1}from"module-name";import{default as alias}from"module-name";import{export1,export2}from"module-name";import{export1,export2 as alias2}from"module-name";import{"string name" as alias}from"module-name";import defaultExport,{export1}from"module-name";import defaultExport,*as name from"module-name";import"module-name";import{}from"mod";export let name1,name2;export const name3=1,name4=2;export function functionName(){}export class ClassName{}export function*generatorFunctionName(){}export const {name5,name2:bar}=o;export const [name6,name7]=array;export{name8,name81};export{variable1 as name9,variable2 as name10,name82};export{variable1 as "string name"};export{name1 as default1};export*from"module-name";export*as name11 from"module-name";export{name12,nameN}from"module-name";export{import1 as name13,import2 as name14,name15}from"module-name";export{default}from"module-name";export{default as name16}from"module-name";
20 changes: 10 additions & 10 deletions tasks/minsize/minsize.snap
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
| Oxc | ESBuild | Oxc | ESBuild |
Original | minified | minified | gzip | gzip | Fixture
-------------------------------------------------------------------------------------
72.14 kB | 24.05 kB | 23.70 kB | 8.61 kB | 8.54 kB | react.development.js
72.14 kB | 24.04 kB | 23.70 kB | 8.61 kB | 8.54 kB | react.development.js

173.90 kB | 61.60 kB | 59.82 kB | 19.55 kB | 19.33 kB | moment.js
173.90 kB | 61.60 kB | 59.82 kB | 19.54 kB | 19.33 kB | moment.js

287.63 kB | 92.61 kB | 90.07 kB | 32.27 kB | 31.95 kB | jquery.js

342.15 kB | 121.77 kB | 118.14 kB | 44.58 kB | 44.37 kB | vue.js
342.15 kB | 121.57 kB | 118.14 kB | 44.64 kB | 44.37 kB | vue.js

544.10 kB | 73.37 kB | 72.48 kB | 26.13 kB | 26.20 kB | lodash.js
544.10 kB | 73.37 kB | 72.48 kB | 26.14 kB | 26.20 kB | lodash.js

555.77 kB | 276.22 kB | 270.13 kB | 91.15 kB | 90.80 kB | d3.js
555.77 kB | 276.21 kB | 270.13 kB | 91.16 kB | 90.80 kB | d3.js

1.01 MB | 467.14 kB | 458.89 kB | 126.74 kB | 126.71 kB | bundle.min.js
1.01 MB | 467.13 kB | 458.89 kB | 126.76 kB | 126.71 kB | bundle.min.js

1.25 MB | 662.66 kB | 646.76 kB | 164.00 kB | 163.73 kB | three.js
1.25 MB | 662.63 kB | 646.76 kB | 164.01 kB | 163.73 kB | three.js

2.14 MB | 740.54 kB | 724.14 kB | 181.37 kB | 181.07 kB | victory.js
2.14 MB | 740.53 kB | 724.14 kB | 181.38 kB | 181.07 kB | victory.js

3.20 MB | 1.02 MB | 1.01 MB | 332.09 kB | 331.56 kB | echarts.js
3.20 MB | 1.02 MB | 1.01 MB | 332.11 kB | 331.56 kB | echarts.js

6.69 MB | 2.39 MB | 2.31 MB | 495.63 kB | 488.28 kB | antd.js

10.95 MB | 3.55 MB | 3.49 MB | 909.67 kB | 915.50 kB | typescript.js
10.95 MB | 3.55 MB | 3.49 MB | 909.73 kB | 915.50 kB | typescript.js

0 comments on commit 373279b

Please sign in to comment.