Skip to content

Commit

Permalink
fix(codegen): print quote correctly for directive (#7735)
Browse files Browse the repository at this point in the history
closes #7734
  • Loading branch information
Boshen committed Dec 9, 2024
1 parent 6f38790 commit b701232
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 12 deletions.
26 changes: 23 additions & 3 deletions crates/oxc_codegen/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,29 @@ impl Gen for Directive<'_> {
// A Use Strict Directive may not contain an EscapeSequence or LineContinuation.
// So here should print original `directive` value, the `expression` value is escaped str.
// See https://github.com/babel/babel/blob/v7.26.2/packages/babel-generator/src/generators/base.ts#L64
p.wrap_quote(|p, _| {
p.print_str(self.directive.as_str());
});
let directive = self.directive.as_str();

let mut chars = directive.chars().peekable();
let mut quote = p.quote;
while let Some(c) = chars.next() {
match c {
'"' => {
quote = b'\'';
break;
}
'\'' => {
quote = b'"';
break;
}
'\\' => {
chars.next();
}
_ => {}
}
}
p.print_ascii_byte(quote);
p.print_str(directive);
p.print_ascii_byte(quote);
p.print_ascii_byte(b';');
p.print_soft_newline();
}
Expand Down
10 changes: 3 additions & 7 deletions crates/oxc_codegen/tests/integration/tester.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,14 @@ use oxc_parser::Parser;
use oxc_span::SourceType;

pub fn test(source_text: &str, expected: &str) {
let source_type = SourceType::jsx();
let allocator = Allocator::default();
let ret = Parser::new(&allocator, source_text, source_type).parse();
let result = CodeGenerator::new().build(&ret.program).code;
assert_eq!(result, expected, "\nfor source: {source_text:?}");
test_options(source_text, expected, CodegenOptions::default());
}

pub fn test_without_source(source_text: &str, expected: &str) {
pub fn test_options(source_text: &str, expected: &str, options: CodegenOptions) {
let source_type = SourceType::jsx();
let allocator = Allocator::default();
let ret = Parser::new(&allocator, source_text, source_type).parse();
let result = CodeGenerator::new().build(&ret.program).code;
let result = CodeGenerator::new().with_options(options).build(&ret.program).code;
assert_eq!(result, expected, "\nfor source: {source_text:?}");
}

Expand Down
16 changes: 14 additions & 2 deletions crates/oxc_codegen/tests/integration/unit.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::tester::{test, test_minify, test_minify_same, test_without_source};
use oxc_codegen::CodegenOptions;

use crate::tester::{test, test_minify, test_minify_same, test_options};

#[test]
fn module_decl() {
Expand Down Expand Up @@ -94,7 +96,6 @@ fn regex() {
fn test_all(source: &str, expect: &str, minify: &str) {
test(source, expect);
test_minify(source, minify);
test_without_source(source, expect);
}
test_all("/regex/giv", "/regex/giv;\n", "/regex/giv;");
test_all(
Expand Down Expand Up @@ -383,3 +384,14 @@ fn big_int_minify() {
test_minify("0xaef_en;", "44798n;");
test_minify("0xaefen;", "44798n;");
}

#[test]
fn directive() {
let single_quote = CodegenOptions { single_quote: true, ..CodegenOptions::default() };
test_options("\"'\"", "\"'\";\n", single_quote.clone());
test_options("'\"'", "'\"';\n", single_quote);
let double_quote = CodegenOptions { single_quote: false, ..CodegenOptions::default() };
test_options("\"'\"", "\"'\";\n", double_quote.clone());
test_options("'\"'", "'\"';\n", double_quote.clone());
test_options(r#""'\"""#, "\"'\\\"\";\n", double_quote);
}

0 comments on commit b701232

Please sign in to comment.