Skip to content

Commit ba5298c

Browse files
feat: Add ability to adjust SourceMapIndex offset rows
Closes #114
1 parent 096eeab commit ba5298c

File tree

1 file changed

+217
-1
lines changed

1 file changed

+217
-1
lines changed

src/types.rs

Lines changed: 217 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,31 @@ impl SourceMapIndex {
12791279
pub fn x_metro_module_paths(&self) -> Option<&[String]> {
12801280
self.x_metro_module_paths.as_ref().map(|x| &x[..])
12811281
}
1282+
1283+
/// Adjusts all of the sections' offset rows by the given amount.
1284+
/// Returns a boolean indicating whether the adjustment was successful
1285+
/// (false indicating that not all of the sections could be adjusted
1286+
/// because we overflowed the u32, true if adjustment was successful).
1287+
/// If false is returned, then the sourcemap index is unchanged.
1288+
pub fn adjust_sections_offset_rows(&mut self, amount: u32) -> bool {
1289+
let adjusted_rows: Vec<_> = self
1290+
.sections
1291+
.iter()
1292+
// Filter map will filter out adjustments that overflow
1293+
.filter_map(|section| section.offset.0.checked_add(amount))
1294+
.collect();
1295+
1296+
if adjusted_rows.len() != self.sections.len() {
1297+
// We overflowed at least one section
1298+
return false;
1299+
}
1300+
1301+
for (section, adjustment) in self.sections.iter_mut().zip(adjusted_rows) {
1302+
section.offset.0 = adjustment;
1303+
}
1304+
1305+
true
1306+
}
12821307
}
12831308

12841309
impl SourceMapSection {
@@ -1344,7 +1369,7 @@ impl SourceMapSection {
13441369
mod tests {
13451370
use std::collections::BTreeSet;
13461371

1347-
use super::{DecodedMap, RewriteOptions, SourceMap, SourceMapIndex};
1372+
use super::{DecodedMap, RewriteOptions, SourceMap, SourceMapIndex, SourceMapSection};
13481373
use debugid::DebugId;
13491374

13501375
#[test]
@@ -1547,6 +1572,197 @@ mod tests {
15471572
);
15481573
}
15491574

1575+
#[test]
1576+
fn test_adjust_sections_offset_rows_basic() {
1577+
// Create a sourcemap index with sections starting at (0, 0) and (10, 0)
1578+
let mut smi = SourceMapIndex::new(
1579+
Some("test.js".to_string()),
1580+
vec![
1581+
SourceMapSection::new((0, 0), None, None),
1582+
SourceMapSection::new((10, 0), None, None),
1583+
],
1584+
);
1585+
1586+
// Adjust by 1
1587+
assert!(smi.adjust_sections_offset_rows(1));
1588+
1589+
// Check that the entire SourceMapIndex was adjusted correctly
1590+
assert_eq!(
1591+
smi,
1592+
SourceMapIndex::new(
1593+
Some("test.js".to_string()),
1594+
vec![
1595+
SourceMapSection::new((1, 0), None, None),
1596+
SourceMapSection::new((11, 0), None, None),
1597+
],
1598+
)
1599+
);
1600+
}
1601+
1602+
#[test]
1603+
fn test_adjust_sections_offset_rows_zero() {
1604+
// Create a sourcemap index with sections starting at (0, 0) and (10, 0)
1605+
let mut smi = SourceMapIndex::new(
1606+
Some("test.js".to_string()),
1607+
vec![
1608+
SourceMapSection::new((0, 0), None, None),
1609+
SourceMapSection::new((10, 0), None, None),
1610+
],
1611+
);
1612+
1613+
// Adjust by zero
1614+
assert!(smi.adjust_sections_offset_rows(0));
1615+
1616+
// Check that the entire SourceMapIndex remained unchanged
1617+
assert_eq!(
1618+
smi,
1619+
SourceMapIndex::new(
1620+
Some("test.js".to_string()),
1621+
vec![
1622+
SourceMapSection::new((0, 0), None, None),
1623+
SourceMapSection::new((10, 0), None, None),
1624+
],
1625+
)
1626+
);
1627+
}
1628+
1629+
#[test]
1630+
fn test_adjust_sections_offset_rows_multiple_sections() {
1631+
// Create a sourcemap index with multiple sections
1632+
let mut smi = SourceMapIndex::new(
1633+
Some("test.js".to_string()),
1634+
vec![
1635+
SourceMapSection::new((0, 0), None, None),
1636+
SourceMapSection::new((10, 0), None, None),
1637+
SourceMapSection::new((20, 10), None, None),
1638+
SourceMapSection::new((30, 40), None, None),
1639+
],
1640+
);
1641+
1642+
// Adjust by 1
1643+
assert!(smi.adjust_sections_offset_rows(1));
1644+
1645+
// Check that the entire SourceMapIndex was adjusted correctly
1646+
assert_eq!(
1647+
smi,
1648+
SourceMapIndex::new(
1649+
Some("test.js".to_string()),
1650+
vec![
1651+
SourceMapSection::new((1, 0), None, None),
1652+
SourceMapSection::new((11, 0), None, None),
1653+
SourceMapSection::new((21, 10), None, None),
1654+
SourceMapSection::new((31, 40), None, None),
1655+
],
1656+
)
1657+
);
1658+
}
1659+
1660+
#[test]
1661+
fn test_adjust_sections_offset_rows_overflow() {
1662+
// Create a sourcemap index with a section at u32::MAX
1663+
let mut smi = SourceMapIndex::new(
1664+
Some("test.js".to_string()),
1665+
vec![
1666+
SourceMapSection::new((0, 0), None, None),
1667+
SourceMapSection::new((u32::MAX, 0), None, None),
1668+
],
1669+
);
1670+
1671+
// Store the original state
1672+
let original_smi = smi.clone();
1673+
1674+
// An adjustment of 1 would overflow
1675+
assert!(!smi.adjust_sections_offset_rows(1));
1676+
1677+
// Verify the sourcemap index remains unchanged
1678+
assert_eq!(smi, original_smi);
1679+
}
1680+
1681+
#[test]
1682+
fn test_adjust_sections_offset_rows_partial_overflow() {
1683+
// Create a sourcemap index with multiple sections, one at u32::MAX
1684+
let mut smi = SourceMapIndex::new(
1685+
Some("test.js".to_string()),
1686+
vec![
1687+
SourceMapSection::new((0, 0), None, None),
1688+
SourceMapSection::new((10, 0), None, None),
1689+
SourceMapSection::new((20, 0), None, None),
1690+
SourceMapSection::new((u32::MAX, 0), None, None),
1691+
],
1692+
);
1693+
1694+
// Store the original state
1695+
let original_smi = smi.clone();
1696+
1697+
// Try to adjust by an amount that would cause overflow for one section
1698+
assert!(!smi.adjust_sections_offset_rows(1));
1699+
1700+
// Verify the sourcemap index remains unchanged
1701+
assert_eq!(smi, original_smi);
1702+
}
1703+
1704+
#[test]
1705+
fn test_adjust_sections_offset_rows_large_amount() {
1706+
// Create a sourcemap index with sections
1707+
let mut smi = SourceMapIndex::new(
1708+
Some("test.js".to_string()),
1709+
vec![
1710+
SourceMapSection::new((0, 0), None, None),
1711+
SourceMapSection::new((10, 0), None, None),
1712+
],
1713+
);
1714+
1715+
assert!(smi.adjust_sections_offset_rows(1_000_000));
1716+
1717+
// Check that the entire SourceMapIndex was adjusted correctly
1718+
assert_eq!(
1719+
smi,
1720+
SourceMapIndex::new(
1721+
Some("test.js".to_string()),
1722+
vec![
1723+
SourceMapSection::new((1_000_000, 0), None, None),
1724+
SourceMapSection::new((1_000_010, 0), None, None),
1725+
],
1726+
)
1727+
);
1728+
}
1729+
1730+
#[test]
1731+
fn adjust_sections_offset_rows_large_amount_overflow() {
1732+
// Create a sourcemap index with a section at a positive amount
1733+
let mut smi = SourceMapIndex::new(
1734+
Some("test.js".to_string()),
1735+
vec![
1736+
SourceMapSection::new((0, 0), None, None),
1737+
SourceMapSection::new((10, 0), None, None),
1738+
],
1739+
);
1740+
1741+
// Store the original state
1742+
let original_smi = smi.clone();
1743+
1744+
// An adjustment of u32::MAX would overflow
1745+
assert!(!smi.adjust_sections_offset_rows(u32::MAX));
1746+
1747+
// Verify the sourcemap index remains unchanged
1748+
assert_eq!(smi, original_smi);
1749+
}
1750+
1751+
#[test]
1752+
fn adjust_sections_offset_rows_no_sections() {
1753+
// Create a sourcemap index with no sections
1754+
let mut smi = SourceMapIndex::new(Some("test.js".to_string()), vec![]);
1755+
1756+
// An adjustment by 1 should return true and no-op
1757+
assert!(smi.adjust_sections_offset_rows(1));
1758+
1759+
// The sourcemap index should remain unchanged
1760+
assert_eq!(
1761+
smi,
1762+
SourceMapIndex::new(Some("test.js".to_string()), vec![])
1763+
);
1764+
}
1765+
15501766
mod prop {
15511767
//! This module exists to test the following property:
15521768
//!

0 commit comments

Comments
 (0)