diff --git a/bindings/Cargo.lock b/bindings/Cargo.lock index d574a4430d42..c1e528a6d62c 100644 --- a/bindings/Cargo.lock +++ b/bindings/Cargo.lock @@ -714,6 +714,12 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "data-encoding" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" + [[package]] name = "digest" version = "0.10.6" @@ -2252,11 +2258,11 @@ checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" [[package]] name = "sourcemap" -version = "6.2.1" +version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebe057d110ddba043708da3fb010bf562ff6e9d4d60c9ee92860527bcbeccd6" +checksum = "3562681c4e0890af6cd22f09a0eeed4afd855d5011cd5f9358c834b670932382" dependencies = [ - "base64", + "data-encoding", "if_chain", "rustc_version", "serde", @@ -2576,6 +2582,7 @@ dependencies = [ "relative-path", "serde", "serde_json", + "sourcemap", "swc_core", "tracing", "tracing-chrome", diff --git a/bindings/swc_cli/Cargo.toml b/bindings/swc_cli/Cargo.toml index ba3798efc127..88be9b3aedf9 100644 --- a/bindings/swc_cli/Cargo.toml +++ b/bindings/swc_cli/Cargo.toml @@ -26,6 +26,7 @@ rayon = "1" relative-path = "1.6.1" serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["unbounded_depth"] } +sourcemap = "6.2.2" swc_core = { version = "0.59.36", features = [ "trace_macro", "common_concurrent", diff --git a/bindings/swc_cli/src/commands/compile.rs b/bindings/swc_cli/src/commands/compile.rs index 2f2bbc429c19..f517ee19fd29 100644 --- a/bindings/swc_cli/src/commands/compile.rs +++ b/bindings/swc_cli/src/commands/compile.rs @@ -1,4 +1,5 @@ use std::{ + borrow::Cow, fs::{self, File}, io::{self, Read, Write}, path::{Component, Path, PathBuf}, @@ -212,10 +213,22 @@ fn resolve_output_file_path( fn emit_output( mut output: TransformOutput, + source_file_name: &Option, + source_root: &Option, out_dir: &Option, file_path: &Path, file_extension: PathBuf, ) -> anyhow::Result<()> { + let source_map = if let Some(ref source_map) = &output.map { + Some(extend_source_map( + source_map.to_owned(), + source_file_name, + source_root, + )?) + } else { + None + }; + if let Some(out_dir) = out_dir { let output_file_path = resolve_output_file_path(out_dir, file_path, file_extension)?; let output_dir = output_file_path @@ -226,7 +239,7 @@ fn emit_output( fs::create_dir_all(output_dir)?; } - if let Some(source_map) = &output.map { + if let Some(ref source_map) = source_map { let source_map_path = output_file_path.with_extension("js.map"); output.code.push_str("\n//# sourceMappingURL="); @@ -239,16 +252,13 @@ fn emit_output( fs::write(output_file_path, &output.code)?; } else { - println!( - "{}\n{}\n{}", - file_path.display(), - output.code, - output - .map - .as_ref() - .map(|m| m.to_string()) - .unwrap_or_default() - ); + let source_map = if let Some(ref source_map) = source_map { + String::from_utf8_lossy(source_map) + } else { + Cow::Borrowed("") + }; + + println!("{}\n{}\n{}", file_path.display(), output.code, source_map,); }; Ok(()) } @@ -324,6 +334,9 @@ impl CompileOptions { "true" => SourceMapsConfig::Bool(true), value => SourceMapsConfig::Str(value.to_string()), }); + + options.source_file_name = self.source_file_name.to_owned(); + options.source_root = self.source_root.to_owned(); } Ok(options) @@ -469,10 +482,17 @@ impl CompileOptions { buf_srcmap = Some(File::create(map_out_file)?); } + let source_map = extend_source_map( + src_map.to_owned(), + &self.source_file_name, + &self.source_root, + ) + .unwrap(); + buf_srcmap .as_ref() .expect("Srcmap buffer should be available") - .write(src_map.as_bytes()) + .write(&source_map) .and(Ok(()))?; } @@ -498,9 +518,14 @@ impl CompileOptions { let result = execute(compiler, fm, options); match result { - Ok(output) => { - emit_output(output, &self.out_dir, &file_path, file_extension) - } + Ok(output) => emit_output( + output, + &self.source_file_name, + &self.source_root, + &self.out_dir, + &file_path, + file_extension, + ), Err(e) => Err(e), } }, @@ -509,6 +534,31 @@ impl CompileOptions { } } +// TODO: remove once fixed in core https://github.com/swc-project/swc/issues/1388 +fn extend_source_map( + source_map: String, + source_file_name: &Option, + source_root: &Option, +) -> anyhow::Result> { + let mut source_map = sourcemap::SourceMap::from_reader(source_map.as_bytes()) + .context("failed to encode source map")?; + + if let Some(ref source_file_name) = source_file_name { + source_map.set_source(0u32, source_file_name); + } + + if source_root.is_some() { + source_map.set_source_root(source_root.clone()); + } + + let mut buf = vec![]; + source_map + .to_writer(&mut buf) + .context("failed to decode source map")?; + + Ok(buf) +} + #[swc_trace] impl super::CommandRunner for CompileOptions { fn execute(&self) -> anyhow::Result<()> { diff --git a/bindings/swc_cli/src/commands/plugin.rs b/bindings/swc_cli/src/commands/plugin.rs index d4af97cb5e65..83c56efb8732 100644 --- a/bindings/swc_cli/src/commands/plugin.rs +++ b/bindings/swc_cli/src/commands/plugin.rs @@ -202,7 +202,11 @@ build-wasm32 = "build --target wasm32-unknown-unknown" .context("failed to write config toml file")?; // Create package.json for npm package publishing. - let dist_output_path = format!("target/{}/release/{}.wasm", build_target, name.replace("-", "_")); + let dist_output_path = format!( + "target/{}/release/{}.wasm", + build_target, + name.replace("-", "_") + ); fs::write( &path.join("package.json"), format!(