swc_sourcemap 10.0.0

Forked from https://github.com/getsentry/rust-sourcemap
Documentation
use std::collections::HashMap;

use swc_sourcemap::{DecodedMap, SourceMapIndex};

#[test]
fn test_basic_indexed_sourcemap() {
    let input: &[_] = br#"{
        "version": 3,
        "file": "min.js",
        "sections": [
            {
                "offset": {
                    "line": 0,
                    "column": 0
                },
                "map": {
                    "version":3,
                    "sources":["file1.js"],
                    "names":["add","a","b"],
                    "mappings":"AAAA,QAASA,KAAIC,EAAGC,GACf,YACA,OAAOD,GAAIC",
                    "file":"file1.min.js"
                }
            },
            {
                "offset": {
                    "line": 1,
                    "column": 1
                },
                "map": {
                    "version":3,
                    "sources":["file2.js"],
                    "names":["multiply","a","b","divide","add","c","e","Raven","captureException"],
                    "mappings":"AAAA,QAASA,UAASC,EAAGC,GACpB,YACA,OAAOD,GAAIC,EAEZ,QAASC,QAAOF,EAAGC,GAClB,YACA,KACC,MAAOF,UAASI,IAAIH,EAAGC,GAAID,EAAGC,GAAKG,EAClC,MAAOC,GACRC,MAAMC,iBAAiBF",
                    "file":"file2.min.js"
                }
            }
        ]
    }"#;

    let f1 = "function add(a, b) {\n \"use strict\";\n return a + b; // fôo\n}";
    let f2 = "function multiply(a, b) {\n \"use strict\";\n return a * b;\n}\nfunction divide(a, \
              b) {\n \"use strict\";\n try {\n  return multiply(add(a, b), a, b) / c;\n } catch \
              (e) {\n  Raven.captureException(e);\n }\n}";

    let mut raw_files = HashMap::new();
    raw_files.insert("file1.js", f1);
    raw_files.insert("file2.js", f2);

    let mut files: HashMap<_, Vec<_>> = HashMap::new();
    files.insert("file1.js", f1.lines().collect());
    files.insert("file2.js", f2.lines().collect());

    let mut ism = SourceMapIndex::from_reader(input).unwrap();
    assert!(!ism.is_for_ram_bundle());

    for section_id in 0..ism.get_section_count() {
        let section = ism.get_section_mut(section_id).unwrap();
        let map = match section.get_sourcemap_mut().unwrap() {
            DecodedMap::Regular(sm) => sm,
            _ => panic!("Invalid section type!"),
        };
        let contents = {
            let filename = map.get_source(0).unwrap();
            raw_files[&**filename]
        };
        map.set_source_contents(0, Some(contents.into()));
    }
    let flat_map = ism.flatten().unwrap();

    let mut out: Vec<u8> = vec![];
    flat_map.to_writer(&mut out).ok();
    println!("{}", String::from_utf8(out).unwrap());

    for token in flat_map.tokens() {
        let src = &files[&**token.get_source().unwrap()];
        if let Some(name) = token.get_name() {
            let line = src[token.get_src_line() as usize];
            let idx = token.get_src_col() as usize;
            let span = &line[idx..idx + name.len()];
            assert_eq!(span, name);
        }
    }

    for (src_id, filename) in flat_map.sources().enumerate() {
        let ref_contents = &files[&**filename];
        let contents: Vec<_> = flat_map
            .get_source_contents(src_id as u32)
            .unwrap_or_else(|| panic!("no source for {}", filename))
            .lines()
            .collect();
        assert_eq!(&contents, ref_contents);

        let view = flat_map
            .get_source_view(src_id as u32)
            .unwrap_or_else(|| panic!("no source for {}", filename));
        assert_eq!(&view.lines().collect::<Vec<_>>(), ref_contents);
    }

    assert_eq!(
        ism.lookup_token(0, 0).unwrap().to_tuple(),
        ("file1.js", 0, 0, None)
    );
    assert_eq!(
        ism.lookup_token(1, 0).unwrap().to_tuple(),
        ("file1.js", 2, 12, Some("b"))
    );
    assert_eq!(
        ism.lookup_token(1, 1).unwrap().to_tuple(),
        ("file2.js", 0, 0, None)
    );
    assert_eq!(
        ism.lookup_token(1, 8).unwrap().to_tuple(),
        ("file2.js", 0, 0, None)
    );
    assert_eq!(
        ism.lookup_token(1, 9).unwrap().to_tuple(),
        ("file2.js", 0, 9, Some("multiply"))
    );
}

#[test]
fn test_indexed_sourcemap_for_react_native() {
    let input: &[_] = br#"{
        "version": 3,
        "file": "bla",
        "sections": [
            {
                "offset": {
                    "line": 0,
                    "column": 0
                },
                "map": {
                    "version":3,
                    "sources":["file1.js"],
                    "names":["add","a","b"],
                    "mappings":"AAAA,QAASA,KAAIC,EAAGC,GACf,YACA,OAAOD,GAAIC",
                    "file":"file1.min.js"
                }
            },
            {
                "offset": {
                    "line": 1,
                    "column": 0
                },
                "map": {
                    "version":3,
                    "sources":["file2.js"],
                    "names":["multiply","a","b","divide","add","c","e","Raven","captureException"],
                    "mappings":"AAAA,QAASA,UAASC,EAAGC,GACpB,YACA,OAAOD,GAAIC,EAEZ,QAASC,QAAOF,EAAGC,GAClB,YACA,KACC,MAAOF,UAASI,IAAIH,EAAGC,GAAID,EAAGC,GAAKG,EAClC,MAAOC,GACRC,MAAMC,iBAAiBF",
                    "file":"file2.min.js"
                }
            }
        ],
        "x_facebook_offsets": [],
        "x_metro_module_paths": []
    }"#;

    let ism = SourceMapIndex::from_reader(input).unwrap();
    assert!(ism.is_for_ram_bundle());
}

#[test]
fn test_flatten_indexed_sourcemap_with_ignore_list() {
    let input: &[_] = br#"{
        "version": 3,
        "file": "bla",
        "sections": [
            {
                "offset": {
                    "line": 0,
                    "column": 0
                },
                "map": {
                    "version":3,
                    "sources":["file1.js"],
                    "names":["add","a","b"],
                    "mappings":"AAAA,QAASA,KAAIC,EAAGC,GACf,YACA,OAAOD,GAAIC",
                    "file":"file1.min.js"
                }
            },
            {
                "offset": {
                    "line": 1,
                    "column": 0
                },
                "map": {
                    "version":3,
                    "sources":["file2.js"],
                    "names":["multiply","a","b","divide","add","c","e","Raven","captureException"],
                    "mappings":"AAAA,QAASA,UAASC,EAAGC,GACpB,YACA,OAAOD,GAAIC,EAEZ,QAASC,QAAOF,EAAGC,GAClB,YACA,KACC,MAAOF,UAASI,IAAIH,EAAGC,GAAID,EAAGC,GAAKG,EAClC,MAAOC,GACRC,MAAMC,iBAAiBF",
                    "file":"file2.min.js",
                    "ignoreList": [0]
                }
            }
        ]
    }"#;

    let ism = SourceMapIndex::from_reader(input).unwrap();
    assert_eq!(
        ism.flatten()
            .unwrap()
            .ignore_list()
            .copied()
            .collect::<Vec<u32>>(),
        vec![1]
    );
}