Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 43 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/mako/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ indexmap = "2.0.0"
indicatif = "0.17.8"
md5 = "0.7.0"
mdxjs = "0.1.14"
merge-source-map = "1.2.0"
mime_guess = "2.0.4"
nohash-hasher = "0.2.0"
notify = { version = "6.1.1", default-features = false, features = ["macos_kqueue"] }
notify-debouncer-full = { version = "0.3.1", default-features = false }
parking_lot = { version = "0.12", features = ["nightly"] }
Expand Down
156 changes: 29 additions & 127 deletions crates/mako/src/ast/sourcemap.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::collections::HashMap;
use std::path::PathBuf;

use merge_source_map::sourcemap::SourceMap as MergeSourceMap;
use merge_source_map::{merge, MergeOptions};
use pathdiff::diff_paths;
use swc_core::base::sourcemap as swc_sourcemap;
use swc_core::base::sourcemap;
use swc_core::common::source_map::SourceMapGenConfig;
use swc_core::common::sync::Lrc;
use swc_core::common::{BytePos, FileName, LineCol, SourceMap};
Expand Down Expand Up @@ -33,7 +34,7 @@ pub fn build_source_map_to_buf(mappings: &[(BytePos, LineCol)], cm: &Lrc<SourceM
pub fn build_source_map(
mappings: &[(BytePos, LineCol)],
cm: &Lrc<SourceMap>,
) -> swc_sourcemap::SourceMap {
) -> sourcemap::SourceMap {
let config = SwcSourceMapGenConfig;

cm.build_source_map_with_config(mappings, None, config)
Expand All @@ -44,14 +45,14 @@ pub fn build_source_map(
#[derive(Clone, Default, Debug)]
pub struct RawSourceMap {
pub file: Option<String>,
pub tokens: Vec<swc_sourcemap::RawToken>,
pub tokens: Vec<sourcemap::RawToken>,
pub names: Vec<String>,
pub sources: Vec<String>,
pub sources_content: Vec<Option<String>>,
}

impl From<swc_sourcemap::SourceMap> for RawSourceMap {
fn from(sm: swc_sourcemap::SourceMap) -> Self {
impl From<sourcemap::SourceMap> for RawSourceMap {
fn from(sm: sourcemap::SourceMap) -> Self {
Self {
file: sm.get_file().map(|f| f.to_owned()),
tokens: sm.tokens().map(|t| t.get_raw_token()).collect(),
Expand All @@ -65,7 +66,7 @@ impl From<swc_sourcemap::SourceMap> for RawSourceMap {
}
}

impl From<RawSourceMap> for swc_sourcemap::SourceMap {
impl From<RawSourceMap> for sourcemap::SourceMap {
fn from(rsm: RawSourceMap) -> Self {
Self::new(
rsm.file,
Expand All @@ -77,124 +78,25 @@ impl From<RawSourceMap> for swc_sourcemap::SourceMap {
}
}

pub fn merge_source_map(
target_source_map: swc_sourcemap::SourceMap,
chain_map: HashMap<String, Vec<swc_sourcemap::SourceMap>>,
root: &PathBuf,
) -> swc_sourcemap::SourceMap {
let mut builder = swc_sourcemap::SourceMapBuilder::new(None);
target_source_map.tokens().for_each(|token| {
if let Some(source) = token.get_source() {
let mut final_token = token;
let mut searched_in_chain = true;

if let Some(source_map_chain) = chain_map.get(source)
&& !source_map_chain.is_empty()
{
for map in source_map_chain.iter().rev() {
if let Some(map_token) =
map.lookup_token(token.get_src_line(), token.get_src_col())
{
final_token = map_token;
} else {
searched_in_chain = false;
break;
}
}

if !searched_in_chain {
return;
}

// replace source
let replaced_source = final_token.get_source().map(|src| {
diff_paths(src, root)
.unwrap_or(src.into())
.to_string_lossy()
.to_string()
});

// add mapping
let added_token = builder.add(
token.get_dst_line(),
token.get_dst_col(),
final_token.get_src_line(),
final_token.get_src_col(),
replaced_source.as_deref(),
final_token.get_name(),
);

// add source centent
if !builder.has_source_contents(added_token.src_id) {
let source_content = final_token.get_source_view().map(|view| view.source());

builder.set_source_contents(added_token.src_id, source_content);
}
}
}
});

builder.into_sourcemap()
}

#[cfg(test)]
mod test {
use std::collections::HashMap;
use std::path::PathBuf;
use std::str::FromStr;

use crate::ast::sourcemap::{merge_source_map, swc_sourcemap};

#[test]
fn test_merge() {
let sourcemap1 = r#"{
"version": 3,
"file": "index.js",
"sourceRoot": "",
"sources": [
"index.ts"
],
"names": [],
"mappings": "AAAA,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,CAAC,GAAG,CAAC,iBAAU,IAAI,CAAE,CAAC,CAAC;AAChC,CAAC",
"sourcesContent": [
"function sayHello(name: string) {\n console.log(`Hello, ${name}`);\n}\n"
]
}"#;
let sourcemap2 = r#"{
"version": 3,
"file": "minify.js",
"sourceRoot": "",
"sources": [
"index.ts"
],
"names": [
"sayHello",
"name",
"console",
"log",
"concat"
],
"mappings": "AAAA,SAASA,SAASC,CAAI,EAClBC,QAAQC,GAAG,CAAC,UAAUC,MAAM,CAACH,GACjC",
"sourcesContent": [
"function sayHello(name) {\n console.log(\"Hello, \".concat(name));\n}\n"
]
}"#;

let merged_source_map = merge_source_map(
swc_sourcemap::SourceMap::from_reader(sourcemap2.as_bytes()).unwrap(),
HashMap::<String, Vec<swc_sourcemap::SourceMap>>::from([(
"index.ts".to_string(),
vec![swc_sourcemap::SourceMap::from_reader(sourcemap1.as_bytes()).unwrap()],
)]),
&PathBuf::from_str("./").unwrap(),
);

let mut buf = vec![];

merged_source_map.to_writer(&mut buf).unwrap();

let merged = String::from_utf8(buf).unwrap();

assert!(merged.eq(r#"{"version":3,"sources":["index.ts"],"sourcesContent":["function sayHello(name: string) {\n console.log(`Hello, ${name}`);\n}\n"],"names":[],"mappings":"AAAA,SAAS,SAAS,CAAY,EAC5B,QAAQ,GAAG,CAAC,UAAA,MAAA,CAAU,GACxB"}"#));
}
pub fn merge_source_map(source_map_chain: Vec<Vec<u8>>, root: PathBuf) -> Vec<u8> {
let source_map_chain = source_map_chain
.iter()
.map(|s| MergeSourceMap::from_slice(s).unwrap())
.collect::<Vec<_>>();

let merged = merge(
source_map_chain,
MergeOptions {
source_replacer: Some(Box::new(move |src| {
diff_paths(src, &root)
.unwrap_or(src.into())
.to_string_lossy()
.to_string()
})),
},
);

let mut buf = vec![];
merged.to_writer(&mut buf).unwrap();
buf
}
Loading