From 348a9c83f5b96798dadce02fbc7b1e5437163409 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 18:51:02 -0700 Subject: [PATCH 01/62] Rename ObservableArray to TypeScript --- src/domain/session/room/timeline/TilesCollection.js | 2 +- src/observable/index.js | 2 +- src/observable/list/AsyncMappedList.js | 2 +- src/observable/list/ConcatList.js | 2 +- src/observable/list/MappedList.js | 2 +- src/observable/list/{ObservableArray.js => ObservableArray.ts} | 0 6 files changed, 5 insertions(+), 5 deletions(-) rename src/observable/list/{ObservableArray.js => ObservableArray.ts} (100%) diff --git a/src/domain/session/room/timeline/TilesCollection.js b/src/domain/session/room/timeline/TilesCollection.js index b3696fad..d83dc5bd 100644 --- a/src/domain/session/room/timeline/TilesCollection.js +++ b/src/domain/session/room/timeline/TilesCollection.js @@ -253,7 +253,7 @@ export class TilesCollection extends BaseObservableList { } } -import {ObservableArray} from "../../../../observable/list/ObservableArray.js"; +import {ObservableArray} from "../../../../observable/list/ObservableArray"; import {UpdateAction} from "./UpdateAction.js"; export function tests() { diff --git a/src/observable/index.js b/src/observable/index.js index 47b68e91..27d8a7ef 100644 --- a/src/observable/index.js +++ b/src/observable/index.js @@ -20,7 +20,7 @@ import {MappedMap} from "./map/MappedMap.js"; import {JoinedMap} from "./map/JoinedMap.js"; import {BaseObservableMap} from "./map/BaseObservableMap.js"; // re-export "root" (of chain) collections -export { ObservableArray } from "./list/ObservableArray.js"; +export { ObservableArray } from "./list/ObservableArray"; export { SortedArray } from "./list/SortedArray.js"; export { MappedList } from "./list/MappedList.js"; export { AsyncMappedList } from "./list/AsyncMappedList.js"; diff --git a/src/observable/list/AsyncMappedList.js b/src/observable/list/AsyncMappedList.js index 9af1f95a..9d6e2dd6 100644 --- a/src/observable/list/AsyncMappedList.js +++ b/src/observable/list/AsyncMappedList.js @@ -143,7 +143,7 @@ class ResetEvent { } } -import {ObservableArray} from "./ObservableArray.js"; +import {ObservableArray} from "./ObservableArray"; import {ListObserver} from "../../mocks/ListObserver.js"; export function tests() { diff --git a/src/observable/list/ConcatList.js b/src/observable/list/ConcatList.js index e87ccb60..69ce5efd 100644 --- a/src/observable/list/ConcatList.js +++ b/src/observable/list/ConcatList.js @@ -104,7 +104,7 @@ export class ConcatList extends BaseObservableList { } } -import {ObservableArray} from "./ObservableArray.js"; +import {ObservableArray} from "./ObservableArray"; export async function tests() { return { test_length(assert) { diff --git a/src/observable/list/MappedList.js b/src/observable/list/MappedList.js index c799fcff..39a2cf0d 100644 --- a/src/observable/list/MappedList.js +++ b/src/observable/list/MappedList.js @@ -56,7 +56,7 @@ export class MappedList extends BaseMappedList { } } -import {ObservableArray} from "./ObservableArray.js"; +import {ObservableArray} from "./ObservableArray"; import {BaseObservableList} from "./BaseObservableList"; export async function tests() { diff --git a/src/observable/list/ObservableArray.js b/src/observable/list/ObservableArray.ts similarity index 100% rename from src/observable/list/ObservableArray.js rename to src/observable/list/ObservableArray.ts From b148f3ca9e4537394a46d7e74638b2a93faf0077 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 18:55:31 -0700 Subject: [PATCH 02/62] Add type annotations to ObservableArray --- src/observable/list/ObservableArray.ts | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/observable/list/ObservableArray.ts b/src/observable/list/ObservableArray.ts index 5d9f5c12..718ac99f 100644 --- a/src/observable/list/ObservableArray.ts +++ b/src/observable/list/ObservableArray.ts @@ -16,52 +16,54 @@ limitations under the License. import {BaseObservableList} from "./BaseObservableList"; -export class ObservableArray extends BaseObservableList { - constructor(initialValues = []) { +export class ObservableArray extends BaseObservableList { + private _items: T[]; + + constructor(initialValues: T[] = []) { super(); this._items = initialValues; } - append(item) { + append(item: T): void { this._items.push(item); this.emitAdd(this._items.length - 1, item); } - remove(idx) { + remove(idx: number): void { const [item] = this._items.splice(idx, 1); this.emitRemove(idx, item); } - insertMany(idx, items) { + insertMany(idx: number, items: T[]): void { for(let item of items) { this.insert(idx, item); idx += 1; } } - insert(idx, item) { + insert(idx: number, item: T): void { this._items.splice(idx, 0, item); this.emitAdd(idx, item); } - update(idx, item, params = null) { + update(idx: number, item: T, params: any = null): void { if (idx < this._items.length) { this._items[idx] = item; this.emitUpdate(idx, item, params); } } - get array() { + get array(): Readonly { return this._items; } - at(idx) { + at(idx: number): T | undefined { if (this._items && idx >= 0 && idx < this._items.length) { return this._items[idx]; } } - get length() { + get length(): number { return this._items.length; } From e6de873b6e8c2822910007a67ca93f089209b6c1 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 18:56:28 -0700 Subject: [PATCH 03/62] Rename AsyncMappedList to TypeScript --- src/observable/index.js | 2 +- src/observable/list/{AsyncMappedList.js => AsyncMappedList.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/observable/list/{AsyncMappedList.js => AsyncMappedList.ts} (100%) diff --git a/src/observable/index.js b/src/observable/index.js index 27d8a7ef..8b2e5367 100644 --- a/src/observable/index.js +++ b/src/observable/index.js @@ -23,7 +23,7 @@ import {BaseObservableMap} from "./map/BaseObservableMap.js"; export { ObservableArray } from "./list/ObservableArray"; export { SortedArray } from "./list/SortedArray.js"; export { MappedList } from "./list/MappedList.js"; -export { AsyncMappedList } from "./list/AsyncMappedList.js"; +export { AsyncMappedList } from "./list/AsyncMappedList"; export { ConcatList } from "./list/ConcatList.js"; export { ObservableMap } from "./map/ObservableMap.js"; diff --git a/src/observable/list/AsyncMappedList.js b/src/observable/list/AsyncMappedList.ts similarity index 100% rename from src/observable/list/AsyncMappedList.js rename to src/observable/list/AsyncMappedList.ts From 0e6c59983f8758f6238ed1a6457e29e1e4d284f7 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 19:11:19 -0700 Subject: [PATCH 04/62] Generalize BaseMappedList to allow mappers to promises --- src/observable/list/BaseMappedList.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/observable/list/BaseMappedList.ts b/src/observable/list/BaseMappedList.ts index f2203d34..b5a669d1 100644 --- a/src/observable/list/BaseMappedList.ts +++ b/src/observable/list/BaseMappedList.ts @@ -21,15 +21,15 @@ import {findAndUpdateInArray} from "./common"; export type Mapper = (value: F) => T export type Updater = (mappedValue: T, params: any, value: F) => void; -export class BaseMappedList extends BaseObservableList { +export class BaseMappedList extends BaseObservableList { protected _sourceList: BaseObservableList; protected _sourceUnsubscribe: (() => void) | null = null; - _mapper: Mapper; + _mapper: Mapper; _updater: Updater; _removeCallback?: (value: T) => void; _mappedValues: T[] | null = null; - constructor(sourceList: BaseObservableList, mapper: Mapper, updater: Updater, removeCallback?: (value: T) => void) { + constructor(sourceList: BaseObservableList, mapper: Mapper, updater: Updater, removeCallback?: (value: T) => void) { super(); this._sourceList = sourceList; this._mapper = mapper; @@ -50,12 +50,12 @@ export class BaseMappedList extends BaseObservableList { } } -export function runAdd(list: BaseMappedList, index: number, mappedValue: T): void { +export function runAdd(list: BaseMappedList, index: number, mappedValue: T): void { list._mappedValues!.splice(index, 0, mappedValue); list.emitAdd(index, mappedValue); } -export function runUpdate(list: BaseMappedList, index: number, value: F, params: any): void { +export function runUpdate(list: BaseMappedList, index: number, value: F, params: any): void { const mappedValue = list._mappedValues![index]; if (list._updater) { list._updater(mappedValue, params, value); @@ -63,7 +63,7 @@ export function runUpdate(list: BaseMappedList, index: number, value: list.emitUpdate(index, mappedValue, params); } -export function runRemove(list: BaseMappedList, index: number): void { +export function runRemove(list: BaseMappedList, index: number): void { const mappedValue = list._mappedValues![index]; list._mappedValues!.splice(index, 1); if (list._removeCallback) { @@ -72,14 +72,14 @@ export function runRemove(list: BaseMappedList, index: number): void { list.emitRemove(index, mappedValue); } -export function runMove(list: BaseMappedList, fromIdx: number, toIdx: number): void { +export function runMove(list: BaseMappedList, fromIdx: number, toIdx: number): void { const mappedValue = list._mappedValues![fromIdx]; list._mappedValues!.splice(fromIdx, 1); list._mappedValues!.splice(toIdx, 0, mappedValue); list.emitMove(fromIdx, toIdx, mappedValue); } -export function runReset(list: BaseMappedList): void { +export function runReset(list: BaseMappedList): void { list._mappedValues = []; list.emitReset(); } From 8466a910da48d329f8b6a0fff085136763884027 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 19:13:38 -0700 Subject: [PATCH 05/62] Add type annotations to AsyncMappedList --- src/observable/list/AsyncMappedList.ts | 79 +++++++++++--------------- 1 file changed, 34 insertions(+), 45 deletions(-) diff --git a/src/observable/list/AsyncMappedList.ts b/src/observable/list/AsyncMappedList.ts index 9d6e2dd6..0a919cdc 100644 --- a/src/observable/list/AsyncMappedList.ts +++ b/src/observable/list/AsyncMappedList.ts @@ -15,15 +15,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseMappedList, runAdd, runUpdate, runRemove, runMove, runReset} from "./BaseMappedList"; +import {IListObserver} from "./BaseObservableList"; +import {BaseMappedList, Mapper, Updater, runAdd, runUpdate, runRemove, runMove, runReset} from "./BaseMappedList"; -export class AsyncMappedList extends BaseMappedList { - constructor(sourceList, mapper, updater, removeCallback) { - super(sourceList, mapper, updater, removeCallback); - this._eventQueue = null; - } +export class AsyncMappedList extends BaseMappedList> implements IListObserver { + private _eventQueue: AsyncEvent[] | null = null; + private _flushing: boolean = false; - onSubscribeFirst() { + onSubscribeFirst(): void { this._sourceUnsubscribe = this._sourceList.subscribe(this); this._eventQueue = []; this._mappedValues = []; @@ -35,110 +34,100 @@ export class AsyncMappedList extends BaseMappedList { this._flush(); } - async _flush() { + async _flush(): Promise { if (this._flushing) { return; } this._flushing = true; try { - while (this._eventQueue.length) { - const event = this._eventQueue.shift(); - await event.run(this); + while (this._eventQueue!.length) { + const event = this._eventQueue!.shift(); + await event!.run(this); } } finally { this._flushing = false; } } - onReset() { + onReset(): void { if (this._eventQueue) { this._eventQueue.push(new ResetEvent()); this._flush(); } } - onAdd(index, value) { + onAdd(index: number, value: F): void { if (this._eventQueue) { this._eventQueue.push(new AddEvent(index, value)); this._flush(); } } - onUpdate(index, value, params) { + onUpdate(index: number, value: F, params: any): void { if (this._eventQueue) { this._eventQueue.push(new UpdateEvent(index, value, params)); this._flush(); } } - onRemove(index) { + onRemove(index: number): void { if (this._eventQueue) { this._eventQueue.push(new RemoveEvent(index)); this._flush(); } } - onMove(fromIdx, toIdx) { + onMove(fromIdx: number, toIdx: number): void { if (this._eventQueue) { this._eventQueue.push(new MoveEvent(fromIdx, toIdx)); this._flush(); } } - onUnsubscribeLast() { - this._sourceUnsubscribe(); + onUnsubscribeLast(): void { + this._sourceUnsubscribe!(); this._eventQueue = null; this._mappedValues = null; } } -class AddEvent { - constructor(index, value) { - this.index = index; - this.value = value; - } +type AsyncEvent = AddEvent | UpdateEvent | RemoveEvent | MoveEvent | ResetEvent - async run(list) { +class AddEvent { + constructor(public index: number, public value: F) {} + + async run(list: AsyncMappedList): Promise { const mappedValue = await list._mapper(this.value); runAdd(list, this.index, mappedValue); } } -class UpdateEvent { - constructor(index, value, params) { - this.index = index; - this.value = value; - this.params = params; - } +class UpdateEvent { + constructor(public index: number, public value: F, public params: any) {} - async run(list) { + async run(list: AsyncMappedList): Promise { runUpdate(list, this.index, this.value, this.params); } } -class RemoveEvent { - constructor(index) { - this.index = index; - } +class RemoveEvent { + constructor(public index: number) {} - async run(list) { + async run(list: AsyncMappedList): Promise { runRemove(list, this.index); } } -class MoveEvent { - constructor(fromIdx, toIdx) { - this.fromIdx = fromIdx; - this.toIdx = toIdx; - } +class MoveEvent { + constructor(public fromIdx: number, public toIdx: number) {} - async run(list) { + async run(list: AsyncMappedList): Promise { runMove(list, this.fromIdx, this.toIdx); } } -class ResetEvent { - async run(list) { +class ResetEvent { + async run(list: AsyncMappedList): Promise { runReset(list); } } @@ -150,7 +139,7 @@ export function tests() { return { "events are emitted in order": async assert => { const double = n => n * n; - const source = new ObservableArray(); + const source = new ObservableArray(); const mapper = new AsyncMappedList(source, async n => { await new Promise(r => setTimeout(r, n)); return {n: double(n)}; From ddca467e304cc4965c7f76446e391960c532d91e Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 19:15:55 -0700 Subject: [PATCH 06/62] Rename ConcatList to TypeScript --- src/observable/index.js | 2 +- src/observable/list/{ConcatList.js => ConcatList.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/observable/list/{ConcatList.js => ConcatList.ts} (100%) diff --git a/src/observable/index.js b/src/observable/index.js index 8b2e5367..9784444b 100644 --- a/src/observable/index.js +++ b/src/observable/index.js @@ -24,7 +24,7 @@ export { ObservableArray } from "./list/ObservableArray"; export { SortedArray } from "./list/SortedArray.js"; export { MappedList } from "./list/MappedList.js"; export { AsyncMappedList } from "./list/AsyncMappedList"; -export { ConcatList } from "./list/ConcatList.js"; +export { ConcatList } from "./list/ConcatList"; export { ObservableMap } from "./map/ObservableMap.js"; // avoid circular dependency between these classes diff --git a/src/observable/list/ConcatList.js b/src/observable/list/ConcatList.ts similarity index 100% rename from src/observable/list/ConcatList.js rename to src/observable/list/ConcatList.ts From 588da9b7193eb5ce04ab2e2622df4e1b8230602d Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 19:25:47 -0700 Subject: [PATCH 07/62] Relax types on BaseObservableList and add helper for tests --- src/observable/list/BaseObservableList.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/observable/list/BaseObservableList.ts b/src/observable/list/BaseObservableList.ts index 9ba6559a..6d8bd1af 100644 --- a/src/observable/list/BaseObservableList.ts +++ b/src/observable/list/BaseObservableList.ts @@ -24,6 +24,17 @@ export interface IListObserver { onMove(from: number, to: number, value: T, list: BaseObservableList): void } +export function defaultObserverWith(overrides: { [key in keyof IListObserver]?: IListObserver[key] }): IListObserver { + const defaults = { + onReset(){}, + onAdd(){}, + onUpdate(){}, + onRemove(){}, + onMove(){}, + } + return Object.assign(defaults, overrides); +} + export abstract class BaseObservableList extends BaseObservable> { emitReset() { for(let h of this._handlers) { @@ -38,7 +49,7 @@ export abstract class BaseObservableList extends BaseObservable extends BaseObservable; + abstract [Symbol.iterator](); abstract get length(): number; } From 3b131f2db69e2f4e95530266078e6744a038c016 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 19:28:00 -0700 Subject: [PATCH 08/62] Add type annotations to ConcatList --- src/observable/list/ConcatList.ts | 39 +++++++++++++++++-------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/observable/list/ConcatList.ts b/src/observable/list/ConcatList.ts index 69ce5efd..5822468a 100644 --- a/src/observable/list/ConcatList.ts +++ b/src/observable/list/ConcatList.ts @@ -14,16 +14,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableList} from "./BaseObservableList"; +import {BaseObservableList, IListObserver} from "./BaseObservableList"; -export class ConcatList extends BaseObservableList { - constructor(...sourceLists) { +export class ConcatList extends BaseObservableList implements IListObserver { + protected _sourceLists: BaseObservableList[]; + protected _sourceUnsubscribes: (() => void)[] | null = null; + + constructor(...sourceLists: BaseObservableList[]) { super(); this._sourceLists = sourceLists; - this._sourceUnsubscribes = null; } - _offsetForSource(sourceList) { + _offsetForSource(sourceList: BaseObservableList): number { const listIdx = this._sourceLists.indexOf(sourceList); let offset = 0; for (let i = 0; i < listIdx; ++i) { @@ -32,17 +34,17 @@ export class ConcatList extends BaseObservableList { return offset; } - onSubscribeFirst() { + onSubscribeFirst(): void { this._sourceUnsubscribes = this._sourceLists.map(sourceList => sourceList.subscribe(this)); } - onUnsubscribeLast() { - for (const sourceUnsubscribe of this._sourceUnsubscribes) { + onUnsubscribeLast(): void { + for (const sourceUnsubscribe of this._sourceUnsubscribes!) { sourceUnsubscribe(); } } - onReset() { + onReset(): void { // TODO: not ideal if other source lists are large // but working impl for now // reset, and @@ -54,11 +56,11 @@ export class ConcatList extends BaseObservableList { } } - onAdd(index, value, sourceList) { + onAdd(index: number, value: T, sourceList: BaseObservableList): void { this.emitAdd(this._offsetForSource(sourceList) + index, value); } - onUpdate(index, value, params, sourceList) { + onUpdate(index: number, value: T, params: any, sourceList: BaseObservableList): void { // if an update is emitted while calling source.subscribe() from onSubscribeFirst, ignore it // as we are not supposed to call `length` on any uninitialized list if (!this._sourceUnsubscribes) { @@ -67,16 +69,16 @@ export class ConcatList extends BaseObservableList { this.emitUpdate(this._offsetForSource(sourceList) + index, value, params); } - onRemove(index, value, sourceList) { + onRemove(index: number, value: T, sourceList: BaseObservableList): void { this.emitRemove(this._offsetForSource(sourceList) + index, value); } - onMove(fromIdx, toIdx, value, sourceList) { + onMove(fromIdx: number, toIdx: number, value: T, sourceList: BaseObservableList): void { const offset = this._offsetForSource(sourceList); this.emitMove(offset + fromIdx, offset + toIdx, value); } - get length() { + get length(): number { let len = 0; for (let i = 0; i < this._sourceLists.length; ++i) { len += this._sourceLists[i].length; @@ -105,6 +107,7 @@ export class ConcatList extends BaseObservableList { } import {ObservableArray} from "./ObservableArray"; +import {defaultObserverWith} from "./BaseObservableList"; export async function tests() { return { test_length(assert) { @@ -133,13 +136,13 @@ export async function tests() { const list2 = new ObservableArray([11, 12, 13]); const all = new ConcatList(list1, list2); let fired = false; - all.subscribe({ + all.subscribe(defaultObserverWith({ onAdd(index, value) { fired = true; assert.equal(index, 4); assert.equal(value, 11.5); } - }); + })); list2.insert(1, 11.5); assert(fired); }, @@ -148,13 +151,13 @@ export async function tests() { const list2 = new ObservableArray([11, 12, 13]); const all = new ConcatList(list1, list2); let fired = false; - all.subscribe({ + all.subscribe(defaultObserverWith({ onUpdate(index, value) { fired = true; assert.equal(index, 4); assert.equal(value, 10); } - }); + })); list2.emitUpdate(1, 10); assert(fired); }, From 0466b4952080d3db5ad5b1529fc50602df2cbc0b Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 19:31:00 -0700 Subject: [PATCH 09/62] Rename MappedList to TypeScript --- src/domain/session/room/timeline/ReactionsViewModel.js | 2 +- src/observable/index.js | 2 +- src/observable/list/{MappedList.js => MappedList.ts} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/observable/list/{MappedList.js => MappedList.ts} (100%) diff --git a/src/domain/session/room/timeline/ReactionsViewModel.js b/src/domain/session/room/timeline/ReactionsViewModel.js index 25d74b49..c049dd11 100644 --- a/src/domain/session/room/timeline/ReactionsViewModel.js +++ b/src/domain/session/room/timeline/ReactionsViewModel.js @@ -188,7 +188,7 @@ import {NullLogItem, NullLogger} from "../../../../logging/NullLogger.js"; import {HomeServer as MockHomeServer} from "../../../../mocks/HomeServer.js"; // other imports import {BaseMessageTile} from "./tiles/BaseMessageTile.js"; -import {MappedList} from "../../../../observable/list/MappedList.js"; +import {MappedList} from "../../../../observable/list/MappedList"; import {ObservableValue} from "../../../../observable/ObservableValue"; import {PowerLevels} from "../../../../matrix/room/PowerLevels.js"; diff --git a/src/observable/index.js b/src/observable/index.js index 9784444b..35ecaffc 100644 --- a/src/observable/index.js +++ b/src/observable/index.js @@ -22,7 +22,7 @@ import {BaseObservableMap} from "./map/BaseObservableMap.js"; // re-export "root" (of chain) collections export { ObservableArray } from "./list/ObservableArray"; export { SortedArray } from "./list/SortedArray.js"; -export { MappedList } from "./list/MappedList.js"; +export { MappedList } from "./list/MappedList"; export { AsyncMappedList } from "./list/AsyncMappedList"; export { ConcatList } from "./list/ConcatList"; export { ObservableMap } from "./map/ObservableMap.js"; diff --git a/src/observable/list/MappedList.js b/src/observable/list/MappedList.ts similarity index 100% rename from src/observable/list/MappedList.js rename to src/observable/list/MappedList.ts From 84187ce10957f0336d116ee4fe2e55d95f4af745 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 19:40:21 -0700 Subject: [PATCH 10/62] Make updater optional in BaseObservableList --- src/observable/list/BaseMappedList.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/observable/list/BaseMappedList.ts b/src/observable/list/BaseMappedList.ts index b5a669d1..4e3d05e0 100644 --- a/src/observable/list/BaseMappedList.ts +++ b/src/observable/list/BaseMappedList.ts @@ -25,11 +25,11 @@ export class BaseMappedList extends BaseObservableList { protected _sourceList: BaseObservableList; protected _sourceUnsubscribe: (() => void) | null = null; _mapper: Mapper; - _updater: Updater; + _updater?: Updater; _removeCallback?: (value: T) => void; _mappedValues: T[] | null = null; - constructor(sourceList: BaseObservableList, mapper: Mapper, updater: Updater, removeCallback?: (value: T) => void) { + constructor(sourceList: BaseObservableList, mapper: Mapper, updater?: Updater, removeCallback?: (value: T) => void) { super(); this._sourceList = sourceList; this._mapper = mapper; From 1363af24a7d5010e86db9bb4ae586f5f68f7f6bf Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 19:40:48 -0700 Subject: [PATCH 11/62] Add type annotations to MappedList --- src/observable/list/MappedList.ts | 42 ++++++++++++++++--------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/observable/list/MappedList.ts b/src/observable/list/MappedList.ts index 39a2cf0d..ebb418d3 100644 --- a/src/observable/list/MappedList.ts +++ b/src/observable/list/MappedList.ts @@ -15,9 +15,10 @@ See the License for the specific language governing permissions and limitations under the License. */ +import {IListObserver} from "./BaseObservableList"; import {BaseMappedList, runAdd, runUpdate, runRemove, runMove, runReset} from "./BaseMappedList"; -export class MappedList extends BaseMappedList { +export class MappedList extends BaseMappedList implements IListObserver { onSubscribeFirst() { this._sourceUnsubscribe = this._sourceList.subscribe(this); this._mappedValues = []; @@ -26,16 +27,16 @@ export class MappedList extends BaseMappedList { } } - onReset() { + onReset(): void { runReset(this); } - onAdd(index, value) { + onAdd(index: number, value: F): void { const mappedValue = this._mapper(value); runAdd(this, index, mappedValue); } - onUpdate(index, value, params) { + onUpdate(index: number, value: F, params: any): void { // if an update is emitted while calling source.subscribe() from onSubscribeFirst, ignore it if (!this._mappedValues) { return; @@ -43,24 +44,25 @@ export class MappedList extends BaseMappedList { runUpdate(this, index, value, params); } - onRemove(index) { + onRemove(index: number): void { runRemove(this, index); } - onMove(fromIdx, toIdx) { + onMove(fromIdx: number, toIdx: number): void { runMove(this, fromIdx, toIdx); } - onUnsubscribeLast() { - this._sourceUnsubscribe(); + onUnsubscribeLast(): void { + this._sourceUnsubscribe!(); } } import {ObservableArray} from "./ObservableArray"; import {BaseObservableList} from "./BaseObservableList"; +import {defaultObserverWith} from "./BaseObservableList"; export async function tests() { - class MockList extends BaseObservableList { + class MockList extends BaseObservableList { get length() { return 0; } @@ -74,26 +76,26 @@ export async function tests() { const source = new MockList(); const mapped = new MappedList(source, n => {return {n: n*n};}); let fired = false; - const unsubscribe = mapped.subscribe({ + const unsubscribe = mapped.subscribe(defaultObserverWith({ onAdd(idx, value) { fired = true; assert.equal(idx, 0); assert.equal(value.n, 36); } - }); + })); source.emitAdd(0, 6); assert(fired); unsubscribe(); }, test_update(assert) { const source = new MockList(); - const mapped = new MappedList( + const mapped = new MappedList( source, n => {return {n: n*n};}, (o, p, n) => o.m = n*n ); let fired = false; - const unsubscribe = mapped.subscribe({ + const unsubscribe = mapped.subscribe(defaultObserverWith({ onAdd() {}, onUpdate(idx, value) { fired = true; @@ -101,7 +103,7 @@ export async function tests() { assert.equal(value.n, 36); assert.equal(value.m, 49); } - }); + })); source.emitAdd(0, 6); source.emitUpdate(0, 7); assert(fired); @@ -113,9 +115,9 @@ export async function tests() { source, n => {return n*n;} ); - mapped.subscribe({ + mapped.subscribe(defaultObserverWith({ onUpdate() { assert.fail(); } - }); + })); assert.equal(mapped.findAndUpdate( n => n === 100, () => assert.fail() @@ -127,9 +129,9 @@ export async function tests() { source, n => {return n*n;} ); - mapped.subscribe({ + mapped.subscribe(defaultObserverWith({ onUpdate() { assert.fail(); } - }); + })); let fired = false; assert.equal(mapped.findAndUpdate( n => n === 9, @@ -148,14 +150,14 @@ export async function tests() { n => {return n*n;} ); let fired = false; - mapped.subscribe({ + mapped.subscribe(defaultObserverWith({ onUpdate(idx, n, params) { assert.equal(idx, 1); assert.equal(n, 9); assert.equal(params, "param"); fired = true; } - }); + })); assert.equal(mapped.findAndUpdate(n => n === 9, () => "param"), true); assert.equal(fired, true); }, From 7b2e452cd5c61fb6265fcb16820423162e27a0cf Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 19:43:48 -0700 Subject: [PATCH 12/62] Rename SortedArray to TypeScript --- src/matrix/room/sending/SendQueue.js | 2 +- src/observable/index.js | 2 +- src/observable/list/{SortedArray.js => SortedArray.ts} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/observable/list/{SortedArray.js => SortedArray.ts} (100%) diff --git a/src/matrix/room/sending/SendQueue.js b/src/matrix/room/sending/SendQueue.js index 28408e34..7ba48b15 100644 --- a/src/matrix/room/sending/SendQueue.js +++ b/src/matrix/room/sending/SendQueue.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {SortedArray} from "../../../observable/list/SortedArray.js"; +import {SortedArray} from "../../../observable/list/SortedArray"; import {ConnectionError} from "../../error.js"; import {PendingEvent, SendStatus} from "./PendingEvent.js"; import {makeTxnId, isTxnId} from "../../common.js"; diff --git a/src/observable/index.js b/src/observable/index.js index 35ecaffc..4d7f18a3 100644 --- a/src/observable/index.js +++ b/src/observable/index.js @@ -21,7 +21,7 @@ import {JoinedMap} from "./map/JoinedMap.js"; import {BaseObservableMap} from "./map/BaseObservableMap.js"; // re-export "root" (of chain) collections export { ObservableArray } from "./list/ObservableArray"; -export { SortedArray } from "./list/SortedArray.js"; +export { SortedArray } from "./list/SortedArray"; export { MappedList } from "./list/MappedList"; export { AsyncMappedList } from "./list/AsyncMappedList"; export { ConcatList } from "./list/ConcatList"; diff --git a/src/observable/list/SortedArray.js b/src/observable/list/SortedArray.ts similarity index 100% rename from src/observable/list/SortedArray.js rename to src/observable/list/SortedArray.ts From 3d2c74a760ceeaafe920dca141e0eb4b58792510 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 19:52:35 -0700 Subject: [PATCH 13/62] Add type annotations to SortedArray --- src/observable/list/SortedArray.ts | 47 +++++++++++++++++------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/observable/list/SortedArray.ts b/src/observable/list/SortedArray.ts index 874d1b04..9feade07 100644 --- a/src/observable/list/SortedArray.ts +++ b/src/observable/list/SortedArray.ts @@ -18,18 +18,22 @@ import {BaseObservableList} from "./BaseObservableList"; import {sortedIndex} from "../../utils/sortedIndex.js"; import {findAndUpdateInArray} from "./common"; -export class SortedArray extends BaseObservableList { - constructor(comparator) { +declare function sortedIndex(array: T[], value: T, comparator: (left: T, right: T) => number): number; + +export class SortedArray extends BaseObservableList { + private _comparator: (left: T, right: T) => number; + private _items: T[] = []; + + constructor(comparator: (left: T, right: T) => number) { super(); this._comparator = comparator; - this._items = []; } - setManyUnsorted(items) { + setManyUnsorted(items: T[]): void { this.setManySorted(items); } - setManySorted(items) { + setManySorted(items: T[]): void { // TODO: we can make this way faster by only looking up the first and last key, // and merging whatever is inbetween with items // if items is not sorted, 💩🌀 will follow! @@ -42,11 +46,11 @@ export class SortedArray extends BaseObservableList { } } - findAndUpdate(predicate, updater) { + findAndUpdate(predicate: (value: T) => boolean, updater: (value: T) => any | false): boolean { return findAndUpdateInArray(predicate, this._items, this, updater); } - getAndUpdate(item, updater, updateParams = null) { + getAndUpdate(item: T, updater: (existing: T, item: T) => any, updateParams: any = null): void { const idx = this.indexOf(item); if (idx !== -1) { const existingItem = this._items[idx]; @@ -56,7 +60,7 @@ export class SortedArray extends BaseObservableList { } } - update(item, updateParams = null) { + update(item: T, updateParams: any = null): void { const idx = this.indexOf(item); if (idx !== -1) { this._items[idx] = item; @@ -64,7 +68,7 @@ export class SortedArray extends BaseObservableList { } } - indexOf(item) { + indexOf(item: T): number { const idx = sortedIndex(this._items, item, this._comparator); if (idx < this._items.length && this._comparator(this._items[idx], item) === 0) { return idx; @@ -73,7 +77,7 @@ export class SortedArray extends BaseObservableList { } } - _getNext(item) { + _getNext(item: T): T | undefined { let idx = sortedIndex(this._items, item, this._comparator); while(idx < this._items.length && this._comparator(this._items[idx], item) <= 0) { idx += 1; @@ -81,7 +85,7 @@ export class SortedArray extends BaseObservableList { return this.get(idx); } - set(item, updateParams = null) { + set(item: T, updateParams: any = null): void { const idx = sortedIndex(this._items, item, this._comparator); if (idx >= this._items.length || this._comparator(this._items[idx], item) !== 0) { this._items.splice(idx, 0, item); @@ -92,21 +96,21 @@ export class SortedArray extends BaseObservableList { } } - get(idx) { + get(idx: number): T | undefined { return this._items[idx]; } - remove(idx) { + remove(idx: number): void { const item = this._items[idx]; this._items.splice(idx, 1); this.emitRemove(idx, item); } - get array() { + get array(): T[] { return this._items; } - get length() { + get length(): number { return this._items.length; } @@ -116,8 +120,11 @@ export class SortedArray extends BaseObservableList { } // iterator that works even if the current value is removed while iterating -class Iterator { - constructor(sortedArray) { +class Iterator { + private _sortedArray: SortedArray | null + private _current: T | null | undefined + + constructor(sortedArray: SortedArray) { this._sortedArray = sortedArray; this._current = null; } @@ -145,7 +152,7 @@ class Iterator { export function tests() { return { "setManyUnsorted": assert => { - const sa = new SortedArray((a, b) => a.localeCompare(b)); + const sa = new SortedArray((a, b) => a.localeCompare(b)); sa.setManyUnsorted(["b", "a", "c"]); assert.equal(sa.length, 3); assert.equal(sa.get(0), "a"); @@ -153,7 +160,7 @@ export function tests() { assert.equal(sa.get(2), "c"); }, "_getNext": assert => { - const sa = new SortedArray((a, b) => a.localeCompare(b)); + const sa = new SortedArray((a, b) => a.localeCompare(b)); sa.setManyUnsorted(["b", "a", "f"]); assert.equal(sa._getNext("a"), "b"); assert.equal(sa._getNext("b"), "f"); @@ -162,7 +169,7 @@ export function tests() { assert.equal(sa._getNext("f"), undefined); }, "iterator with removals": assert => { - const queue = new SortedArray((a, b) => a.idx - b.idx); + const queue = new SortedArray<{idx: number}>((a, b) => a.idx - b.idx); queue.setManyUnsorted([{idx: 5}, {idx: 3}, {idx: 1}, {idx: 4}, {idx: 2}]); const it = queue[Symbol.iterator](); assert.equal(it.next().value.idx, 1); From 7772643b0d34357dd7c9aa08c0689164c6ddf862 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 15 Nov 2021 12:45:27 +0530 Subject: [PATCH 14/62] Disposables.js --> Disposables.ts --- src/utils/{Disposables.js => Disposables.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/utils/{Disposables.js => Disposables.ts} (100%) diff --git a/src/utils/Disposables.js b/src/utils/Disposables.ts similarity index 100% rename from src/utils/Disposables.js rename to src/utils/Disposables.ts From dd74ed19570f7091769d15f20e25957758e1a4b9 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 15 Nov 2021 13:08:32 +0530 Subject: [PATCH 15/62] Add types to disposeValue --- src/utils/Disposables.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/utils/Disposables.ts b/src/utils/Disposables.ts index b63cba85..6b9200f0 100644 --- a/src/utils/Disposables.ts +++ b/src/utils/Disposables.ts @@ -14,7 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -function disposeValue(value) { +type func = () => void; +type Disposable = { dispose: func; [key: string]: any } | func; + +function disposeValue(value: Disposable): void { if (typeof value === "function") { value(); } else { @@ -27,9 +30,7 @@ function isDisposable(value) { } export class Disposables { - constructor() { - this._disposables = []; - } + private readonly _disposables = []; track(disposable) { if (!isDisposable(disposable)) { From 7270918b652438be2124d178c01b325dc8c0f5a4 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 15 Nov 2021 13:43:39 +0530 Subject: [PATCH 16/62] Convert Disposables to typescript --- src/utils/Disposables.ts | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/utils/Disposables.ts b/src/utils/Disposables.ts index 6b9200f0..e05b1e87 100644 --- a/src/utils/Disposables.ts +++ b/src/utils/Disposables.ts @@ -25,14 +25,15 @@ function disposeValue(value: Disposable): void { } } -function isDisposable(value) { +function isDisposable(value: Disposable): boolean { + // todo: value can be undefined I think? return value && (typeof value === "function" || typeof value.dispose === "function"); } export class Disposables { - private readonly _disposables = []; + private _disposables: Disposable[] | null = []; - track(disposable) { + track(disposable: Disposable): Disposable { if (!isDisposable(disposable)) { throw new Error("Not a disposable"); } @@ -41,19 +42,23 @@ export class Disposables { disposeValue(disposable); return disposable; } - this._disposables.push(disposable); + this._disposables!.push(disposable); return disposable; } - untrack(disposable) { - const idx = this._disposables.indexOf(disposable); + untrack(disposable: Disposable) { + if (this.isDisposed) { + console.warn("Disposables already disposed, cannot untrack"); + return; + } + const idx = this._disposables!.indexOf(disposable); if (idx >= 0) { - this._disposables.splice(idx, 1); + this._disposables!.splice(idx, 1); } return null; } - dispose() { + dispose(): void { if (this._disposables) { for (const d of this._disposables) { disposeValue(d); @@ -62,17 +67,17 @@ export class Disposables { } } - get isDisposed() { + get isDisposed(): boolean { return this._disposables === null; } - disposeTracked(value) { + disposeTracked(value: Disposable): null { if (value === undefined || value === null || this.isDisposed) { return null; } - const idx = this._disposables.indexOf(value); + const idx = this._disposables!.indexOf(value); if (idx !== -1) { - const [foundValue] = this._disposables.splice(idx, 1); + const [foundValue] = this._disposables!.splice(idx, 1); disposeValue(foundValue); } else { console.warn("disposable not found, did it leak?", value); From 7d12c2ba54a34fb837f620ae76ba46bd25cff03d Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 14:09:37 +0530 Subject: [PATCH 17/62] Add return types --- src/utils/Disposables.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/utils/Disposables.ts b/src/utils/Disposables.ts index e05b1e87..dc538c99 100644 --- a/src/utils/Disposables.ts +++ b/src/utils/Disposables.ts @@ -26,7 +26,6 @@ function disposeValue(value: Disposable): void { } function isDisposable(value: Disposable): boolean { - // todo: value can be undefined I think? return value && (typeof value === "function" || typeof value.dispose === "function"); } @@ -46,10 +45,10 @@ export class Disposables { return disposable; } - untrack(disposable: Disposable) { + untrack(disposable: Disposable): null { if (this.isDisposed) { console.warn("Disposables already disposed, cannot untrack"); - return; + return null; } const idx = this._disposables!.indexOf(disposable); if (idx >= 0) { From ef53a12f7ab24705d57c53178d18aa415677877c Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 14:13:35 +0530 Subject: [PATCH 18/62] Fix imports --- src/domain/ViewModel.js | 2 +- src/matrix/room/timeline/Timeline.js | 2 +- src/platform/web/Platform.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/domain/ViewModel.js b/src/domain/ViewModel.js index f0e109f8..0c665194 100644 --- a/src/domain/ViewModel.js +++ b/src/domain/ViewModel.js @@ -19,7 +19,7 @@ limitations under the License. // we do need to return a disposable from EventEmitter.on, or at least have a method here to easily track a subscription to an EventEmitter import {EventEmitter} from "../utils/EventEmitter"; -import {Disposables} from "../utils/Disposables.js"; +import {Disposables} from "../utils/Disposables"; export class ViewModel extends EventEmitter { constructor(options = {}) { diff --git a/src/matrix/room/timeline/Timeline.js b/src/matrix/room/timeline/Timeline.js index bd89ee8d..04adde0d 100644 --- a/src/matrix/room/timeline/Timeline.js +++ b/src/matrix/room/timeline/Timeline.js @@ -16,7 +16,7 @@ limitations under the License. */ import {SortedArray, AsyncMappedList, ConcatList, ObservableArray} from "../../../observable/index.js"; -import {Disposables} from "../../../utils/Disposables.js"; +import {Disposables} from "../../../utils/Disposables"; import {Direction} from "./Direction"; import {TimelineReader} from "./persistence/TimelineReader.js"; import {PendingEventEntry} from "./entries/PendingEventEntry.js"; diff --git a/src/platform/web/Platform.js b/src/platform/web/Platform.js index f6cd2895..3e1d6791 100644 --- a/src/platform/web/Platform.js +++ b/src/platform/web/Platform.js @@ -35,7 +35,7 @@ import {WorkerPool} from "./dom/WorkerPool.js"; import {BlobHandle} from "./dom/BlobHandle.js"; import {hasReadPixelPermission, ImageHandle, VideoHandle} from "./dom/ImageHandle.js"; import {downloadInIframe} from "./dom/download.js"; -import {Disposables} from "../../utils/Disposables.js"; +import {Disposables} from "../../utils/Disposables"; import {parseHTML} from "./parsehtml.js"; import {handleAvatarError} from "./ui/avatar.js"; From 4ce7634201e8fd56d503a1c3572cb89b19ba9d18 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 14:21:47 +0530 Subject: [PATCH 19/62] Convert error.js to ts --- src/matrix/error.js | 2 +- src/matrix/net/ExponentialRetryDelay.js | 2 +- src/matrix/net/RequestScheduler.js | 2 +- src/matrix/room/sending/PendingEvent.js | 2 +- src/matrix/storage/idb/utils.ts | 2 +- src/mocks/Request.js | 2 +- src/observable/ObservableValue.ts | 2 +- src/platform/web/dom/Clock.js | 2 +- src/platform/web/dom/WorkerPool.js | 2 +- src/utils/{error.js => error.ts} | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) rename src/utils/{error.js => error.ts} (96%) diff --git a/src/matrix/error.js b/src/matrix/error.js index 07144acd..0dd2b688 100644 --- a/src/matrix/error.js +++ b/src/matrix/error.js @@ -38,7 +38,7 @@ export class HomeServerError extends Error { } } -export {AbortError} from "../utils/error.js"; +export {AbortError} from "../utils/error"; export class ConnectionError extends Error { constructor(message, isTimeout) { diff --git a/src/matrix/net/ExponentialRetryDelay.js b/src/matrix/net/ExponentialRetryDelay.js index eac4bec0..853f8758 100644 --- a/src/matrix/net/ExponentialRetryDelay.js +++ b/src/matrix/net/ExponentialRetryDelay.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {AbortError} from "../../utils/error.js"; +import {AbortError} from "../../utils/error"; export class ExponentialRetryDelay { constructor(createTimeout) { diff --git a/src/matrix/net/RequestScheduler.js b/src/matrix/net/RequestScheduler.js index 53ab50ac..f9adec97 100644 --- a/src/matrix/net/RequestScheduler.js +++ b/src/matrix/net/RequestScheduler.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {AbortError} from "../../utils/error.js"; +import {AbortError} from "../../utils/error"; import {HomeServerError} from "../error.js"; import {HomeServerApi} from "./HomeServerApi.js"; import {ExponentialRetryDelay} from "./ExponentialRetryDelay.js"; diff --git a/src/matrix/room/sending/PendingEvent.js b/src/matrix/room/sending/PendingEvent.js index 01874178..4c7a0e99 100644 --- a/src/matrix/room/sending/PendingEvent.js +++ b/src/matrix/room/sending/PendingEvent.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ import {createEnum} from "../../../utils/enum.js"; -import {AbortError} from "../../../utils/error.js"; +import {AbortError} from "../../../utils/error"; import {REDACTION_TYPE} from "../common.js"; import {getRelationFromContent, getRelationTarget, setRelationTarget} from "../timeline/relations.js"; diff --git a/src/matrix/storage/idb/utils.ts b/src/matrix/storage/idb/utils.ts index ca6e06de..4ac373d2 100644 --- a/src/matrix/storage/idb/utils.ts +++ b/src/matrix/storage/idb/utils.ts @@ -17,7 +17,7 @@ limitations under the License. import { IDBRequestError } from "./error"; import { StorageError } from "../common"; -import { AbortError } from "../../../utils/error.js"; +import { AbortError } from "../../../utils/error"; let needsSyncPromise = false; diff --git a/src/mocks/Request.js b/src/mocks/Request.js index 1984f06f..14a3fabf 100644 --- a/src/mocks/Request.js +++ b/src/mocks/Request.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {AbortError} from "../utils/error.js"; +import {AbortError} from "../utils/error"; export class BaseRequest { constructor() { diff --git a/src/observable/ObservableValue.ts b/src/observable/ObservableValue.ts index 02d5fc69..b3ffa6ee 100644 --- a/src/observable/ObservableValue.ts +++ b/src/observable/ObservableValue.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {AbortError} from "../utils/error.js"; +import {AbortError} from "../utils/error"; import {BaseObservable} from "./BaseObservable"; // like an EventEmitter, but doesn't have an event type diff --git a/src/platform/web/dom/Clock.js b/src/platform/web/dom/Clock.js index 7e64de47..855e925c 100644 --- a/src/platform/web/dom/Clock.js +++ b/src/platform/web/dom/Clock.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {AbortError} from "../../../utils/error.js"; +import {AbortError} from "../../../utils/error"; class Timeout { constructor(ms) { diff --git a/src/platform/web/dom/WorkerPool.js b/src/platform/web/dom/WorkerPool.js index aeb6ca89..c36ffb78 100644 --- a/src/platform/web/dom/WorkerPool.js +++ b/src/platform/web/dom/WorkerPool.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {AbortError} from "../../../utils/error.js"; +import {AbortError} from "../../../utils/error"; class WorkerState { constructor(worker) { diff --git a/src/utils/error.js b/src/utils/error.ts similarity index 96% rename from src/utils/error.js rename to src/utils/error.ts index 820f0673..dcade6ce 100644 --- a/src/utils/error.js +++ b/src/utils/error.ts @@ -15,7 +15,7 @@ limitations under the License. */ export class AbortError extends Error { - get name() { + get name(): string { return "AbortError"; } } From a3460d8c2aa8acc58799eca1ef599b4982576b5c Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 14:44:16 +0530 Subject: [PATCH 20/62] Convert formatSize to ts --- src/domain/session/room/timeline/tiles/FileTile.js | 2 +- src/utils/{formatSize.js => formatSize.ts} | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) rename src/utils/{formatSize.js => formatSize.ts} (92%) diff --git a/src/domain/session/room/timeline/tiles/FileTile.js b/src/domain/session/room/timeline/tiles/FileTile.js index c761e68e..1007d28c 100644 --- a/src/domain/session/room/timeline/tiles/FileTile.js +++ b/src/domain/session/room/timeline/tiles/FileTile.js @@ -16,7 +16,7 @@ limitations under the License. */ import {BaseMessageTile} from "./BaseMessageTile.js"; -import {formatSize} from "../../../../../utils/formatSize.js"; +import {formatSize} from "../../../../../utils/formatSize"; import {SendStatus} from "../../../../../matrix/room/sending/PendingEvent.js"; export class FileTile extends BaseMessageTile { diff --git a/src/utils/formatSize.js b/src/utils/formatSize.ts similarity index 92% rename from src/utils/formatSize.js rename to src/utils/formatSize.ts index d001dacd..14ec6387 100644 --- a/src/utils/formatSize.js +++ b/src/utils/formatSize.ts @@ -14,7 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -export function formatSize(size, decimals = 2) { + +export function formatSize(size: number, decimals: number = 2): string | undefined { if (Number.isSafeInteger(size)) { const base = Math.min(3, Math.floor(Math.log(size) / Math.log(1024))); const formattedSize = Math.round(size / Math.pow(1024, base)).toFixed(decimals); From c8eb7ea7ac911a53242c239dfe461d5450b91ee5 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 15:06:19 +0530 Subject: [PATCH 21/62] Convert Lock.js to ts --- src/matrix/e2ee/olm/Decryption.js | 2 +- src/utils/{Lock.js => Lock.ts} | 26 ++++++++++++-------------- src/utils/LockMap.js | 2 +- 3 files changed, 14 insertions(+), 16 deletions(-) rename src/utils/{Lock.js => Lock.ts} (83%) diff --git a/src/matrix/e2ee/olm/Decryption.js b/src/matrix/e2ee/olm/Decryption.js index 0af3bd23..16e617a5 100644 --- a/src/matrix/e2ee/olm/Decryption.js +++ b/src/matrix/e2ee/olm/Decryption.js @@ -16,7 +16,7 @@ limitations under the License. import {DecryptionError} from "../common.js"; import {groupBy} from "../../../utils/groupBy"; -import {MultiLock} from "../../../utils/Lock.js"; +import {MultiLock} from "../../../utils/Lock"; import {Session} from "./Session.js"; import {DecryptionResult} from "../DecryptionResult.js"; diff --git a/src/utils/Lock.js b/src/utils/Lock.ts similarity index 83% rename from src/utils/Lock.js rename to src/utils/Lock.ts index 8cfc733f..ce7101de 100644 --- a/src/utils/Lock.js +++ b/src/utils/Lock.ts @@ -15,12 +15,10 @@ limitations under the License. */ export class Lock { - constructor() { - this._promise = null; - this._resolve = null; - } + private _promise: Promise | null = null; + private _resolve: (() => void) | null = null; - tryTake() { + tryTake(): boolean { if (!this._promise) { this._promise = new Promise(resolve => { this._resolve = resolve; @@ -30,17 +28,17 @@ export class Lock { return false; } - async take() { + async take(): Promise { while(!this.tryTake()) { await this.released(); } } - get isTaken() { + get isTaken(): boolean { return !!this._promise; } - release() { + release(): void { if (this._resolve) { this._promise = null; const resolve = this._resolve; @@ -49,17 +47,17 @@ export class Lock { } } - released() { + released(): Promise | null { return this._promise; } } export class MultiLock { - constructor(locks) { - this.locks = locks; + + constructor(public readonly locks: Lock[]) { } - release() { + release(): void { for (const lock of this.locks) { lock.release(); } @@ -86,9 +84,9 @@ export function tests() { lock.tryTake(); let first; - lock.released().then(() => first = lock.tryTake()); + lock.released()!.then(() => first = lock.tryTake()); let second; - lock.released().then(() => second = lock.tryTake()); + lock.released()!.then(() => second = lock.tryTake()); const promise = lock.released(); lock.release(); await promise; diff --git a/src/utils/LockMap.js b/src/utils/LockMap.js index a73dee4a..567acf4c 100644 --- a/src/utils/LockMap.js +++ b/src/utils/LockMap.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {Lock} from "./Lock.js"; +import {Lock} from "./Lock"; export class LockMap { constructor() { From 1549d8add0874737c80093918e052281822fe785 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 15:26:40 +0530 Subject: [PATCH 22/62] Convert LockMap to ts --- src/matrix/Session.js | 2 +- src/utils/{LockMap.js => LockMap.ts} | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) rename src/utils/{LockMap.js => LockMap.ts} (92%) diff --git a/src/matrix/Session.js b/src/matrix/Session.js index 37fd90ad..874bfecd 100644 --- a/src/matrix/Session.js +++ b/src/matrix/Session.js @@ -34,7 +34,7 @@ import {Encryption as MegOlmEncryption} from "./e2ee/megolm/Encryption.js"; import {MEGOLM_ALGORITHM} from "./e2ee/common.js"; import {RoomEncryption} from "./e2ee/RoomEncryption.js"; import {DeviceTracker} from "./e2ee/DeviceTracker.js"; -import {LockMap} from "../utils/LockMap.js"; +import {LockMap} from "../utils/LockMap"; import {groupBy} from "../utils/groupBy"; import { keyFromCredential as ssssKeyFromCredential, diff --git a/src/utils/LockMap.js b/src/utils/LockMap.ts similarity index 92% rename from src/utils/LockMap.js rename to src/utils/LockMap.ts index 567acf4c..5952f031 100644 --- a/src/utils/LockMap.js +++ b/src/utils/LockMap.ts @@ -17,11 +17,9 @@ limitations under the License. import {Lock} from "./Lock"; export class LockMap { - constructor() { - this._map = new Map(); - } + private readonly _map: Map = new Map(); - async takeLock(key) { + async takeLock(key: unknown): Promise { let lock = this._map.get(key); if (lock) { await lock.take(); @@ -31,10 +29,10 @@ export class LockMap { this._map.set(key, lock); } // don't leave old locks lying around - lock.released().then(() => { + lock.released()!.then(() => { // give others a chance to take the lock first Promise.resolve().then(() => { - if (!lock.isTaken) { + if (!lock!.isTaken) { this._map.delete(key); } }); @@ -67,6 +65,7 @@ export function tests() { ranSecond = true; assert.equal(returnedLock.isTaken, true); // peek into internals, naughty + // @ts-ignore assert.equal(lockMap._map.get("foo"), returnedLock); }); lock.release(); @@ -84,6 +83,7 @@ export function tests() { // double delay to make sure cleanup logic ran await Promise.resolve(); await Promise.resolve(); + // @ts-ignore assert.equal(lockMap._map.has("foo"), false); }, From 88ec1b575d96f566b56bd3c6242aceaef4927575 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 15:37:32 +0530 Subject: [PATCH 23/62] Convert mergeMap.js to ts --- src/matrix/e2ee/RoomEncryption.js | 2 +- src/matrix/e2ee/megolm/decryption/DecryptionPreparation.js | 2 +- src/utils/{mergeMap.js => mergeMap.ts} | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/utils/{mergeMap.js => mergeMap.ts} (93%) diff --git a/src/matrix/e2ee/RoomEncryption.js b/src/matrix/e2ee/RoomEncryption.js index 430d9af3..d9151a85 100644 --- a/src/matrix/e2ee/RoomEncryption.js +++ b/src/matrix/e2ee/RoomEncryption.js @@ -16,7 +16,7 @@ limitations under the License. import {MEGOLM_ALGORITHM, DecryptionSource} from "./common.js"; import {groupEventsBySession} from "./megolm/decryption/utils"; -import {mergeMap} from "../../utils/mergeMap.js"; +import {mergeMap} from "../../utils/mergeMap"; import {groupBy} from "../../utils/groupBy"; import {makeTxnId} from "../common.js"; diff --git a/src/matrix/e2ee/megolm/decryption/DecryptionPreparation.js b/src/matrix/e2ee/megolm/decryption/DecryptionPreparation.js index 02ee32df..618955bb 100644 --- a/src/matrix/e2ee/megolm/decryption/DecryptionPreparation.js +++ b/src/matrix/e2ee/megolm/decryption/DecryptionPreparation.js @@ -15,7 +15,7 @@ limitations under the License. */ import {DecryptionChanges} from "./DecryptionChanges.js"; -import {mergeMap} from "../../../../utils/mergeMap.js"; +import {mergeMap} from "../../../../utils/mergeMap"; /** * Class that contains all the state loaded from storage to decrypt the given events diff --git a/src/utils/mergeMap.js b/src/utils/mergeMap.ts similarity index 93% rename from src/utils/mergeMap.js rename to src/utils/mergeMap.ts index a0aed207..21ad0086 100644 --- a/src/utils/mergeMap.js +++ b/src/utils/mergeMap.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -export function mergeMap(src, dst) { +export function mergeMap(src: Map | undefined, dst: Map) { if (src) { for (const [key, value] of src.entries()) { dst.set(key, value); From ea0adb440715414a6a19641cdbf2206c8910db20 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 15:41:50 +0530 Subject: [PATCH 24/62] Convert RetainedValue.js to ts --- src/matrix/room/members/MemberList.js | 2 +- src/utils/{RetainedValue.js => RetainedValue.ts} | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) rename src/utils/{RetainedValue.js => RetainedValue.ts} (82%) diff --git a/src/matrix/room/members/MemberList.js b/src/matrix/room/members/MemberList.js index de07adf5..9923fb87 100644 --- a/src/matrix/room/members/MemberList.js +++ b/src/matrix/room/members/MemberList.js @@ -15,7 +15,7 @@ limitations under the License. */ import {ObservableMap} from "../../../observable/map/ObservableMap.js"; -import {RetainedValue} from "../../../utils/RetainedValue.js"; +import {RetainedValue} from "../../../utils/RetainedValue"; export class MemberList extends RetainedValue { constructor({members, closeCallback}) { diff --git a/src/utils/RetainedValue.js b/src/utils/RetainedValue.ts similarity index 82% rename from src/utils/RetainedValue.js rename to src/utils/RetainedValue.ts index b3ed7a91..a67b848b 100644 --- a/src/utils/RetainedValue.js +++ b/src/utils/RetainedValue.ts @@ -15,16 +15,18 @@ limitations under the License. */ export class RetainedValue { - constructor(freeCallback) { + private readonly _freeCallback: () => void; + private _retentionCount: number = 1; + + constructor(freeCallback: () => void) { this._freeCallback = freeCallback; - this._retentionCount = 1; } - retain() { + retain(): void { this._retentionCount += 1; } - release() { + release(): void { this._retentionCount -= 1; if (this._retentionCount === 0) { this._freeCallback(); From 8a169d5ddc6886eb0a289ea4517bf4f2d374a8c9 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 15:52:42 +0530 Subject: [PATCH 25/62] Convert sortedIndex.js to ts --- src/domain/session/room/timeline/TilesCollection.js | 2 +- src/observable/list/SortedArray.js | 2 +- src/observable/list/SortedMapList.js | 2 +- src/utils/{sortedIndex.js => sortedIndex.ts} | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/utils/{sortedIndex.js => sortedIndex.ts} (93%) diff --git a/src/domain/session/room/timeline/TilesCollection.js b/src/domain/session/room/timeline/TilesCollection.js index b3696fad..8dce4125 100644 --- a/src/domain/session/room/timeline/TilesCollection.js +++ b/src/domain/session/room/timeline/TilesCollection.js @@ -15,7 +15,7 @@ limitations under the License. */ import {BaseObservableList} from "../../../../observable/list/BaseObservableList"; -import {sortedIndex} from "../../../../utils/sortedIndex.js"; +import {sortedIndex} from "../../../../utils/sortedIndex"; // maps 1..n entries to 0..1 tile. Entries are what is stored in the timeline, either an event or fragmentboundary // for now, tileCreator should be stable in whether it returns a tile or not. diff --git a/src/observable/list/SortedArray.js b/src/observable/list/SortedArray.js index 874d1b04..1201845c 100644 --- a/src/observable/list/SortedArray.js +++ b/src/observable/list/SortedArray.js @@ -15,7 +15,7 @@ limitations under the License. */ import {BaseObservableList} from "./BaseObservableList"; -import {sortedIndex} from "../../utils/sortedIndex.js"; +import {sortedIndex} from "../../utils/sortedIndex"; import {findAndUpdateInArray} from "./common"; export class SortedArray extends BaseObservableList { diff --git a/src/observable/list/SortedMapList.js b/src/observable/list/SortedMapList.js index 2421419e..38900380 100644 --- a/src/observable/list/SortedMapList.js +++ b/src/observable/list/SortedMapList.js @@ -15,7 +15,7 @@ limitations under the License. */ import {BaseObservableList} from "./BaseObservableList"; -import {sortedIndex} from "../../utils/sortedIndex.js"; +import {sortedIndex} from "../../utils/sortedIndex"; /* diff --git a/src/utils/sortedIndex.js b/src/utils/sortedIndex.ts similarity index 93% rename from src/utils/sortedIndex.js rename to src/utils/sortedIndex.ts index e0acb5ff..0022cb87 100644 --- a/src/utils/sortedIndex.js +++ b/src/utils/sortedIndex.ts @@ -22,7 +22,7 @@ limitations under the License. * Based on Underscore.js 1.8.3 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors */ -export function sortedIndex(array, value, comparator) { +export function sortedIndex(array: T[], value: T, comparator: (x:T, y:T) => number): number { let low = 0; let high = array.length; From afecac3e3cd8b851c8a2df90b9556ea6f01a54a2 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 16:14:13 +0530 Subject: [PATCH 26/62] Convert timeout.js to ts --- src/platform/web/dom/request/fetch.js | 2 +- src/utils/{timeout.js => timeout.ts} | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) rename src/utils/{timeout.js => timeout.ts} (88%) diff --git a/src/platform/web/dom/request/fetch.js b/src/platform/web/dom/request/fetch.js index 66f1a148..adf833ef 100644 --- a/src/platform/web/dom/request/fetch.js +++ b/src/platform/web/dom/request/fetch.js @@ -19,7 +19,7 @@ import { AbortError, ConnectionError } from "../../../../matrix/error.js"; -import {abortOnTimeout} from "../../../../utils/timeout.js"; +import {abortOnTimeout} from "../../../../utils/timeout"; import {addCacheBuster} from "./common.js"; import {xhrRequest} from "./xhr.js"; diff --git a/src/utils/timeout.js b/src/utils/timeout.ts similarity index 88% rename from src/utils/timeout.js rename to src/utils/timeout.ts index 6bfc0d7e..96efc10d 100644 --- a/src/utils/timeout.js +++ b/src/utils/timeout.ts @@ -16,9 +16,13 @@ limitations under the License. */ import {ConnectionError} from "../matrix/error.js"; +import type {Timeout} from "../platform/web/dom/Clock.js" +type TimeoutCreator = (ms: number) => Timeout; +// ts-todo: export type RequestResult from fetch.js? we'll need to wait until it's typescript though. +type Abortable = { abort(): void; [key: string]: any }; -export function abortOnTimeout(createTimeout, timeoutAmount, requestResult, responsePromise) { +export function abortOnTimeout(createTimeout: TimeoutCreator, timeoutAmount: number, requestResult: Abortable, responsePromise: Promise) { const timeout = createTimeout(timeoutAmount); // abort request if timeout finishes first let timedOut = false; From 6c2aa1bf61fce74bb3c80d73a2d71b784740a627 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 14:04:43 +0530 Subject: [PATCH 27/62] Convert hkdf.js to ts --- src/platform/web/LegacyPlatform.js | 2 +- src/utils/crypto/{hkdf.js => hkdf.ts} | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) rename src/utils/crypto/{hkdf.js => hkdf.ts} (83%) diff --git a/src/platform/web/LegacyPlatform.js b/src/platform/web/LegacyPlatform.js index e6bf7774..5cbfb52f 100644 --- a/src/platform/web/LegacyPlatform.js +++ b/src/platform/web/LegacyPlatform.js @@ -15,7 +15,7 @@ limitations under the License. */ import aesjs from "../../../lib/aes-js/index.js"; -import {hkdf} from "../../utils/crypto/hkdf.js"; +import {hkdf} from "../../utils/crypto/hkdf"; import {Platform as ModernPlatform} from "./Platform.js"; export function Platform(container, paths) { diff --git a/src/utils/crypto/hkdf.js b/src/utils/crypto/hkdf.ts similarity index 83% rename from src/utils/crypto/hkdf.js rename to src/utils/crypto/hkdf.ts index d46dc496..25c1faf6 100644 --- a/src/utils/crypto/hkdf.js +++ b/src/utils/crypto/hkdf.ts @@ -6,8 +6,10 @@ * Based on https://github.com/junkurihara/jscu/blob/develop/packages/js-crypto-hkdf/src/hkdf.ts */ +import type {Crypto} from "../../platform/web/dom/Crypto.js"; + // forked this code to make it use the cryptoDriver for HMAC that is more backwards-compatible -export async function hkdf(cryptoDriver, key, salt, info, hash, length) { +export async function hkdf(cryptoDriver: Crypto, key: Uint8Array, salt: Uint8Array, info: Uint8Array, hash: string, length: number): Promise { length = length / 8; const len = cryptoDriver.digestSize(hash); From a945edfe07808867f87191ae4cce8c394aa26315 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 14:24:30 +0530 Subject: [PATCH 28/62] Convert pbkdf2.js to ts --- src/utils/crypto/{pbkdf2.js => pbkdf2.ts} | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) rename src/utils/crypto/{pbkdf2.js => pbkdf2.ts} (83%) diff --git a/src/utils/crypto/pbkdf2.js b/src/utils/crypto/pbkdf2.ts similarity index 83% rename from src/utils/crypto/pbkdf2.js rename to src/utils/crypto/pbkdf2.ts index 5a239791..6a8b8495 100644 --- a/src/utils/crypto/pbkdf2.js +++ b/src/utils/crypto/pbkdf2.ts @@ -6,17 +6,19 @@ * Based on https://github.com/junkurihara/jscu/blob/develop/packages/js-crypto-pbkdf/src/pbkdf.ts */ +import type {Crypto} from "../../platform/web/dom/Crypto.js"; + // not used atm, but might in the future // forked this code to make it use the cryptoDriver for HMAC that is more backwards-compatible -const nwbo = (num, len) => { +const nwbo = (num: number, len: number): Uint8Array => { const arr = new Uint8Array(len); for(let i=0; i> ((len - i - 1)*8)); return arr; }; -export async function pbkdf2(cryptoDriver, password, iterations, salt, hash, length) { +export async function pbkdf2(cryptoDriver: Crypto, password: Uint8Array, iterations: number, salt: Uint8Array, hash: string, length: number): Promise { const dkLen = length / 8; if (iterations <= 0) { throw new Error('InvalidIterationCount'); @@ -30,7 +32,7 @@ export async function pbkdf2(cryptoDriver, password, iterations, salt, hash, len const l = Math.ceil(dkLen/hLen); const r = dkLen - (l-1)*hLen; - const funcF = async (i) => { + const funcF = async (i: number) => { const seed = new Uint8Array(salt.length + 4); seed.set(salt); seed.set(nwbo(i+1, 4), salt.length); @@ -46,7 +48,7 @@ export async function pbkdf2(cryptoDriver, password, iterations, salt, hash, len return {index: i, value: outputF}; }; - const Tis = []; + const Tis: Promise<{index: number, value: Uint8Array}>[] = []; const DK = new Uint8Array(dkLen); for(let i = 0; i < l; i++) { Tis.push(funcF(i)); From 0e18247184f0d041659cc46b07da197b17569bea Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 14:36:15 +0530 Subject: [PATCH 29/62] Use constant type --- src/utils/crypto/hkdf.ts | 2 +- src/utils/crypto/pbkdf2.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/crypto/hkdf.ts b/src/utils/crypto/hkdf.ts index 25c1faf6..44f66029 100644 --- a/src/utils/crypto/hkdf.ts +++ b/src/utils/crypto/hkdf.ts @@ -9,7 +9,7 @@ import type {Crypto} from "../../platform/web/dom/Crypto.js"; // forked this code to make it use the cryptoDriver for HMAC that is more backwards-compatible -export async function hkdf(cryptoDriver: Crypto, key: Uint8Array, salt: Uint8Array, info: Uint8Array, hash: string, length: number): Promise { +export async function hkdf(cryptoDriver: Crypto, key: Uint8Array, salt: Uint8Array, info: Uint8Array, hash: "SHA-256" | "SHA-512", length: number): Promise { length = length / 8; const len = cryptoDriver.digestSize(hash); diff --git a/src/utils/crypto/pbkdf2.ts b/src/utils/crypto/pbkdf2.ts index 6a8b8495..a9108377 100644 --- a/src/utils/crypto/pbkdf2.ts +++ b/src/utils/crypto/pbkdf2.ts @@ -18,7 +18,7 @@ const nwbo = (num: number, len: number): Uint8Array => { return arr; }; -export async function pbkdf2(cryptoDriver: Crypto, password: Uint8Array, iterations: number, salt: Uint8Array, hash: string, length: number): Promise { +export async function pbkdf2(cryptoDriver: Crypto, password: Uint8Array, iterations: number, salt: Uint8Array, hash: "SHA-256" | "SHA-512", length: number): Promise { const dkLen = length / 8; if (iterations <= 0) { throw new Error('InvalidIterationCount'); From ebd1caf6d19583ece0e6795a109bc38fa7ce6b5b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 15:50:04 +0530 Subject: [PATCH 30/62] Convert enum.js to ts --- src/utils/{enum.js => enum.ts} | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) rename src/utils/{enum.js => enum.ts} (80%) diff --git a/src/utils/enum.js b/src/utils/enum.ts similarity index 80% rename from src/utils/enum.js rename to src/utils/enum.ts index 4defcfd7..71365984 100644 --- a/src/utils/enum.js +++ b/src/utils/enum.ts @@ -14,12 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -export function createEnum(...values) { +export function createEnum(...values: string[]): Readonly<{}> { const obj = {}; for (const value of values) { - if (typeof value !== "string") { - throw new Error("Invalid enum value name" + value?.toString()); - } obj[value] = value; } return Object.freeze(obj); From 0c424cb77f054bc5706b49325683fb12c654f476 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 15:54:44 +0530 Subject: [PATCH 31/62] Fix imports --- src/domain/session/SessionStatusViewModel.js | 2 +- src/domain/session/room/timeline/tiles/BaseTextTile.js | 2 +- src/domain/session/settings/SessionBackupViewModel.js | 2 +- src/matrix/SessionContainer.js | 2 +- src/matrix/Sync.js | 2 +- src/matrix/e2ee/common.js | 2 +- src/matrix/net/Reconnector.js | 2 +- src/matrix/room/sending/PendingEvent.js | 2 +- src/matrix/ssss/index.js | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/domain/session/SessionStatusViewModel.js b/src/domain/session/SessionStatusViewModel.js index 108d2aca..27dad7cc 100644 --- a/src/domain/session/SessionStatusViewModel.js +++ b/src/domain/session/SessionStatusViewModel.js @@ -15,7 +15,7 @@ limitations under the License. */ import {ViewModel} from "../ViewModel.js"; -import {createEnum} from "../../utils/enum.js"; +import {createEnum} from "../../utils/enum"; import {ConnectionStatus} from "../../matrix/net/Reconnector.js"; import {SyncStatus} from "../../matrix/Sync.js"; diff --git a/src/domain/session/room/timeline/tiles/BaseTextTile.js b/src/domain/session/room/timeline/tiles/BaseTextTile.js index fb61cb4b..60024ca6 100644 --- a/src/domain/session/room/timeline/tiles/BaseTextTile.js +++ b/src/domain/session/room/timeline/tiles/BaseTextTile.js @@ -16,7 +16,7 @@ limitations under the License. import {BaseMessageTile} from "./BaseMessageTile.js"; import {stringAsBody} from "../MessageBody.js"; -import {createEnum} from "../../../../../utils/enum.js"; +import {createEnum} from "../../../../../utils/enum"; export const BodyFormat = createEnum("Plain", "Html"); diff --git a/src/domain/session/settings/SessionBackupViewModel.js b/src/domain/session/settings/SessionBackupViewModel.js index 533d0f6d..52be43b4 100644 --- a/src/domain/session/settings/SessionBackupViewModel.js +++ b/src/domain/session/settings/SessionBackupViewModel.js @@ -16,7 +16,7 @@ limitations under the License. import {ViewModel} from "../../ViewModel.js"; import {KeyType} from "../../../matrix/ssss/index.js"; -import {createEnum} from "../../../utils/enum.js"; +import {createEnum} from "../../../utils/enum"; export const Status = createEnum("Enabled", "SetupKey", "SetupPhrase", "Pending"); diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 3e3dab66..dc9f9ee8 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {createEnum} from "../utils/enum.js"; +import {createEnum} from "../utils/enum"; import {lookupHomeserver} from "./well-known.js"; import {AbortableOperation} from "../utils/AbortableOperation"; import {ObservableValue} from "../observable/ObservableValue"; diff --git a/src/matrix/Sync.js b/src/matrix/Sync.js index 0be48007..de09a96d 100644 --- a/src/matrix/Sync.js +++ b/src/matrix/Sync.js @@ -16,7 +16,7 @@ limitations under the License. */ import {ObservableValue} from "../observable/ObservableValue"; -import {createEnum} from "../utils/enum.js"; +import {createEnum} from "../utils/enum"; const INCREMENTAL_TIMEOUT = 30000; diff --git a/src/matrix/e2ee/common.js b/src/matrix/e2ee/common.js index fa970236..775e3dd0 100644 --- a/src/matrix/e2ee/common.js +++ b/src/matrix/e2ee/common.js @@ -15,7 +15,7 @@ limitations under the License. */ import anotherjson from "../../../lib/another-json/index.js"; -import {createEnum} from "../../utils/enum.js"; +import {createEnum} from "../../utils/enum"; export const DecryptionSource = createEnum("Sync", "Timeline", "Retry"); diff --git a/src/matrix/net/Reconnector.js b/src/matrix/net/Reconnector.js index 6fd2ca94..6eaa78d7 100644 --- a/src/matrix/net/Reconnector.js +++ b/src/matrix/net/Reconnector.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {createEnum} from "../../utils/enum.js"; +import {createEnum} from "../../utils/enum"; import {ObservableValue} from "../../observable/ObservableValue"; export const ConnectionStatus = createEnum( diff --git a/src/matrix/room/sending/PendingEvent.js b/src/matrix/room/sending/PendingEvent.js index 4c7a0e99..d4c10704 100644 --- a/src/matrix/room/sending/PendingEvent.js +++ b/src/matrix/room/sending/PendingEvent.js @@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import {createEnum} from "../../../utils/enum.js"; +import {createEnum} from "../../../utils/enum"; import {AbortError} from "../../../utils/error"; import {REDACTION_TYPE} from "../common.js"; import {getRelationFromContent, getRelationTarget, setRelationTarget} from "../timeline/relations.js"; diff --git a/src/matrix/ssss/index.js b/src/matrix/ssss/index.js index cb795766..b063ab0b 100644 --- a/src/matrix/ssss/index.js +++ b/src/matrix/ssss/index.js @@ -18,7 +18,7 @@ import {KeyDescription, Key} from "./common.js"; import {keyFromPassphrase} from "./passphrase.js"; import {keyFromRecoveryKey} from "./recoveryKey.js"; import {SESSION_E2EE_KEY_PREFIX} from "../e2ee/common.js"; -import {createEnum} from "../../utils/enum.js"; +import {createEnum} from "../../utils/enum"; const SSSS_KEY = `${SESSION_E2EE_KEY_PREFIX}ssssKey`; From 1beb153f21fa27b6cd9013b6f125231af493f013 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 16:26:19 +0530 Subject: [PATCH 32/62] func --> Func --- src/utils/Disposables.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/Disposables.ts b/src/utils/Disposables.ts index dc538c99..0317825b 100644 --- a/src/utils/Disposables.ts +++ b/src/utils/Disposables.ts @@ -14,8 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -type func = () => void; -type Disposable = { dispose: func; [key: string]: any } | func; +type Func = () => void; +type Disposable = { dispose: Func; [key: string]: any } | Func; function disposeValue(value: Disposable): void { if (typeof value === "function") { From 5a0c06473c215ebb86ba09c0373e6f82e9f6eb50 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 16:28:14 +0530 Subject: [PATCH 33/62] Use undefined instead of null --- src/utils/Lock.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/utils/Lock.ts b/src/utils/Lock.ts index ce7101de..238d88f9 100644 --- a/src/utils/Lock.ts +++ b/src/utils/Lock.ts @@ -15,8 +15,8 @@ limitations under the License. */ export class Lock { - private _promise: Promise | null = null; - private _resolve: (() => void) | null = null; + private _promise?: Promise; + private _resolve?: (() => void); tryTake(): boolean { if (!this._promise) { @@ -40,14 +40,14 @@ export class Lock { release(): void { if (this._resolve) { - this._promise = null; + this._promise = undefined; const resolve = this._resolve; - this._resolve = null; + this._resolve = undefined; resolve(); } } - released(): Promise | null { + released(): Promise | undefined { return this._promise; } } From 08ef84d1121cc6b22d8421b06ad99d4f93cf1100 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 16:33:37 +0530 Subject: [PATCH 34/62] Mention return type --- src/utils/mergeMap.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/mergeMap.ts b/src/utils/mergeMap.ts index 21ad0086..b5d9b524 100644 --- a/src/utils/mergeMap.ts +++ b/src/utils/mergeMap.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -export function mergeMap(src: Map | undefined, dst: Map) { +export function mergeMap(src: Map | undefined, dst: Map): void { if (src) { for (const [key, value] of src.entries()) { dst.set(key, value); From a14a8c3a07cbdbcf7b901e789a44ab0617e93132 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Wed, 17 Nov 2021 19:40:21 +0530 Subject: [PATCH 35/62] Create interface IDisposable Co-authored-by: Bruno Windels --- src/utils/Disposables.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utils/Disposables.ts b/src/utils/Disposables.ts index 0317825b..9671665f 100644 --- a/src/utils/Disposables.ts +++ b/src/utils/Disposables.ts @@ -15,7 +15,11 @@ limitations under the License. */ type Func = () => void; -type Disposable = { dispose: Func; [key: string]: any } | Func; +export interface IDisposable { + dispose(): void; +} + +type Disposable = IDisposable | (() => void); function disposeValue(value: Disposable): void { if (typeof value === "function") { From 048547828d5e70e93a3b107ada97d30253e42778 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 19:41:03 +0530 Subject: [PATCH 36/62] Remove type Func --- src/utils/Disposables.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils/Disposables.ts b/src/utils/Disposables.ts index 9671665f..19a5983c 100644 --- a/src/utils/Disposables.ts +++ b/src/utils/Disposables.ts @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -type Func = () => void; export interface IDisposable { dispose(): void; } From 64a9892ee20e3440e42dbb1028cacdca004c07f7 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 19:44:19 +0530 Subject: [PATCH 37/62] Use generic T in LockMap --- src/utils/LockMap.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/LockMap.ts b/src/utils/LockMap.ts index 5952f031..4c7cba13 100644 --- a/src/utils/LockMap.ts +++ b/src/utils/LockMap.ts @@ -16,10 +16,10 @@ limitations under the License. import {Lock} from "./Lock"; -export class LockMap { - private readonly _map: Map = new Map(); +export class LockMap { + private readonly _map: Map = new Map(); - async takeLock(key: unknown): Promise { + async takeLock(key: T): Promise { let lock = this._map.get(key); if (lock) { await lock.take(); From ea2842f37fc907f29980afe84cbcdb3a8e8ca4a3 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 19:57:38 +0530 Subject: [PATCH 38/62] Return empty string --- src/utils/formatSize.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utils/formatSize.ts b/src/utils/formatSize.ts index 14ec6387..f611c79e 100644 --- a/src/utils/formatSize.ts +++ b/src/utils/formatSize.ts @@ -15,7 +15,7 @@ limitations under the License. */ -export function formatSize(size: number, decimals: number = 2): string | undefined { +export function formatSize(size: number, decimals: number = 2): string { if (Number.isSafeInteger(size)) { const base = Math.min(3, Math.floor(Math.log(size) / Math.log(1024))); const formattedSize = Math.round(size / Math.pow(1024, base)).toFixed(decimals); @@ -26,4 +26,5 @@ export function formatSize(size: number, decimals: number = 2): string | undefin case 3: return `${formattedSize} GB`; } } + return ""; } From 8fcfd713e07e8a04f4f2f39abf056cf45da9298f Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 20:27:23 +0530 Subject: [PATCH 39/62] Use IAbortable --- src/utils/AbortableOperation.ts | 2 +- src/utils/timeout.ts | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/utils/AbortableOperation.ts b/src/utils/AbortableOperation.ts index 0cc49e10..d03f820a 100644 --- a/src/utils/AbortableOperation.ts +++ b/src/utils/AbortableOperation.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -interface IAbortable { +export interface IAbortable { abort(); } diff --git a/src/utils/timeout.ts b/src/utils/timeout.ts index 96efc10d..f0460047 100644 --- a/src/utils/timeout.ts +++ b/src/utils/timeout.ts @@ -17,12 +17,11 @@ limitations under the License. import {ConnectionError} from "../matrix/error.js"; import type {Timeout} from "../platform/web/dom/Clock.js" +import type {IAbortable} from "./AbortableOperation"; type TimeoutCreator = (ms: number) => Timeout; -// ts-todo: export type RequestResult from fetch.js? we'll need to wait until it's typescript though. -type Abortable = { abort(): void; [key: string]: any }; -export function abortOnTimeout(createTimeout: TimeoutCreator, timeoutAmount: number, requestResult: Abortable, responsePromise: Promise) { +export function abortOnTimeout(createTimeout: TimeoutCreator, timeoutAmount: number, requestResult: IAbortable, responsePromise: Promise) { const timeout = createTimeout(timeoutAmount); // abort request if timeout finishes first let timedOut = false; From 91f2a96403e466be902d5a1e4015dd5d421cb8ae Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 24 Nov 2021 13:40:04 +0530 Subject: [PATCH 40/62] Make LoginMethod an interface --- .../login/{LoginMethod.js => LoginMethod.ts} | 17 +++++------------ src/matrix/login/PasswordLoginMethod.js | 2 +- src/matrix/login/TokenLoginMethod.js | 2 +- 3 files changed, 7 insertions(+), 14 deletions(-) rename src/matrix/login/{LoginMethod.js => LoginMethod.ts} (61%) diff --git a/src/matrix/login/LoginMethod.js b/src/matrix/login/LoginMethod.ts similarity index 61% rename from src/matrix/login/LoginMethod.js rename to src/matrix/login/LoginMethod.ts index ece18871..342632a6 100644 --- a/src/matrix/login/LoginMethod.js +++ b/src/matrix/login/LoginMethod.ts @@ -14,17 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -export class LoginMethod { - constructor({homeserver}) { - this.homeserver = homeserver; - } +import type {ILogItem} from "../../logging/types"; +import type {HomeServerApi} from "../net/HomeServerApi.js"; - // eslint-disable-next-line no-unused-vars - async login(hsApi, deviceName, log) { - /* - Regardless of the login method, SessionContainer.startWithLogin() - can do SomeLoginMethod.login() - */ - throw("Not Implemented"); - } +export interface ILoginMethod { + homeserver: string; + login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Response["body"]; } diff --git a/src/matrix/login/PasswordLoginMethod.js b/src/matrix/login/PasswordLoginMethod.js index 5c90ccf8..f147f229 100644 --- a/src/matrix/login/PasswordLoginMethod.js +++ b/src/matrix/login/PasswordLoginMethod.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {LoginMethod} from "./LoginMethod.js"; +import {LoginMethod} from "./LoginMethod"; export class PasswordLoginMethod extends LoginMethod { constructor(options) { diff --git a/src/matrix/login/TokenLoginMethod.js b/src/matrix/login/TokenLoginMethod.js index e55cedcf..1c623045 100644 --- a/src/matrix/login/TokenLoginMethod.js +++ b/src/matrix/login/TokenLoginMethod.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {LoginMethod} from "./LoginMethod.js"; +import {LoginMethod} from "./LoginMethod"; import {makeTxnId} from "../common.js"; export class TokenLoginMethod extends LoginMethod { From e4c443c73a9544f26c44022fd1e3b021f725742b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 24 Nov 2021 13:47:26 +0530 Subject: [PATCH 41/62] Convert PasswordLoginMethod to ts --- src/matrix/login/LoginMethod.ts | 2 +- ...dLoginMethod.js => PasswordLoginMethod.ts} | 20 ++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) rename src/matrix/login/{PasswordLoginMethod.js => PasswordLoginMethod.ts} (54%) diff --git a/src/matrix/login/LoginMethod.ts b/src/matrix/login/LoginMethod.ts index 342632a6..c4456180 100644 --- a/src/matrix/login/LoginMethod.ts +++ b/src/matrix/login/LoginMethod.ts @@ -19,5 +19,5 @@ import type {HomeServerApi} from "../net/HomeServerApi.js"; export interface ILoginMethod { homeserver: string; - login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Response["body"]; + login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise; } diff --git a/src/matrix/login/PasswordLoginMethod.js b/src/matrix/login/PasswordLoginMethod.ts similarity index 54% rename from src/matrix/login/PasswordLoginMethod.js rename to src/matrix/login/PasswordLoginMethod.ts index f147f229..d9edd3e7 100644 --- a/src/matrix/login/PasswordLoginMethod.js +++ b/src/matrix/login/PasswordLoginMethod.ts @@ -14,16 +14,22 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {LoginMethod} from "./LoginMethod"; +import {ILogItem} from "../../logging/types"; +import {ILoginMethod} from "./LoginMethod"; +import {HomeServerApi} from "../net/HomeServerApi.js"; -export class PasswordLoginMethod extends LoginMethod { - constructor(options) { - super(options); - this.username = options.username; - this.password = options.password; +export class PasswordLoginMethod implements ILoginMethod { + public username: string; + public password: string; + public homeserver: string; + + constructor({username, password, homeserver}: {username: string, password: string, homeserver: string}) { + this.username = username; + this.password = password; + this.homeserver = homeserver; } - async login(hsApi, deviceName, log) { + async login(hsApi: HomeServerApi, deviceName: string, log: ILogItem) { return await hsApi.passwordLogin(this.username, this.password, deviceName, {log}).response(); } } From 64037cb32a24e6a045fcb59f3d3a23d00f45ae83 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 24 Nov 2021 13:56:47 +0530 Subject: [PATCH 42/62] Convert TokenLoginMethod to ts --- src/matrix/SessionContainer.js | 2 +- ...{TokenLoginMethod.js => TokenLoginMethod.ts} | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) rename src/matrix/login/{TokenLoginMethod.js => TokenLoginMethod.ts} (57%) diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 3e3dab66..01ea85ff 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -27,7 +27,7 @@ import {RequestScheduler} from "./net/RequestScheduler.js"; import {Sync, SyncStatus} from "./Sync.js"; import {Session} from "./Session.js"; import {PasswordLoginMethod} from "./login/PasswordLoginMethod.js"; -import {TokenLoginMethod} from "./login/TokenLoginMethod.js"; +import {TokenLoginMethod} from "./login/TokenLoginMethod"; import {SSOLoginHelper} from "./login/SSOLoginHelper.js"; import {getDehydratedDevice} from "./e2ee/Dehydration.js"; diff --git a/src/matrix/login/TokenLoginMethod.js b/src/matrix/login/TokenLoginMethod.ts similarity index 57% rename from src/matrix/login/TokenLoginMethod.js rename to src/matrix/login/TokenLoginMethod.ts index 1c623045..63701604 100644 --- a/src/matrix/login/TokenLoginMethod.js +++ b/src/matrix/login/TokenLoginMethod.ts @@ -14,16 +14,21 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {LoginMethod} from "./LoginMethod"; import {makeTxnId} from "../common.js"; +import {ILogItem} from "../../logging/types"; +import {ILoginMethod} from "./LoginMethod"; +import {HomeServerApi} from "../net/HomeServerApi.js"; -export class TokenLoginMethod extends LoginMethod { - constructor(options) { - super(options); - this._loginToken = options.loginToken; +export class TokenLoginMethod implements ILoginMethod { + public readonly homeserver: string; + private readonly _loginToken: string; + + constructor({ homeserver, loginToken }: { homeserver: string, loginToken: string}) { + this.homeserver = homeserver; + this._loginToken = loginToken; } - async login(hsApi, deviceName, log) { + async login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise { return await hsApi.tokenLogin(this._loginToken, makeTxnId(), deviceName, {log}).response(); } } From a1367f8e724e850124a8a9924c35943bd713ce9b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 24 Nov 2021 14:00:26 +0530 Subject: [PATCH 43/62] Fix password login --- src/matrix/SessionContainer.js | 2 +- src/matrix/login/PasswordLoginMethod.ts | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 01ea85ff..2e64a2f6 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -26,7 +26,7 @@ import {MediaRepository} from "./net/MediaRepository.js"; import {RequestScheduler} from "./net/RequestScheduler.js"; import {Sync, SyncStatus} from "./Sync.js"; import {Session} from "./Session.js"; -import {PasswordLoginMethod} from "./login/PasswordLoginMethod.js"; +import {PasswordLoginMethod} from "./login/PasswordLoginMethod"; import {TokenLoginMethod} from "./login/TokenLoginMethod"; import {SSOLoginHelper} from "./login/SSOLoginHelper.js"; import {getDehydratedDevice} from "./e2ee/Dehydration.js"; diff --git a/src/matrix/login/PasswordLoginMethod.ts b/src/matrix/login/PasswordLoginMethod.ts index d9edd3e7..46fdd211 100644 --- a/src/matrix/login/PasswordLoginMethod.ts +++ b/src/matrix/login/PasswordLoginMethod.ts @@ -19,17 +19,17 @@ import {ILoginMethod} from "./LoginMethod"; import {HomeServerApi} from "../net/HomeServerApi.js"; export class PasswordLoginMethod implements ILoginMethod { - public username: string; - public password: string; - public homeserver: string; + private readonly _username: string; + private readonly _password: string; + public readonly homeserver: string; constructor({username, password, homeserver}: {username: string, password: string, homeserver: string}) { - this.username = username; - this.password = password; + this._username = username; + this._password = password; this.homeserver = homeserver; } - async login(hsApi: HomeServerApi, deviceName: string, log: ILogItem) { - return await hsApi.passwordLogin(this.username, this.password, deviceName, {log}).response(); + async login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise { + return await hsApi.passwordLogin(this._username, this._password, deviceName, {log}).response(); } } From c54ca168ed90cc75f233c2052af7dc626955aafa Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 24 Nov 2021 14:49:08 +0530 Subject: [PATCH 44/62] Convert SSOLoginHelper.js to ts --- src/matrix/SessionContainer.js | 2 +- src/matrix/login/{SSOLoginHelper.js => SSOLoginHelper.ts} | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) rename src/matrix/login/{SSOLoginHelper.js => SSOLoginHelper.ts} (80%) diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 2e64a2f6..0b917426 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -28,7 +28,7 @@ import {Sync, SyncStatus} from "./Sync.js"; import {Session} from "./Session.js"; import {PasswordLoginMethod} from "./login/PasswordLoginMethod"; import {TokenLoginMethod} from "./login/TokenLoginMethod"; -import {SSOLoginHelper} from "./login/SSOLoginHelper.js"; +import {SSOLoginHelper} from "./login/SSOLoginHelper"; import {getDehydratedDevice} from "./e2ee/Dehydration.js"; export const LoadStatus = createEnum( diff --git a/src/matrix/login/SSOLoginHelper.js b/src/matrix/login/SSOLoginHelper.ts similarity index 80% rename from src/matrix/login/SSOLoginHelper.js rename to src/matrix/login/SSOLoginHelper.ts index a15c8ef9..0fe3d6b8 100644 --- a/src/matrix/login/SSOLoginHelper.js +++ b/src/matrix/login/SSOLoginHelper.ts @@ -15,13 +15,15 @@ limitations under the License. */ export class SSOLoginHelper{ - constructor(homeserver) { + private _homeserver: string; + + constructor(homeserver: string) { this._homeserver = homeserver; } - get homeserver() { return this._homeserver; } + get homeserver(): string { return this._homeserver; } - createSSORedirectURL(returnURL) { + createSSORedirectURL(returnURL: string): string { return `${this._homeserver}/_matrix/client/r0/login/sso/redirect?redirectUrl=${returnURL}`; } } From a31860dc5f15d37a208232424a9735a7b00c9955 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 24 Nov 2021 14:55:44 +0530 Subject: [PATCH 45/62] Fix formatting --- src/matrix/login/LoginMethod.ts | 2 +- src/matrix/login/TokenLoginMethod.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/matrix/login/LoginMethod.ts b/src/matrix/login/LoginMethod.ts index c4456180..91977bf1 100644 --- a/src/matrix/login/LoginMethod.ts +++ b/src/matrix/login/LoginMethod.ts @@ -19,5 +19,5 @@ import type {HomeServerApi} from "../net/HomeServerApi.js"; export interface ILoginMethod { homeserver: string; - login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise; + login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise; } diff --git a/src/matrix/login/TokenLoginMethod.ts b/src/matrix/login/TokenLoginMethod.ts index 63701604..5caae19f 100644 --- a/src/matrix/login/TokenLoginMethod.ts +++ b/src/matrix/login/TokenLoginMethod.ts @@ -20,8 +20,8 @@ import {ILoginMethod} from "./LoginMethod"; import {HomeServerApi} from "../net/HomeServerApi.js"; export class TokenLoginMethod implements ILoginMethod { - public readonly homeserver: string; private readonly _loginToken: string; + public readonly homeserver: string; constructor({ homeserver, loginToken }: { homeserver: string, loginToken: string}) { this.homeserver = homeserver; From 346e95c33cb8e9cb801484a2dbb96bc33ab768ff Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 25 Nov 2021 12:33:12 +0530 Subject: [PATCH 46/62] Change return type --- src/matrix/login/LoginMethod.ts | 2 +- src/matrix/login/PasswordLoginMethod.ts | 2 +- src/matrix/login/TokenLoginMethod.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/matrix/login/LoginMethod.ts b/src/matrix/login/LoginMethod.ts index 91977bf1..2b2a8ff3 100644 --- a/src/matrix/login/LoginMethod.ts +++ b/src/matrix/login/LoginMethod.ts @@ -19,5 +19,5 @@ import type {HomeServerApi} from "../net/HomeServerApi.js"; export interface ILoginMethod { homeserver: string; - login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise; + login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise>; } diff --git a/src/matrix/login/PasswordLoginMethod.ts b/src/matrix/login/PasswordLoginMethod.ts index 46fdd211..65e96ff0 100644 --- a/src/matrix/login/PasswordLoginMethod.ts +++ b/src/matrix/login/PasswordLoginMethod.ts @@ -29,7 +29,7 @@ export class PasswordLoginMethod implements ILoginMethod { this.homeserver = homeserver; } - async login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise { + async login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise> { return await hsApi.passwordLogin(this._username, this._password, deviceName, {log}).response(); } } diff --git a/src/matrix/login/TokenLoginMethod.ts b/src/matrix/login/TokenLoginMethod.ts index 5caae19f..4f1e3cc7 100644 --- a/src/matrix/login/TokenLoginMethod.ts +++ b/src/matrix/login/TokenLoginMethod.ts @@ -28,7 +28,7 @@ export class TokenLoginMethod implements ILoginMethod { this._loginToken = loginToken; } - async login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise { + async login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise> { return await hsApi.tokenLogin(this._loginToken, makeTxnId(), deviceName, {log}).response(); } } From 3d9fbb685a440facb21f652082f1a276c704e11d Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 25 Nov 2021 13:23:05 +0530 Subject: [PATCH 47/62] Convert Pusher.js to ts --- src/matrix/Session.js | 2 +- src/matrix/push/Pusher.js | 50 ---------------------- src/matrix/push/Pusher.ts | 90 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 51 deletions(-) delete mode 100644 src/matrix/push/Pusher.js create mode 100644 src/matrix/push/Pusher.ts diff --git a/src/matrix/Session.js b/src/matrix/Session.js index 37fd90ad..c3faf213 100644 --- a/src/matrix/Session.js +++ b/src/matrix/Session.js @@ -19,7 +19,7 @@ import {Room} from "./room/Room.js"; import {ArchivedRoom} from "./room/ArchivedRoom.js"; import {RoomStatus} from "./room/RoomStatus.js"; import {Invite} from "./room/Invite.js"; -import {Pusher} from "./push/Pusher.js"; +import {Pusher} from "./push/Pusher"; import { ObservableMap } from "../observable/index.js"; import {User} from "./User.js"; import {DeviceMessageHandler} from "./DeviceMessageHandler.js"; diff --git a/src/matrix/push/Pusher.js b/src/matrix/push/Pusher.js deleted file mode 100644 index 99baeae6..00000000 --- a/src/matrix/push/Pusher.js +++ /dev/null @@ -1,50 +0,0 @@ -export class Pusher { - constructor(description) { - this._description = description; - } - - static httpPusher(host, appId, pushkey, data) { - return new Pusher({ - kind: "http", - append: true, // as pushkeys are shared between multiple users on one origin - data: Object.assign({}, data, {url: host + "/_matrix/push/v1/notify"}), - pushkey, - app_id: appId, - app_display_name: "Hydrogen", - device_display_name: "Hydrogen", - lang: "en" - }); - } - - static createDefaultPayload(sessionId) { - return {session_id: sessionId}; - } - - async enable(hsApi, log) { - try { - log.set("endpoint", new URL(this._description.data.endpoint).host); - } catch { - log.set("endpoint", null); - } - await hsApi.setPusher(this._description, {log}).response(); - } - - async disable(hsApi, log) { - const deleteDescription = Object.assign({}, this._description, {kind: null}); - await hsApi.setPusher(deleteDescription, {log}).response(); - } - - serialize() { - return this._description; - } - - equals(pusher) { - if (this._description.app_id !== pusher._description.app_id) { - return false; - } - if (this._description.pushkey !== pusher._description.pushkey) { - return false; - } - return JSON.stringify(this._description.data) === JSON.stringify(pusher._description.data); - } -} diff --git a/src/matrix/push/Pusher.ts b/src/matrix/push/Pusher.ts new file mode 100644 index 00000000..f9a35a2c --- /dev/null +++ b/src/matrix/push/Pusher.ts @@ -0,0 +1,90 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import type {HomeServerApi} from "../net/HomeServerApi.js"; +import type {ILogItem} from "../../logging/types"; + +export interface IPusherDescription { + kind: "http" | "email" | "null"; + lang: string; + device_display_name: string; + app_display_name: string; + app_id: string; + pushkey: string; + data: IPusherData; + append?: boolean; + profile_tag?: string; +} + +interface IPusherData { + format?: string; + url?: string; + // todo: where did this come from? + endpoint?: string; +} + +export class Pusher { + private readonly _description: IPusherDescription; + + constructor(description: IPusherDescription) { + this._description = description; + } + + static httpPusher(host: string, appId: string, pushkey: string, data: IPusherData): Pusher { + return new Pusher({ + kind: "http", + append: true, // as pushkeys are shared between multiple users on one origin + data: Object.assign({}, data, {url: host + "/_matrix/push/v1/notify"}), + pushkey, + app_id: appId, + app_display_name: "Hydrogen", + device_display_name: "Hydrogen", + lang: "en" + }); + } + + static createDefaultPayload(sessionId: string): {session_id: string} { + return {session_id: sessionId}; + } + + async enable(hsApi: HomeServerApi, log: ILogItem): Promise { + try { + log.set("endpoint", new URL(this._description.data.endpoint!).host); + } catch { + log.set("endpoint", null); + } + await hsApi.setPusher(this._description, {log}).response(); + } + + async disable(hsApi: HomeServerApi, log: ILogItem): Promise { + const deleteDescription = Object.assign({}, this._description, {kind: null}); + await hsApi.setPusher(deleteDescription, {log}).response(); + } + + serialize(): IPusherDescription { + return this._description; + } + + equals(pusher): boolean { + if (this._description.app_id !== pusher._description.app_id) { + return false; + } + if (this._description.pushkey !== pusher._description.pushkey) { + return false; + } + return JSON.stringify(this._description.data) === JSON.stringify(pusher._description.data); + } +} From bb18af414b9ef60f7a232ee9f83f9faeeb4ebdac Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 25 Nov 2021 15:18:03 +0530 Subject: [PATCH 48/62] Convert SessionInfoStorage.js to ts --- ...onInfoStorage.js => SessionInfoStorage.ts} | 35 +++++++++++++++---- src/platform/web/Platform.js | 2 +- 2 files changed, 29 insertions(+), 8 deletions(-) rename src/matrix/sessioninfo/localstorage/{SessionInfoStorage.js => SessionInfoStorage.ts} (64%) diff --git a/src/matrix/sessioninfo/localstorage/SessionInfoStorage.js b/src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts similarity index 64% rename from src/matrix/sessioninfo/localstorage/SessionInfoStorage.js rename to src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts index ce795916..fd407c6a 100644 --- a/src/matrix/sessioninfo/localstorage/SessionInfoStorage.js +++ b/src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts @@ -14,12 +14,33 @@ See the License for the specific language governing permissions and limitations under the License. */ -export class SessionInfoStorage { - constructor(name) { +interface ISessionInfo { + id: string; + deviceId: string; + userId: string; + homeserver: string; + homeServer: string; + accessToken: string; + lastUsed: number; +} + +// todo: this should probably be in platform/types? +interface ISessionInfoStorage { + getAll(): Promise; + updateLastUsed(id: string, timestamp: number): Promise; + get(id: string): Promise; + add(sessionInfo: ISessionInfo): Promise; + delete(sessionId: string): Promise; +} + +export class SessionInfoStorage implements ISessionInfoStorage { + private readonly _name: string; + + constructor(name: string) { this._name = name; } - getAll() { + getAll(): Promise { const sessionsJson = localStorage.getItem(this._name); if (sessionsJson) { const sessions = JSON.parse(sessionsJson); @@ -30,7 +51,7 @@ export class SessionInfoStorage { return Promise.resolve([]); } - async updateLastUsed(id, timestamp) { + async updateLastUsed(id: string, timestamp: number): Promise { const sessions = await this.getAll(); if (sessions) { const session = sessions.find(session => session.id === id); @@ -41,20 +62,20 @@ export class SessionInfoStorage { } } - async get(id) { + async get(id: string): Promise { const sessions = await this.getAll(); if (sessions) { return sessions.find(session => session.id === id); } } - async add(sessionInfo) { + async add(sessionInfo: ISessionInfo): Promise { const sessions = await this.getAll(); sessions.push(sessionInfo); localStorage.setItem(this._name, JSON.stringify(sessions)); } - async delete(sessionId) { + async delete(sessionId: string): Promise { let sessions = await this.getAll(); sessions = sessions.filter(s => s.id !== sessionId); localStorage.setItem(this._name, JSON.stringify(sessions)); diff --git a/src/platform/web/Platform.js b/src/platform/web/Platform.js index f6cd2895..67f747ab 100644 --- a/src/platform/web/Platform.js +++ b/src/platform/web/Platform.js @@ -17,7 +17,7 @@ limitations under the License. import {createFetchRequest} from "./dom/request/fetch.js"; import {xhrRequest} from "./dom/request/xhr.js"; import {StorageFactory} from "../../matrix/storage/idb/StorageFactory"; -import {SessionInfoStorage} from "../../matrix/sessioninfo/localstorage/SessionInfoStorage.js"; +import {SessionInfoStorage} from "../../matrix/sessioninfo/localstorage/SessionInfoStorage"; import {SettingsStorage} from "./dom/SettingsStorage.js"; import {Encoding} from "./utils/Encoding.js"; import {OlmWorker} from "../../matrix/e2ee/OlmWorker.js"; From d981a852397b825f136e75d0a22efa3552fafaf8 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 29 Nov 2021 11:43:43 +0530 Subject: [PATCH 49/62] Filter token out of stack trace --- src/logging/LogItem.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index da009b06..bb8815db 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -19,6 +19,11 @@ import {LogLevel, LogFilter} from "./LogFilter"; import type {BaseLogger} from "./BaseLogger"; import type {ISerializedItem, ILogItem, LogItemValues, LabelOrValues, FilterCreator, LogCallback} from "./types"; +// Make sure that loginToken does not end up in the logs +function filterLoginToken(trace?: string): string | undefined { + return trace?.replace(/(?<=\/\?loginToken=).+/, ""); +} + export class LogItem implements ILogItem { public readonly start: number; public logLevel: LogLevel; @@ -155,7 +160,7 @@ export class LogItem implements ILogItem { if (this.error) { // (e)rror item.e = { - stack: this.error.stack, + stack: filterLoginToken(this.error.stack), name: this.error.name, message: this.error.message.split("\n")[0] }; @@ -259,3 +264,14 @@ export class LogItem implements ILogItem { return this._children; } } + +export function tests() { + return { + "Login token removed from item": (assert) => { + const str = "main http://localhost:3000/src/main.js:55\n http://localhost:3000/?loginToken=secret:26"; + const result = filterLoginToken(str); + const index = result?.search("secret"); + assert.equal(index, -1); + } + } +} From 104590e34dbb278735005f237940bd7c2b43f118 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 29 Nov 2021 11:48:05 +0530 Subject: [PATCH 50/62] Use ! in test --- src/logging/LogItem.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index bb8815db..4ddd687c 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -270,7 +270,7 @@ export function tests() { "Login token removed from item": (assert) => { const str = "main http://localhost:3000/src/main.js:55\n http://localhost:3000/?loginToken=secret:26"; const result = filterLoginToken(str); - const index = result?.search("secret"); + const index = result!.search("secret"); assert.equal(index, -1); } } From 3322827979bc7068dc9f457476ea682667c7370c Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 08:04:45 +0100 Subject: [PATCH 51/62] upgrade impunity to propagate exit code --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 8cda0543..017510d6 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "eslint": "^7.32.0", "fake-indexeddb": "^3.1.2", "finalhandler": "^1.1.1", - "impunity": "^1.0.8", + "impunity": "^1.0.9", "mdn-polyfills": "^5.20.0", "postcss": "^8.1.1", "postcss-css-variables": "^0.17.0", diff --git a/yarn.lock b/yarn.lock index 64926972..11356c4e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3124,10 +3124,10 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -impunity@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/impunity/-/impunity-1.0.8.tgz#d6db44e8a15ca2cdaed6a5c478a770853cb5a56e" - integrity sha512-6jMqYrvY2SA/PZ+yheJYd3eJ3zcO8dWmHRVy/BSjnKMEmIVB+lMO30MZOkG+kHH0eJuaGOKv0BrZmgwE6NUDRg== +impunity@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/impunity/-/impunity-1.0.9.tgz#8524d96f07c26987519ec693c4c4d3ab49254b03" + integrity sha512-tfy7GRHeE9JVURKM7dqfTAZItGFeA/DRrlhgMLUuzSig3jF+AYSUV26tGTMGrfCN0Cb9hNz6xrZnNwa5M1hz4Q== dependencies: colors "^1.3.3" commander "^6.1.0" From fe77b71c97d20e3d82c2ee39468e4550e195100d Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 30 Nov 2021 13:28:28 +0530 Subject: [PATCH 52/62] use transformer function --- src/logging/BaseLogger.ts | 6 +++-- src/logging/IDBLogger.ts | 13 ++++++---- src/logging/LogItem.ts | 27 +++++++++----------- src/platform/web/Platform.js | 48 ++++++++++++++++++++++++++++++++---- 4 files changed, 66 insertions(+), 28 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 723c2f17..e32b9f0f 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -17,15 +17,17 @@ limitations under the License. import {LogItem} from "./LogItem"; import {LogLevel, LogFilter} from "./LogFilter"; -import type {ILogger, ILogExport, FilterCreator, LabelOrValues, LogCallback, ILogItem} from "./types"; +import type {ILogger, ILogExport, FilterCreator, LabelOrValues, LogCallback, ILogItem, ISerializedItem} from "./types"; import type {Platform} from "../platform/web/Platform.js"; export abstract class BaseLogger implements ILogger { protected _openItems: Set = new Set(); protected _platform: Platform; + protected _serializedTransformer: (item: ISerializedItem) => ISerializedItem; - constructor({platform}) { + constructor({platform, serializedTransformer = (item: ISerializedItem) => item}) { this._platform = platform; + this._serializedTransformer = serializedTransformer; } log(labelOrValues: LabelOrValues, logLevel: LogLevel = LogLevel.Info): void { diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index 96147ca1..8ab81964 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -26,7 +26,7 @@ import {BaseLogger} from "./BaseLogger"; import type {Interval} from "../platform/web/dom/Clock"; import type {Platform} from "../platform/web/Platform.js"; import type {BlobHandle} from "../platform/web/dom/BlobHandle.js"; -import type {ILogItem, ILogExport} from "./types"; +import type {ILogItem, ILogExport, ISerializedItem} from "./types"; import type {LogFilter} from "./LogFilter"; type QueuedItem = { @@ -40,7 +40,7 @@ export class IDBLogger extends BaseLogger { private readonly _flushInterval: Interval; private _queuedItems: QueuedItem[]; - constructor(options: {name: string, flushInterval?: number, limit?: number, platform: Platform}) { + constructor(options: {name: string, flushInterval?: number, limit?: number, platform: Platform, serializedTransformer: (item: ISerializedItem) => ISerializedItem}) { super(options); const {name, flushInterval = 60 * 1000, limit = 3000} = options; this._name = name; @@ -119,9 +119,12 @@ export class IDBLogger extends BaseLogger { _persistItem(logItem: ILogItem, filter: LogFilter, forced: boolean): void { const serializedItem = logItem.serialize(filter, undefined, forced); - this._queuedItems.push({ - json: JSON.stringify(serializedItem) - }); + if (serializedItem) { + const transformedSerializedItem = this._serializedTransformer(serializedItem); + this._queuedItems.push({ + json: JSON.stringify(transformedSerializedItem) + }); + } } _persistQueuedItems(items: QueuedItem[]): void { diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 4ddd687c..5bd94f93 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -19,11 +19,6 @@ import {LogLevel, LogFilter} from "./LogFilter"; import type {BaseLogger} from "./BaseLogger"; import type {ISerializedItem, ILogItem, LogItemValues, LabelOrValues, FilterCreator, LogCallback} from "./types"; -// Make sure that loginToken does not end up in the logs -function filterLoginToken(trace?: string): string | undefined { - return trace?.replace(/(?<=\/\?loginToken=).+/, ""); -} - export class LogItem implements ILogItem { public readonly start: number; public logLevel: LogLevel; @@ -160,7 +155,7 @@ export class LogItem implements ILogItem { if (this.error) { // (e)rror item.e = { - stack: filterLoginToken(this.error.stack), + stack: this.error.stack, name: this.error.name, message: this.error.message.split("\n")[0] }; @@ -265,13 +260,13 @@ export class LogItem implements ILogItem { } } -export function tests() { - return { - "Login token removed from item": (assert) => { - const str = "main http://localhost:3000/src/main.js:55\n http://localhost:3000/?loginToken=secret:26"; - const result = filterLoginToken(str); - const index = result!.search("secret"); - assert.equal(index, -1); - } - } -} +// export function tests() { +// return { +// "Login token removed from item": (assert) => { +// const str = "main http://localhost:3000/src/main.js:55\n http://localhost:3000/?loginToken=secret:26"; +// const result = filterLoginToken(str); +// const index = result!.search("secret"); +// assert.equal(index, -1); +// } +// } +// } diff --git a/src/platform/web/Platform.js b/src/platform/web/Platform.js index f6cd2895..c871bb9e 100644 --- a/src/platform/web/Platform.js +++ b/src/platform/web/Platform.js @@ -132,11 +132,7 @@ export class Platform { this.clock = new Clock(); this.encoding = new Encoding(); this.random = Math.random; - if (options?.development) { - this.logger = new ConsoleLogger({platform: this}); - } else { - this.logger = new IDBLogger({name: "hydrogen_logs", platform: this}); - } + this._createLogger(options?.development); this.history = new History(); this.onlineStatus = new OnlineStatus(); this._serviceWorkerHandler = null; @@ -162,6 +158,21 @@ export class Platform { this._disposables = new Disposables(); } + _createLogger(isDevelopment) { + // Make sure that loginToken does not end up in the logs + const transformer = (item) => { + if (item.e?.stack) { + item.e.stack = item.e.stack.replace(/(?<=\/\?loginToken=).+/, ""); + } + return item; + }; + if (isDevelopment) { + this.logger = new ConsoleLogger({platform: this}); + } else { + this.logger = new IDBLogger({name: "hydrogen_logs", platform: this, serializedTransformer: transformer}); + } + } + get updateService() { return this._serviceWorkerHandler; } @@ -272,3 +283,30 @@ export class Platform { this._disposables.dispose(); } } + +import {LogItem} from "../../logging/LogItem"; +export function tests() { + return { + "loginToken should not be in logs": (assert) => { + const transformer = (item) => { + if (item.e?.stack) { + item.e.stack = item.e.stack.replace(/(?<=\/\?loginToken=).+/, ""); + } + return item; + }; + const logger = { + _queuedItems: [], + _serializedTransformer: transformer, + _now: () => {} + }; + logger.persist = IDBLogger.prototype._persistItem.bind(logger); + const logItem = new LogItem("test", 1, logger); + logItem.error = new Error(); + logItem.error.stack = "main http://localhost:3000/src/main.js:55\n http://localhost:3000/?loginToken=secret:26" + logger.persist(logItem, null, false); + const item = logger._queuedItems.pop(); + console.log(item); + assert.strictEqual(item.json.search("secret"), -1); + } + }; +} From 6699b71bd54cf70e43e9a0edfb41c8fb42bc92b6 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 30 Nov 2021 13:38:25 +0530 Subject: [PATCH 53/62] transformer is optional --- src/logging/IDBLogger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index 8ab81964..ab9474b0 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -40,7 +40,7 @@ export class IDBLogger extends BaseLogger { private readonly _flushInterval: Interval; private _queuedItems: QueuedItem[]; - constructor(options: {name: string, flushInterval?: number, limit?: number, platform: Platform, serializedTransformer: (item: ISerializedItem) => ISerializedItem}) { + constructor(options: {name: string, flushInterval?: number, limit?: number, platform: Platform, serializedTransformer?: (item: ISerializedItem) => ISerializedItem}) { super(options); const {name, flushInterval = 60 * 1000, limit = 3000} = options; this._name = name; From 66fbc37ec4e45a6603737312117539753c288e6e Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 30 Nov 2021 14:15:49 +0530 Subject: [PATCH 54/62] Remove comments --- src/logging/LogItem.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 5bd94f93..da009b06 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -259,14 +259,3 @@ export class LogItem implements ILogItem { return this._children; } } - -// export function tests() { -// return { -// "Login token removed from item": (assert) => { -// const str = "main http://localhost:3000/src/main.js:55\n http://localhost:3000/?loginToken=secret:26"; -// const result = filterLoginToken(str); -// const index = result!.search("secret"); -// assert.equal(index, -1); -// } -// } -// } From 2e57e99e34d853edfe4b645efaf1cbf9c9f248a4 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 14:15:25 +0000 Subject: [PATCH 55/62] clarify when to use type and interface --- doc/TS-MIGRATION.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/TS-MIGRATION.md b/doc/TS-MIGRATION.md index 7cb5bb34..006b3077 100644 --- a/doc/TS-MIGRATION.md +++ b/doc/TS-MIGRATION.md @@ -5,3 +5,11 @@ - find all methods and getters that throw or are empty in base classes and turn into abstract method or if all methods are abstract, into an interface. - change child impls to not call super.method and to add override - don't allow implicit override in ts config + +## Use `type` rather than `interface` for named parameters and POJO return values. + +`type` and `interface` can be used somewhat interchangebly used, but let's use `type` to describe data and `interface` to describe (polymorphic) behaviour. + +Good examples of data are option objects to have named parameters, and POJO (plain old javascript objects) without any methods, just fields. + +Also see [this playground](https://www.typescriptlang.org/play?#code/C4TwDgpgBACghgJwgO2AeTMAlge2QZygF4oBvAKCiqmTgFsIAuKfYBLZAcwG5LqATCABs4IAPzNkAVzoAjCAl4BfcuVCQoAYQAWWIfwzY8hEvCSpDuAlABkZPlQDGOITgTNW7LstWOR+QjMUYHtqKGcCNilHYDcAChxMK3xmIIsk4wBKewcoFRVyPzgArV19KAgAD2AUfkDEYNDqCM9o2IQEjIJmHT0DLvxsijCw-ClIDsSjAkzeEebjEIYAuE5oEgADABJSKeSAOloGJSgsQh29433nVwQlDbnqfKA) From 49443d4f6e0621591ac1d37f021c474e1decc888 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 14:17:51 +0000 Subject: [PATCH 56/62] Update TS-MIGRATION.md --- doc/TS-MIGRATION.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/doc/TS-MIGRATION.md b/doc/TS-MIGRATION.md index 006b3077..d7ebc7f4 100644 --- a/doc/TS-MIGRATION.md +++ b/doc/TS-MIGRATION.md @@ -1,10 +1,4 @@ -# Typescript migration - -## Introduce `abstract` & `override` - - - find all methods and getters that throw or are empty in base classes and turn into abstract method or if all methods are abstract, into an interface. - - change child impls to not call super.method and to add override - - don't allow implicit override in ts config +# Typescript style guide ## Use `type` rather than `interface` for named parameters and POJO return values. From 581ef47c78db67fed09fb1f314acaad8f3610feb Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 16:53:59 +0100 Subject: [PATCH 57/62] fix conflicting sortedIndex declaration --- src/observable/list/SortedArray.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/observable/list/SortedArray.ts b/src/observable/list/SortedArray.ts index abbfa481..c85cca27 100644 --- a/src/observable/list/SortedArray.ts +++ b/src/observable/list/SortedArray.ts @@ -18,8 +18,6 @@ import {BaseObservableList} from "./BaseObservableList"; import {sortedIndex} from "../../utils/sortedIndex"; import {findAndUpdateInArray} from "./common"; -declare function sortedIndex(array: T[], value: T, comparator: (left: T, right: T) => number): number; - export class SortedArray extends BaseObservableList { private _comparator: (left: T, right: T) => number; private _items: T[] = []; From de8995fa7ed320b3ed6cc826ae55766be7268e39 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 16:58:56 +0100 Subject: [PATCH 58/62] fix handlers in test missing methods, now that observable list is typed --- src/platform/web/ui/general/ListRange.ts | 61 ++++++++++++------------ 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/platform/web/ui/general/ListRange.ts b/src/platform/web/ui/general/ListRange.ts index 4f62ba21..66ee8dfb 100644 --- a/src/platform/web/ui/general/ListRange.ts +++ b/src/platform/web/ui/general/ListRange.ts @@ -15,6 +15,7 @@ limitations under the License. */ import {Range, RangeZone} from "./Range"; +import {defaultObserverWith} from "../../../../observable/list/BaseObservableList"; function skipOnIterator(it: Iterator, pos: number): boolean { let i = 0; @@ -268,7 +269,7 @@ export function tests() { const list = new ObservableArray(["b", "c", "d", "e"]); const range = new ListRange(1, 3, list.length); let added = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onAdd(idx, value) { added = true; const result = range.queryAdd(idx, value, list); @@ -280,7 +281,7 @@ export function tests() { newRange: new ListRange(1, 3, 5) }); } - }); + })); list.insert(0, "a"); assert(added); }, @@ -288,7 +289,7 @@ export function tests() { const list = new ObservableArray(["a", "b", "d", "e"]); const range = new ListRange(1, 3, list.length); let added = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onAdd(idx, value) { added = true; const result = range.queryAdd(idx, value, list); @@ -300,7 +301,7 @@ export function tests() { newRange: new ListRange(1, 3, 5) }); } - }); + })); list.insert(2, "c"); assert(added); }, @@ -308,7 +309,7 @@ export function tests() { const list = new ObservableArray(["a", "b", "c", "d"]); const range = new ListRange(1, 3, list.length); let added = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onAdd(idx, value) { added = true; const result = range.queryAdd(idx, value, list); @@ -317,7 +318,7 @@ export function tests() { newRange: new ListRange(1, 3, 5) }); } - }); + })); list.insert(4, "e"); assert(added); }, @@ -326,7 +327,7 @@ export function tests() { const viewportItemCount = 4; const range = new ListRange(0, 3, list.length, viewportItemCount); let added = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onAdd(idx, value) { added = true; const result = range.queryAdd(idx, value, list); @@ -337,7 +338,7 @@ export function tests() { value: "c" }); } - }); + })); list.insert(2, "c"); assert(added); }, @@ -345,7 +346,7 @@ export function tests() { const list = new ObservableArray(["a", "b", "c", "d", "e"]); const range = new ListRange(1, 3, list.length); let removed = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onRemove(idx) { removed = true; const result = range.queryRemove(idx, list); @@ -357,7 +358,7 @@ export function tests() { newRange: new ListRange(1, 3, 4) }); } - }); + })); list.remove(0); assert(removed); }, @@ -365,7 +366,7 @@ export function tests() { const list = new ObservableArray(["a", "b", "c", "d", "e"]); const range = new ListRange(1, 3, list.length); let removed = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onRemove(idx) { removed = true; const result = range.queryRemove(idx, list); @@ -378,7 +379,7 @@ export function tests() { }); assert.equal(list.length, 4); } - }); + })); list.remove(2); assert(removed); }, @@ -386,7 +387,7 @@ export function tests() { const list = new ObservableArray(["a", "b", "c", "d", "e"]); const range = new ListRange(1, 3, list.length); let removed = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onRemove(idx) { removed = true; const result = range.queryRemove(idx, list); @@ -395,7 +396,7 @@ export function tests() { newRange: new ListRange(1, 3, 4) }); } - }); + })); list.remove(3); assert(removed); }, @@ -403,7 +404,7 @@ export function tests() { const list = new ObservableArray(["a", "b", "c"]); const range = new ListRange(1, 3, list.length); let removed = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onRemove(idx) { removed = true; const result = range.queryRemove(idx, list); @@ -415,7 +416,7 @@ export function tests() { value: "a" }); } - }); + })); list.remove(2); assert(removed); }, @@ -423,7 +424,7 @@ export function tests() { const list = new ObservableArray(["a", "b", "c"]); const range = new ListRange(0, 3, list.length); let removed = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onRemove(idx) { removed = true; const result = range.queryRemove(idx, list); @@ -433,7 +434,7 @@ export function tests() { removeIdx: 2, }); } - }); + })); list.remove(2); assert(removed); }, @@ -441,7 +442,7 @@ export function tests() { const list = new ObservableArray(["a", "b", "c", "d", "e"]); const range = new ListRange(1, 4, list.length); let moved = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onMove(fromIdx, toIdx, value) { moved = true; const result = range.queryMove(fromIdx, toIdx, value, list); @@ -451,7 +452,7 @@ export function tests() { toIdx: 3 }); } - }); + })); list.move(2, 3); assert(moved); }, @@ -459,7 +460,7 @@ export function tests() { const list = new ObservableArray(["a", "b", "c", "d", "e"]); const range = new ListRange(2, 5, list.length); let moved = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onMove(fromIdx, toIdx, value) { moved = true; const result = range.queryMove(fromIdx, toIdx, value, list); @@ -470,7 +471,7 @@ export function tests() { value: "a" }); } - }); + })); list.move(0, 3); // move "a" to after "d" assert(moved); }, @@ -478,7 +479,7 @@ export function tests() { const list = new ObservableArray(["a", "b", "c", "d", "e"]); const range = new ListRange(0, 3, list.length); let moved = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onMove(fromIdx, toIdx, value) { moved = true; const result = range.queryMove(fromIdx, toIdx, value, list); @@ -489,7 +490,7 @@ export function tests() { value: "e" }); } - }); + })); list.move(4, 1); // move "e" to before "b" assert(moved); }, @@ -497,7 +498,7 @@ export function tests() { const list = new ObservableArray(["a", "b", "c", "d", "e"]); const range = new ListRange(0, 3, list.length); let moved = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onMove(fromIdx, toIdx, value) { moved = true; const result = range.queryMove(fromIdx, toIdx, value, list); @@ -508,7 +509,7 @@ export function tests() { value: "d" }); } - }); + })); list.move(1, 3); // move "b" to after "d" assert(moved); }, @@ -516,7 +517,7 @@ export function tests() { const list = new ObservableArray(["a", "b", "c", "d", "e"]); const range = new ListRange(2, 5, list.length); let moved = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onMove(fromIdx, toIdx, value) { moved = true; const result = range.queryMove(fromIdx, toIdx, value, list); @@ -527,7 +528,7 @@ export function tests() { value: "b" }); } - }); + })); list.move(3, 0); // move "d" to before "a" assert(moved); }, @@ -535,7 +536,7 @@ export function tests() { const list = new ObservableArray(["a", "b", "c", "d", "e"]); const range = new ListRange(1, 4, list.length); let moved = false; - list.subscribe({ + list.subscribe(defaultObserverWith({ onMove(fromIdx, toIdx, value) { moved = true; const result = range.queryMove(fromIdx, toIdx, value, list); @@ -546,7 +547,7 @@ export function tests() { value: "e" }); } - }); + })); list.move(0, 4); // move "a" to after "e" assert(moved); }, From 8c3ae57497eed173b2a469da61f0938410ca5c2f Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 17:05:39 +0100 Subject: [PATCH 59/62] fix Iterator vs IterableIterator confusion --- src/observable/list/BaseObservableList.ts | 4 ++-- src/platform/web/ui/general/Range.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/observable/list/BaseObservableList.ts b/src/observable/list/BaseObservableList.ts index 6d8bd1af..d103eb64 100644 --- a/src/observable/list/BaseObservableList.ts +++ b/src/observable/list/BaseObservableList.ts @@ -35,7 +35,7 @@ export function defaultObserverWith(overrides: { [key in keyof IListObserver< return Object.assign(defaults, overrides); } -export abstract class BaseObservableList extends BaseObservable> { +export abstract class BaseObservableList extends BaseObservable> implements Iterable { emitReset() { for(let h of this._handlers) { h.onReset(this); @@ -69,6 +69,6 @@ export abstract class BaseObservableList extends BaseObservable; abstract get length(): number; } diff --git a/src/platform/web/ui/general/Range.ts b/src/platform/web/ui/general/Range.ts index 16dc0a33..a3ca54c0 100644 --- a/src/platform/web/ui/general/Range.ts +++ b/src/platform/web/ui/general/Range.ts @@ -43,7 +43,7 @@ export class Range { return range.start < this.end && this.start < range.end; } - forEachInIterator(it: IterableIterator, callback: ((T, i: number) => void)) { + forEachInIterator(it: Iterator, callback: ((T, i: number) => void)) { let i = 0; for (i = 0; i < this.start; i += 1) { it.next(); From 85385a0aa7c9e725f16ff192893ddf34032f7fe6 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 1 Dec 2021 09:43:58 +0100 Subject: [PATCH 60/62] adjust path --- src/platform/web/ui/general/ListRange.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/web/ui/general/ListRange.ts b/src/platform/web/ui/general/ListRange.ts index 66ee8dfb..23e0ab2e 100644 --- a/src/platform/web/ui/general/ListRange.ts +++ b/src/platform/web/ui/general/ListRange.ts @@ -215,7 +215,7 @@ export class ListRange extends Range { } } -import {ObservableArray} from "../../../../observable/list/ObservableArray.js"; +import {ObservableArray} from "../../../../observable/list/ObservableArray"; export function tests() { return { From 9f82e7f7fc2f0b734884c0da6a5ca8dbd25a6423 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 2 Dec 2021 11:17:41 +0530 Subject: [PATCH 61/62] Add proper type --- src/matrix/push/Pusher.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/matrix/push/Pusher.ts b/src/matrix/push/Pusher.ts index f9a35a2c..9f970322 100644 --- a/src/matrix/push/Pusher.ts +++ b/src/matrix/push/Pusher.ts @@ -32,8 +32,8 @@ export interface IPusherDescription { interface IPusherData { format?: string; url?: string; - // todo: where did this come from? - endpoint?: string; + endpoint?: PushSubscriptionJSON["endpoint"]; + keys?: PushSubscriptionJSON["keys"]; } export class Pusher { From 0c464608616c54a20d1e96e3da69af9e2939c9cf Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 2 Dec 2021 11:20:40 +0530 Subject: [PATCH 62/62] Add comment --- src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts b/src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts index fd407c6a..ebe575f6 100644 --- a/src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts +++ b/src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts @@ -19,7 +19,7 @@ interface ISessionInfo { deviceId: string; userId: string; homeserver: string; - homeServer: string; + homeServer: string; // deprecate this over time accessToken: string; lastUsed: number; }