Skip to content

Commit

Permalink
fix: Fix the problem that the inline sourcemap file reports an error …
Browse files Browse the repository at this point in the history
…when inputSourceMap is set to true
  • Loading branch information
guodeshi.gds authored and limerickgds committed Mar 6, 2023
1 parent a504e2a commit 765aa68
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 79 deletions.
174 changes: 95 additions & 79 deletions crates/swc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,99 +269,115 @@ impl Compiler {
self.run(|| -> Result<_, Error> {
let name = &fm.name;

// Load original source map
match input_src_map {
InputSourceMap::Bool(false) => Ok(None),
InputSourceMap::Bool(true) => {
let s = "sourceMappingURL=";
let idx = fm.src.rfind(s);
let src_mapping_url = idx.map(|idx| &fm.src[idx + s.len()..]);

// Load original source map if possible
match &name {
FileName::Real(filename) => {
let dir = match filename.parent() {
let read_inline_sourcemap =
|data_url: Option<&str>| -> Result<Option<sourcemap::SourceMap>, Error> {
match data_url {
Some(data_url) => {
let url = Url::parse(data_url).with_context(|| {
format!("failed to parse inline source map url\n{}", data_url)
})?;

let idx = match url.path().find("base64,") {
Some(v) => v,
None => {
bail!("unexpected: root directory is given as a input file")
}
};

let path = match src_mapping_url {
Some(src_mapping_url) => {
dir.join(src_mapping_url).display().to_string()
}
None => {
format!("{}.map", dir.join(filename).display())
bail!(
"failed to parse inline source map: not base64: {:?}",
url
)
}
};

let file = File::open(&path)
.or_else(|err| {
// Old behavior. This check would prevent regressions.
let f = format!("{}.map", filename.display());
let content = url.path()[idx + "base64,".len()..].trim();

match File::open(&f) {
Ok(v) => Ok(v),
Err(_) => Err(err),
}
})
.context("failed to open input source map file");

let file = if !is_default {
file?
} else {
match file {
Ok(v) => v,
Err(_) => return Ok(None),
}
};
let res = base64::decode_config(
content.as_bytes(),
base64::Config::new(base64::CharacterSet::Standard, true),
)
.context("failed to decode base64-encoded source map")?;

Ok(Some(sourcemap::SourceMap::from_reader(file).with_context(
|| format!("failed to read input source map from file at {}", path),
Ok(Some(sourcemap::SourceMap::from_slice(&res).context(
"failed to read input source map from inlined base64 encoded \
string",
)?))
}
_ => {
tracing::error!("Failed to load source map for non-file input");
Ok(None)
None => {
bail!("failed to parse inline source map: `sourceMappingURL` not found")
}
}
}
InputSourceMap::Str(ref s) => {
if s == "inline" {
const NEEDLE: &str = "sourceMappingURL=";
// Load inline source map by simple string
// operations
let idx = fm.src.rfind(NEEDLE);
let idx = match idx {
None => bail!(
"failed to parse inline source map: `sourceMappingURL` not found"
),
Some(v) => v,
};
let data_url = fm.src[idx + NEEDLE.len()..].trim();
let url = Url::parse(data_url).with_context(|| {
format!("failed to parse inline source map url\n{}", data_url)
})?;

let idx = match url.path().find("base64,") {
Some(v) => v,
None => {
bail!("failed to parse inline source map: not base64: {:?}", url)
}
};
};

let content = url.path()[idx + "base64,".len()..].trim();
let read_sourcemap = || -> Result<Option<sourcemap::SourceMap>, Error> {
let s = "sourceMappingURL=";
let idx = fm.src.rfind(s);
let data_url = idx.map(|idx| &fm.src[idx + s.len()..]);

match read_inline_sourcemap(data_url) {
Ok(r) => Ok(r),
Err(_) => {
// Load original source map if possible
match &name {
FileName::Real(filename) => {
let dir = match filename.parent() {
Some(v) => v,
None => {
bail!("unexpected: root directory is given as a input file")
}
};

let res = base64::decode_config(
content.as_bytes(),
base64::Config::new(base64::CharacterSet::Standard, true),
)
.context("failed to decode base64-encoded source map")?;
let path = match data_url {
Some(data_url) => dir.join(data_url).display().to_string(),
None => {
format!("{}.map", dir.join(filename).display())
}
};

let file = File::open(&path)
.or_else(|err| {
// Old behavior. This check would prevent
// regressions.
let f = format!("{}.map", filename.display());

match File::open(&f) {
Ok(v) => Ok(v),
Err(_) => Err(err),
}
})
.context("failed to open input source map file");

let file = if !is_default {
file?
} else {
match file {
Ok(v) => v,
Err(_) => return Ok(None),
}
};

Ok(Some(sourcemap::SourceMap::from_reader(file).with_context(
|| {
format!(
"failed to read input source map from file at {}",
path
)
},
)?))
}
_ => {
tracing::error!("Failed to load source map for non-file input");
Ok(None)
}
}
}
}
};

Ok(Some(sourcemap::SourceMap::from_slice(&res).context(
"failed to read input source map from inlined base64 encoded string",
)?))
// Load original source map
match input_src_map {
InputSourceMap::Bool(false) => Ok(None),
InputSourceMap::Bool(true) => read_sourcemap(),
InputSourceMap::Str(ref s) => {
if s == "inline" {
read_sourcemap()
} else {
// Load source map passed by user
Ok(Some(
Expand Down
5 changes: 5 additions & 0 deletions crates/swc/tests/source_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ fn file(f: &str, config: Config) -> Result<(), StdErr> {
})
}

#[test]
fn case_inline() {
inline("tests/srcmap/case-inline/index.js");
}

#[test]
fn issue_622() {
file("tests/srcmap/issue-622/index.js", Default::default()).unwrap();
Expand Down
3 changes: 3 additions & 0 deletions crates/swc/tests/srcmap/case-inline/.swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"inputSourceMap": true,
}
26 changes: 26 additions & 0 deletions crates/swc/tests/srcmap/case-inline/index.js

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

0 comments on commit 765aa68

Please sign in to comment.