Skip to content

Commit ec1a139

Browse files
fix: trim replacements longer than the range they replace (#312)
1 parent 25d7461 commit ec1a139

2 files changed

Lines changed: 37 additions & 6 deletions

File tree

src/Chunk.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,14 @@ export default class Chunk {
164164

165165
if (trimmed.length) {
166166
if (trimmed !== this.content) {
167-
this.split(this.start + trimmed.length).edit('', undefined, true)
168167
if (this.edited) {
169-
// save the change, if it has been edited
168+
// the content of an edited chunk no longer lines up with its range in the
169+
// original string, so there is no index to split at - trim it in place
170170
this.edit(trimmed, this.storeName, true)
171171
}
172+
else {
173+
this.split(this.start + trimmed.length).edit('', undefined, true)
174+
}
172175
}
173176
return true
174177
}
@@ -190,12 +193,15 @@ export default class Chunk {
190193

191194
if (trimmed.length) {
192195
if (trimmed !== this.content) {
193-
const newChunk = this.split(this.end - trimmed.length)
194196
if (this.edited) {
195-
// save the change, if it has been edited
196-
newChunk.edit(trimmed, this.storeName, true)
197+
// the content of an edited chunk no longer lines up with its range in the
198+
// original string, so there is no index to split at - trim it in place
199+
this.edit(trimmed, this.storeName, true)
200+
}
201+
else {
202+
this.split(this.end - trimmed.length)
203+
this.edit('', undefined, true)
197204
}
198-
this.edit('', undefined, true)
199205
}
200206
return true
201207
}

test/MagicString.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,6 +1675,31 @@ describe('magicString', () => {
16751675
assert.equal(s.toString(), 'abcd')
16761676
})
16771677

1678+
it('should trim a replacement that is longer than the range it replaces', () => {
1679+
const s = new MagicString('ab')
1680+
s.overwrite(0, 1, ' xyz')
1681+
s.trimStart()
1682+
1683+
assert.equal(s.toString(), 'xyzb')
1684+
1685+
for (const line of s.generateDecodedMap({ source: 'in.js' }).mappings) {
1686+
for (const segment of line) {
1687+
if (segment.length > 1) {
1688+
assert.ok(segment[1]! >= 0 && segment[2]! >= 0 && segment[3]! >= 0, `segment ${JSON.stringify(segment)} points outside the original`)
1689+
}
1690+
}
1691+
}
1692+
})
1693+
1694+
it('should trim the end of a replacement that is longer than the range it replaces', () => {
1695+
const s = new MagicString('ab')
1696+
s.overwrite(1, 2, 'xyz ')
1697+
s.trimEnd()
1698+
1699+
assert.equal(s.toString(), 'axyz')
1700+
assert.equal(s.slice(0, 2), 'axyz')
1701+
})
1702+
16781703
it('should trim original content before replaced content', () => {
16791704
const s = new MagicString('abc def')
16801705

0 commit comments

Comments
 (0)