Skip to content

Commit 3b3ef84

Browse files
kdy1claude
andcommitted
Merge upstream/master into main
Integrate changes from upstream getsentry/rust-sourcemap v9.3.0 release: - Update CHANGELOG.md with upstream changes - Merge improvements to decoder, encoder, and type definitions - Update test suite with upstream enhancements Conflicts resolved by keeping swc-project fork modifications: - Cargo.toml: Maintain package name as 'swc_sourcemap' and current version - src/sourceview.rs: Keep BytesStr-based implementation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
2 parents 64fcb47 + e293721 commit 3b3ef84

File tree

8 files changed

+179
-59
lines changed

8 files changed

+179
-59
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Changelog
22

3+
## 9.3.0
4+
5+
### New Features ✨
6+
7+
- feat(debugId): Serialize source maps with `debugId`, not `debug_id` by @szokeasaurusrex in [#134](https://github.com/getsentry/rust-sourcemap/pull/134)
8+
9+
### Build / dependencies / internal 🔧
10+
11+
- chore: Fix 1.88.0 clippy lints by @loewenheim in [#130](https://github.com/getsentry/rust-sourcemap/pull/130)
12+
13+
### Other
14+
15+
- Store SourceView linecache as offsets rather than pointers by @coolreader18 in [#133](https://github.com/getsentry/rust-sourcemap/pull/133)
16+
317
## 9.2.2
418

519
### Various fixes & improvements

cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cli"
3-
version = "9.2.2"
3+
version = "9.3.0"
44
authors = ["Armin Ronacher <[email protected]>"]
55
edition = "2018"
66

src/decoder.rs

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -267,9 +267,7 @@ pub fn decode_regular(rsm: RawSourceMap) -> Result<SourceMap> {
267267

268268
let mut sm = SourceMap::new(file, tokens, names, sources, source_content);
269269
sm.set_source_root(rsm.source_root);
270-
// Use _debug_id_new (from "debugId" key) only if debug_id
271-
// from ( "debug_id" key) is unset
272-
sm.set_debug_id(rsm.debug_id.or(rsm._debug_id_new));
270+
sm.set_debug_id(rsm.debug_id.into());
273271
if let Some(ignore_list) = rsm.ignore_list {
274272
for idx in ignore_list {
275273
sm.add_to_ignore_list(idx);
@@ -307,7 +305,7 @@ fn decode_index(rsm: RawSourceMap) -> Result<SourceMapIndex> {
307305
rsm.x_facebook_offsets,
308306
rsm.x_metro_module_paths,
309307
)
310-
.with_debug_id(rsm._debug_id_new.or(rsm.debug_id)))
308+
.with_debug_id(rsm.debug_id.into()))
311309
}
312310

313311
fn decode_common(rsm: RawSourceMap) -> Result<DecodedMap> {
@@ -419,8 +417,7 @@ mod tests {
419417
x_facebook_offsets: None,
420418
x_metro_module_paths: None,
421419
x_facebook_sources: None,
422-
debug_id: None,
423-
_debug_id_new: None,
420+
debug_id: None.into(),
424421
};
425422

426423
let decoded = decode_common(raw).expect("should decoded");
@@ -448,40 +445,7 @@ mod tests {
448445
x_facebook_offsets: None,
449446
x_metro_module_paths: None,
450447
x_facebook_sources: None,
451-
debug_id: None,
452-
_debug_id_new: Some(DEBUG_ID.parse().expect("valid debug id")),
453-
};
454-
455-
let decoded = decode_common(raw).expect("should decode");
456-
assert_eq!(
457-
decoded,
458-
DecodedMap::Index(
459-
SourceMapIndex::new(Some("test.js".into()), vec![])
460-
.with_debug_id(Some(DEBUG_ID.parse().expect("valid debug id")))
461-
)
462-
);
463-
}
464-
465-
#[test]
466-
fn test_decode_sourcemap_index_debug_id_from_legacy_key() {
467-
const DEBUG_ID: &str = "0123456789abcdef0123456789abcdef";
468-
469-
let raw = RawSourceMap {
470-
version: Some(3),
471-
file: Some("test.js".into()),
472-
sources: None,
473-
source_root: None,
474-
sources_content: None,
475-
sections: Some(vec![]),
476-
names: None,
477-
range_mappings: None,
478-
mappings: None,
479-
ignore_list: None,
480-
x_facebook_offsets: None,
481-
x_metro_module_paths: None,
482-
x_facebook_sources: None,
483-
debug_id: Some(DEBUG_ID.parse().expect("valid debug id")),
484-
_debug_id_new: None,
448+
debug_id: Some(DEBUG_ID.parse().expect("valid debug id")).into(),
485449
};
486450

487451
let decoded = decode_common(raw).expect("should decode");

src/encoder.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,7 @@ impl Encodable for SourceMap {
178178
x_facebook_offsets: None,
179179
x_metro_module_paths: None,
180180
x_facebook_sources: None,
181-
debug_id: self.get_debug_id(),
182-
_debug_id_new: None,
181+
debug_id: self.get_debug_id().into(),
183182
}
184183
}
185184
}
@@ -213,9 +212,7 @@ impl Encodable for SourceMapIndex {
213212
x_facebook_offsets: None,
214213
x_metro_module_paths: None,
215214
x_facebook_sources: None,
216-
debug_id: None,
217-
// Put the debug ID on _debug_id_new to serialize it to the debugId field.
218-
_debug_id_new: self.debug_id(),
215+
debug_id: self.debug_id().into(),
219216
}
220217
}
221218
}
@@ -278,8 +275,7 @@ mod tests {
278275
x_facebook_offsets: None,
279276
x_metro_module_paths: None,
280277
x_facebook_sources: None,
281-
debug_id: None,
282-
_debug_id_new: None,
278+
debug_id: None.into(),
283279
}
284280
);
285281
}
@@ -308,8 +304,7 @@ mod tests {
308304
x_facebook_offsets: None,
309305
x_metro_module_paths: None,
310306
x_facebook_sources: None,
311-
debug_id: None,
312-
_debug_id_new: Some(DEBUG_ID.parse().expect("valid debug id")),
307+
debug_id: Some(DEBUG_ID.parse().expect("valid debug id")).into(),
313308
}
314309
);
315310
}

src/jsontypes.rs

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use bytes_str::BytesStr;
22
use debugid::DebugId;
33
use serde::de::IgnoredAny;
4-
use serde::{Deserialize, Serialize};
4+
use serde::{Deserialize, Deserializer, Serialize};
55
use serde_json::Value;
6+
use std::fmt::Debug;
67

78
#[derive(Serialize, Deserialize, PartialEq, Debug)]
89
pub struct RawSectionOffset {
@@ -55,12 +56,8 @@ pub struct RawSourceMap {
5556
pub x_metro_module_paths: Option<Vec<String>>,
5657
#[serde(skip_serializing_if = "Option::is_none")]
5758
pub x_facebook_sources: FacebookSources,
58-
#[serde(skip_serializing_if = "Option::is_none")]
59-
pub debug_id: Option<DebugId>,
60-
// This field only exists to be able to deserialize from "debugId" keys
61-
// if "debug_id" is unset.
62-
#[serde(skip_serializing_if = "Option::is_none", rename = "debugId")]
63-
pub(crate) _debug_id_new: Option<DebugId>,
59+
#[serde(flatten)]
60+
pub debug_id: DebugIdField,
6461
}
6562

6663
#[derive(Deserialize)]
@@ -76,3 +73,91 @@ pub struct MinimalRawSourceMap {
7673
pub names: Option<IgnoredAny>,
7774
pub mappings: Option<IgnoredAny>,
7875
}
76+
77+
/// This struct represents a `RawSourceMap`'s debug ID fields.
78+
///
79+
/// The reason this exists as a seperate struct is so that we can have custom deserialization
80+
/// logic, which can read both the legacy snake_case debug_id and the new camelCase debugId
81+
/// fields. In case both are provided, the camelCase field takes precedence.
82+
///
83+
/// The field is always serialized as `debugId`.
84+
#[derive(Serialize, Clone, PartialEq, Debug, Default)]
85+
pub(crate) struct DebugIdField {
86+
#[serde(rename = "debugId", skip_serializing_if = "Option::is_none")]
87+
value: Option<DebugId>,
88+
}
89+
90+
impl<'de> Deserialize<'de> for DebugIdField {
91+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
92+
where
93+
D: Deserializer<'de>,
94+
{
95+
// We cannot use serde(alias), as that would cause an error when both fields are present.
96+
97+
#[derive(Deserialize)]
98+
struct Helper {
99+
#[serde(rename = "debugId")]
100+
camel: Option<DebugId>,
101+
#[serde(rename = "debug_id")]
102+
legacy: Option<DebugId>,
103+
}
104+
105+
let Helper { camel, legacy } = Helper::deserialize(deserializer)?;
106+
Ok(camel.or(legacy).into())
107+
}
108+
}
109+
110+
impl From<Option<DebugId>> for DebugIdField {
111+
fn from(value: Option<DebugId>) -> Self {
112+
Self { value }
113+
}
114+
}
115+
116+
impl From<DebugIdField> for Option<DebugId> {
117+
fn from(value: DebugIdField) -> Self {
118+
value.value
119+
}
120+
}
121+
122+
#[cfg(test)]
123+
mod tests {
124+
use super::*;
125+
use serde_json::json;
126+
127+
fn parse_debug_id(input: &str) -> DebugId {
128+
input.parse().expect("valid debug id")
129+
}
130+
131+
fn empty_sourcemap() -> RawSourceMap {
132+
serde_json::from_value::<RawSourceMap>(serde_json::json!({}))
133+
.expect("can deserialize empty JSON to RawSourceMap")
134+
}
135+
136+
#[test]
137+
fn raw_sourcemap_serializes_camel_case_debug_id() {
138+
let camel = "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
139+
let raw = RawSourceMap {
140+
debug_id: Some(parse_debug_id(camel)).into(),
141+
..empty_sourcemap()
142+
};
143+
144+
let value = serde_json::to_value(raw).expect("should serialize without error");
145+
let obj = value.as_object().expect("should be an object");
146+
assert!(obj.get("debug_id").is_none());
147+
assert_eq!(obj.get("debugId"), Some(&json!(parse_debug_id(camel))));
148+
}
149+
150+
#[test]
151+
fn raw_sourcemap_prefers_camel_case_on_deserialize() {
152+
let legacy = "ffffffffffffffffffffffffffffffff";
153+
let camel = "00000000000000000000000000000000";
154+
let json = serde_json::json!({
155+
"debug_id": legacy,
156+
"debugId": camel
157+
});
158+
let raw: RawSourceMap =
159+
serde_json::from_value(json).expect("can deserialize as RawSourceMap");
160+
let value: Option<DebugId> = raw.debug_id.into();
161+
assert_eq!(value, Some(parse_debug_id(camel)));
162+
}
163+
}

src/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,8 +1665,8 @@ mod tests {
16651665
"sources":["coolstuff.js"],
16661666
"names":["x","alert"],
16671667
"mappings":"AAAA,GAAIA,GAAI,EACR,IAAIA,GAAK,EAAG,CACVC,MAAM",
1668-
"debug_id":"00000000-0000-0000-0000-000000000000",
1669-
"debugId": "11111111-1111-1111-1111-111111111111"
1668+
"debug_id": "11111111-1111-1111-1111-111111111111",
1669+
"debugId":"00000000-0000-0000-0000-000000000000"
16701670
}"#;
16711671

16721672
let sm = SourceMap::from_slice(input).unwrap();

tests/test_encoder.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,35 @@ fn test_empty_range() {
6262
let out = String::from_utf8(out).unwrap();
6363
assert!(!out.contains("rangeMappings"));
6464
}
65+
66+
#[test]
67+
fn test_sourcemap_serializes_camel_case_debug_id() {
68+
const DEBUG_ID: &str = "0123456789abcdef0123456789abcdef";
69+
let input = format!(
70+
r#"{{
71+
"version": 3,
72+
"sources": [],
73+
"names": [],
74+
"mappings": "",
75+
"debug_id": "{}"
76+
}}"#,
77+
DEBUG_ID
78+
);
79+
80+
let sm = SourceMap::from_reader(input.as_bytes()).unwrap();
81+
let expected = sm.get_debug_id().expect("debug id parsed").to_string();
82+
let mut out: Vec<u8> = vec![];
83+
sm.to_writer(&mut out).unwrap();
84+
let serialized = String::from_utf8(out).unwrap();
85+
86+
assert!(
87+
serialized.contains(&format!(r#""debugId":"{}""#, expected)),
88+
"expected camelCase debugId in {}",
89+
serialized
90+
);
91+
assert!(
92+
!serialized.contains("debug_id"),
93+
"unexpected snake_case key in {}",
94+
serialized
95+
);
96+
}

tests/test_index.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,33 @@ fn test_flatten_indexed_sourcemap_with_ignore_list() {
205205
vec![1]
206206
);
207207
}
208+
209+
#[test]
210+
fn test_sourcemap_index_serializes_camel_case_debug_id() {
211+
const DEBUG_ID: &str = "fedcba9876543210fedcba9876543210";
212+
let input = format!(
213+
r#"{{
214+
"version": 3,
215+
"file": "bundle.js",
216+
"sections": [],
217+
"debugId": "{}"
218+
}}"#,
219+
DEBUG_ID
220+
);
221+
222+
let smi = SourceMapIndex::from_reader(input.as_bytes()).unwrap();
223+
let mut out = Vec::new();
224+
smi.to_writer(&mut out).unwrap();
225+
let serialized = String::from_utf8(out).unwrap();
226+
227+
assert!(
228+
serialized.contains(r#""debugId":"#),
229+
"expected camelCase debugId in {}",
230+
serialized
231+
);
232+
assert!(
233+
!serialized.contains("debug_id"),
234+
"unexpected snake_case key in {}",
235+
serialized
236+
);
237+
}

0 commit comments

Comments
 (0)