fix fragmentId:0 being evaluated as falsy

This commit is contained in:
Bruno Windels 2019-06-02 19:27:23 +02:00
parent 4b5b90e199
commit bb5f139355
4 changed files with 54 additions and 9 deletions

View file

@ -22,31 +22,31 @@ until no more fragments
*/ */
import {isValidFragmentId} from "./common.js";
function findBackwardSiblingFragments(current, byId) { function findBackwardSiblingFragments(current, byId) {
const sortedSiblings = []; const sortedSiblings = [];
while (current.previousId) { while (isValidFragmentId(current.previousId)) {
const previous = byId.get(current.previousId); const previous = byId.get(current.previousId);
if (!previous) { if (!previous) {
throw new Error(`Unknown previousId ${current.previousId} on ${current.id}`); break;
} }
if (previous.nextId !== current.id) { if (previous.nextId !== current.id) {
throw new Error(`Previous fragment ${previous.id} doesn't point back to ${current.id}`); throw new Error(`Previous fragment ${previous.id} doesn't point back to ${current.id}`);
} }
byId.delete(current.previousId); byId.delete(current.previousId);
sortedSiblings.push(previous); sortedSiblings.unshift(previous);
current = previous; current = previous;
} }
sortedSiblings.reverse();
return sortedSiblings; return sortedSiblings;
} }
function findForwardSiblingFragments(current, byId) { function findForwardSiblingFragments(current, byId) {
const sortedSiblings = []; const sortedSiblings = [];
while (current.nextId) { while (isValidFragmentId(current.nextId)) {
const next = byId.get(current.nextId); const next = byId.get(current.nextId);
if (!next) { if (!next) {
throw new Error(`Unknown nextId ${current.nextId} on ${current.id}`); break;
} }
if (next.previousId !== current.id) { if (next.previousId !== current.id) {
throw new Error(`Next fragment ${next.id} doesn't point back to ${current.id}`); throw new Error(`Next fragment ${next.id} doesn't point back to ${current.id}`);
@ -143,7 +143,7 @@ export default class FragmentIdComparer {
} }
add(fragment) { add(fragment) {
this._fragmentsById[fragment.id] = fragment; this._fragmentsById.set(fragment.id, fragment);
this.rebuild(this._fragmentsById.values()); this.rebuild(this._fragmentsById.values());
} }
} }
@ -168,6 +168,44 @@ export function tests() {
assert.equal(index.compare(1, 1), 0); assert.equal(index.compare(1, 1), 0);
}, },
test_falsy_id(assert) {
const index = new FragmentIdComparer([
{id: 0, nextId: 1},
{id: 1, previousId: 0},
]);
assert(index.compare(0, 1) < 0);
assert(index.compare(1, 0) > 0);
},
test_falsy_id_reverse(assert) {
const index = new FragmentIdComparer([
{id: 1, previousId: 0},
{id: 0, nextId: 1},
]);
assert(index.compare(0, 1) < 0);
assert(index.compare(1, 0) > 0);
},
test_allow_unknown_id(assert) {
// as we tend to load fragments incrementally
// as events come into view, we need to allow
// unknown previousId/nextId in the fragments that we do load
assert.doesNotThrow(() => {
new FragmentIdComparer([
{id: 1, previousId: 2},
{id: 0, nextId: 3},
]);
});
},
test_throw_on_link_mismatch(assert) {
// as we tend to load fragments incrementally
// as events come into view, we need to allow
// unknown previousId/nextId in the fragments that we do load
assert.throws(() => {
new FragmentIdComparer([
{id: 1, previousId: 0},
{id: 0, nextId: 2},
]);
});
},
test_2_island_dont_compare(assert) { test_2_island_dont_compare(assert) {
const index = new FragmentIdComparer([ const index = new FragmentIdComparer([
{id: 1}, {id: 1},

View file

@ -0,0 +1,3 @@
export function isValidFragmentId(id) {
return typeof id === "number";
}

View file

@ -1,5 +1,6 @@
import BaseEntry from "./BaseEntry.js"; import BaseEntry from "./BaseEntry.js";
import Direction from "../Direction.js"; import Direction from "../Direction.js";
import {isValidFragmentId} from "../common.js";
export default class FragmentBoundaryEntry extends BaseEntry { export default class FragmentBoundaryEntry extends BaseEntry {
constructor(fragment, isFragmentStart, fragmentIdComparator) { constructor(fragment, isFragmentStart, fragmentIdComparator) {
@ -77,6 +78,10 @@ export default class FragmentBoundaryEntry extends BaseEntry {
} }
} }
get hasLinkedFragment() {
return isValidFragmentId(this.linkedFragmentId);
}
get direction() { get direction() {
if (this.started) { if (this.started) {
return Direction.Backward; return Direction.Backward;

View file

@ -25,7 +25,6 @@ export default class TimelineReader {
async _readFrom(eventKey, direction, amount, txn) { async _readFrom(eventKey, direction, amount, txn) {
let entries = []; let entries = [];
const timelineStore = txn.timelineEvents; const timelineStore = txn.timelineEvents;
const fragmentStore = txn.timelineFragments; const fragmentStore = txn.timelineFragments;
@ -47,7 +46,7 @@ export default class TimelineReader {
// append or prepend fragmentEntry, reuse func from GapWriter? // append or prepend fragmentEntry, reuse func from GapWriter?
directionalAppend(entries, fragmentEntry, direction); directionalAppend(entries, fragmentEntry, direction);
// don't count it in amount perhaps? or do? // don't count it in amount perhaps? or do?
if (fragmentEntry.linkedFragmentId) { if (fragmentEntry.hasLinkedFragment) {
const nextFragment = await fragmentStore.get(this._roomId, fragmentEntry.linkedFragmentId); const nextFragment = await fragmentStore.get(this._roomId, fragmentEntry.linkedFragmentId);
this._fragmentIdComparer.add(nextFragment); this._fragmentIdComparer.add(nextFragment);
const nextFragmentEntry = new FragmentBoundaryEntry(nextFragment, direction.isForward, this._fragmentIdComparer); const nextFragmentEntry = new FragmentBoundaryEntry(nextFragment, direction.isForward, this._fragmentIdComparer);