Skip to content

Commit

Permalink
Add support for ignoreList property (#93)
Browse files Browse the repository at this point in the history
Sourcemaps can now specify an `ignoreList`, a list of indexes into sources for which those sources should be shown as ignored in dev tools, for example as collapsed stack frames in program stacks.

This adds the list to the SourceMap structure but only includes it in serialized output when it’s non-zero.
  • Loading branch information
wbinnssmith authored Nov 7, 2024
1 parent 6bc558e commit 9130f31
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 1 deletion.
10 changes: 10 additions & 0 deletions src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![cfg_attr(not(any(unix, windows, target_os = "redox")), allow(unused_imports))]

use std::collections::BTreeSet;
use std::env;
use std::fs;
use std::io::Read;
Expand Down Expand Up @@ -28,6 +29,7 @@ pub struct SourceMapBuilder {
sources: Vec<Arc<str>>,
source_contents: Vec<Option<Arc<str>>>,
sources_mapping: Vec<u32>,
ignore_list: BTreeSet<u32>,
debug_id: Option<DebugId>,
}

Expand Down Expand Up @@ -61,6 +63,7 @@ impl SourceMapBuilder {
sources: vec![],
source_contents: vec![],
sources_mapping: vec![],
ignore_list: BTreeSet::default(),
debug_id: None,
}
}
Expand Down Expand Up @@ -116,6 +119,10 @@ impl SourceMapBuilder {
self.sources.get(src_id as usize).map(|x| &x[..])
}

pub fn add_to_ignore_list(&mut self, src_id: u32) {
self.ignore_list.insert(src_id);
}

/// Sets the source contents for an already existing source.
pub fn set_source_contents(&mut self, src_id: u32, contents: Option<&str>) {
assert!(src_id != !0, "Cannot set sources for tombstone source id");
Expand Down Expand Up @@ -304,6 +311,9 @@ impl SourceMapBuilder {
let mut sm = SourceMap::new(self.file, self.tokens, self.names, self.sources, contents);
sm.set_source_root(self.source_root);
sm.set_debug_id(self.debug_id);
for ignored_src_id in self.ignore_list {
sm.add_to_ignore_list(ignored_src_id);
}

sm
}
Expand Down
5 changes: 5 additions & 0 deletions src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,11 @@ pub fn decode_regular(rsm: RawSourceMap) -> Result<SourceMap> {
let mut sm = SourceMap::new(file, tokens, names, sources, source_content);
sm.set_source_root(rsm.source_root);
sm.set_debug_id(rsm.debug_id);
if let Some(ignore_list) = rsm.ignore_list {
for idx in ignore_list {
sm.add_to_ignore_list(idx);
}
}

Ok(sm)
}
Expand Down
6 changes: 6 additions & 0 deletions src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ impl Encodable for SourceMap {
names: Some(self.names().map(|x| Value::String(x.to_string())).collect()),
range_mappings: serialize_range_mappings(self),
mappings: Some(serialize_mappings(self)),
ignore_list: if self.ignore_list.is_empty() {
None
} else {
Some(self.ignore_list.iter().cloned().collect())
},
x_facebook_offsets: None,
x_metro_module_paths: None,
x_facebook_sources: None,
Expand Down Expand Up @@ -203,6 +208,7 @@ impl Encodable for SourceMapIndex {
names: None,
range_mappings: None,
mappings: None,
ignore_list: None,
x_facebook_offsets: None,
x_metro_module_paths: None,
x_facebook_sources: None,
Expand Down
2 changes: 2 additions & 0 deletions src/jsontypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub struct RawSourceMap {
pub range_mappings: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mappings: Option<String>,
#[serde(rename = "ignoreList", skip_serializing_if = "Option::is_none")]
pub ignore_list: Option<Vec<u32>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub x_facebook_offsets: Option<Vec<Option<u32>>>,
#[serde(skip_serializing_if = "Option::is_none")]
Expand Down
15 changes: 15 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::borrow::Cow;
use std::cmp::Ordering;
use std::collections::BTreeSet;
use std::fmt;
use std::io::{Read, Write};
use std::path::Path;
Expand Down Expand Up @@ -464,6 +465,7 @@ pub struct SourceMap {
pub(crate) sources: Vec<Arc<str>>,
pub(crate) sources_prefixed: Option<Vec<Arc<str>>>,
pub(crate) sources_content: Vec<Option<SourceView>>,
pub(crate) ignore_list: BTreeSet<u32>,
pub(crate) debug_id: Option<DebugId>,
}

Expand Down Expand Up @@ -571,6 +573,7 @@ impl SourceMap {
/// - `names`: a vector of names
/// - `sources` a vector of source filenames
/// - `sources_content` optional source contents
/// - `ignore_list` optional list of source indexes for devtools to ignore
pub fn new(
file: Option<Arc<str>>,
mut tokens: Vec<RawToken>,
Expand All @@ -591,6 +594,7 @@ impl SourceMap {
.into_iter()
.map(|opt| opt.map(SourceView::new))
.collect(),
ignore_list: BTreeSet::default(),
debug_id: None,
}
}
Expand Down Expand Up @@ -651,6 +655,14 @@ impl SourceMap {
}
}

pub fn add_to_ignore_list(&mut self, src_id: u32) {
self.ignore_list.insert(src_id);
}

pub fn ignore_list(&self) -> impl Iterator<Item = &u32> {
self.ignore_list.iter()
}

/// Looks up a token by its index.
pub fn get_token(&self, idx: usize) -> Option<Token<'_>> {
self.tokens.get(idx).map(|raw| Token {
Expand Down Expand Up @@ -1201,6 +1213,9 @@ impl SourceMapIndex {
map.get_source_contents(token.get_src_id()),
);
}
if map.ignore_list.contains(&token.get_src_id()) {
builder.add_to_ignore_list(raw.src_id);
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion tests/test_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ fn test_builder_into_sourcemap() {
builder.set_source_root(Some("/foo/bar"));
builder.add_source("baz.js");
builder.add_name("x");
builder.add_to_ignore_list(0);

let sm = builder.into_sourcemap();
assert_eq!(sm.get_source_root(), Some("/foo/bar"));
assert_eq!(sm.get_source(0), Some("/foo/bar/baz.js"));
assert_eq!(sm.get_name(0), Some("x"));

let expected = br#"{"version":3,"sources":["baz.js"],"sourceRoot":"/foo/bar","names":["x"],"mappings":""}"#;
let expected = br#"{"version":3,"sources":["baz.js"],"sourceRoot":"/foo/bar","names":["x"],"mappings":"","ignoreList":[0]}"#;
let mut output: Vec<u8> = vec![];
sm.to_writer(&mut output).unwrap();
assert_eq!(output, expected);
Expand Down
47 changes: 47 additions & 0 deletions tests/test_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,50 @@ fn test_indexed_sourcemap_for_react_native() {
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]
);
}

0 comments on commit 9130f31

Please sign in to comment.