feat(es/codegen): Support preamble (#7551)

**Related issue:**

 - Closes #7475.
This commit is contained in:
Donny/강동윤 2023-06-20 14:35:46 +09:00 committed by GitHub
parent f27d6ea58c
commit 6e5d8b3cf1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 118 additions and 3 deletions

View File

@ -138,6 +138,7 @@ impl Task for BundleTask {
None,
true,
false,
Default::default(),
)?;
Ok((k, output))

View File

@ -51,6 +51,7 @@ impl Task for PrintTask {
None,
options.config.emit_source_map_columns.into_bool(),
false,
Default::default(),
)
.convert_err()
})
@ -112,6 +113,7 @@ pub fn print_sync(program: String, options: Buffer) -> napi::Result<TransformOut
None,
options.config.emit_source_map_columns.into_bool(),
false,
Default::default(),
)
.convert_err()
})

View File

@ -258,6 +258,7 @@ macro_rules! build_print_sync {
None,
opts.config.emit_source_map_columns.into_bool(),
false,
Default::default(),
),"failed to print code")?;
serde_wasm_bindgen::to_value(&s)

View File

@ -123,6 +123,7 @@ fn bench_codegen(b: &mut Bencher, _target: EsVersion) {
None,
false,
false,
Default::default(),
)
.unwrap()
}));

View File

@ -612,6 +612,15 @@ impl Options {
}
});
let preamble = if !cfg.jsc.output.preamble.is_empty() {
cfg.jsc.output.preamble
} else {
js_minify
.as_ref()
.map(|v| v.format.preamble.clone())
.unwrap_or_default()
};
let pass = PassBuilder::new(
cm,
handler,
@ -842,7 +851,7 @@ impl Options {
comments: comments.cloned(),
preserve_comments,
emit_source_map_columns: cfg.emit_source_map_columns.into_bool(),
output: JscOutputConfig { charset },
output: JscOutputConfig { charset, preamble },
})
}
}
@ -1401,6 +1410,9 @@ pub struct JscConfig {
pub struct JscOutputConfig {
#[serde(default)]
pub charset: Option<OutputCharset>,
#[serde(default)]
pub preamble: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]

View File

@ -506,6 +506,7 @@ impl Compiler {
comments: Option<&dyn Comments>,
emit_source_map_columns: bool,
ascii_only: bool,
preamble: &str,
) -> Result<TransformOutput, Error>
where
T: Node + VisitWith<IdentCollector>,
@ -518,7 +519,7 @@ impl Compiler {
let src = {
let mut buf = vec![];
{
let mut wr = Box::new(swc_ecma_codegen::text_writer::JsWriter::new(
let mut w = swc_ecma_codegen::text_writer::JsWriter::new(
self.cm.clone(),
"\n",
&mut buf,
@ -527,7 +528,9 @@ impl Compiler {
} else {
None
},
)) as Box<dyn WriteJs>;
);
w.preamble(preamble).unwrap();
let mut wr = Box::new(w) as Box<dyn WriteJs>;
if minify {
wr = Box::new(swc_ecma_codegen::text_writer::omit_trailing_semi(wr));
@ -1158,6 +1161,7 @@ impl Compiler {
Some(&comments),
opts.emit_source_map_columns,
opts.format.ascii_only,
&opts.format.preamble,
)
})
}
@ -1236,6 +1240,7 @@ impl Compiler {
.charset
.map(|v| matches!(v, OutputCharset::Ascii))
.unwrap_or(false),
&config.output.preamble,
)
})
}

View File

@ -0,0 +1,5 @@
{
"format": {
"preamble": "/** @license */\n"
}
}

View File

@ -0,0 +1,5 @@
function foo() {
console.log('Foo')
}
foo()

View File

@ -0,0 +1,2 @@
/** @license */
function foo(){console.log("Foo")}foo();

View File

@ -0,0 +1,15 @@
{
"mappings": ";AAAA,SAASA,MACLC,QAAQC,GAAG,CAAC,MAChB,CAEAF",
"names": [
"foo",
"console",
"log"
],
"sources": [
"$DIR/tests/minify/issue-7475/1-with-preamble/input.js"
],
"sourcesContent": [
"function foo() {\n console.log('Foo')\n}\n\nfoo()"
],
"version": 3
}

View File

@ -0,0 +1,3 @@
{
"format": {}
}

View File

@ -0,0 +1,5 @@
function foo() {
console.log('Foo')
}
foo()

View File

@ -0,0 +1 @@
function foo(){console.log("Foo")}foo();

View File

@ -0,0 +1,15 @@
{
"mappings": "AAAA,SAASA,MACLC,QAAQC,GAAG,CAAC,MAChB,CAEAF",
"names": [
"foo",
"console",
"log"
],
"sources": [
"$DIR/tests/minify/issue-7475/2-no-preamble/input.js"
],
"sourcesContent": [
"function foo() {\n console.log('Foo')\n}\n\nfoo()"
],
"version": 3
}

View File

@ -769,6 +769,7 @@ fn should_visit() {
Some(&comments),
config.emit_source_map_columns,
false,
Default::default(),
)
.unwrap()
.code)
@ -1130,3 +1131,36 @@ fn issue_7513_2() {
println!("{}", output.code);
assert_eq!(output.code, "const a={ignoreBOM:!0,fatal:!0};");
}
#[testing::fixture("tests/minify/**/input.js")]
fn minify(input_js: PathBuf) {
let input_dir = input_js.parent().unwrap();
let config_json_path = input_dir.join("config.json");
testing::run_test2(false, |cm, handler| {
let c = Compiler::new(cm);
let fm = c.cm.load_file(&input_js).unwrap();
let mut config: JsMinifyOptions =
serde_json::from_str(&std::fs::read_to_string(&config_json_path).unwrap()).unwrap();
config.source_map = BoolOrDataConfig::from_bool(true);
let output = c.minify(fm, &handler, &config).unwrap();
NormalizedOutput::from(output.code)
.compare_to_file(input_dir.join("output.js"))
.unwrap();
let map = output.map.map(|json| {
let json: serde_json::Value = serde_json::from_str(&json).unwrap();
serde_json::to_string_pretty(&json).unwrap()
});
NormalizedOutput::from(map.unwrap())
.compare_to_file(input_dir.join("output.map"))
.unwrap();
Ok(())
})
.unwrap()
}

View File

@ -46,6 +46,13 @@ impl<'a, W: Write> JsWriter<'a, W> {
}
}
pub fn preamble(&mut self, s: &str) -> Result {
self.raw_write(s)?;
self.update_pos(s);
Ok(())
}
/// Sets the indentation string. Defaults to four spaces.
pub fn set_indent_str(&mut self, indent_str: &'static str) {
self.indent_str = indent_str;

View File

@ -99,6 +99,7 @@ fn pass(input_dir: PathBuf) {
Some(&comments),
false,
false,
Default::default(),
)
.expect("failed to print?")
.code;