Skip to content

Commit 9130f31

Browse files
authored
Add support for ignoreList property (#93)
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.
1 parent 6bc558e commit 9130f31

File tree

7 files changed

+87
-1
lines changed

7 files changed

+87
-1
lines changed

src/builder.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![cfg_attr(not(any(unix, windows, target_os = "redox")), allow(unused_imports))]
22

3+
use std::collections::BTreeSet;
34
use std::env;
45
use std::fs;
56
use std::io::Read;
@@ -28,6 +29,7 @@ pub struct SourceMapBuilder {
2829
sources: Vec<Arc<str>>,
2930
source_contents: Vec<Option<Arc<str>>>,
3031
sources_mapping: Vec<u32>,
32+
ignore_list: BTreeSet<u32>,
3133
debug_id: Option<DebugId>,
3234
}
3335

@@ -61,6 +63,7 @@ impl SourceMapBuilder {
6163
sources: vec![],
6264
source_contents: vec![],
6365
sources_mapping: vec![],
66+
ignore_list: BTreeSet::default(),
6467
debug_id: None,
6568
}
6669
}
@@ -116,6 +119,10 @@ impl SourceMapBuilder {
116119
self.sources.get(src_id as usize).map(|x| &x[..])
117120
}
118121

122+
pub fn add_to_ignore_list(&mut self, src_id: u32) {
123+
self.ignore_list.insert(src_id);
124+
}
125+
119126
/// Sets the source contents for an already existing source.
120127
pub fn set_source_contents(&mut self, src_id: u32, contents: Option<&str>) {
121128
assert!(src_id != !0, "Cannot set sources for tombstone source id");
@@ -304,6 +311,9 @@ impl SourceMapBuilder {
304311
let mut sm = SourceMap::new(self.file, self.tokens, self.names, self.sources, contents);
305312
sm.set_source_root(self.source_root);
306313
sm.set_debug_id(self.debug_id);
314+
for ignored_src_id in self.ignore_list {
315+
sm.add_to_ignore_list(ignored_src_id);
316+
}
307317

308318
sm
309319
}

src/decoder.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,11 @@ pub fn decode_regular(rsm: RawSourceMap) -> Result<SourceMap> {
254254
let mut sm = SourceMap::new(file, tokens, names, sources, source_content);
255255
sm.set_source_root(rsm.source_root);
256256
sm.set_debug_id(rsm.debug_id);
257+
if let Some(ignore_list) = rsm.ignore_list {
258+
for idx in ignore_list {
259+
sm.add_to_ignore_list(idx);
260+
}
261+
}
257262

258263
Ok(sm)
259264
}

src/encoder.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ impl Encodable for SourceMap {
170170
names: Some(self.names().map(|x| Value::String(x.to_string())).collect()),
171171
range_mappings: serialize_range_mappings(self),
172172
mappings: Some(serialize_mappings(self)),
173+
ignore_list: if self.ignore_list.is_empty() {
174+
None
175+
} else {
176+
Some(self.ignore_list.iter().cloned().collect())
177+
},
173178
x_facebook_offsets: None,
174179
x_metro_module_paths: None,
175180
x_facebook_sources: None,
@@ -203,6 +208,7 @@ impl Encodable for SourceMapIndex {
203208
names: None,
204209
range_mappings: None,
205210
mappings: None,
211+
ignore_list: None,
206212
x_facebook_offsets: None,
207213
x_metro_module_paths: None,
208214
x_facebook_sources: None,

src/jsontypes.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ pub struct RawSourceMap {
4646
pub range_mappings: Option<String>,
4747
#[serde(skip_serializing_if = "Option::is_none")]
4848
pub mappings: Option<String>,
49+
#[serde(rename = "ignoreList", skip_serializing_if = "Option::is_none")]
50+
pub ignore_list: Option<Vec<u32>>,
4951
#[serde(skip_serializing_if = "Option::is_none")]
5052
pub x_facebook_offsets: Option<Vec<Option<u32>>>,
5153
#[serde(skip_serializing_if = "Option::is_none")]

src/types.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::borrow::Cow;
22
use std::cmp::Ordering;
3+
use std::collections::BTreeSet;
34
use std::fmt;
45
use std::io::{Read, Write};
56
use std::path::Path;
@@ -464,6 +465,7 @@ pub struct SourceMap {
464465
pub(crate) sources: Vec<Arc<str>>,
465466
pub(crate) sources_prefixed: Option<Vec<Arc<str>>>,
466467
pub(crate) sources_content: Vec<Option<SourceView>>,
468+
pub(crate) ignore_list: BTreeSet<u32>,
467469
pub(crate) debug_id: Option<DebugId>,
468470
}
469471

@@ -571,6 +573,7 @@ impl SourceMap {
571573
/// - `names`: a vector of names
572574
/// - `sources` a vector of source filenames
573575
/// - `sources_content` optional source contents
576+
/// - `ignore_list` optional list of source indexes for devtools to ignore
574577
pub fn new(
575578
file: Option<Arc<str>>,
576579
mut tokens: Vec<RawToken>,
@@ -591,6 +594,7 @@ impl SourceMap {
591594
.into_iter()
592595
.map(|opt| opt.map(SourceView::new))
593596
.collect(),
597+
ignore_list: BTreeSet::default(),
594598
debug_id: None,
595599
}
596600
}
@@ -651,6 +655,14 @@ impl SourceMap {
651655
}
652656
}
653657

658+
pub fn add_to_ignore_list(&mut self, src_id: u32) {
659+
self.ignore_list.insert(src_id);
660+
}
661+
662+
pub fn ignore_list(&self) -> impl Iterator<Item = &u32> {
663+
self.ignore_list.iter()
664+
}
665+
654666
/// Looks up a token by its index.
655667
pub fn get_token(&self, idx: usize) -> Option<Token<'_>> {
656668
self.tokens.get(idx).map(|raw| Token {
@@ -1201,6 +1213,9 @@ impl SourceMapIndex {
12011213
map.get_source_contents(token.get_src_id()),
12021214
);
12031215
}
1216+
if map.ignore_list.contains(&token.get_src_id()) {
1217+
builder.add_to_ignore_list(raw.src_id);
1218+
}
12041219
}
12051220
}
12061221

tests/test_builder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ fn test_builder_into_sourcemap() {
66
builder.set_source_root(Some("/foo/bar"));
77
builder.add_source("baz.js");
88
builder.add_name("x");
9+
builder.add_to_ignore_list(0);
910

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

15-
let expected = br#"{"version":3,"sources":["baz.js"],"sourceRoot":"/foo/bar","names":["x"],"mappings":""}"#;
16+
let expected = br#"{"version":3,"sources":["baz.js"],"sourceRoot":"/foo/bar","names":["x"],"mappings":"","ignoreList":[0]}"#;
1617
let mut output: Vec<u8> = vec![];
1718
sm.to_writer(&mut output).unwrap();
1819
assert_eq!(output, expected);

tests/test_index.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,50 @@ fn test_indexed_sourcemap_for_react_native() {
158158
let ism = SourceMapIndex::from_reader(input).unwrap();
159159
assert!(ism.is_for_ram_bundle());
160160
}
161+
162+
#[test]
163+
fn test_flatten_indexed_sourcemap_with_ignore_list() {
164+
let input: &[_] = br#"{
165+
"version": 3,
166+
"file": "bla",
167+
"sections": [
168+
{
169+
"offset": {
170+
"line": 0,
171+
"column": 0
172+
},
173+
"map": {
174+
"version":3,
175+
"sources":["file1.js"],
176+
"names":["add","a","b"],
177+
"mappings":"AAAA,QAASA,KAAIC,EAAGC,GACf,YACA,OAAOD,GAAIC",
178+
"file":"file1.min.js"
179+
}
180+
},
181+
{
182+
"offset": {
183+
"line": 1,
184+
"column": 0
185+
},
186+
"map": {
187+
"version":3,
188+
"sources":["file2.js"],
189+
"names":["multiply","a","b","divide","add","c","e","Raven","captureException"],
190+
"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",
191+
"file":"file2.min.js",
192+
"ignoreList": [0]
193+
}
194+
}
195+
]
196+
}"#;
197+
198+
let ism = SourceMapIndex::from_reader(input).unwrap();
199+
assert_eq!(
200+
ism.flatten()
201+
.unwrap()
202+
.ignore_list()
203+
.copied()
204+
.collect::<Vec<u32>>(),
205+
vec![1]
206+
);
207+
}

0 commit comments

Comments
 (0)