forked from mystiq/hydrogen-web
fix fragmentId:0 being evaluated as falsy
This commit is contained in:
parent
4b5b90e199
commit
bb5f139355
4 changed files with 54 additions and 9 deletions
|
@ -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},
|
||||||
|
|
3
src/matrix/room/timeline/common.js
Normal file
3
src/matrix/room/timeline/common.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export function isValidFragmentId(id) {
|
||||||
|
return typeof id === "number";
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue