Skip to content

Commit

Permalink
Fix a bug in decoration set mapping
Browse files Browse the repository at this point in the history
FIX: Fix a bug in `DecorationSet.map` that could cause invalid mapping when
step maps contain multiple replaced ranges.

See #136
  • Loading branch information
marijnh committed Aug 11, 2022
1 parent 6ef04c3 commit 978011f
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 14 deletions.
28 changes: 16 additions & 12 deletions src/decoration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,20 +550,24 @@ function mapChildren(

// Mark the children that are directly touched by changes, and
// move those that are after the changes.
let shift = (oldStart: number, oldEnd: number, newStart: number, newEnd: number) => {
for (let i = 0; i < children.length; i += 3) {
let end = children[i + 1] as number, dSize
if (end < 0 || oldStart > end + oldOffset) continue
let start = (children[i] as number) + oldOffset
if (oldEnd >= start) {
children[i + 1] = oldStart <= start ? -2 : -1
} else if (newStart >= offset && (dSize = (newEnd - newStart) - (oldEnd - oldStart))) {
;(children[i] as number) += dSize
;(children[i + 1] as number) += dSize
for (let i = 0; i < mapping.maps.length; i++) {
let moved = 0
mapping.maps[i].forEach((oldStart: number, oldEnd: number, newStart: number, newEnd: number) => {
let dSize = (newEnd - newStart) - (oldEnd - oldStart)
for (let i = 0; i < children.length; i += 3) {
let end = children[i + 1] as number
if (end < 0 || oldStart > end + oldOffset - moved) continue
let start = (children[i] as number) + oldOffset - moved
if (oldEnd >= start) {
children[i + 1] = oldStart <= start ? -2 : -1
} else if (newStart >= offset && dSize) {
;(children[i] as number) += dSize
;(children[i + 1] as number) += dSize
}
}
}
moved += dSize
})
}
for (let i = 0; i < mapping.maps.length; i++) mapping.maps[i].forEach(shift)

// Find the child nodes that still correspond to a single node,
// recursively call mapInner on them and update their positions.
Expand Down
5 changes: 3 additions & 2 deletions test/webtest-decoration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,13 @@ describe("DecorationSet", () => {

// We want inline decorations to be preserved, so we'll use a custom step that allows this
class MyStep extends ReplaceStep {
constructor(from, to, slice, structure, ranges) {
ranges: readonly number[]
constructor(from: number, to: number, slice: Slice, structure: boolean, ranges: readonly number[]) {
super(from, to, slice, structure)
this.ranges = ranges
}
getMap() { return new StepMap(this.ranges) }
merge(other) { return null }
merge(other: MyStep) { return null }
}
const posBeforeFirstWord = di.tag.start - 1
const ranges = [posBeforeFirstWord, 1, 0] // Remove first word's opening token
Expand Down

0 comments on commit 978011f

Please sign in to comment.