Skip to content

Commit f816f33

Browse files
committed
fixes #19: array (patch): fixes CommentArray::sort
test/array: more test cases
1 parent 91e4173 commit f816f33

File tree

2 files changed

+88
-15
lines changed

2 files changed

+88
-15
lines changed

src/array.js

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ const move_comments = (
6969
}
7070
}
7171

72+
const get_mapped = (map, key) => {
73+
let mapped = key
74+
75+
while (mapped in map) {
76+
mapped = map[mapped]
77+
}
78+
79+
return mapped
80+
}
81+
82+
7283
class CommentArray extends Array {
7384
// - deleteCount + items.length
7485

@@ -225,36 +236,49 @@ class CommentArray extends Array {
225236
)
226237

227238
// For example,
228-
// if we sort ['c', 'a', 'b', 'd'],
229-
// then `result` will be [1, 2, 0, 3], and the array is ['a', 'b', 'c', 'd']
239+
// if we sort ['b', 'd', 'c', 'a'],
240+
// then `result` will be [3, 0, 2, 1], and the array is ['a', 'b', 'c', 'd']
241+
242+
// First, we swap index 0 (b) and index 3 (a), then the array comments are
243+
// ['a.comments', 'd.comments', 'c.comments', 'b.comments']
244+
// index 0 is finalized
245+
// index 3 is actually mapped to original index 0, we present as 0 -> 3
230246

231-
// First, we swap index 0 and index 1, then the array comments are
232-
// ['a.comments', 'c.comments', 'b.comments', 'd.comments']
247+
// Then swap index 1 (d) and index 0 (-> 3, b)
248+
// 1 (index) -> 0 (new index) -> 3 (real_index)
249+
// ['d.comments', 'b.comments', 'c.comments', 'd.comments']
250+
// index 1 is finalized
251+
// index 3 is contains the item of original index 1
252+
// - we present as 1 -> 3
253+
// - it is ok that we don't remove mapping 0 -> 3
233254

234-
// Then swap index 1 and index 2
235-
// ['a.comments', 'b.comments', 'c.comments', 'd.comments']
255+
// Then index 2 should be skipped
236256

237-
// And we should not swap index 2 and index 0
257+
// Then swap index 3 (d) and index 1 (-> 3, b), skipped
238258

239-
const sorted = new Set()
259+
const map = Object.create(null)
240260

241-
result.forEach((new_index, original_index) => {
242-
if (new_index === original_index) {
261+
result.forEach((source_index, index) => {
262+
if (source_index === index) {
243263
return
244264
}
245265

246-
if (sorted.has(new_index) && sorted.has(original_index)) {
266+
const real_source_index = get_mapped(map, source_index)
267+
268+
if (real_source_index === index) {
247269
return
248270
}
249271

250-
sorted.add(new_index)
251-
sorted.add(original_index)
272+
// The item of index `index` gets the final value
273+
// delete map[index]
274+
map[index] = real_source_index
252275

253-
swap_comments(this, new_index, original_index)
276+
swap_comments(this, index, real_source_index)
254277
})
255278
}
256279
}
257280

281+
258282
module.exports = {
259283
CommentArray
260284
}

test/array.test.js

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,58 @@ const CASES = [
224224
// 1
225225
1
226226
]`)
227-
]
227+
],
228+
[
229+
'sort, default lex sort',
230+
`[
231+
// before c
232+
"c",
233+
"a", // after a
234+
"b" /* after b value */,
235+
"d"
236+
]`,
237+
array => {
238+
array.sort()
239+
return array
240+
},
241+
unshift(['a', 'b', 'c', 'd'], `[
242+
"a", // after a
243+
"b" /* after b value */,
244+
// before c
245+
"c",
246+
"d"
247+
]`)
248+
],
249+
[
250+
'sort, with `compareFunction`',
251+
`[
252+
// before c
253+
"c",
254+
"a", // after a
255+
"b" /* after b value */,
256+
// before d
257+
"d"
258+
]`,
259+
array => {
260+
array.sort(
261+
(a, b) => a > b
262+
? - 1
263+
: 1
264+
)
265+
return array
266+
},
267+
unshift(['d', 'c', 'b', 'a'], `[
268+
// before d
269+
"d",
270+
// before c
271+
"c",
272+
"b" /* after b value */,
273+
"a" // after a
274+
]`)
275+
],
228276
]
229277

278+
230279
CASES.forEach(([d, a, run, e, s]) => {
231280
test(d, t => {
232281
const parsed = parse(a)

0 commit comments

Comments
 (0)