Skip to content

Commit 6a94e3f

Browse files
committed
fix(codegen): fixes for esbuild test cases (#4503)
1 parent b1b66e2 commit 6a94e3f

File tree

13 files changed

+811
-930
lines changed

13 files changed

+811
-930
lines changed

crates/oxc_codegen/src/gen.rs

Lines changed: 86 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,13 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Program<'a> {
4343
if let Some(hashbang) = &self.hashbang {
4444
hashbang.gen(p, ctx);
4545
}
46-
p.print_directives_and_statements(Some(&self.directives), &self.body, ctx);
46+
for directive in &self.directives {
47+
directive.gen(p, ctx);
48+
}
49+
for stmt in &self.body {
50+
stmt.gen(p, ctx);
51+
p.print_semicolon_if_needed();
52+
}
4753
}
4854
}
4955

@@ -64,7 +70,8 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Directive<'a> {
6470
p.wrap_quote(|p, _| {
6571
p.print_str(self.directive.as_str());
6672
});
67-
p.print_semicolon_after_statement();
73+
p.print_char(b';');
74+
p.print_soft_newline();
6875
}
6976
}
7077

@@ -112,9 +119,9 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Statement<'a> {
112119
decl.gen(p, ctx);
113120
p.print_soft_newline();
114121
}
115-
Self::UsingDeclaration(declaration) => {
122+
Self::UsingDeclaration(decl) => {
116123
p.print_indent();
117-
declaration.gen(p, ctx);
124+
decl.gen(p, ctx);
118125
p.print_semicolon_after_statement();
119126
}
120127
Self::TSModuleDeclaration(decl) => {
@@ -560,11 +567,9 @@ impl<const MINIFY: bool> Gen<MINIFY> for DebuggerStatement {
560567
impl<'a, const MINIFY: bool> Gen<MINIFY> for UsingDeclaration<'a> {
561568
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
562569
if self.is_await {
563-
p.print_str("await");
564-
p.print_soft_space();
570+
p.print_str("await ");
565571
}
566-
p.print_str("using");
567-
p.print_soft_space();
572+
p.print_str("using ");
568573
p.print_list(&self.declarations, ctx);
569574
}
570575
}
@@ -665,7 +670,13 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Function<'a> {
665670
impl<'a, const MINIFY: bool> Gen<MINIFY> for FunctionBody<'a> {
666671
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
667672
p.print_curly_braces(self.span, self.is_empty(), |p| {
668-
p.print_directives_and_statements(Some(&self.directives), &self.statements, ctx);
673+
for directive in &self.directives {
674+
directive.gen(p, ctx);
675+
}
676+
for stmt in &self.statements {
677+
p.print_semicolon_if_needed();
678+
stmt.gen(p, ctx);
679+
}
669680
});
670681
p.needs_semicolon = false;
671682
}
@@ -711,9 +722,9 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ImportDeclaration<'a> {
711722
p.print_soft_space();
712723
p.print_str("from");
713724
p.print_soft_space();
714-
p.print_char(b'\'');
725+
p.print_char(b'"');
715726
p.print_str(self.source.value.as_str());
716-
p.print_char(b'\'');
727+
p.print_char(b'"');
717728
if self.with_clause.is_some() {
718729
p.print_hard_space();
719730
}
@@ -996,7 +1007,10 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportDefaultDeclarationKind<'a> {
9961007
self.to_expression().gen_expr(p, Precedence::Assign, Context::default());
9971008
p.print_semicolon_after_statement();
9981009
}
999-
Self::FunctionDeclaration(fun) => fun.gen(p, ctx),
1010+
Self::FunctionDeclaration(fun) => {
1011+
fun.gen(p, ctx);
1012+
p.print_soft_newline();
1013+
}
10001014
Self::ClassDeclaration(class) => {
10011015
class.gen(p, ctx);
10021016
p.print_soft_newline();
@@ -1477,23 +1491,36 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ArrayExpression<'a> {
14771491
impl<'a, const MINIFY: bool> GenExpr<MINIFY> for ObjectExpression<'a> {
14781492
fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, _precedence: Precedence, ctx: Context) {
14791493
let n = p.code_len();
1480-
p.wrap(p.start_of_stmt == n || p.start_of_arrow_expr == n, |p| {
1481-
let single_line = self.properties.len() <= 1;
1482-
p.print_curly_braces(self.span, single_line, |p| {
1483-
for (index, item) in self.properties.iter().enumerate() {
1484-
if index != 0 {
1485-
p.print_comma();
1486-
p.print_soft_newline();
1487-
}
1488-
if !single_line {
1489-
p.print_indent();
1490-
}
1491-
item.gen(p, ctx);
1494+
let len = self.properties.len();
1495+
let is_multi_line = len > 1;
1496+
let wrap = p.start_of_stmt == n || p.start_of_arrow_expr == n;
1497+
p.wrap(wrap, |p| {
1498+
p.add_source_mapping(self.span.start);
1499+
p.print_char(b'{');
1500+
if is_multi_line {
1501+
p.indent();
1502+
}
1503+
for (i, item) in self.properties.iter().enumerate() {
1504+
if i != 0 {
1505+
p.print_comma();
14921506
}
1493-
if !single_line {
1507+
if is_multi_line {
14941508
p.print_soft_newline();
1509+
p.print_indent();
1510+
} else {
1511+
p.print_soft_space();
14951512
}
1496-
});
1513+
item.gen(p, ctx);
1514+
}
1515+
if is_multi_line {
1516+
p.print_soft_newline();
1517+
p.dedent();
1518+
p.print_indent();
1519+
} else if len > 0 {
1520+
p.print_soft_space();
1521+
}
1522+
p.add_source_mapping(self.span.end);
1523+
p.print_char(b'}');
14971524
});
14981525
}
14991526
}
@@ -1555,7 +1582,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ObjectProperty<'a> {
15551582
let mut shorthand = false;
15561583
if let PropertyKey::StaticIdentifier(key) = &self.key {
15571584
if let Expression::Identifier(ident) = self.value.without_parenthesized() {
1558-
if key.name == p.get_identifier_reference_name(ident) {
1585+
if key.name == p.get_identifier_reference_name(ident) && key.name != "__proto__" {
15591586
shorthand = true;
15601587
}
15611588
}
@@ -1981,7 +2008,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for AssignmentTargetRest<'a> {
19812008
impl<'a, const MINIFY: bool> GenExpr<MINIFY> for SequenceExpression<'a> {
19822009
fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, _ctx: Context) {
19832010
p.wrap(precedence > self.precedence(), |p| {
1984-
p.print_expressions(&self.expressions, Precedence::Assign, Context::default());
2011+
p.print_expressions(&self.expressions, Precedence::Comma, Context::default());
19852012
});
19862013
}
19872014
}
@@ -2278,17 +2305,17 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for JSXAttributeItem<'a> {
22782305
impl<'a, const MINIFY: bool> Gen<MINIFY> for JSXOpeningElement<'a> {
22792306
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
22802307
p.add_source_mapping(self.span.start);
2281-
p.print_str("<");
2308+
p.print_char(b'<');
22822309
self.name.gen(p, ctx);
22832310
for attr in &self.attributes {
22842311
p.print_hard_space();
22852312
attr.gen(p, ctx);
22862313
}
22872314
if self.self_closing {
2288-
p.print_str("/>");
2289-
} else {
2290-
p.print_char(b'>');
2315+
p.print_soft_space();
2316+
p.print_str("/");
22912317
}
2318+
p.print_char(b'>');
22922319
}
22932320
}
22942321

@@ -2490,9 +2517,12 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for AccessorProperty<'a> {
24902517
if self.r#static {
24912518
p.print_str("static ");
24922519
}
2493-
p.print_str("accessor ");
2520+
p.print_str("accessor");
24942521
if self.computed {
2522+
p.print_soft_space();
24952523
p.print_char(b'[');
2524+
} else {
2525+
p.print_hard_space();
24962526
}
24972527
self.key.gen(p, ctx);
24982528
if self.computed {
@@ -2559,10 +2589,22 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for BindingProperty<'a> {
25592589

25602590
let mut shorthand = false;
25612591
if let PropertyKey::StaticIdentifier(key) = &self.key {
2562-
if let BindingPatternKind::BindingIdentifier(ident) = &self.value.kind {
2563-
if key.name == p.get_binding_identifier_name(ident) {
2592+
match &self.value.kind {
2593+
BindingPatternKind::BindingIdentifier(ident)
2594+
if key.name == p.get_binding_identifier_name(ident) =>
2595+
{
25642596
shorthand = true;
25652597
}
2598+
BindingPatternKind::AssignmentPattern(assignment_pattern) => {
2599+
if let BindingPatternKind::BindingIdentifier(ident) =
2600+
&assignment_pattern.left.kind
2601+
{
2602+
if key.name == p.get_binding_identifier_name(ident) {
2603+
shorthand = true;
2604+
}
2605+
}
2606+
}
2607+
_ => {}
25662608
}
25672609
}
25682610

@@ -2595,9 +2637,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ArrayPattern<'a> {
25952637
for (index, item) in self.elements.iter().enumerate() {
25962638
if index != 0 {
25972639
p.print_comma();
2598-
if item.is_some() {
2599-
p.print_soft_space();
2600-
}
2640+
p.print_soft_space();
26012641
}
26022642
if let Some(item) = item {
26032643
item.gen(p, ctx);
@@ -3365,8 +3405,15 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSModuleBlock<'a> {
33653405
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
33663406
let is_empty = self.directives.is_empty() && self.body.is_empty();
33673407
p.print_curly_braces(self.span, is_empty, |p| {
3368-
p.print_directives_and_statements(Some(&self.directives), &self.body, ctx);
3408+
for directive in &self.directives {
3409+
directive.gen(p, ctx);
3410+
}
3411+
for stmt in &self.body {
3412+
p.print_semicolon_if_needed();
3413+
stmt.gen(p, ctx);
3414+
}
33693415
});
3416+
p.needs_semicolon = false;
33703417
}
33713418
}
33723419

crates/oxc_codegen/src/lib.rs

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ use std::{borrow::Cow, ops::Range};
1414
use rustc_hash::FxHashMap;
1515

1616
use oxc_ast::{
17-
ast::{
18-
BindingIdentifier, BlockStatement, Directive, Expression, IdentifierReference, Program,
19-
Statement,
20-
},
17+
ast::{BindingIdentifier, BlockStatement, Expression, IdentifierReference, Program, Statement},
2118
Comment, Trivias,
2219
};
2320
use oxc_mangler::Mangler;
@@ -392,7 +389,10 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
392389

393390
fn print_block_statement(&mut self, stmt: &BlockStatement<'_>, ctx: Context) {
394391
self.print_curly_braces(stmt.span, stmt.body.is_empty(), |p| {
395-
p.print_directives_and_statements(None, &stmt.body, ctx);
392+
for stmt in &stmt.body {
393+
p.print_semicolon_if_needed();
394+
stmt.gen(p, ctx);
395+
}
396396
});
397397
self.needs_semicolon = false;
398398
}
@@ -500,33 +500,6 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
500500
self.print_char(self.quote);
501501
}
502502

503-
fn print_directives_and_statements(
504-
&mut self,
505-
directives: Option<&[Directive]>,
506-
statements: &[Statement<'_>],
507-
ctx: Context,
508-
) {
509-
if let Some(directives) = directives {
510-
if directives.is_empty() {
511-
if let Some(Statement::ExpressionStatement(s)) = statements.first() {
512-
if matches!(s.expression.get_inner_expression(), Expression::StringLiteral(_)) {
513-
self.print_semicolon();
514-
self.print_soft_newline();
515-
}
516-
}
517-
} else {
518-
for directive in directives {
519-
directive.gen(self, ctx);
520-
self.print_semicolon_if_needed();
521-
}
522-
}
523-
}
524-
for stmt in statements {
525-
self.print_semicolon_if_needed();
526-
stmt.gen(self, ctx);
527-
}
528-
}
529-
530503
fn add_source_mapping(&mut self, position: u32) {
531504
if let Some(sourcemap_builder) = self.sourcemap_builder.as_mut() {
532505
sourcemap_builder.add_source_mapping(&self.code, position, None);

0 commit comments

Comments
 (0)