Skip to content

Sourcemap parsing incorrectly prefixes sources with sourceRoot #75

@loewenheim

Description

@loewenheim

When we parse a sourcemap, we prefix the sources with the sourceRoot under some circumstances:

let x = x.unwrap_or_default();
let is_valid = !x.is_empty()
&& (x.starts_with('/')
|| x.starts_with("http:")
|| x.starts_with("https:"));
if is_valid {
x
} else {
format!("{source_root}/{x}")
}

This is a problem because in the parsed sourcemap each source is now prefixed, but the sourceRoot field is also still around. This means that when we write the sourcemap out, the prefix is duplicated. Reading the sourcemap again then prepends another copy of the prefix to each source, and so on.

For a simple example, consider the test

#[test]
fn test_roundtrip() {
    let sm = br#"{
        "version": 3,
        "file": "foo.js",
        "sources": [
            "./bar.js",
            "./baz.js"
        ],
        "sourceRoot": "webpack:///",
        "sourcesContent": [null, null],
        "names": [],
        "mappings": ""
    }"#;

    let sm = SourceMap::from_slice(sm).unwrap();
    let mut out = Vec::new();
    sm.to_writer(&mut out).unwrap();

    let sm_new = SourceMap::from_slice(&out).unwrap();
    assert_eq!(sm_new.sources, sm.sources);
}

It fails with

assertion `left == right` failed
  left: ["webpack:///webpack:///./bar.js", "webpack:///webpack:///./baz.js"]
 right: ["webpack:///./bar.js", "webpack:///./baz.js"]

Metadata

Metadata

Assignees

Labels

No labels
No labels
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions