From 348a9c83f5b96798dadce02fbc7b1e5437163409 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 29 Sep 2021 18:51:02 -0700 Subject: [PATCH 001/242] 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 002/242] 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 003/242] 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 004/242] 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 005/242] 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 006/242] 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 007/242] 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 008/242] 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 009/242] 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 010/242] 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 011/242] 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 012/242] 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 013/242] 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 d31371b4865e53a7ada510b015c0ea9936ea336e Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 8 Nov 2021 14:37:32 +0530 Subject: [PATCH 014/242] Return on upload in sw --- src/platform/web/docroot/sw.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/platform/web/docroot/sw.js b/src/platform/web/docroot/sw.js index 29b124d9..21fdf2d2 100644 --- a/src/platform/web/docroot/sw.js +++ b/src/platform/web/docroot/sw.js @@ -69,6 +69,9 @@ async function purgeOldCaches() { } self.addEventListener('fetch', (event) => { + if (event.request.url.indexOf("upload") !== -1) { + return; + } event.respondWith(handleRequest(event.request)); }); From d1491cc2033cae8d666eaf6e0840514d99c29e10 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 8 Nov 2021 15:11:41 +0530 Subject: [PATCH 015/242] More checks before returning --- src/platform/web/docroot/sw.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/platform/web/docroot/sw.js b/src/platform/web/docroot/sw.js index 21fdf2d2..9b5da128 100644 --- a/src/platform/web/docroot/sw.js +++ b/src/platform/web/docroot/sw.js @@ -68,8 +68,10 @@ async function purgeOldCaches() { } } -self.addEventListener('fetch', (event) => { - if (event.request.url.indexOf("upload") !== -1) { +self.addEventListener('fetch', async (event) => { + if (event.request.method === "POST" && + (await event.request.blob()).type !== "application/json" && + event.request.body) { return; } event.respondWith(handleRequest(event.request)); From db3e8a9c6b88adb2a2e4997a2699dbdaf639eac8 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 5 Oct 2021 17:10:17 +0200 Subject: [PATCH 016/242] rearrange assets and main.js to make them run with vite --- package.json | 5 +- .../platform/web/assets}/config.json | 0 .../web/assets}/download-sandbox.html | 0 .../platform/web/assets}/icon-maskable.png | Bin .../platform/web/assets}/icon-maskable.svg | 0 {assets => src/platform/web/assets}/icon.png | Bin {assets => src/platform/web/assets}/icon.svg | 0 .../platform/web/assets}/manifest.json | 0 src/platform/web/{docroot => }/index.html | 23 ++- src/{ => platform/web}/main.js | 6 +- src/platform/web/sdk/paths/vite.ts | 14 ++ src/platform/web/{docroot => }/sw.js | 0 src/sdk/paths/vite.ts | 12 -- .../ui/view-gallery.html => view-gallery.html | 0 vite.config.js | 7 + yarn.lock | 140 ++++++++++++++++++ 16 files changed, 177 insertions(+), 30 deletions(-) rename {assets => src/platform/web/assets}/config.json (100%) rename {assets => src/platform/web/assets}/download-sandbox.html (100%) rename {assets => src/platform/web/assets}/icon-maskable.png (100%) rename {assets => src/platform/web/assets}/icon-maskable.svg (100%) rename {assets => src/platform/web/assets}/icon.png (100%) rename {assets => src/platform/web/assets}/icon.svg (100%) rename {assets => src/platform/web/assets}/manifest.json (100%) rename src/platform/web/{docroot => }/index.html (62%) rename src/{ => platform/web}/main.js (91%) create mode 100644 src/platform/web/sdk/paths/vite.ts rename src/platform/web/{docroot => }/sw.js (100%) delete mode 100644 src/sdk/paths/vite.ts rename src/platform/web/ui/view-gallery.html => view-gallery.html (100%) create mode 100644 vite.config.js diff --git a/package.json b/package.json index b391a3c0..562b6c7b 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "lint": "eslint --cache src/", "lint-ts": "eslint src/ -c .ts-eslintrc.js --ext .ts", "lint-ci": "eslint src/", - "test": "impunity --entry-point src/main.js --force-esm-dirs lib/ src/", + "test": "impunity --entry-point src/platform/web/main.js --force-esm-dirs lib/ src/", "start": "snowpack dev --port 3000", "build": "node --experimental-modules scripts/build.mjs", "postinstall": "node ./scripts/post-install.js" @@ -66,6 +66,7 @@ "dompurify": "^2.3.0", "es6-promise": "https://github.com/bwindels/es6-promise.git#bwindels/expose-flush", "rollup": "^2.26.4", - "text-encoding": "^0.7.0" + "text-encoding": "^0.7.0", + "vite": "^2.6.3" } } diff --git a/assets/config.json b/src/platform/web/assets/config.json similarity index 100% rename from assets/config.json rename to src/platform/web/assets/config.json diff --git a/assets/download-sandbox.html b/src/platform/web/assets/download-sandbox.html similarity index 100% rename from assets/download-sandbox.html rename to src/platform/web/assets/download-sandbox.html diff --git a/assets/icon-maskable.png b/src/platform/web/assets/icon-maskable.png similarity index 100% rename from assets/icon-maskable.png rename to src/platform/web/assets/icon-maskable.png diff --git a/assets/icon-maskable.svg b/src/platform/web/assets/icon-maskable.svg similarity index 100% rename from assets/icon-maskable.svg rename to src/platform/web/assets/icon-maskable.svg diff --git a/assets/icon.png b/src/platform/web/assets/icon.png similarity index 100% rename from assets/icon.png rename to src/platform/web/assets/icon.png diff --git a/assets/icon.svg b/src/platform/web/assets/icon.svg similarity index 100% rename from assets/icon.svg rename to src/platform/web/assets/icon.svg diff --git a/assets/manifest.json b/src/platform/web/assets/manifest.json similarity index 100% rename from assets/manifest.json rename to src/platform/web/assets/manifest.json diff --git a/src/platform/web/docroot/index.html b/src/platform/web/index.html similarity index 62% rename from src/platform/web/docroot/index.html rename to src/platform/web/index.html index 16f164ae..397aae66 100644 --- a/src/platform/web/docroot/index.html +++ b/src/platform/web/index.html @@ -9,11 +9,11 @@ - + - - - + + + diff --git a/src/main.js b/src/platform/web/main.js similarity index 91% rename from src/main.js rename to src/platform/web/main.js index 0754b2ab..34522ea8 100644 --- a/src/main.js +++ b/src/platform/web/main.js @@ -16,9 +16,9 @@ limitations under the License. */ // import {RecordRequester, ReplayRequester} from "./matrix/net/request/replay.js"; -import {SessionContainer} from "./matrix/SessionContainer.js"; -import {RootViewModel} from "./domain/RootViewModel.js"; -import {createNavigation, createRouter} from "./domain/navigation/index.js"; +import {SessionContainer} from "../../matrix/SessionContainer.js"; +import {RootViewModel} from "../../domain/RootViewModel.js"; +import {createNavigation, createRouter} from "../../domain/navigation/index.js"; // Don't use a default export here, as we use multiple entries during legacy build, // which does not support default exports, // see https://github.com/rollup/plugins/tree/master/packages/multi-entry diff --git a/src/platform/web/sdk/paths/vite.ts b/src/platform/web/sdk/paths/vite.ts new file mode 100644 index 00000000..eca08827 --- /dev/null +++ b/src/platform/web/sdk/paths/vite.ts @@ -0,0 +1,14 @@ +import _downloadSandboxPath from "../../assets/download-sandbox.html?url"; +import _workerPath from "../../worker/main.js?url"; +import olmWasmPath from "@matrix-org/olm/olm.wasm?url"; +import olmJsPath from "@matrix-org/olm/olm.js?url"; +import olmLegacyJsPath from "@matrix-org/olm/olm_legacy.js?url"; + +export const olmPaths = { + wasm: olmWasmPath, + legacyBundle: olmLegacyJsPath, + wasmBundle: olmJsPath, +}; + +export const downloadSandboxPath = _downloadSandboxPath; +export const workerPath = _workerPath; diff --git a/src/platform/web/docroot/sw.js b/src/platform/web/sw.js similarity index 100% rename from src/platform/web/docroot/sw.js rename to src/platform/web/sw.js diff --git a/src/sdk/paths/vite.ts b/src/sdk/paths/vite.ts deleted file mode 100644 index e38648eb..00000000 --- a/src/sdk/paths/vite.ts +++ /dev/null @@ -1,12 +0,0 @@ -import _downloadSandboxPath from "../../../assets/download-sandbox.html?url"; -import olmWasmPath from "../../../lib/olm/olm.wasm?url"; -import olmJsPath from "../../../lib/olm/olm.js?url"; -import olmLegacyJsPath from "../../../lib/olm/olm_legacy.js?url"; - -export const olmPaths = { - wasm: olmWasmPath, - legacyBundle: olmLegacyJsPath, - wasmBundle: olmJsPath, -}; - -export const downloadSandboxPath = _downloadSandboxPath; diff --git a/src/platform/web/ui/view-gallery.html b/view-gallery.html similarity index 100% rename from src/platform/web/ui/view-gallery.html rename to view-gallery.html diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 00000000..d27d8a3a --- /dev/null +++ b/vite.config.js @@ -0,0 +1,7 @@ +export default { + public: false, + root: "src/platform/web", + server: { + hmr: false + } +}; diff --git a/yarn.lock b/yarn.lock index fc159a40..93747878 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2293,6 +2293,61 @@ es-module-lexer@^0.6.0: version "4.2.8" resolved "https://github.com/bwindels/es6-promise.git#112f78f5829e627055b0ff56a52fecb63f6003b1" +esbuild-android-arm64@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.13.4.tgz#5178a20d2b7aba741a31c19609f9e67b346996b9" + integrity sha512-elDJt+jNyoHFId0/dKsuVYUPke3EcquIyUwzJCH17a3ERglN3A9aMBI5zbz+xNZ+FbaDNdpn0RaJHCFLbZX+fA== + +esbuild-darwin-64@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.13.4.tgz#7a3e66c8e1271b650541b25eed65c84f3564a69d" + integrity sha512-zJQGyHRAdZUXlRzbN7W+7ykmEiGC+bq3Gc4GxKYjjWTgDRSEly98ym+vRNkDjXwXYD3gGzSwvH35+MiHAtWvLA== + +esbuild-darwin-arm64@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.4.tgz#793feca6032b2a57ef291eb9b2d33768d60a49d6" + integrity sha512-r8oYvAtqSGq8HNTZCAx4TdLE7jZiGhX9ooGi5AQAey37MA6XNaP8ZNlw9OCpcgpx3ryU2WctXwIqPzkHO7a8dg== + +esbuild-freebsd-64@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.4.tgz#294aec3c2cf4b41fb6900212fc9c33dd8fbbb4a2" + integrity sha512-u9DRGkn09EN8+lCh6z7FKle7awi17PJRBuAKdRNgSo5ZrH/3m+mYaJK2PR2URHMpAfXiwJX341z231tSdVe3Yw== + +esbuild-freebsd-arm64@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.4.tgz#09fe66c751c12f9b976976b1d83f3de594cb2787" + integrity sha512-q3B2k68Uf6gfjATjcK16DqxvjqRQkHL8aPoOfj4op+lSqegdXvBacB1d8jw8PxbWJ8JHpdTLdAVUYU80kotQXA== + +esbuild-linux-32@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.13.4.tgz#a9f0793d7bcc9cef4f4ffa4398c525877fba5839" + integrity sha512-UUYJPHSiKAO8KoN3Ls/iZtgDLZvK5HarES96aolDPWZnq9FLx4dIHM/x2z4Rxv9IYqQ/DxlPoE2Co1UPBIYYeA== + +esbuild-linux-64@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.13.4.tgz#c0d0b4c9d62e3bbf8bdf2cece37403aa6d60fc2e" + integrity sha512-+RnohAKiiUW4UHLGRkNR1AnENW1gCuDWuygEtd4jxTNPIoeC7lbXGor7rtgjj9AdUzFgOEvAXyNNX01kJ8NueQ== + +esbuild-linux-arm64@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.4.tgz#1292d97bfa64a08d12728f8a7837bf92776c779b" + integrity sha512-+A188cAdd6QuSRxMIwRrWLjgphQA0LDAQ/ECVlrPVJwnx+1i64NjDZivoqPYLOTkSPIKntiWwMhhf0U5/RrPHQ== + +esbuild-linux-arm@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.13.4.tgz#186cd9b8885ac132b9953a4a0afe668168debd10" + integrity sha512-BH5gKve4jglS7UPSsfwHSX79I5agC/lm4eKoRUEyo8lwQs89frQSRp2Xup+6SFQnxt3md5EsKcd2Dbkqeb3gPA== + +esbuild-linux-mips64le@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.4.tgz#42049bf72bc586817b4a51cc9e32148d13e5e807" + integrity sha512-0xkwtPaUkG5xMTFGaQPe1AadSe5QAiQuD4Gix1O9k5Xo/U8xGIkw9UFUTvfEUeu71vFb6ZgsIacfP1NLoFjWNw== + +esbuild-linux-ppc64le@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.4.tgz#adf1ce2ef2302757c4383887da6ac4dd25be9d4f" + integrity sha512-E1+oJPP7A+j23GPo3CEpBhGwG1bni4B8IbTA3/3rvzjURwUMZdcN3Fhrz24rnjzdLSHmULtOE4VsbT42h1Om4Q== + esbuild-node-loader@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/esbuild-node-loader/-/esbuild-node-loader-0.3.1.tgz#fa761e020eff316549ddc3c51a25ec9ffc159ff2" @@ -2300,11 +2355,58 @@ esbuild-node-loader@^0.3.1: dependencies: esbuild "^0.12.6" +esbuild-openbsd-64@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.4.tgz#1c8122101898c52a20c8786935cf3eb7a19b83b4" + integrity sha512-xEkI1o5HYxDzbv9jSox0EsDxpwraG09SRiKKv0W8pH6O3bt+zPSlnoK7+I7Q69tkvONkpIq5n2o+c55uq0X7cw== + +esbuild-sunos-64@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.13.4.tgz#4ec95faa14a60f295fe485bebffefff408739337" + integrity sha512-bjXUMcODMnB6hQicLBBmmnBl7OMDyVpFahKvHGXJfDChIi5udiIRKCmFUFIRn+AUAKVlfrofRKdyPC7kBsbvGQ== + +esbuild-windows-32@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.13.4.tgz#3182c380487b797b04d0ec2c80c2945666869080" + integrity sha512-z4CH07pfyVY0XF98TCsGmLxKCl0kyvshKDbdpTekW9f2d+dJqn5mmoUyWhpSVJ0SfYWJg86FoD9nMbbaMVyGdg== + +esbuild-windows-64@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.13.4.tgz#b9e995f92d81f433a04f33611e603e82f9232e69" + integrity sha512-uVL11vORRPjocGLYam67rwFLd0LvkrHEs+JG+1oJN4UD9MQmNGZPa4gBHo6hDpF+kqRJ9kXgQSeDqUyRy0tj/Q== + +esbuild-windows-arm64@0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.4.tgz#fb239532f07b764d158f4cc787178ef4c6fadb5c" + integrity sha512-vA6GLvptgftRcDcWngD5cMlL4f4LbL8JjU2UMT9yJ0MT5ra6hdZNFWnOeOoEtY4GtJ6OjZ0i+81sTqhAB0fMkg== + esbuild@^0.12.6: version "0.12.20" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.12.20.tgz#4d3c9d83c99a4031e027b42a4c398c23b6827cb0" integrity sha512-u7+0qTo9Z64MD9PhooEngCmzyEYJ6ovFhPp8PLNh3UasR5Ihjv6HWVXqm8uHmasdQlpsAf0IsY4U0YVUfCpt4Q== +esbuild@^0.13.2: + version "0.13.4" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.13.4.tgz#ce2deb56c4fb360938311cbfc67f8e467bb6841b" + integrity sha512-wMA5eUwpavTBiNl+It6j8OQuKVh69l6z4DKDLzoTIqC+gChnPpcmqdA8WNHptUHRnfyML+mKEQPlW7Mybj8gHg== + optionalDependencies: + esbuild-android-arm64 "0.13.4" + esbuild-darwin-64 "0.13.4" + esbuild-darwin-arm64 "0.13.4" + esbuild-freebsd-64 "0.13.4" + esbuild-freebsd-arm64 "0.13.4" + esbuild-linux-32 "0.13.4" + esbuild-linux-64 "0.13.4" + esbuild-linux-arm "0.13.4" + esbuild-linux-arm64 "0.13.4" + esbuild-linux-mips64le "0.13.4" + esbuild-linux-ppc64le "0.13.4" + esbuild-openbsd-64 "0.13.4" + esbuild-sunos-64 "0.13.4" + esbuild-windows-32 "0.13.4" + esbuild-windows-64 "0.13.4" + esbuild-windows-arm64 "0.13.4" + esbuild@~0.9.0: version "0.9.7" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.9.7.tgz#ea0d639cbe4b88ec25fbed4d6ff00c8d788ef70b" @@ -3683,6 +3785,11 @@ nanoid@^3.1.23: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== +nanoid@^3.1.28: + version "3.1.28" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.28.tgz#3c01bac14cb6c5680569014cc65a2f26424c6bd4" + integrity sha512-gSu9VZ2HtmoKYe/lmyPFES5nknFrHa+/DT9muUFWFMi6Jh9E1I7bkvlQ8xxf1Kos9pi9o8lBnIOkatMhKX/YUw== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -4105,6 +4212,11 @@ periscopic@^2.0.3: estree-walker "^2.0.2" is-reference "^1.1.4" +picocolors@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" + integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== + picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" @@ -4271,6 +4383,15 @@ postcss@^8.3.5: nanoid "^3.1.23" source-map-js "^0.6.2" +postcss@^8.3.8: + version "8.3.9" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.9.tgz#98754caa06c4ee9eb59cc48bd073bb6bd3437c31" + integrity sha512-f/ZFyAKh9Dnqytx5X62jgjhhzttjZS7hMsohcI7HEI5tjELX/HxCy3EFhsRxyzGvrzFF+82XPvCS8T9TFleVJw== + dependencies: + nanoid "^3.1.28" + picocolors "^0.2.1" + source-map-js "^0.6.2" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -4602,6 +4723,13 @@ rollup@^2.26.4: optionalDependencies: fsevents "~2.1.2" +rollup@^2.57.0: + version "2.58.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.58.0.tgz#a643983365e7bf7f5b7c62a8331b983b7c4c67fb" + integrity sha512-NOXpusKnaRpbS7ZVSzcEXqxcLDOagN6iFS8p45RkoiMqPHDLwJm758UF05KlMoCRbLBTZsPOIa887gZJ1AiXvw== + optionalDependencies: + fsevents "~2.3.2" + rollup@~2.37.1: version "2.37.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.37.1.tgz#aa7aadffd75c80393f9314f9857e851b0ffd34e7" @@ -5239,6 +5367,18 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vite@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/vite/-/vite-2.6.3.tgz#5bbc1d3fcff6bfee9c5e3c0d0a689b18e5974b38" + integrity sha512-mLiN4WR8zpmn04khhBf7YvC3FHrGhZt9S6xm53uDWgtYcUVNtV5LXHLI2Sc4SpL8jd/dsSIHzRxj7JTIu+MTDQ== + dependencies: + esbuild "^0.13.2" + postcss "^8.3.8" + resolve "^1.20.0" + rollup "^2.57.0" + optionalDependencies: + fsevents "~2.3.2" + vm2@^3.9.2: version "3.9.3" resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.3.tgz#29917f6cc081cc43a3f580c26c5b553fd3c91f40" From b6fda8865faf3e1857f6eca18d82176af224da18 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 5 Oct 2021 17:51:10 +0200 Subject: [PATCH 017/242] make all dependencies use vite and remove post-install script / lib dir --- package.json | 5 +- scripts/post-install.js | 132 ------------------ .../session/room/timeline/deserialize.js | 2 +- src/matrix/e2ee/Account.js | 2 +- src/matrix/e2ee/common.js | 2 +- src/mocks/Storage.ts | 3 +- src/platform/web/LegacyPlatform.js | 2 +- src/platform/web/dom/Crypto.js | 2 +- src/platform/web/legacy-polyfill.js | 2 +- src/platform/web/utils/Base58.js | 2 +- src/platform/web/utils/Base64.js | 2 +- src/platform/web/worker/polyfill.js | 2 +- vite.config.js | 6 + 13 files changed, 19 insertions(+), 145 deletions(-) delete mode 100644 scripts/post-install.js diff --git a/package.json b/package.json index 562b6c7b..edf2e673 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,9 @@ "lint": "eslint --cache src/", "lint-ts": "eslint src/ -c .ts-eslintrc.js --ext .ts", "lint-ci": "eslint src/", - "test": "impunity --entry-point src/platform/web/main.js --force-esm-dirs lib/ src/", + "test": "impunity --entry-point src/platform/web/main.js --force-esm-dirs src/", "start": "snowpack dev --port 3000", - "build": "node --experimental-modules scripts/build.mjs", - "postinstall": "node ./scripts/post-install.js" + "build": "node --experimental-modules scripts/build.mjs" }, "repository": { "type": "git", diff --git a/scripts/post-install.js b/scripts/post-install.js deleted file mode 100644 index 39ccf06a..00000000 --- a/scripts/post-install.js +++ /dev/null @@ -1,132 +0,0 @@ -/* -Copyright 2020 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. -*/ - -const fsRoot = require("fs"); -const fs = fsRoot.promises; -const path = require("path"); -const { rollup } = require('rollup'); -const { fileURLToPath } = require('url'); -const { dirname } = require('path'); -// needed to translate commonjs modules to esm -const commonjs = require('@rollup/plugin-commonjs'); -const json = require('@rollup/plugin-json'); -const { nodeResolve } = require('@rollup/plugin-node-resolve'); - -const projectDir = path.join(__dirname, "../"); - -async function removeDirIfExists(targetDir) { - try { - await fs.rmdir(targetDir, {recursive: true}); - } catch (err) { - if (err.code !== "ENOENT") { - throw err; - } - } -} - -/** function used to resolve common-js require calls below. */ -function packageIterator(request, start, defaultIterator) { - // this is just working for bs58, would need to tune it further for other dependencies - if (request === "safe-buffer") { - return [path.join(projectDir, "/scripts/package-overrides/safe-buffer")]; - } else if (request === "buffer/") { - return [path.join(projectDir, "/scripts/package-overrides/buffer")]; - } else { - return defaultIterator(); - } -} - -async function commonjsToESM(src, dst) { - // create js bundle - const bundle = await rollup({ - treeshake: {moduleSideEffects: false}, - input: src, - plugins: [commonjs(), json(), nodeResolve({ - browser: true, - preferBuiltins: false, - customResolveOptions: {packageIterator} - })] - }); - const {output} = await bundle.generate({ - format: 'es' - }); - const code = output[0].code; - await fs.writeFile(dst, code, "utf8"); -} - -async function populateLib() { - const libDir = path.join(projectDir, "lib/"); - await removeDirIfExists(libDir); - await fs.mkdir(libDir); - const olmSrcDir = path.dirname(require.resolve("@matrix-org/olm")); - const olmDstDir = path.join(libDir, "olm/"); - await fs.mkdir(olmDstDir); - for (const file of ["olm.js", "olm.wasm", "olm_legacy.js"]) { - await fs.copyFile(path.join(olmSrcDir, file), path.join(olmDstDir, file)); - } - // transpile node-html-parser to esm - await fs.mkdir(path.join(libDir, "node-html-parser/")); - await commonjsToESM( - require.resolve('node-html-parser/dist/index.js'), - path.join(libDir, "node-html-parser/index.js") - ); - // transpile another-json to esm - await fs.mkdir(path.join(libDir, "another-json/")); - await commonjsToESM( - require.resolve('another-json/another-json.js'), - path.join(libDir, "another-json/index.js") - ); - // transpile bs58 to esm - await fs.mkdir(path.join(libDir, "bs58/")); - await commonjsToESM( - require.resolve('bs58/index.js'), - path.join(libDir, "bs58/index.js") - ); - // transpile base64-arraybuffer to esm - await fs.mkdir(path.join(libDir, "base64-arraybuffer/")); - await commonjsToESM( - require.resolve('base64-arraybuffer/lib/base64-arraybuffer.js'), - path.join(libDir, "base64-arraybuffer/index.js") - ); - // this probably should no go in here, we can just import "aes-js" from legacy-extras.js - // as that file is never loaded from a browser - - // transpile aesjs to esm - await fs.mkdir(path.join(libDir, "aes-js/")); - await commonjsToESM( - require.resolve('aes-js/index.js'), - path.join(libDir, "aes-js/index.js") - ); - // es6-promise is already written as an es module, - // but it does need to be babelified, and current we don't babelify - // anything in node_modules in the build script, so make a bundle that - // is conveniently not placed in node_modules rather than symlinking. - await fs.mkdir(path.join(libDir, "es6-promise/")); - await commonjsToESM( - require.resolve('es6-promise/lib/es6-promise/promise.js'), - path.join(libDir, "es6-promise/index.js") - ); - // fake-indexeddb, used for tests (but unresolvable bare imports also makes the build complain) - // and might want to use it for in-memory storage too, although we probably do ts->es6 with esm - // directly rather than ts->es5->es6 as we do now. The bundle is 240K currently. - await fs.mkdir(path.join(libDir, "fake-indexeddb/")); - await commonjsToESM( - path.join(projectDir, "/scripts/package-overrides/fake-indexeddb.js"), - path.join(libDir, "fake-indexeddb/index.js") - ); -} - -populateLib(); diff --git a/src/domain/session/room/timeline/deserialize.js b/src/domain/session/room/timeline/deserialize.js index ce690732..ecddb5b7 100644 --- a/src/domain/session/room/timeline/deserialize.js +++ b/src/domain/session/room/timeline/deserialize.js @@ -352,7 +352,7 @@ export function parseHTMLBody(platform, mediaRepository, allowReplies, html) { return new MessageBody(html, parts); } -import parse from '../../../../../lib/node-html-parser/index.js'; +import parse from "node-html-parser"; export function tests() { class HTMLParseResult { diff --git a/src/matrix/e2ee/Account.js b/src/matrix/e2ee/Account.js index 13792ddc..ac651819 100644 --- a/src/matrix/e2ee/Account.js +++ b/src/matrix/e2ee/Account.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import anotherjson from "../../../lib/another-json/index.js"; +import anotherjson from "another-json"; import {SESSION_E2EE_KEY_PREFIX, OLM_ALGORITHM, MEGOLM_ALGORITHM} from "./common.js"; // use common prefix so it's easy to clear properties that are not e2ee related during session clear diff --git a/src/matrix/e2ee/common.js b/src/matrix/e2ee/common.js index fa970236..90252b15 100644 --- a/src/matrix/e2ee/common.js +++ b/src/matrix/e2ee/common.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import anotherjson from "../../../lib/another-json/index.js"; +import anotherjson from "another-json"; import {createEnum} from "../../utils/enum.js"; export const DecryptionSource = createEnum("Sync", "Timeline", "Retry"); diff --git a/src/mocks/Storage.ts b/src/mocks/Storage.ts index 5dba796a..0d8db7f0 100644 --- a/src/mocks/Storage.ts +++ b/src/mocks/Storage.ts @@ -14,7 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {FDBFactory, FDBKeyRange} from "../../lib/fake-indexeddb/index.js"; +import {FDBFactory} from "fake-indexeddb/lib/FDBFactory.js"; +import {FDBKeyRange} from "fake-indexeddb/lib/FDBKeyRange.js"; import {StorageFactory} from "../matrix/storage/idb/StorageFactory"; import {IDOMStorage} from "../matrix/storage/idb/types"; import {Storage} from "../matrix/storage/idb/Storage"; diff --git a/src/platform/web/LegacyPlatform.js b/src/platform/web/LegacyPlatform.js index e6bf7774..624600ff 100644 --- a/src/platform/web/LegacyPlatform.js +++ b/src/platform/web/LegacyPlatform.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import aesjs from "../../../lib/aes-js/index.js"; +import aesjs from "aes-js"; import {hkdf} from "../../utils/crypto/hkdf.js"; import {Platform as ModernPlatform} from "./Platform.js"; diff --git a/src/platform/web/dom/Crypto.js b/src/platform/web/dom/Crypto.js index b28897fa..441daf31 100644 --- a/src/platform/web/dom/Crypto.js +++ b/src/platform/web/dom/Crypto.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import base64 from "../../../../lib/base64-arraybuffer/index.js"; +import base64 from "base64-arraybuffer"; // turn IE11 result into promise function subtleCryptoResult(promiseOrOp, method) { diff --git a/src/platform/web/legacy-polyfill.js b/src/platform/web/legacy-polyfill.js index 45628f2c..e3dd8fb0 100644 --- a/src/platform/web/legacy-polyfill.js +++ b/src/platform/web/legacy-polyfill.js @@ -15,7 +15,7 @@ limitations under the License. */ // polyfills needed for IE11 -import Promise from "../../../lib/es6-promise/index.js"; +import Promise from "es6-promise/lib/es6-promise/promise.js"; import {checkNeedsSyncPromise} from "../../matrix/storage/idb/utils"; if (typeof window.Promise === "undefined") { diff --git a/src/platform/web/utils/Base58.js b/src/platform/web/utils/Base58.js index ebe4a969..b3f0bca7 100644 --- a/src/platform/web/utils/Base58.js +++ b/src/platform/web/utils/Base58.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import bs58 from "../../../../lib/bs58/index.js"; +import bs58 from "bs58"; export class Base58 { encode(buffer) { diff --git a/src/platform/web/utils/Base64.js b/src/platform/web/utils/Base64.js index 6c114fe6..83b5ccc5 100644 --- a/src/platform/web/utils/Base64.js +++ b/src/platform/web/utils/Base64.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import base64 from "../../../../lib/base64-arraybuffer/index.js"; +import base64 from "base64-arraybuffer"; export class Base64 { encodeUnpadded(buffer) { diff --git a/src/platform/web/worker/polyfill.js b/src/platform/web/worker/polyfill.js index d7f4b0d2..3c1f60e5 100644 --- a/src/platform/web/worker/polyfill.js +++ b/src/platform/web/worker/polyfill.js @@ -19,7 +19,7 @@ limitations under the License. // just enough to run olm, have promises and async/await // load this first just in case anything else depends on it -import Promise from "../../../../lib/es6-promise/index.js"; +import Promise from "es6-promise/lib/es6-promise/promise.js"; // not calling checkNeedsSyncPromise from here as we don't do any idb in the worker, // mainly because IE doesn't handle multiple concurrent connections well self.Promise = Promise; diff --git a/vite.config.js b/vite.config.js index d27d8a3a..450b8d40 100644 --- a/vite.config.js +++ b/vite.config.js @@ -3,5 +3,11 @@ export default { root: "src/platform/web", server: { hmr: false + }, + resolve: { + alias: { + "safe-buffer": "./scripts/package-overrides/safe-buffer/index.js", + "buffer": "./scripts/package-overrides/buffer/index.js" + } } }; From 01712c3f237019b6b676d3421a80e46c33900a6c Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 5 Oct 2021 19:28:19 +0200 Subject: [PATCH 018/242] make tests run again --- package.json | 2 +- .../session/room/timeline/deserialize.js | 3 ++- src/mocks/Storage.ts | 4 +-- yarn.lock | 25 ++++++++----------- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index edf2e673..e9c9e991 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "lint-ci": "eslint src/", "test": "impunity --entry-point src/platform/web/main.js --force-esm-dirs src/", "start": "snowpack dev --port 3000", - "build": "node --experimental-modules scripts/build.mjs" + "test": "impunity --entry-point src/platform/web/main.js --force-esm-dirs src/ --root-dir src/", }, "repository": { "type": "git", diff --git a/src/domain/session/room/timeline/deserialize.js b/src/domain/session/room/timeline/deserialize.js index ecddb5b7..9421f8f1 100644 --- a/src/domain/session/room/timeline/deserialize.js +++ b/src/domain/session/room/timeline/deserialize.js @@ -352,7 +352,8 @@ export function parseHTMLBody(platform, mediaRepository, allowReplies, html) { return new MessageBody(html, parts); } -import parse from "node-html-parser"; +import nodeHtmlParser from "node-html-parser"; +const {parse} = nodeHtmlParser; export function tests() { class HTMLParseResult { diff --git a/src/mocks/Storage.ts b/src/mocks/Storage.ts index 0d8db7f0..2760c061 100644 --- a/src/mocks/Storage.ts +++ b/src/mocks/Storage.ts @@ -14,8 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {FDBFactory} from "fake-indexeddb/lib/FDBFactory.js"; -import {FDBKeyRange} from "fake-indexeddb/lib/FDBKeyRange.js"; +import FDBFactory from "fake-indexeddb/lib/FDBFactory.js"; +import FDBKeyRange from "fake-indexeddb/lib/FDBKeyRange.js"; import {StorageFactory} from "../matrix/storage/idb/StorageFactory"; import {IDOMStorage} from "../matrix/storage/idb/types"; import {Storage} from "../matrix/storage/idb/Storage"; diff --git a/yarn.lock b/yarn.lock index 93747878..d2e3035d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1847,9 +1847,9 @@ commander@^6.0.0: integrity sha512-s7EA+hDtTYNhuXkTlhqew4txMZVdszBmKWSPEMxGr8ru8JXR7bLUFIAtPhcSuFdJQ0ILMxnJi8GkQL0yvDy/YA== commander@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-6.1.0.tgz#f8d722b78103141006b66f4c7ba1e97315ba75bc" - integrity sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA== + version "6.2.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== common-ancestor-path@^1.0.1: version "1.0.1" @@ -2349,11 +2349,11 @@ esbuild-linux-ppc64le@0.13.4: integrity sha512-E1+oJPP7A+j23GPo3CEpBhGwG1bni4B8IbTA3/3rvzjURwUMZdcN3Fhrz24rnjzdLSHmULtOE4VsbT42h1Om4Q== esbuild-node-loader@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/esbuild-node-loader/-/esbuild-node-loader-0.3.1.tgz#fa761e020eff316549ddc3c51a25ec9ffc159ff2" - integrity sha512-75xPOySulti9R5LwYOMmKiwHyXGr/f89I7UkHolLxRqeBiUNqcyCmNTjv+fO2WV9G3f7LDKVZJlbWoYh5LBpfQ== + version "0.3.2" + resolved "https://registry.yarnpkg.com/esbuild-node-loader/-/esbuild-node-loader-0.3.2.tgz#39918776ece52da31f771be9dbcedc459ccf814b" + integrity sha512-4Y6sTwvB5pH+A7gmpd/xzyPkOZC4nmEWRoGBi4BQoE0DhZvrrzHqSmT+jb4x7m1rwv4BCuNbajN13LN8D0PGoA== dependencies: - esbuild "^0.12.6" + esbuild "^0.13.2" esbuild-openbsd-64@0.13.4: version "0.13.4" @@ -2380,11 +2380,6 @@ esbuild-windows-arm64@0.13.4: resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.4.tgz#fb239532f07b764d158f4cc787178ef4c6fadb5c" integrity sha512-vA6GLvptgftRcDcWngD5cMlL4f4LbL8JjU2UMT9yJ0MT5ra6hdZNFWnOeOoEtY4GtJ6OjZ0i+81sTqhAB0fMkg== -esbuild@^0.12.6: - version "0.12.20" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.12.20.tgz#4d3c9d83c99a4031e027b42a4c398c23b6827cb0" - integrity sha512-u7+0qTo9Z64MD9PhooEngCmzyEYJ6ovFhPp8PLNh3UasR5Ihjv6HWVXqm8uHmasdQlpsAf0IsY4U0YVUfCpt4Q== - esbuild@^0.13.2: version "0.13.4" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.13.4.tgz#ce2deb56c4fb360938311cbfc67f8e467bb6841b" @@ -3124,9 +3119,9 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: resolve-from "^4.0.0" impunity@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/impunity/-/impunity-1.0.1.tgz#e1d19c468bd7b8ae3dc7ad44ccbe81f17c626fde" - integrity sha512-MbQ6+UcLNdpMZPBYvr0OLY3pQCr8UMjMK45YCIrRFsZUO9hj/eMurLjpjiO3HBgCkZcw+5FlU6JCHjm5Q3u7mw== + version "1.0.2" + resolved "https://registry.yarnpkg.com/impunity/-/impunity-1.0.2.tgz#17819562cef60a4e74dd095438012131211687f4" + integrity sha512-tv61TSxBUd02Tap2IFajD8pQ+PCo4/lZG4DOd4nWmRYyH/KyxKEU6I0u4jn3mqWhCF6ECdRh5g98abWcvNPcHA== dependencies: colors "^1.3.3" commander "^6.1.0" From e2b20f466ddd09bdf7a08327e26b9a17653781a0 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 5 Oct 2021 19:28:38 +0200 Subject: [PATCH 019/242] remove unneeded package override --- scripts/package-overrides/fake-indexeddb.js | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 scripts/package-overrides/fake-indexeddb.js diff --git a/scripts/package-overrides/fake-indexeddb.js b/scripts/package-overrides/fake-indexeddb.js deleted file mode 100644 index 65159813..00000000 --- a/scripts/package-overrides/fake-indexeddb.js +++ /dev/null @@ -1,4 +0,0 @@ -// we have our own main file for this module as we need both these symbols to -// be exported, and we also don't want to auto behaviour that modifies global vars -exports.FDBFactory = require("fake-indexeddb/lib/FDBFactory.js"); -exports.FDBKeyRange = require("fake-indexeddb/lib/FDBKeyRange.js"); \ No newline at end of file From afadd258856e0b5d8e063c6058c49d0b6a26909e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 5 Oct 2021 19:29:00 +0200 Subject: [PATCH 020/242] tweak build settings somewhat for now --- vite.config.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vite.config.js b/vite.config.js index 450b8d40..9c119b41 100644 --- a/vite.config.js +++ b/vite.config.js @@ -9,5 +9,9 @@ export default { "safe-buffer": "./scripts/package-overrides/safe-buffer/index.js", "buffer": "./scripts/package-overrides/buffer/index.js" } + }, + build: { + outDir: "../../../target", + minify: false } }; From 3fe1c0cdc320a053690f5505a99571d51adc38be Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 5 Oct 2021 19:29:28 +0200 Subject: [PATCH 021/242] tweak build and start command to use vite --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e9c9e991..7cced96b 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,9 @@ "lint": "eslint --cache src/", "lint-ts": "eslint src/ -c .ts-eslintrc.js --ext .ts", "lint-ci": "eslint src/", - "test": "impunity --entry-point src/platform/web/main.js --force-esm-dirs src/", - "start": "snowpack dev --port 3000", "test": "impunity --entry-point src/platform/web/main.js --force-esm-dirs src/ --root-dir src/", + "start": "vite --port 3000", + "build": "vite build" }, "repository": { "type": "git", From 216afd45cc307588c5b239b16e9f0cca208abb25 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 6 Oct 2021 20:34:16 +0200 Subject: [PATCH 022/242] vite/rollup plugin to inject and transform manifest & service worker --- scripts/build-plugins/manifest.js | 46 ++++++++++ scripts/build-plugins/service-worker.js | 110 ++++++++++++++++++++++++ src/platform/web/assets/manifest.json | 4 +- src/platform/web/index.html | 1 + vite.config.js | 13 ++- 5 files changed, 170 insertions(+), 4 deletions(-) create mode 100644 scripts/build-plugins/manifest.js create mode 100644 scripts/build-plugins/service-worker.js diff --git a/scripts/build-plugins/manifest.js b/scripts/build-plugins/manifest.js new file mode 100644 index 00000000..bcd96fa4 --- /dev/null +++ b/scripts/build-plugins/manifest.js @@ -0,0 +1,46 @@ +const fs = require('fs/promises'); +const path = require('path'); + +module.exports = function injectWebManifest(manifestFile) { + let root; + let manifestHref; + return { + name: "injectWebManifest", + apply: "build", + configResolved: config => { + root = config.root; + }, + transformIndexHtml: { + transform(html) { + return [{ + tag: "link", + attrs: {rel: "manifest", href: manifestHref}, + injectTo: "head" + }]; + }, + }, + generateBundle: async function() { + const absoluteManifestFile = path.resolve(root, manifestFile); + const manifestDir = path.dirname(absoluteManifestFile); + const json = await fs.readFile(absoluteManifestFile, {encoding: "utf8"}); + const manifest = JSON.parse(json); + for (const icon of manifest.icons) { + const iconFileName = path.resolve(manifestDir, icon.src); + const imgData = await fs.readFile(iconFileName); + const ref = this.emitFile({ + type: "asset", + name: path.basename(iconFileName), + source: imgData + }); + icon.src = this.getFileName(ref); + } + const outputName = path.basename(absoluteManifestFile); + const manifestRef = this.emitFile({ + type: "asset", + name: outputName, + source: JSON.stringify(manifest) + }); + manifestHref = this.getFileName(manifestRef); + } + }; +} diff --git a/scripts/build-plugins/service-worker.js b/scripts/build-plugins/service-worker.js new file mode 100644 index 00000000..420618fb --- /dev/null +++ b/scripts/build-plugins/service-worker.js @@ -0,0 +1,110 @@ +const fs = require('fs/promises'); +const path = require('path'); +const xxhash = require('xxhashjs'); + +function contentHash(str) { + var hasher = new xxhash.h32(0); + hasher.update(str); + return hasher.digest(); +} + +module.exports = function injectServiceWorker(swFile) { + let root; + let manifestHref; + return { + name: "injectServiceWorker", + apply: "build", + enforce: "post", + configResolved: config => { + root = config.root; + }, + generateBundle: async function(_, bundle) { + const absoluteSwFile = path.resolve(root, swFile); + const packageManifest = path.resolve(path.join(__dirname, "../../package.json")); + const version = JSON.parse(await fs.readFile(packageManifest, "utf8")).version; + let swSource = await fs.readFile(absoluteSwFile, {encoding: "utf8"}); + const assets = Object.values(bundle).filter(a => a.type === "asset"); + const cachedFileNames = assets.map(o => o.fileName).filter(fileName => fileName !== "index.html"); + const uncachedFileContentMap = { + "index.html": assets.find(o => o.fileName === "index.html").source, + "sw.js": swSource + }; + const globalHash = getBuildHash(cachedFileNames, uncachedFileContentMap); + swSource = await buildServiceWorker(swSource, version, globalHash, assets); + const outputName = path.basename(absoluteSwFile); + this.emitFile({ + type: "asset", + fileName: outputName, + source: swSource + }); + } + }; +} + +function getBuildHash(cachedFileNames, uncachedFileContentMap) { + const unhashedHashes = Object.entries(uncachedFileContentMap).map(([fileName, content]) => { + return `${fileName}-${contentHash(Buffer.from(content))}`; + }); + const globalHashAssets = cachedFileNames.concat(unhashedHashes); + globalHashAssets.sort(); + return contentHash(globalHashAssets.join(",")).toString(); +} + +const NON_PRECACHED_JS = [ + "hydrogen-legacy.js", + "olm_legacy.js", + // most environments don't need the worker + "main.js" +]; + +function isPreCached(asset) { + const {name, fileName} = asset; + return name.endsWith(".svg") || + name.endsWith(".png") || + name.endsWith(".css") || + name.endsWith(".wasm") || + name.endsWith(".html") || + // the index and vendor chunks don't have an extension in `name`, so check extension on `fileName` + fileName.endsWith(".js") && !NON_PRECACHED_JS.includes(path.basename(name)); +} + +async function buildServiceWorker(swSource, version, globalHash, assets) { + const unhashedPreCachedAssets = []; + const hashedPreCachedAssets = []; + const hashedCachedOnRequestAssets = []; + + for (const asset of assets) { + const {name: unresolved, fileName: resolved} = asset; + if (!unresolved || resolved === unresolved) { + unhashedPreCachedAssets.push(resolved); + } else if (isPreCached(asset)) { + hashedPreCachedAssets.push(resolved); + } else { + hashedCachedOnRequestAssets.push(resolved); + } + } + + const replaceArrayInSource = (name, value) => { + const newSource = swSource.replace(`${name} = []`, `${name} = ${JSON.stringify(value)}`); + if (newSource === swSource) { + throw new Error(`${name} was not found in the service worker source`); + } + return newSource; + }; + const replaceStringInSource = (name, value) => { + const newSource = swSource.replace(new RegExp(`${name}\\s=\\s"[^"]*"`), `${name} = ${JSON.stringify(value)}`); + if (newSource === swSource) { + throw new Error(`${name} was not found in the service worker source`); + } + return newSource; + }; + + // write service worker + swSource = swSource.replace(`"%%VERSION%%"`, `"${version}"`); + swSource = swSource.replace(`"%%GLOBAL_HASH%%"`, `"${globalHash}"`); + swSource = replaceArrayInSource("UNHASHED_PRECACHED_ASSETS", unhashedPreCachedAssets); + swSource = replaceArrayInSource("HASHED_PRECACHED_ASSETS", hashedPreCachedAssets); + swSource = replaceArrayInSource("HASHED_CACHED_ON_REQUEST_ASSETS", hashedCachedOnRequestAssets); + swSource = replaceStringInSource("NOTIFICATION_BADGE_ICON", assets.find(a => a.name === "icon.png").fileName); + return swSource; +} diff --git a/src/platform/web/assets/manifest.json b/src/platform/web/assets/manifest.json index 01728ff9..92dde01a 100644 --- a/src/platform/web/assets/manifest.json +++ b/src/platform/web/assets/manifest.json @@ -5,8 +5,8 @@ "description": "Lightweight matrix client with legacy and mobile browser support", "start_url": "index.html", "icons": [ - {"src": "assets/icon.png", "sizes": "384x384", "type": "image/png"}, - {"src": "assets/icon-maskable.png", "sizes": "384x384", "type": "image/png", "purpose": "maskable"} + {"src": "icon.png", "sizes": "384x384", "type": "image/png"}, + {"src": "icon-maskable.png", "sizes": "384x384", "type": "image/png", "purpose": "maskable"} ], "theme_color": "#0DBD8B" } diff --git a/src/platform/web/index.html b/src/platform/web/index.html index 397aae66..5130cd39 100644 --- a/src/platform/web/index.html +++ b/src/platform/web/index.html @@ -30,6 +30,7 @@ downloadSandbox: downloadSandboxPath, defaultHomeServer: "matrix.org", // NOTE: uncomment this if you want the service worker for local development + // and adjust apply in the service-worker build plugin // serviceWorker: "sw.js", // NOTE: provide push config if you want push notifs for local development // see assets/config.json for what the config looks like diff --git a/vite.config.js b/vite.config.js index 9c119b41..4fd46691 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,3 +1,6 @@ +const injectWebManifest = require("./scripts/build-plugins/manifest"); +const injectServiceWorker = require("./scripts/build-plugins/service-worker"); + export default { public: false, root: "src/platform/web", @@ -12,6 +15,12 @@ export default { }, build: { outDir: "../../../target", - minify: false - } + emptyOutDir: true, + minify: true, + sourcemap: true + }, + plugins: [ + injectWebManifest("assets/manifest.json"), + injectServiceWorker("sw.js") + ] }; From 923a1a20572b07efcd9e774077e5b42ad0427a82 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 7 Oct 2021 15:09:16 +0200 Subject: [PATCH 023/242] use vite define option to inject version number everywhere --- scripts/build-plugins/service-worker.js | 3 ++- src/platform/web/Platform.js | 2 +- src/platform/web/dom/ServiceWorkerHandler.js | 2 +- src/platform/web/index.html | 4 ---- src/platform/web/ui/login/common.js | 6 +++--- vite.config.js | 9 ++++++++- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/scripts/build-plugins/service-worker.js b/scripts/build-plugins/service-worker.js index 420618fb..d80f0bbf 100644 --- a/scripts/build-plugins/service-worker.js +++ b/scripts/build-plugins/service-worker.js @@ -10,6 +10,7 @@ function contentHash(str) { module.exports = function injectServiceWorker(swFile) { let root; + let version; let manifestHref; return { name: "injectServiceWorker", @@ -17,11 +18,11 @@ module.exports = function injectServiceWorker(swFile) { enforce: "post", configResolved: config => { root = config.root; + version = JSON.parse(config.define.HYDROGEN_VERSION); // unquote }, generateBundle: async function(_, bundle) { const absoluteSwFile = path.resolve(root, swFile); const packageManifest = path.resolve(path.join(__dirname, "../../package.json")); - const version = JSON.parse(await fs.readFile(packageManifest, "utf8")).version; let swSource = await fs.readFile(absoluteSwFile, {encoding: "utf8"}); const assets = Object.values(bundle).filter(a => a.type === "asset"); const cachedFileNames = assets.map(o => o.fileName).filter(fileName => fileName !== "index.html"); diff --git a/src/platform/web/Platform.js b/src/platform/web/Platform.js index 1530ed12..efb939d9 100644 --- a/src/platform/web/Platform.js +++ b/src/platform/web/Platform.js @@ -265,7 +265,7 @@ export class Platform { } get version() { - return window.HYDROGEN_VERSION; + return HYDROGEN_VERSION; } dispose() { diff --git a/src/platform/web/dom/ServiceWorkerHandler.js b/src/platform/web/dom/ServiceWorkerHandler.js index dd2c755f..08c687c9 100644 --- a/src/platform/web/dom/ServiceWorkerHandler.js +++ b/src/platform/web/dom/ServiceWorkerHandler.js @@ -181,7 +181,7 @@ export class ServiceWorkerHandler { } get version() { - return window.HYDROGEN_VERSION; + return HYDROGEN_VERSION; } get buildHash() { diff --git a/src/platform/web/index.html b/src/platform/web/index.html index 5130cd39..d0718098 100644 --- a/src/platform/web/index.html +++ b/src/platform/web/index.html @@ -16,10 +16,6 @@ - diff --git a/vite.config.js b/vite.config.js index e0dd0f99..45ab94c9 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,9 +1,15 @@ const injectWebManifest = require("./scripts/build-plugins/manifest"); const injectServiceWorker = require("./scripts/build-plugins/service-worker"); +const legacyBuild = require("./scripts/build-plugins/legacy-build"); const fs = require("fs"); const path = require("path"); - +// we could also just import {version} from "../../package.json" where needed, +// but this won't work in the service worker yet as it is not transformed yet +// TODO: we should emit a chunk early on and then transform the asset again once we know all the other assets to cache const version = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8")).version; +const {defineConfig} = require("vite"); +let polyfillSrc; +let polyfillRef; export default { public: false, @@ -14,18 +20,25 @@ export default { resolve: { alias: { "safe-buffer": "./scripts/package-overrides/safe-buffer/index.js", - "buffer": "./scripts/package-overrides/buffer/index.js" + "buffer": "./scripts/package-overrides/buffer/index.js", } }, build: { outDir: "../../../target", emptyOutDir: true, - minify: true, - sourcemap: true + minify: false, + sourcemap: false, + assetsInlineLimit: 0, + polyfillModulePreload: false, }, plugins: [ + legacyBuild(path.join(__dirname, "src/platform/web/index.html?html-proxy&index=0.js"), { + "./Platform": "./LegacyPlatform" + }, "hydrogen-legacy", [ + './legacy-polyfill', + ]), injectWebManifest("assets/manifest.json"), - injectServiceWorker("sw.js") + injectServiceWorker("sw.js"), ], define: { "HYDROGEN_VERSION": JSON.stringify(version) diff --git a/yarn.lock b/yarn.lock index d2e3035d..30c71c52 100644 --- a/yarn.lock +++ b/yarn.lock @@ -825,6 +825,11 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/standalone@^7.15.7": + version "7.15.8" + resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.15.8.tgz#3cb40b81892a702968a3e0bba2bdd1115f034876" + integrity sha512-EF2uQLeuwflnPRGetWH2Z400ITOSK7YbkXIKxY91EWSiOJ8xsbupT3sx3sFRwVyQgjsHSILFDzLcSo/rGspLhQ== + "@babel/template@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" @@ -1294,6 +1299,17 @@ "@typescript-eslint/types" "4.29.2" eslint-visitor-keys "^2.0.0" +"@vitejs/plugin-legacy@^1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-legacy/-/plugin-legacy-1.6.1.tgz#45f0e006de2d25758151b098b8dcb912c62a95dc" + integrity sha512-isBi2ti+AlCZUpfA1P6L8gseltBy/qi6Rsi92aDzeL2elpwXgN4Hv/xLS2UUSSj9F0mFmxXCYPWlBPaJnlYamQ== + dependencies: + "@babel/standalone" "^7.15.7" + core-js "^3.18.1" + magic-string "^0.25.7" + regenerator-runtime "^0.13.9" + systemjs "^6.10.3" + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -1898,6 +1914,11 @@ core-js@^2.5.3: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== +core-js@^3.18.1: + version "3.18.2" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.2.tgz#63a551e8a29f305cd4123754846e65896619ba5b" + integrity sha512-zNhPOUoSgoizoSQFdX1MeZO16ORRb9FFQLts8gSYbZU5FcgXhp24iMWMxnOQo5uIaIG7/6FA/IqJPwev1o9ZXQ== + core-js@^3.6.5: version "3.6.5" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" @@ -4554,6 +4575,11 @@ regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== +regenerator-runtime@^0.13.9: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + regenerator-transform@^0.14.2: version "0.14.5" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" @@ -5118,6 +5144,11 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +systemjs@^6.10.3: + version "6.10.3" + resolved "https://registry.yarnpkg.com/systemjs/-/systemjs-6.10.3.tgz#7e783fccb58232f1d9eb05c7e1a661268945cade" + integrity sha512-mXwfLJdaADqWg1J5+Z0bGQEdcXSe+ePPTfzffMB29aVls5cXveRl0vneSV/19t3SfuUBsAraLP8W/g5u9cmYXA== + table@^6.0.9: version "6.7.1" resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" From 7dce579ac38e6e0bbfe4a0751a3ebbee4582d8ea Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 12 Oct 2021 16:33:30 +0200 Subject: [PATCH 027/242] make babel plugin run after commonjs one added by vite --- scripts/build-plugins/legacy-build.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/build-plugins/legacy-build.js b/scripts/build-plugins/legacy-build.js index 3d069d4d..e1a2e1df 100644 --- a/scripts/build-plugins/legacy-build.js +++ b/scripts/build-plugins/legacy-build.js @@ -92,6 +92,7 @@ async function buildLegacyChunk(root, chunkName, code) { ] ] }); + babelPlugin.enforce = "post"; const bundle = await build({ root, configFile: false, From 3b72157e64243b4a37ca86be6c69247023c2ce16 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 12 Oct 2021 16:33:48 +0200 Subject: [PATCH 028/242] apparently, package-overrides should use esm otherwise they don't get transpiled for some reason --- scripts/package-overrides/buffer/index.js | 2 +- scripts/package-overrides/safe-buffer/index.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/package-overrides/buffer/index.js b/scripts/package-overrides/buffer/index.js index 0ed6d01c..2ac44010 100644 --- a/scripts/package-overrides/buffer/index.js +++ b/scripts/package-overrides/buffer/index.js @@ -1,4 +1,4 @@ -module.exports = class Buffer { +export default class Buffer { static isBuffer(array) {return array instanceof Uint8Array;} static from(arrayBuffer) {return arrayBuffer;} static allocUnsafe(size) {return Buffer.alloc(size);} diff --git a/scripts/package-overrides/safe-buffer/index.js b/scripts/package-overrides/safe-buffer/index.js index 93a10446..a1c7d0bb 100644 --- a/scripts/package-overrides/safe-buffer/index.js +++ b/scripts/package-overrides/safe-buffer/index.js @@ -1 +1,2 @@ -module.exports.Buffer = require("buffer"); +import Buffer from "buffer"; +export {Buffer}; From fcde50718380ae6f66731a07c51e60b84acdaa15 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 13 Oct 2021 12:21:26 +0200 Subject: [PATCH 029/242] WIP --- package.json | 2 + scripts/build-plugins/legacy-build.js | 95 +++++++---- vite.config.js | 2 +- yarn.lock | 232 ++++++++++++++++++++++++-- 4 files changed, 281 insertions(+), 50 deletions(-) diff --git a/package.json b/package.json index 2c02fb1f..d89d3627 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,9 @@ "homepage": "https://github.com/vector-im/hydrogen-web/#readme", "devDependencies": { "@babel/core": "^7.11.1", + "@babel/plugin-transform-runtime": "^7.15.8", "@babel/preset-env": "^7.11.0", + "@babel/standalone": "^7.15.8", "@rollup/plugin-babel": "^5.1.0", "@rollup/plugin-multi-entry": "^4.0.0", "@typescript-eslint/eslint-plugin": "^4.29.2", diff --git a/scripts/build-plugins/legacy-build.js b/scripts/build-plugins/legacy-build.js index e1a2e1df..43f87fba 100644 --- a/scripts/build-plugins/legacy-build.js +++ b/scripts/build-plugins/legacy-build.js @@ -6,6 +6,7 @@ const VIRTUAL_ENTRY = "hydrogen:legacy-entry"; module.exports = function legacyBuild(entryModuleId, entryImportReplacements, chunkName, extraImports) { let parentRoot; let code; + let legacyBundleRef; let legacyBundleFileName; return { name: "hydrogen:legacyBuild", @@ -26,14 +27,18 @@ module.exports = function legacyBuild(entryModuleId, entryImportReplacements, ch code = replaceImport(this, code, importSource, newImportSource); } code = addExtraImports(code, extraImports); - const mainChunk = await buildLegacyChunk(parentRoot, chunkName, code); - this.emitFile({ + const bundleCode = await buildLegacyChunk(parentRoot, chunkName, code); + legacyBundleRef = this.emitFile({ type: "asset", - source: mainChunk.code, - fileName: mainChunk.fileName, - name: mainChunk.name + source: bundleCode, + name: `${chunkName}.js` }); - legacyBundleFileName = mainChunk.fileName; + }, + generateBundle() { + if (!legacyBundleRef) { + throw new Error("no bundle"); + } + legacyBundleFileName = this.getFileName(legacyBundleRef); }, transformIndexHtml: { transform(html) { @@ -70,37 +75,34 @@ function addExtraImports(code, extraImports) { } async function buildLegacyChunk(root, chunkName, code) { - if (!babel) { - babel = require('@rollup/plugin-babel'); - } - // compile down to whatever IE 11 needs - const babelPlugin = babel.babel({ - babelHelpers: 'bundled', - exclude: 'node_modules/**', - presets: [ - [ - "@babel/preset-env", - { - useBuiltIns: "entry", - corejs: "3.4", - targets: "IE 11", - // we provide our own promise polyfill (es6-promise) - // with support for synchronous flushing of - // the queue for idb where needed - exclude: ["es.promise", "es.promise.all-settled", "es.promise.finally"] - } - ] - ] - }); - babelPlugin.enforce = "post"; + // // compile down to whatever IE 11 needs + // const babelPlugin = babel.getBabelOutputPlugin({ + // // babelHelpers: 'bundled', + // exclude: 'node_modules/**', + // presets: [ + // [ + // "@babel/preset-env", + // { + // useBuiltIns: "entry", + // corejs: "3.4", + // targets: "IE 11", + // // we provide our own promise polyfill (es6-promise) + // // with support for synchronous flushing of + // // the queue for idb where needed + // exclude: ["es.promise", "es.promise.all-settled", "es.promise.finally"] + // } + // ] + // ] + // }); + // babelPlugin.enforce = "post"; const bundle = await build({ root, configFile: false, logLevel: 'error', build: { write: false, - target: false, - minify: true, + minify: false, + target: "esnext", assetsInlineLimit: 0, polyfillModulePreload: false, rollupOptions: { @@ -127,12 +129,35 @@ async function buildLegacyChunk(root, chunkName, code) { if (id === VIRTUAL_ENTRY) { return code; } - } - }, - babelPlugin + }, + } ] }); const assets = Array.isArray(bundle.output) ? bundle.output : [bundle.output]; const mainChunk = assets.find(a => a.name === chunkName); - return mainChunk; + + if (!babel) { + babel = require('@babel/standalone'); + } + const {code: babelCode} = babel.transform(mainChunk.code, { + babelrc: false, + configFile: false, + presets: [ + [ + "env", + { + useBuiltIns: "usage", + modules: false, + corejs: "3.4", + targets: "IE 11", + // we provide our own promise polyfill (es6-promise) + // with support for synchronous flushing of + // the queue for idb where needed + exclude: ["es.promise", "es.promise.all-settled", "es.promise.finally"] + } + ] + ] + }); + console.log("code", babelCode.length); + return babelCode; } diff --git a/vite.config.js b/vite.config.js index 45ab94c9..9cc7e4f3 100644 --- a/vite.config.js +++ b/vite.config.js @@ -26,7 +26,7 @@ export default { build: { outDir: "../../../target", emptyOutDir: true, - minify: false, + minify: true, sourcemap: false, assetsInlineLimit: 0, polyfillModulePreload: false, diff --git a/yarn.lock b/yarn.lock index 30c71c52..d3ff1771 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23,6 +23,13 @@ dependencies: "@babel/highlight" "^7.10.4" +"@babel/code-frame@^7.14.5": + version "7.15.8" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.15.8.tgz#45990c47adadb00c03677baa89221f7cc23d2503" + integrity sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg== + dependencies: + "@babel/highlight" "^7.14.5" + "@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" @@ -32,6 +39,11 @@ invariant "^2.2.4" semver "^5.5.0" +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" + integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== + "@babel/core@^7.11.1": version "7.11.1" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.1.tgz#2c55b604e73a40dc21b0e52650b11c65cf276643" @@ -63,6 +75,15 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.15.4": + version "7.15.8" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.8.tgz#fa56be6b596952ceb231048cf84ee499a19c0cd1" + integrity sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g== + dependencies: + "@babel/types" "^7.15.6" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" @@ -89,6 +110,16 @@ levenary "^1.1.1" semver "^5.5.0" +"@babel/helper-compilation-targets@^7.13.0": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz#cf6d94f30fbefc139123e27dd6b02f65aeedb7b9" + integrity sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ== + dependencies: + "@babel/compat-data" "^7.15.0" + "@babel/helper-validator-option" "^7.14.5" + browserslist "^4.16.6" + semver "^6.3.0" + "@babel/helper-create-class-features-plugin@^7.10.4": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" @@ -119,6 +150,20 @@ "@babel/types" "^7.10.5" lodash "^4.17.19" +"@babel/helper-define-polyfill-provider@^0.2.2": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz#0525edec5094653a282688d34d846e4c75e9c0b6" + integrity sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew== + dependencies: + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/traverse" "^7.13.0" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + "@babel/helper-explode-assignable-expression@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz#40a1cd917bff1288f699a94a75b37a1a2dbd8c7c" @@ -136,6 +181,15 @@ "@babel/template" "^7.10.4" "@babel/types" "^7.10.4" +"@babel/helper-function-name@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz#845744dafc4381a4a5fb6afa6c3d36f98a787ebc" + integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw== + dependencies: + "@babel/helper-get-function-arity" "^7.15.4" + "@babel/template" "^7.15.4" + "@babel/types" "^7.15.4" + "@babel/helper-get-function-arity@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" @@ -143,6 +197,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-get-function-arity@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz#098818934a137fce78b536a3e015864be1e2879b" + integrity sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-hoist-variables@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" @@ -150,6 +211,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-hoist-variables@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz#09993a3259c0e918f99d104261dfdfc033f178df" + integrity sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" @@ -164,6 +232,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz#e18007d230632dea19b47853b984476e7b4e103f" + integrity sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" @@ -189,6 +264,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== +"@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" + integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== + "@babel/helper-regex@^7.10.4": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" @@ -239,6 +319,13 @@ dependencies: "@babel/types" "^7.11.0" +"@babel/helper-split-export-declaration@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz#aecab92dcdbef6a10aa3b62ab204b085f776e257" + integrity sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-validator-identifier@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" @@ -249,6 +336,16 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== +"@babel/helper-validator-identifier@^7.14.9": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" + integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== + +"@babel/helper-validator-option@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" + integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== + "@babel/helper-wrap-function@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" @@ -291,6 +388,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.3.tgz#9e1eae46738bcd08e23e867bab43e7b95299a8f9" integrity sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA== +"@babel/parser@^7.15.4": + version "7.15.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.8.tgz#7bacdcbe71bdc3ff936d510c15dcea7cf0b99016" + integrity sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA== + "@babel/plugin-proposal-async-generator-functions@^7.10.4": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" @@ -680,6 +782,18 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-runtime@^7.15.8": + version "7.15.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.8.tgz#9d15b1e94e1c7f6344f65a8d573597d93c6cd886" + integrity sha512-+6zsde91jMzzvkzuEA3k63zCw+tm/GvuuabkpisgbDMTPQsIMHllE3XczJFFtEHLjjhKQFZmGQVRdELetlWpVw== + dependencies: + "@babel/helper-module-imports" "^7.15.4" + "@babel/helper-plugin-utils" "^7.14.5" + babel-plugin-polyfill-corejs2 "^0.2.2" + babel-plugin-polyfill-corejs3 "^0.2.5" + babel-plugin-polyfill-regenerator "^0.2.2" + semver "^6.3.0" + "@babel/plugin-transform-shorthand-properties@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" @@ -825,7 +939,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/standalone@^7.15.7": +"@babel/standalone@^7.15.7", "@babel/standalone@^7.15.8": version "7.15.8" resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.15.8.tgz#3cb40b81892a702968a3e0bba2bdd1115f034876" integrity sha512-EF2uQLeuwflnPRGetWH2Z400ITOSK7YbkXIKxY91EWSiOJ8xsbupT3sx3sFRwVyQgjsHSILFDzLcSo/rGspLhQ== @@ -839,6 +953,15 @@ "@babel/parser" "^7.10.4" "@babel/types" "^7.10.4" +"@babel/template@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" + integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/parser" "^7.15.4" + "@babel/types" "^7.15.4" + "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" @@ -854,6 +977,21 @@ globals "^11.1.0" lodash "^4.17.19" +"@babel/traverse@^7.13.0": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d" + integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.15.4" + "@babel/helper-function-name" "^7.15.4" + "@babel/helper-hoist-variables" "^7.15.4" + "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/parser" "^7.15.4" + "@babel/types" "^7.15.4" + debug "^4.1.0" + globals "^11.1.0" + "@babel/types@^7.10.4": version "7.11.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" @@ -872,6 +1010,14 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@babel/types@^7.15.4", "@babel/types@^7.15.6": + version "7.15.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f" + integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig== + dependencies: + "@babel/helper-validator-identifier" "^7.14.9" + to-fast-properties "^2.0.0" + "@eslint/eslintrc@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" @@ -1515,6 +1661,30 @@ babel-plugin-dynamic-import-node@^2.3.3: dependencies: object.assign "^4.1.0" +babel-plugin-polyfill-corejs2@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz#e9124785e6fd94f94b618a7954e5693053bf5327" + integrity sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ== + dependencies: + "@babel/compat-data" "^7.13.11" + "@babel/helper-define-polyfill-provider" "^0.2.2" + semver "^6.1.1" + +babel-plugin-polyfill-corejs3@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz#2779846a16a1652244ae268b1e906ada107faf92" + integrity sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.2.2" + core-js-compat "^3.16.2" + +babel-plugin-polyfill-regenerator@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz#b310c8d642acada348c1fa3b3e6ce0e851bee077" + integrity sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.2.2" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -1619,6 +1789,17 @@ browserslist@^4.16.6: escalade "^3.1.1" node-releases "^1.1.71" +browserslist@^4.17.3: + version "4.17.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.3.tgz#2844cd6eebe14d12384b0122d217550160d2d624" + integrity sha512-59IqHJV5VGdcJZ+GZ2hU5n4Kv3YiASzW6Xk5g9tf5a/MAzGeFwgGWU39fVzNIOVcgB3+Gp+kiQu0HEfTVU/3VQ== + dependencies: + caniuse-lite "^1.0.30001264" + electron-to-chromium "^1.3.857" + escalade "^3.1.1" + node-releases "^1.1.77" + picocolors "^0.2.1" + bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" @@ -1699,10 +1880,10 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -caniuse-lite@^1.0.30001111, caniuse-lite@^1.0.30001219, caniuse-lite@^1.0.30001230: - version "1.0.30001278" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001278.tgz" - integrity sha512-mpF9KeH8u5cMoEmIic/cr7PNS+F5LWBk0t2ekGT60lFf0Wq+n9LspAj0g3P+o7DQhD3sUdlMln4YFAWhFYn9jg== +caniuse-lite@^1.0.30001111, caniuse-lite@^1.0.30001219, caniuse-lite@^1.0.30001230, caniuse-lite@^1.0.30001264: + version "1.0.30001265" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz" + integrity sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw== caseless@~0.12.0: version "0.12.0" @@ -1901,6 +2082,14 @@ convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" +core-js-compat@^3.16.2: + version "3.18.2" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.18.2.tgz#e40c266fbd613948dd8d2d2156345da8ac03c142" + integrity sha512-25VJYCJtGjZwLguj7d66oiHfmnVw3TMOZ0zV8DyMJp/aeQ3OjR519iOOeck08HMyVVRAqXxafc2Hl+5QstJrsQ== + dependencies: + browserslist "^4.17.3" + semver "7.0.0" + core-js-compat@^3.6.2: version "3.6.5" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" @@ -2237,6 +2426,11 @@ electron-to-chromium@^1.3.723: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.742.tgz#7223215acbbd3a5284962ebcb6df85d88b95f200" integrity sha512-ihL14knI9FikJmH2XUIDdZFWJxvr14rPSdOhJ7PpS27xbz8qmaRwCwyg/bmFwjWKmWK9QyamiCZVCvXm5CH//Q== +electron-to-chromium@^1.3.857: + version "1.3.866" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.866.tgz#d446338f5ad6948b27a50739760e7b0b5cc5032f" + integrity sha512-iYze6TpDXWxk+sfcpUUdTs6Pv/3kG45Pnjer2DxEeFw0N08bZeNLuz97s2lMgy8yObon48o0WHY2Bkg3xuAPOA== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -3523,6 +3717,11 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -3855,6 +4054,11 @@ node-releases@^1.1.71: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe" integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw== +node-releases@^1.1.77: + version "1.1.77" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.77.tgz#50b0cfede855dd374e7585bf228ff34e57c1c32e" + integrity sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ== + nopt@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" @@ -4669,14 +4873,7 @@ resolve@^1.1.7: dependencies: path-parse "^1.0.6" -resolve@^1.17.0, resolve@^1.3.2: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== - dependencies: - path-parse "^1.0.6" - -resolve@^1.20.0: +resolve@^1.14.2, resolve@^1.20.0: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -4684,6 +4881,13 @@ resolve@^1.20.0: is-core-module "^2.2.0" path-parse "^1.0.6" +resolve@^1.17.0, resolve@^1.3.2: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + responselike@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.0.tgz#26391bcc3174f750f9a79eacc40a12a5c42d7723" @@ -4795,7 +4999,7 @@ semver@^5.4.1, semver@^5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0: +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== From ffef4936f93fc0bda12a9e3ae6ac4d1344e9d082 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 8 Nov 2021 11:14:00 +0100 Subject: [PATCH 030/242] update caniuse defs again after rebase --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d3ff1771..6dea2a76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1881,9 +1881,9 @@ callsites@^3.0.0: integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== caniuse-lite@^1.0.30001111, caniuse-lite@^1.0.30001219, caniuse-lite@^1.0.30001230, caniuse-lite@^1.0.30001264: - version "1.0.30001265" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz" - integrity sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw== + version "1.0.30001278" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001278.tgz" + integrity sha512-mpF9KeH8u5cMoEmIic/cr7PNS+F5LWBk0t2ekGT60lFf0Wq+n9LspAj0g3P+o7DQhD3sUdlMln4YFAWhFYn9jg== caseless@~0.12.0: version "0.12.0" From e9586711e00c893054a4adc483b847ca52b476a2 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 8 Nov 2021 11:19:24 +0100 Subject: [PATCH 031/242] add scrollbar when > 5 lines in composer --- src/platform/web/ui/css/themes/element/theme.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/platform/web/ui/css/themes/element/theme.css b/src/platform/web/ui/css/themes/element/theme.css index 1932ecdd..32e048ec 100644 --- a/src/platform/web/ui/css/themes/element/theme.css +++ b/src/platform/web/ui/css/themes/element/theme.css @@ -548,6 +548,8 @@ a { box-sizing: border-box; overflow: hidden; max-height: 113px; /* 5 lines */ + overflow-y: auto; + overflow-y: overlay; } .MessageComposer_input > button.send { From c1a8ffd814083c7003cbadac088e2d1239c9ba2f Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 8 Nov 2021 18:03:20 +0530 Subject: [PATCH 032/242] respond with only for GET requests --- src/platform/web/docroot/sw.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/platform/web/docroot/sw.js b/src/platform/web/docroot/sw.js index 9b5da128..7eab4758 100644 --- a/src/platform/web/docroot/sw.js +++ b/src/platform/web/docroot/sw.js @@ -69,12 +69,9 @@ async function purgeOldCaches() { } self.addEventListener('fetch', async (event) => { - if (event.request.method === "POST" && - (await event.request.blob()).type !== "application/json" && - event.request.body) { - return; + if (event.request.method === "GET") { + event.respondWith(handleRequest(event.request)); } - event.respondWith(handleRequest(event.request)); }); function isCacheableThumbnail(url) { From 57e2c4ea45205195b29858dd16e508d5621a55f1 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 8 Nov 2021 22:20:56 +0530 Subject: [PATCH 033/242] No need for handler to be async --- src/platform/web/docroot/sw.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/web/docroot/sw.js b/src/platform/web/docroot/sw.js index 7eab4758..8542492c 100644 --- a/src/platform/web/docroot/sw.js +++ b/src/platform/web/docroot/sw.js @@ -68,7 +68,7 @@ async function purgeOldCaches() { } } -self.addEventListener('fetch', async (event) => { +self.addEventListener('fetch', (event) => { if (event.request.method === "GET") { event.respondWith(handleRequest(event.request)); } From dad37dece339ec18af53030b20754d48e11a16c2 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 9 Nov 2021 11:46:05 +0530 Subject: [PATCH 034/242] .js --> .ts --- src/logging/{BaseLogger.js => BaseLogger.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/logging/{BaseLogger.js => BaseLogger.ts} (100%) diff --git a/src/logging/BaseLogger.js b/src/logging/BaseLogger.ts similarity index 100% rename from src/logging/BaseLogger.js rename to src/logging/BaseLogger.ts From 030c46264b2e91b5271da67859a9de4d350448a2 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 9 Nov 2021 13:00:37 +0530 Subject: [PATCH 035/242] type annotate fields --- src/logging/BaseLogger.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 584c763b..51a32485 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -17,8 +17,12 @@ limitations under the License. import {LogItem} from "./LogItem.js"; import {LogLevel, LogFilter} from "./LogFilter.js"; +import {Platform} from "../platform/web/Platform.js"; export class BaseLogger { + protected _openItems: Set; + protected _platform: Platform; + constructor({platform}) { this._openItems = new Set(); this._platform = platform; From 377cc4ca1fb89fb576520ad8928bd9d7079a0bff Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 9 Nov 2021 13:52:41 +0530 Subject: [PATCH 036/242] Make BaseLogger abstract --- src/logging/BaseLogger.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 51a32485..d45c2fd3 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -19,7 +19,7 @@ import {LogItem} from "./LogItem.js"; import {LogLevel, LogFilter} from "./LogFilter.js"; import {Platform} from "../platform/web/Platform.js"; -export class BaseLogger { +export abstract class BaseLogger { protected _openItems: Set; protected _platform: Platform; @@ -131,13 +131,9 @@ export class BaseLogger { this._openItems.clear(); } - _persistItem() { - throw new Error("not implemented"); - } + abstract _persistItem(item: LogItem, filter?: LogFilter, forced?: boolean): void; - async export() { - throw new Error("not implemented"); - } + abstract export(): void; // expose log level without needing get level() { From 839d3fb6899cf32d898bb704799a78b2a5d92f5e Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 9 Nov 2021 13:53:07 +0530 Subject: [PATCH 037/242] Throw on export() in ConsoleLogger --- src/logging/ConsoleLogger.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/logging/ConsoleLogger.js b/src/logging/ConsoleLogger.js index 9610795f..aacbf132 100644 --- a/src/logging/ConsoleLogger.js +++ b/src/logging/ConsoleLogger.js @@ -19,6 +19,10 @@ export class ConsoleLogger extends BaseLogger { _persistItem(item) { printToConsole(item); } + + export() { + throw new Error("Cannot export from ConsoleLogger"); + } } const excludedKeysFromTable = ["l", "id"]; From 8fba3f4ca9d40ee5c3c1ea6084d74c7b7552b964 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 9 Nov 2021 15:39:24 +0530 Subject: [PATCH 038/242] Add explaining comment --- src/platform/web/docroot/sw.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/platform/web/docroot/sw.js b/src/platform/web/docroot/sw.js index 8542492c..1dbe21f9 100644 --- a/src/platform/web/docroot/sw.js +++ b/src/platform/web/docroot/sw.js @@ -69,6 +69,11 @@ async function purgeOldCaches() { } self.addEventListener('fetch', (event) => { + /* + service worker shouldn't handle xhr uploads because otherwise + the progress events won't fire. + This has to do with xhr not being supported in service workers. + */ if (event.request.method === "GET") { event.respondWith(handleRequest(event.request)); } From eef116e26b087d68efb71f544d769ddf25ef53a7 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 9 Nov 2021 17:19:46 +0530 Subject: [PATCH 039/242] annotate labelOrValues --- src/logging/BaseLogger.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index d45c2fd3..ab2d600b 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -19,6 +19,9 @@ import {LogItem} from "./LogItem.js"; import {LogLevel, LogFilter} from "./LogFilter.js"; import {Platform} from "../platform/web/Platform.js"; +// todo: move this to LogItem? +type LabelOrValues = string | {l: string; [key: string]: any}; + export abstract class BaseLogger { protected _openItems: Set; protected _platform: Platform; @@ -28,14 +31,14 @@ export abstract class BaseLogger { this._platform = platform; } - log(labelOrValues, logLevel = LogLevel.Info) { + log(labelOrValues: LabelOrValues, logLevel: number = LogLevel.Info) { const item = new LogItem(labelOrValues, logLevel, null, this); item._end = item._start; this._persistItem(item, null, false); } /** if item is a log item, wrap the callback in a child of it, otherwise start a new root log item. */ - wrapOrRun(item, labelOrValues, callback, logLevel = null, filterCreator = null) { + wrapOrRun(item, labelOrValues: LabelOrValues, callback, logLevel = null, filterCreator = null) { if (item) { return item.wrap(labelOrValues, callback, logLevel, filterCreator); } else { @@ -48,7 +51,7 @@ export abstract class BaseLogger { Useful to pair with LogItem.refDetached. @return {LogItem} the log item added, useful to pass to LogItem.refDetached */ - runDetached(labelOrValues, callback, logLevel = null, filterCreator = null) { + runDetached(labelOrValues: LabelOrValues, callback, logLevel = null, filterCreator = null) { if (logLevel === null) { logLevel = LogLevel.Info; } @@ -60,7 +63,7 @@ export abstract class BaseLogger { /** run a callback wrapped in a log operation. Errors and duration are transparently logged, also for async operations. Whatever the callback returns is returned here. */ - run(labelOrValues, callback, logLevel = null, filterCreator = null) { + run(labelOrValues: LabelOrValues, callback, logLevel = null, filterCreator = null) { if (logLevel === null) { logLevel = LogLevel.Info; } From 4c5d0285091ae4e3eba5e50ca66fa05a8888301f Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 9 Nov 2021 17:34:16 +0530 Subject: [PATCH 040/242] any --> unknown --- src/logging/BaseLogger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index ab2d600b..bd9b6811 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -20,7 +20,7 @@ import {LogLevel, LogFilter} from "./LogFilter.js"; import {Platform} from "../platform/web/Platform.js"; // todo: move this to LogItem? -type LabelOrValues = string | {l: string; [key: string]: any}; +type LabelOrValues = string | {l: string; [key: string]: unknown}; export abstract class BaseLogger { protected _openItems: Set; From 7893a121c0d85cf8e747cbfa82005444a96316de Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 9 Nov 2021 17:36:18 +0530 Subject: [PATCH 041/242] Initialize in field --- src/logging/BaseLogger.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index bd9b6811..311af22d 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -23,11 +23,10 @@ import {Platform} from "../platform/web/Platform.js"; type LabelOrValues = string | {l: string; [key: string]: unknown}; export abstract class BaseLogger { - protected _openItems: Set; + protected _openItems: Set = new Set(); protected _platform: Platform; constructor({platform}) { - this._openItems = new Set(); this._platform = platform; } From da7f66a53161de0cb32975009a4b56fcb6cfa6a8 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 9 Nov 2021 14:52:03 +0100 Subject: [PATCH 042/242] setup babel for legacy build as input transform plugin --- package.json | 1 + scripts/build-plugins/legacy-build.js | 134 +++++++++++++------------- yarn.lock | 57 ++++++----- 3 files changed, 97 insertions(+), 95 deletions(-) diff --git a/package.json b/package.json index d89d3627..5d064316 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@babel/standalone": "^7.15.8", "@rollup/plugin-babel": "^5.1.0", "@rollup/plugin-multi-entry": "^4.0.0", + "@rollup/pluginutils": "^4.1.1", "@typescript-eslint/eslint-plugin": "^4.29.2", "@typescript-eslint/parser": "^4.29.2", "@vitejs/plugin-legacy": "^1.6.1", diff --git a/scripts/build-plugins/legacy-build.js b/scripts/build-plugins/legacy-build.js index 43f87fba..b503d437 100644 --- a/scripts/build-plugins/legacy-build.js +++ b/scripts/build-plugins/legacy-build.js @@ -1,7 +1,10 @@ -const { build } = require("vite"); const path = require("path"); -let babel; // big import, only do so when used below +const {build} = require("vite"); +const {babel} = require('@rollup/plugin-babel'); +const {createFilter} = require("@rollup/pluginutils"); + const VIRTUAL_ENTRY = "hydrogen:legacy-entry"; +const NODE_MODULES_NEEDING_TRANSPILATION = ["es6-promise"]; module.exports = function legacyBuild(entryModuleId, entryImportReplacements, chunkName, extraImports) { let parentRoot; @@ -26,7 +29,7 @@ module.exports = function legacyBuild(entryModuleId, entryImportReplacements, ch for (const [importSource, newImportSource] of Object.entries(entryImportReplacements)) { code = replaceImport(this, code, importSource, newImportSource); } - code = addExtraImports(code, extraImports); + code = prependExtraImports(code, extraImports); const bundleCode = await buildLegacyChunk(parentRoot, chunkName, code); legacyBundleRef = this.emitFile({ type: "asset", @@ -55,7 +58,10 @@ module.exports = function legacyBuild(entryModuleId, entryImportReplacements, ch } } - +/** we replace the imports ourselves instead of relying on rollup-alias or similar, because + * we only want to replace imports in the entry module, not anywhere in the import tree. + * This allows to create sub classes for the legacy build that can still import + * the non-legacy class as a base class, like LegacyPlatform does with Platform.*/ function replaceImport(pluginCtx, code, importSource, newImportSource) { const ast = pluginCtx.parse(code); for (const node of ast.body) { @@ -70,31 +76,66 @@ function replaceImport(pluginCtx, code, importSource, newImportSource) { throw new Error(`Could not find import ${JSON.stringify(importSource)} to replace`); } -function addExtraImports(code, extraImports) { +function prependExtraImports(code, extraImports) { return extraImports.map(i => `import ${JSON.stringify(i)};`).join("\n") + code; } async function buildLegacyChunk(root, chunkName, code) { - // // compile down to whatever IE 11 needs - // const babelPlugin = babel.getBabelOutputPlugin({ - // // babelHelpers: 'bundled', - // exclude: 'node_modules/**', - // presets: [ - // [ - // "@babel/preset-env", - // { - // useBuiltIns: "entry", - // corejs: "3.4", - // targets: "IE 11", - // // we provide our own promise polyfill (es6-promise) - // // with support for synchronous flushing of - // // the queue for idb where needed - // exclude: ["es.promise", "es.promise.all-settled", "es.promise.finally"] - // } - // ] - // ] - // }); - // babelPlugin.enforce = "post"; + const projectRootDir = path.resolve(path.join(root, "../../..")); + const nodeModulesDir = path.join(projectRootDir, "node_modules"); + const defaultFilter = createFilter([], [], {resolve: projectRootDir}); + const transpiledModuleDirs = NODE_MODULES_NEEDING_TRANSPILATION.map(m => { + return path.join(nodeModulesDir, m); + }); + + const filterModule = id => { + if (!defaultFilter(id)) { + return false; + } + if (transpiledModuleDirs.some(d => id.startsWith(d))) { + return true; + } + if (id.startsWith(nodeModulesDir)) { + return false; + } + return true; + }; + // compile down to whatever IE 11 needs + const babelPlugin = babel({ + babelrc: false, + filter: filterModule, + //exclude: 'node_modules/**', + babelHelpers: 'bundled', + presets: [ + [ + "@babel/preset-env", + { + useBuiltIns: "entry", + corejs: "3.4", + targets: "IE 11", + // we provide our own promise polyfill (es6-promise) + // with support for synchronous flushing of + // the queue for idb where needed + exclude: ["es.promise", "es.promise.all-settled", "es.promise.finally"] + } + ] + ] + }); + const resolveEntryPlugin = { + name: "hydrogen:resolve-legacy-entry", + resolveId(id, importer) { + if (id === VIRTUAL_ENTRY) { + return id; + } else if (importer === VIRTUAL_ENTRY && id.startsWith("./")) { + return this.resolve(path.join(root, id)); + } + }, + load(id) { + if (id === VIRTUAL_ENTRY) { + return code; + } + }, + }; const bundle = await build({ root, configFile: false, @@ -116,48 +157,11 @@ async function buildLegacyChunk(root, chunkName, code) { }, }, plugins: [ - { - name: "hydrogen:resolve-legacy-entry", - resolveId(id, importer) { - if (id === VIRTUAL_ENTRY) { - return id; - } else if (importer === VIRTUAL_ENTRY && id.startsWith("./")) { - return this.resolve(path.join(root, id)); - } - }, - load(id) { - if (id === VIRTUAL_ENTRY) { - return code; - } - }, - } + resolveEntryPlugin, + babelPlugin ] }); const assets = Array.isArray(bundle.output) ? bundle.output : [bundle.output]; const mainChunk = assets.find(a => a.name === chunkName); - - if (!babel) { - babel = require('@babel/standalone'); - } - const {code: babelCode} = babel.transform(mainChunk.code, { - babelrc: false, - configFile: false, - presets: [ - [ - "env", - { - useBuiltIns: "usage", - modules: false, - corejs: "3.4", - targets: "IE 11", - // we provide our own promise polyfill (es6-promise) - // with support for synchronous flushing of - // the queue for idb where needed - exclude: ["es.promise", "es.promise.all-settled", "es.promise.finally"] - } - ] - ] - }); - console.log("code", babelCode.length); - return babelCode; + return mainChunk.code; } diff --git a/yarn.lock b/yarn.lock index 6dea2a76..10dac018 100644 --- a/yarn.lock +++ b/yarn.lock @@ -226,11 +226,11 @@ "@babel/types" "^7.11.0" "@babel/helper-module-imports@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" - integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz#90538e60b672ecf1b448f5f4f5433d37e79a3ec3" + integrity sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.16.0" "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.15.4": version "7.15.4" @@ -326,21 +326,16 @@ dependencies: "@babel/types" "^7.15.4" -"@babel/helper-validator-identifier@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" - integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== +"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" + integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== "@babel/helper-validator-identifier@^7.14.5": version "7.14.9" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== -"@babel/helper-validator-identifier@^7.14.9": - version "7.15.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" - integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== - "@babel/helper-validator-option@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" @@ -992,13 +987,12 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.10.4": - version "7.11.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" - integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q== +"@babel/types@^7.10.4", "@babel/types@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba" + integrity sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg== dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - lodash "^4.17.19" + "@babel/helper-validator-identifier" "^7.15.7" to-fast-properties "^2.0.0" "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.4.4": @@ -1195,9 +1189,9 @@ read-package-json-fast "^2.0.1" "@rollup/plugin-babel@^5.1.0": - version "5.2.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.2.1.tgz#20fc8f8864dc0eaa1c5578408459606808f72924" - integrity sha512-Jd7oqFR2dzZJ3NWANDyBjwTtX/lYbZpVcmkHrfQcpvawHs9E4c0nYk5U2mfZ6I/DZcIvy506KZJi54XK/jxH7A== + version "5.3.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz#9cb1c5146ddd6a4968ad96f209c50c62f92f9879" + integrity sha512-9uIC8HZOnVLrLHxayq/PTzw+uS25E14KPUBh5ktF+18Mjo5yK0ToMMx6epY0uEgkjwJw0aBW4x2horYXh8juWw== dependencies: "@babel/helper-module-imports" "^7.10.4" "@rollup/pluginutils" "^3.1.0" @@ -1298,6 +1292,14 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@rollup/pluginutils@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.1.tgz#1d4da86dd4eded15656a57d933fda2b9a08d47ec" + integrity sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ== + dependencies: + estree-walker "^2.0.1" + picomatch "^2.2.2" + "@sindresorhus/is@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.1.tgz#d26729db850fa327b7cacc5522252194404226f5" @@ -3737,12 +3739,7 @@ lodash@^4.15.0: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -lodash@^4.17.19: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== - -lodash@^4.7.0: +lodash@^4.17.19, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -4437,12 +4434,12 @@ picocolors@^0.2.1: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== -picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.0: +picomatch@^2.0.4, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== -picomatch@^2.2.1, picomatch@^2.2.2: +picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== From 8cbc81b8bb715f4d3f0bb441998459c5276af6cc Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 9 Nov 2021 20:57:47 +0530 Subject: [PATCH 043/242] Annotate method arguments --- src/logging/BaseLogger.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 311af22d..7117f9d9 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -21,6 +21,10 @@ import {Platform} from "../platform/web/Platform.js"; // todo: move this to LogItem? type LabelOrValues = string | {l: string; [key: string]: unknown}; +type LogCallback = (item: LogItem) => Promise | undefined; +// todo: this should be an enum +type LogLevel = number | null; +type FilterCreator = ((filter: LogFilter, item: LogItem) => LogFilter) | null; export abstract class BaseLogger { protected _openItems: Set = new Set(); @@ -37,7 +41,7 @@ export abstract class BaseLogger { } /** if item is a log item, wrap the callback in a child of it, otherwise start a new root log item. */ - wrapOrRun(item, labelOrValues: LabelOrValues, callback, logLevel = null, filterCreator = null) { + wrapOrRun(item: LogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevel = null, filterCreator: FilterCreator = null) { if (item) { return item.wrap(labelOrValues, callback, logLevel, filterCreator); } else { @@ -50,27 +54,27 @@ export abstract class BaseLogger { Useful to pair with LogItem.refDetached. @return {LogItem} the log item added, useful to pass to LogItem.refDetached */ - runDetached(labelOrValues: LabelOrValues, callback, logLevel = null, filterCreator = null) { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevel = null, filterCreator: FilterCreator = null) { if (logLevel === null) { logLevel = LogLevel.Info; } const item = new LogItem(labelOrValues, logLevel, null, this); - this._run(item, callback, logLevel, filterCreator, false /* don't throw, nobody is awaiting */); + this._run(item, callback, logLevel!, filterCreator, false /* don't throw, nobody is awaiting */); return item; } /** run a callback wrapped in a log operation. Errors and duration are transparently logged, also for async operations. Whatever the callback returns is returned here. */ - run(labelOrValues: LabelOrValues, callback, logLevel = null, filterCreator = null) { + run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevel = null, filterCreator: FilterCreator = null) { if (logLevel === null) { logLevel = LogLevel.Info; } const item = new LogItem(labelOrValues, logLevel, null, this); - return this._run(item, callback, logLevel, filterCreator, true); + return this._run(item, callback, logLevel!, filterCreator, true); } - _run(item, callback, logLevel, filterCreator, shouldThrow) { + _run(item: LogItem, callback: LogCallback, logLevel: number, filterCreator: FilterCreator, shouldThrow: boolean) { this._openItems.add(item); const finishItem = () => { From 55401a746c6d46e57fedfdb75932bf8e109247b7 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 9 Nov 2021 22:28:26 +0530 Subject: [PATCH 044/242] Move type alias to LogItem and add more type annotations --- src/logging/BaseLogger.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 7117f9d9..27dd4983 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -15,16 +15,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {LogItem} from "./LogItem.js"; +import {LogItem, LabelOrValues, FilterCreator} from "./LogItem"; import {LogLevel, LogFilter} from "./LogFilter.js"; import {Platform} from "../platform/web/Platform.js"; -// todo: move this to LogItem? -type LabelOrValues = string | {l: string; [key: string]: unknown}; type LogCallback = (item: LogItem) => Promise | undefined; -// todo: this should be an enum -type LogLevel = number | null; -type FilterCreator = ((filter: LogFilter, item: LogItem) => LogFilter) | null; export abstract class BaseLogger { protected _openItems: Set = new Set(); @@ -36,7 +31,7 @@ export abstract class BaseLogger { log(labelOrValues: LabelOrValues, logLevel: number = LogLevel.Info) { const item = new LogItem(labelOrValues, logLevel, null, this); - item._end = item._start; + item.end = item.start; this._persistItem(item, null, false); } @@ -146,7 +141,7 @@ export abstract class BaseLogger { return LogLevel; } - _now() { + _now(): number { return this._platform.clock.now(); } From 122528f9a9ee46a4cc351896040c9ebfb204d8bb Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 9 Nov 2021 17:59:58 +0100 Subject: [PATCH 045/242] also transpile typescript files note that these have already been converted to javascript by vite --- scripts/build-plugins/legacy-build.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build-plugins/legacy-build.js b/scripts/build-plugins/legacy-build.js index b503d437..be5666e8 100644 --- a/scripts/build-plugins/legacy-build.js +++ b/scripts/build-plugins/legacy-build.js @@ -104,7 +104,7 @@ async function buildLegacyChunk(root, chunkName, code) { const babelPlugin = babel({ babelrc: false, filter: filterModule, - //exclude: 'node_modules/**', + extensions: [".js", ".ts"], babelHelpers: 'bundled', presets: [ [ From 2a5d30d749e5a401f33b860f591d532e9c415d9e Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 9 Nov 2021 22:32:02 +0530 Subject: [PATCH 046/242] Convert to enum --- src/logging/LogFilter.ts | 54 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/logging/LogFilter.ts diff --git a/src/logging/LogFilter.ts b/src/logging/LogFilter.ts new file mode 100644 index 00000000..83f71891 --- /dev/null +++ b/src/logging/LogFilter.ts @@ -0,0 +1,54 @@ +/* +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. +*/ + + +export enum LogLevel { + All = 1, + Debug, + Detail, + Info, + Warn, + Error, + Fatal, + Off +} + +export class LogFilter { + constructor(parentFilter) { + this._parentFilter = parentFilter; + this._min = null; + } + + filter(item, children) { + if (this._parentFilter) { + if (!this._parentFilter.filter(item, children)) { + return false; + } + } + // neither our children or us have a loglevel high enough, filter out. + if (this._min !== null && !Array.isArray(children) && item.logLevel < this._min) { + return false; + } else { + return true; + } + } + + /* methods to build the filter */ + minLevel(logLevel) { + this._min = logLevel; + return this; + } +} From 36a982f7e2bf24582a82613bc49c9d79d69be406 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 9 Nov 2021 18:10:12 +0100 Subject: [PATCH 047/242] WIP to run rollup twice, first with vite and babel, then to inline deps --- scripts/build-plugins/legacy-build.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/build-plugins/legacy-build.js b/scripts/build-plugins/legacy-build.js index be5666e8..e33afd05 100644 --- a/scripts/build-plugins/legacy-build.js +++ b/scripts/build-plugins/legacy-build.js @@ -103,14 +103,14 @@ async function buildLegacyChunk(root, chunkName, code) { // compile down to whatever IE 11 needs const babelPlugin = babel({ babelrc: false, - filter: filterModule, extensions: [".js", ".ts"], babelHelpers: 'bundled', presets: [ [ "@babel/preset-env", { - useBuiltIns: "entry", + modules: false, + useBuiltIns: "usage", corejs: "3.4", targets: "IE 11", // we provide our own promise polyfill (es6-promise) @@ -147,11 +147,12 @@ async function buildLegacyChunk(root, chunkName, code) { assetsInlineLimit: 0, polyfillModulePreload: false, rollupOptions: { + external: id => !filterModule(id), input: { [chunkName]: VIRTUAL_ENTRY }, output: { - format: "iife", + format: "es", manualChunks: undefined } }, From ba4d5453a23ca7185142d628785b758aa1aefdfc Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 10 Nov 2021 12:05:29 +0530 Subject: [PATCH 048/242] Move type LogCallback to LogItem --- src/logging/BaseLogger.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 27dd4983..c47329c2 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -15,11 +15,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {LogItem, LabelOrValues, FilterCreator} from "./LogItem"; +import {LogItem, LabelOrValues, FilterCreator, LogCallback} from "./LogItem"; import {LogLevel, LogFilter} from "./LogFilter.js"; import {Platform} from "../platform/web/Platform.js"; -type LogCallback = (item: LogItem) => Promise | undefined; export abstract class BaseLogger { protected _openItems: Set = new Set(); From 97ec680af2af2676d2ba1faa238198840571c79e Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 10 Nov 2021 12:06:22 +0530 Subject: [PATCH 049/242] Remove .js files --- src/logging/LogFilter.js | 53 --------- src/logging/LogItem.js | 242 --------------------------------------- 2 files changed, 295 deletions(-) delete mode 100644 src/logging/LogFilter.js delete mode 100644 src/logging/LogItem.js diff --git a/src/logging/LogFilter.js b/src/logging/LogFilter.js deleted file mode 100644 index 81bbb33c..00000000 --- a/src/logging/LogFilter.js +++ /dev/null @@ -1,53 +0,0 @@ -/* -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. -*/ - -export const LogLevel = { - All: 1, - Debug: 2, - Detail: 3, - Info: 4, - Warn: 5, - Error: 6, - Fatal: 7, - Off: 8, -} - -export class LogFilter { - constructor(parentFilter) { - this._parentFilter = parentFilter; - this._min = null; - } - - filter(item, children) { - if (this._parentFilter) { - if (!this._parentFilter.filter(item, children)) { - return false; - } - } - // neither our children or us have a loglevel high enough, filter out. - if (this._min !== null && !Array.isArray(children) && item.logLevel < this._min) { - return false; - } else { - return true; - } - } - - /* methods to build the filter */ - minLevel(logLevel) { - this._min = logLevel; - return this; - } -} diff --git a/src/logging/LogItem.js b/src/logging/LogItem.js deleted file mode 100644 index 90747964..00000000 --- a/src/logging/LogItem.js +++ /dev/null @@ -1,242 +0,0 @@ -/* -Copyright 2020 Bruno Windels -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 {LogLevel, LogFilter} from "./LogFilter.js"; - -export class LogItem { - constructor(labelOrValues, logLevel, filterCreator, logger) { - this._logger = logger; - this._start = logger._now(); - this._end = null; - // (l)abel - this._values = typeof labelOrValues === "string" ? {l: labelOrValues} : labelOrValues; - this.error = null; - this.logLevel = logLevel; - this._children = null; - this._filterCreator = filterCreator; - } - - /** start a new root log item and run it detached mode, see BaseLogger.runDetached */ - runDetached(labelOrValues, callback, logLevel, filterCreator) { - return this._logger.runDetached(labelOrValues, callback, logLevel, filterCreator); - } - - /** start a new detached root log item and log a reference to it from this item */ - wrapDetached(labelOrValues, callback, logLevel, filterCreator) { - this.refDetached(this.runDetached(labelOrValues, callback, logLevel, filterCreator)); - } - - /** logs a reference to a different log item, usually obtained from runDetached. - This is useful if the referenced operation can't be awaited. */ - refDetached(logItem, logLevel = null) { - logItem.ensureRefId(); - return this.log({ref: logItem._values.refId}, logLevel); - } - - ensureRefId() { - if (!this._values.refId) { - this.set("refId", this._logger._createRefId()); - } - } - - /** - * Creates a new child item and runs it in `callback`. - */ - wrap(labelOrValues, callback, logLevel = null, filterCreator = null) { - const item = this.child(labelOrValues, logLevel, filterCreator); - return item.run(callback); - } - - get duration() { - if (this._end) { - return this._end - this._start; - } else { - return null; - } - } - - durationWithoutType(type) { - return this.duration - this.durationOfType(type); - } - - durationOfType(type) { - if (this._values.t === type) { - return this.duration; - } else if (this._children) { - return this._children.reduce((sum, c) => { - return sum + c.durationOfType(type); - }, 0); - } else { - return 0; - } - } - - /** - * Creates a new child item that finishes immediately - * and can hence not be modified anymore. - * - * Hence, the child item is not returned. - */ - log(labelOrValues, logLevel = null) { - const item = this.child(labelOrValues, logLevel, null); - item._end = item._start; - } - - set(key, value) { - if(typeof key === "object") { - const values = key; - Object.assign(this._values, values); - } else { - this._values[key] = value; - } - } - - serialize(filter, parentStartTime = null, forced) { - if (this._filterCreator) { - try { - filter = this._filterCreator(new LogFilter(filter), this); - } catch (err) { - console.error("Error creating log filter", err); - } - } - let children; - if (this._children !== null) { - children = this._children.reduce((array, c) => { - const s = c.serialize(filter, this._start, false); - if (s) { - if (array === null) { - array = []; - } - array.push(s); - } - return array; - }, null); - } - if (filter && !filter.filter(this, children)) { - return null; - } - // in (v)alues, (l)abel and (t)ype are also reserved. - const item = { - // (s)tart - s: parentStartTime === null ? this._start : this._start - parentStartTime, - // (d)uration - d: this.duration, - // (v)alues - v: this._values, - // (l)evel - l: this.logLevel - }; - if (this.error) { - // (e)rror - item.e = { - stack: this.error.stack, - name: this.error.name, - message: this.error.message.split("\n")[0] - }; - } - if (forced) { - item.f = true; //(f)orced - } - if (children) { - // (c)hildren - item.c = children; - } - return item; - } - - /** - * You probably want to use `wrap` instead of this. - * - * Runs a callback passing this log item, - * recording the timing and any error. - * - * callback can return a Promise. - * - * Should only be called once. - * - * @param {Function} callback [description] - * @return {[type]} [description] - */ - run(callback) { - if (this._end !== null) { - console.trace("log item is finished, additional logs will likely not be recorded"); - } - let result; - try { - result = callback(this); - if (result instanceof Promise) { - return result.then(promiseResult => { - this.finish(); - return promiseResult; - }, err => { - throw this.catch(err); - }); - } else { - this.finish(); - return result; - } - } catch (err) { - throw this.catch(err); - } - } - - /** - * finished the item, recording the end time. After finishing, an item can't be modified anymore as it will be persisted. - * @internal shouldn't typically be called by hand. allows to force finish if a promise is still running when closing the app - */ - finish() { - if (this._end === null) { - if (this._children !== null) { - for(const c of this._children) { - c.finish(); - } - } - this._end = this._logger._now(); - } - } - - // expose log level without needing import everywhere - get level() { - return LogLevel; - } - - catch(err) { - this.error = err; - this.logLevel = LogLevel.Error; - this.finish(); - return err; - } - - child(labelOrValues, logLevel, filterCreator) { - if (this._end !== null) { - console.trace("log item is finished, additional logs will likely not be recorded"); - } - if (!logLevel) { - logLevel = this.logLevel || LogLevel.Info; - } - const item = new LogItem(labelOrValues, logLevel, filterCreator, this._logger); - if (this._children === null) { - this._children = []; - } - this._children.push(item); - return item; - } - - get logger() { - return this._logger; - } -} From db792ab5a91188f7e4d62f08689ef31cb3829f58 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 10 Nov 2021 12:06:50 +0530 Subject: [PATCH 050/242] Add type annotations to LogItem --- src/logging/LogItem.ts | 270 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 src/logging/LogItem.ts diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts new file mode 100644 index 00000000..bd6958e1 --- /dev/null +++ b/src/logging/LogItem.ts @@ -0,0 +1,270 @@ +/* +Copyright 2020 Bruno Windels +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 {BaseLogger} from "./BaseLogger"; +import {LogLevel, LogFilter} from "./LogFilter.js"; + +type LogItemValues = {l: string; [key: string]: unknown}; +export type LabelOrValues = string | LogItemValues; +export type FilterCreator = ((filter: LogFilter, item: LogItem) => LogFilter) | null; +export type LogCallback = (item: LogItem) => Promise | undefined; + +export class LogItem { + public start: number; + public logLevel: LogLevel; + public error: Error | null; + public end: number | null; + private _values: LogItemValues; + private _logger: BaseLogger; + private _filterCreator: FilterCreator; + private _children: Array | null; + + constructor(labelOrValues: LabelOrValues, logLevel: LogLevel, filterCreator: FilterCreator, logger: BaseLogger) { + this._logger = logger; + this.start = logger._now(); + this.end = null; + // (l)abel + this._values = typeof labelOrValues === "string" ? {l: labelOrValues} : labelOrValues; + this.error = null; + this.logLevel = logLevel; + this._children = null; + this._filterCreator = filterCreator; + } + + /** start a new root log item and run it detached mode, see BaseLogger.runDetached */ + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevel, filterCreator: FilterCreator) { + return this._logger.runDetached(labelOrValues, callback, logLevel, filterCreator); + } + + /** start a new detached root log item and log a reference to it from this item */ + wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevel, filterCreator: FilterCreator) { + this.refDetached(this.runDetached(labelOrValues, callback, logLevel, filterCreator)); + } + + /** logs a reference to a different log item, usually obtained from runDetached. + This is useful if the referenced operation can't be awaited. */ + refDetached(logItem: LogItem, logLevel: LogLevel | null = null) { + logItem.ensureRefId(); + return this.log({ref: logItem._values.refId}, logLevel); + } + + ensureRefId() { + if (!this._values.refId) { + this.set("refId", this._logger._createRefId()); + } + } + + /** + * Creates a new child item and runs it in `callback`. + */ + wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevel | null = null, filterCreator: FilterCreator = null) { + const item = this.child(labelOrValues, logLevel, filterCreator); + return item.run(callback); + } + + get duration() { + if (this.end) { + return this.end - this.start; + } else { + return null; + } + } + + durationWithoutType(type) { + return this.duration - this.durationOfType(type); + } + + durationOfType(type) { + if (this._values.t === type) { + return this.duration; + } else if (this._children) { + return this._children.reduce((sum, c) => { + return sum + c.durationOfType(type); + }, 0); + } else { + return 0; + } + } + + /** + * Creates a new child item that finishes immediately + * and can hence not be modified anymore. + * + * Hence, the child item is not returned. + */ + log(labelOrValues: LabelOrValues, logLevel: LogLevel | null = null) { + const item = this.child(labelOrValues, logLevel, null); + item.end = item.start; + } + + set(key, value) { + if(typeof key === "object") { + const values = key; + Object.assign(this._values, values); + } else { + this._values[key] = value; + } + } + + serialize(filter: LogFilter, parentStartTime: number | null = null, forced: boolean) { + if (this._filterCreator) { + try { + filter = this._filterCreator(new LogFilter(filter), this); + } catch (err) { + console.error("Error creating log filter", err); + } + } + interface Item { + s: number; + d: number | null; + v: LogItemValues; + l: LogLevel; + e?: { + stack: string | undefined; + name: string; + message: string; + }; + f?: boolean; + c?: Array; + }; + let children: Array | null = null; + if (this._children !== null) { + children = this._children.reduce((array: Array, c) => { + const s = c.serialize(filter, this.start, false); + if (s) { + if (array === null) { + array = []; + } + array.push(s); + } + return array; + }, null); + } + if (filter && !filter.filter(this, children)) { + return null; + } + // in (v)alues, (l)abel and (t)ype are also reserved. + const item: Item = { + // (s)tart + s: parentStartTime === null ? this.start : this.start - parentStartTime, + // (d)uration + d: this.duration, + // (v)alues + v: this._values, + // (l)evel + l: this.logLevel + }; + if (this.error) { + // (e)rror + item.e = { + stack: this.error.stack, + name: this.error.name, + message: this.error.message.split("\n")[0] + }; + } + if (forced) { + item.f = true; //(f)orced + } + if (children) { + // (c)hildren + item.c = children; + } + return item; + } + + /** + * You probably want to use `wrap` instead of this. + * + * Runs a callback passing this log item, + * recording the timing and any error. + * + * callback can return a Promise. + * + * Should only be called once. + * + * @param {Function} callback [description] + * @return {[type]} [description] + */ + run(callback: LogCallback) { + if (this.end !== null) { + console.trace("log item is finished, additional logs will likely not be recorded"); + } + let result; + try { + result = callback(this); + if (result instanceof Promise) { + return result.then(promiseResult => { + this.finish(); + return promiseResult; + }, err => { + throw this.catch(err); + }); + } else { + this.finish(); + return result; + } + } catch (err) { + throw this.catch(err); + } + } + + /** + * finished the item, recording the end time. After finishing, an item can't be modified anymore as it will be persisted. + * @internal shouldn't typically be called by hand. allows to force finish if a promise is still running when closing the app + */ + finish() { + if (this.end === null) { + if (this._children !== null) { + for(const c of this._children) { + c.finish(); + } + } + this.end = this._logger._now(); + } + } + + // expose log level without needing import everywhere + get level() { + return LogLevel; + } + + catch(err: Error) { + this.error = err; + this.logLevel = LogLevel.Error; + this.finish(); + return err; + } + + child(labelOrValues: LabelOrValues, logLevel: LogLevel | null, filterCreator: FilterCreator) { + if (this.end !== null) { + console.trace("log item is finished, additional logs will likely not be recorded"); + } + if (!logLevel) { + logLevel = this.logLevel || LogLevel.Info; + } + const item = new LogItem(labelOrValues, logLevel, filterCreator, this._logger); + if (this._children === null) { + this._children = []; + } + this._children.push(item); + return item; + } + + get logger() { + return this._logger; + } +} From 772f7a2757c33ed0dd45a4c7b6a8c60f49c7fe94 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 10 Nov 2021 12:17:43 +0530 Subject: [PATCH 051/242] Account for duration being null --- src/logging/LogItem.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index bd6958e1..0a896841 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -85,7 +85,10 @@ export class LogItem { } durationWithoutType(type) { - return this.duration - this.durationOfType(type); + if (this.duration) { + return this.duration - this.durationOfType(type); + } + return null; } durationOfType(type) { From ceb52eedafffe30b9593ca6e9e14a870cacbc55b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 10 Nov 2021 12:36:56 +0530 Subject: [PATCH 052/242] Fix imports and add type annotations --- src/logging/BaseLogger.ts | 2 +- src/logging/ConsoleLogger.js | 2 +- src/logging/IDBLogger.js | 2 +- src/logging/LogItem.ts | 6 +++--- src/logging/NullLogger.js | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index c47329c2..60388f77 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -16,7 +16,7 @@ limitations under the License. */ import {LogItem, LabelOrValues, FilterCreator, LogCallback} from "./LogItem"; -import {LogLevel, LogFilter} from "./LogFilter.js"; +import {LogLevel, LogFilter} from "./LogFilter"; import {Platform} from "../platform/web/Platform.js"; diff --git a/src/logging/ConsoleLogger.js b/src/logging/ConsoleLogger.js index aacbf132..4d3be73b 100644 --- a/src/logging/ConsoleLogger.js +++ b/src/logging/ConsoleLogger.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 {BaseLogger} from "./BaseLogger.js"; +import {BaseLogger} from "./BaseLogger"; export class ConsoleLogger extends BaseLogger { _persistItem(item) { diff --git a/src/logging/IDBLogger.js b/src/logging/IDBLogger.js index 03c2bf88..2360b54c 100644 --- a/src/logging/IDBLogger.js +++ b/src/logging/IDBLogger.js @@ -22,7 +22,7 @@ import { iterateCursor, fetchResults, } from "../matrix/storage/idb/utils"; -import {BaseLogger} from "./BaseLogger.js"; +import {BaseLogger} from "./BaseLogger"; export class IDBLogger extends BaseLogger { constructor(options) { diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 0a896841..a77b7c3d 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -16,7 +16,7 @@ limitations under the License. */ import {BaseLogger} from "./BaseLogger"; -import {LogLevel, LogFilter} from "./LogFilter.js"; +import {LogLevel, LogFilter} from "./LogFilter"; type LogItemValues = {l: string; [key: string]: unknown}; export type LabelOrValues = string | LogItemValues; @@ -84,14 +84,14 @@ export class LogItem { } } - durationWithoutType(type) { + durationWithoutType(type: string) { if (this.duration) { return this.duration - this.durationOfType(type); } return null; } - durationOfType(type) { + durationOfType(type: string) { if (this._values.t === type) { return this.duration; } else if (this._children) { diff --git a/src/logging/NullLogger.js b/src/logging/NullLogger.js index 060212bd..12eec5c9 100644 --- a/src/logging/NullLogger.js +++ b/src/logging/NullLogger.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 {LogLevel} from "./LogFilter.js"; +import {LogLevel} from "./LogFilter"; function noop () {} From 142d3ef543321e248fc085bd80a7c64c6092b033 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 10 Nov 2021 13:45:37 +0530 Subject: [PATCH 053/242] Split LogItemValues into union of types --- src/logging/LogItem.ts | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index a77b7c3d..a7f05768 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -18,7 +18,25 @@ limitations under the License. import {BaseLogger} from "./BaseLogger"; import {LogLevel, LogFilter} from "./LogFilter"; -type LogItemValues = {l: string; [key: string]: unknown}; +type LogItemWithLabel = { + l: string; + [key: string]: unknown; +}; + +type LogItemNetwork = { + t: "network"; + method: string; + url: string; + [key: string]: unknown; +} + +type LogItemRef = { + ref: number; + [key: string]: unknown; +} + +type LogItemValues = LogItemWithLabel | LogItemNetwork | LogItemRef; + export type LabelOrValues = string | LogItemValues; export type FilterCreator = ((filter: LogFilter, item: LogItem) => LogFilter) | null; export type LogCallback = (item: LogItem) => Promise | undefined; @@ -59,7 +77,7 @@ export class LogItem { This is useful if the referenced operation can't be awaited. */ refDetached(logItem: LogItem, logLevel: LogLevel | null = null) { logItem.ensureRefId(); - return this.log({ref: logItem._values.refId}, logLevel); + return this.log({ref: logItem._values.refId as number}, logLevel); } ensureRefId() { @@ -114,7 +132,7 @@ export class LogItem { item.end = item.start; } - set(key, value) { + set(key: string | object, value: unknown) { if(typeof key === "object") { const values = key; Object.assign(this._values, values); From 0b4eca47249e9a7dfa9272c40fcfd6c1faf2a0fe Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 10 Nov 2021 14:29:23 +0530 Subject: [PATCH 054/242] Create alias for LogLevel | null --- src/logging/BaseLogger.ts | 12 ++++++------ src/logging/LogFilter.ts | 2 ++ src/logging/LogItem.ts | 14 +++++++------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 60388f77..bd17afde 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -16,7 +16,7 @@ limitations under the License. */ import {LogItem, LabelOrValues, FilterCreator, LogCallback} from "./LogItem"; -import {LogLevel, LogFilter} from "./LogFilter"; +import {LogLevel, LogFilter, LogLevelOrNull} from "./LogFilter"; import {Platform} from "../platform/web/Platform.js"; @@ -28,14 +28,14 @@ export abstract class BaseLogger { this._platform = platform; } - log(labelOrValues: LabelOrValues, logLevel: number = LogLevel.Info) { + log(labelOrValues: LabelOrValues, logLevel: LogLevel = LogLevel.Info) { const item = new LogItem(labelOrValues, logLevel, null, this); item.end = item.start; this._persistItem(item, null, false); } /** if item is a log item, wrap the callback in a child of it, otherwise start a new root log item. */ - wrapOrRun(item: LogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevel = null, filterCreator: FilterCreator = null) { + wrapOrRun(item: LogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null) { if (item) { return item.wrap(labelOrValues, callback, logLevel, filterCreator); } else { @@ -48,7 +48,7 @@ export abstract class BaseLogger { Useful to pair with LogItem.refDetached. @return {LogItem} the log item added, useful to pass to LogItem.refDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevel = null, filterCreator: FilterCreator = null) { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null) { if (logLevel === null) { logLevel = LogLevel.Info; } @@ -60,7 +60,7 @@ export abstract class BaseLogger { /** run a callback wrapped in a log operation. Errors and duration are transparently logged, also for async operations. Whatever the callback returns is returned here. */ - run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevel = null, filterCreator: FilterCreator = null) { + run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null) { if (logLevel === null) { logLevel = LogLevel.Info; } @@ -131,7 +131,7 @@ export abstract class BaseLogger { this._openItems.clear(); } - abstract _persistItem(item: LogItem, filter?: LogFilter, forced?: boolean): void; + abstract _persistItem(item: LogItem, filter?: LogFilter | null, forced?: boolean): void; abstract export(): void; diff --git a/src/logging/LogFilter.ts b/src/logging/LogFilter.ts index 83f71891..3099d826 100644 --- a/src/logging/LogFilter.ts +++ b/src/logging/LogFilter.ts @@ -26,6 +26,8 @@ export enum LogLevel { Off } +export type LogLevelOrNull = LogLevel | null; + export class LogFilter { constructor(parentFilter) { this._parentFilter = parentFilter; diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index a7f05768..094dc7a2 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -16,7 +16,7 @@ limitations under the License. */ import {BaseLogger} from "./BaseLogger"; -import {LogLevel, LogFilter} from "./LogFilter"; +import {LogLevel, LogLevelOrNull, LogFilter} from "./LogFilter"; type LogItemWithLabel = { l: string; @@ -64,18 +64,18 @@ export class LogItem { } /** start a new root log item and run it detached mode, see BaseLogger.runDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevel, filterCreator: FilterCreator) { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator) { return this._logger.runDetached(labelOrValues, callback, logLevel, filterCreator); } /** start a new detached root log item and log a reference to it from this item */ - wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevel, filterCreator: FilterCreator) { + wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator) { this.refDetached(this.runDetached(labelOrValues, callback, logLevel, filterCreator)); } /** logs a reference to a different log item, usually obtained from runDetached. This is useful if the referenced operation can't be awaited. */ - refDetached(logItem: LogItem, logLevel: LogLevel | null = null) { + refDetached(logItem: LogItem, logLevel: LogLevelOrNull = null) { logItem.ensureRefId(); return this.log({ref: logItem._values.refId as number}, logLevel); } @@ -89,7 +89,7 @@ export class LogItem { /** * Creates a new child item and runs it in `callback`. */ - wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevel | null = null, filterCreator: FilterCreator = null) { + wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null) { const item = this.child(labelOrValues, logLevel, filterCreator); return item.run(callback); } @@ -127,7 +127,7 @@ export class LogItem { * * Hence, the child item is not returned. */ - log(labelOrValues: LabelOrValues, logLevel: LogLevel | null = null) { + log(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull = null) { const item = this.child(labelOrValues, logLevel, null); item.end = item.start; } @@ -270,7 +270,7 @@ export class LogItem { return err; } - child(labelOrValues: LabelOrValues, logLevel: LogLevel | null, filterCreator: FilterCreator) { + child(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull, filterCreator: FilterCreator) { if (this.end !== null) { console.trace("log item is finished, additional logs will likely not be recorded"); } From e3c85c585e2117c9f45cb5f4c91d56342d8fd0e1 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 10 Nov 2021 14:42:43 +0530 Subject: [PATCH 055/242] Log callbacks can return more than Promises --- 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 094dc7a2..4fdf8ada 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -39,7 +39,7 @@ type LogItemValues = LogItemWithLabel | LogItemNetwork | LogItemRef; export type LabelOrValues = string | LogItemValues; export type FilterCreator = ((filter: LogFilter, item: LogItem) => LogFilter) | null; -export type LogCallback = (item: LogItem) => Promise | undefined; +export type LogCallback = (item: LogItem) => unknown; export class LogItem { public start: number; From ab126729e0ee3efc34e605ce267275e4519d4791 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 10 Nov 2021 14:49:59 +0530 Subject: [PATCH 056/242] Use LogLevel as type instead of number --- src/logging/BaseLogger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index bd17afde..fb91e77b 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -68,7 +68,7 @@ export abstract class BaseLogger { return this._run(item, callback, logLevel!, filterCreator, true); } - _run(item: LogItem, callback: LogCallback, logLevel: number, filterCreator: FilterCreator, shouldThrow: boolean) { + _run(item: LogItem, callback: LogCallback, logLevel: LogLevel, filterCreator: FilterCreator, shouldThrow: boolean) { this._openItems.add(item); const finishItem = () => { From ef2aad89565a8940c3fe32cbae44338a2baceb78 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 10 Nov 2021 15:04:07 +0530 Subject: [PATCH 057/242] Annotate LogFilter --- src/logging/LogFilter.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/logging/LogFilter.ts b/src/logging/LogFilter.ts index 3099d826..f13a6179 100644 --- a/src/logging/LogFilter.ts +++ b/src/logging/LogFilter.ts @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import {LogItem} from "./LogItem"; export enum LogLevel { All = 1, @@ -29,12 +30,14 @@ export enum LogLevel { export type LogLevelOrNull = LogLevel | null; export class LogFilter { - constructor(parentFilter) { + private _min: LogLevelOrNull = null; + private _parentFilter?: LogFilter; + + constructor(parentFilter?: LogFilter) { this._parentFilter = parentFilter; - this._min = null; } - filter(item, children) { + filter(item: LogItem, children: Array | null) { if (this._parentFilter) { if (!this._parentFilter.filter(item, children)) { return false; @@ -49,7 +52,7 @@ export class LogFilter { } /* methods to build the filter */ - minLevel(logLevel) { + minLevel(logLevel: LogLevel) { this._min = logLevel; return this; } From cfa7708b57caafb131b8e4839243ad232fe54c7f Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 10 Nov 2021 18:51:46 +0530 Subject: [PATCH 058/242] Use type imports --- src/logging/BaseLogger.ts | 9 ++++++--- src/logging/LogFilter.ts | 2 +- src/logging/LogItem.ts | 5 +++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index fb91e77b..99a8f9b7 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -15,9 +15,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {LogItem, LabelOrValues, FilterCreator, LogCallback} from "./LogItem"; -import {LogLevel, LogFilter, LogLevelOrNull} from "./LogFilter"; -import {Platform} from "../platform/web/Platform.js"; +import {LogItem} from "./LogItem"; +import {LogLevel, LogFilter} from "./LogFilter"; +import type {FilterCreator, LabelOrValues, LogCallback} from "./LogItem"; +import type {LogLevelOrNull} from "./LogFilter"; +// todo: should this import be here just for getting the type? should it instead be done when Platform.js --> Platform.ts? +import type {Platform} from "../platform/web/Platform.js"; export abstract class BaseLogger { diff --git a/src/logging/LogFilter.ts b/src/logging/LogFilter.ts index f13a6179..476bca0e 100644 --- a/src/logging/LogFilter.ts +++ b/src/logging/LogFilter.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {LogItem} from "./LogItem"; +import type {LogItem} from "./LogItem"; export enum LogLevel { All = 1, diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 4fdf8ada..2e95813a 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -15,8 +15,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseLogger} from "./BaseLogger"; -import {LogLevel, LogLevelOrNull, LogFilter} from "./LogFilter"; +import {LogLevel, LogFilter} from "./LogFilter"; +import type {LogLevelOrNull} from "./LogFilter"; +import type {BaseLogger} from "./BaseLogger"; type LogItemWithLabel = { l: string; From 7a68c971aa36c81317a6ccacbb7cbf7a4dc6ade1 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 10 Nov 2021 19:07:24 +0530 Subject: [PATCH 059/242] Make field readonly --- 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 2e95813a..f58a0185 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -43,7 +43,7 @@ export type FilterCreator = ((filter: LogFilter, item: LogItem) => LogFilter) | export type LogCallback = (item: LogItem) => unknown; export class LogItem { - public start: number; + public readonly start: number; public logLevel: LogLevel; public error: Error | null; public end: number | null; From cd7dccd804852ed38285e7786dc8bc9a5ab6a332 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 10 Nov 2021 19:13:35 +0530 Subject: [PATCH 060/242] Move interface to top --- src/logging/LogItem.ts | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index f58a0185..b0412b02 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -38,6 +38,20 @@ type LogItemRef = { type LogItemValues = LogItemWithLabel | LogItemNetwork | LogItemRef; +interface ISerializedItem { + s: number; + d: number | null; + v: LogItemValues; + l: LogLevel; + e?: { + stack?: string; + name: string; + message: string; + }; + f?: boolean; + c?: Array; +}; + export type LabelOrValues = string | LogItemValues; export type FilterCreator = ((filter: LogFilter, item: LogItem) => LogFilter) | null; export type LogCallback = (item: LogItem) => unknown; @@ -150,22 +164,9 @@ export class LogItem { console.error("Error creating log filter", err); } } - interface Item { - s: number; - d: number | null; - v: LogItemValues; - l: LogLevel; - e?: { - stack: string | undefined; - name: string; - message: string; - }; - f?: boolean; - c?: Array; - }; - let children: Array | null = null; + let children: Array | null = null; if (this._children !== null) { - children = this._children.reduce((array: Array, c) => { + children = this._children.reduce((array: Array, c) => { const s = c.serialize(filter, this.start, false); if (s) { if (array === null) { @@ -180,7 +181,7 @@ export class LogItem { return null; } // in (v)alues, (l)abel and (t)ype are also reserved. - const item: Item = { + const item: ISerializedItem = { // (s)tart s: parentStartTime === null ? this.start : this.start - parentStartTime, // (d)uration From e83781b26a1db34e9f9824ff4baac676f9ef6b73 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 10 Nov 2021 19:10:06 +0100 Subject: [PATCH 061/242] make ie11 compatible --- scripts/package-overrides/buffer/index.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/package-overrides/buffer/index.js b/scripts/package-overrides/buffer/index.js index 2ac44010..e76322c4 100644 --- a/scripts/package-overrides/buffer/index.js +++ b/scripts/package-overrides/buffer/index.js @@ -1,6 +1,7 @@ -export default class Buffer { - static isBuffer(array) {return array instanceof Uint8Array;} - static from(arrayBuffer) {return arrayBuffer;} - static allocUnsafe(size) {return Buffer.alloc(size);} - static alloc(size) {return new Uint8Array(size);} +var Buffer = { + isBuffer: function(array) {return array instanceof Uint8Array;}, + from: function(arrayBuffer) {return arrayBuffer;}, + allocUnsafe: function(size) {return Buffer.alloc(size);}, + alloc: function(size) {return new Uint8Array(size);} }; +export default Buffer; From 7148f6fd41ced2c2e9eb8265630476c22ee9171f Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 10 Nov 2021 19:10:23 +0100 Subject: [PATCH 062/242] wip to not babel deps --- scripts/build-plugins/legacy-build.js | 89 ++++++++++++++++++++------- 1 file changed, 67 insertions(+), 22 deletions(-) diff --git a/scripts/build-plugins/legacy-build.js b/scripts/build-plugins/legacy-build.js index e33afd05..f7f641a3 100644 --- a/scripts/build-plugins/legacy-build.js +++ b/scripts/build-plugins/legacy-build.js @@ -1,7 +1,10 @@ const path = require("path"); const {build} = require("vite"); -const {babel} = require('@rollup/plugin-babel'); +const {babel, getBabelOutputPlugin} = require('@rollup/plugin-babel'); const {createFilter} = require("@rollup/pluginutils"); +const { rollup } = require('rollup'); +const { nodeResolve } = require('@rollup/plugin-node-resolve'); +const commonjs = require('@rollup/plugin-commonjs'); const VIRTUAL_ENTRY = "hydrogen:legacy-entry"; const NODE_MODULES_NEEDING_TRANSPILATION = ["es6-promise"]; @@ -92,6 +95,10 @@ async function buildLegacyChunk(root, chunkName, code) { if (!defaultFilter(id)) { return false; } + if (id.endsWith("?url") || id.endsWith("?raw")) { + // TODO is this needed + return true; + } if (transpiledModuleDirs.some(d => id.startsWith(d))) { return true; } @@ -101,10 +108,11 @@ async function buildLegacyChunk(root, chunkName, code) { return true; }; // compile down to whatever IE 11 needs - const babelPlugin = babel({ + const babelPlugin = getBabelOutputPlugin({ babelrc: false, + compact: false, extensions: [".js", ".ts"], - babelHelpers: 'bundled', + // babelHelpers: 'bundled', presets: [ [ "@babel/preset-env", @@ -121,21 +129,6 @@ async function buildLegacyChunk(root, chunkName, code) { ] ] }); - const resolveEntryPlugin = { - name: "hydrogen:resolve-legacy-entry", - resolveId(id, importer) { - if (id === VIRTUAL_ENTRY) { - return id; - } else if (importer === VIRTUAL_ENTRY && id.startsWith("./")) { - return this.resolve(path.join(root, id)); - } - }, - load(id) { - if (id === VIRTUAL_ENTRY) { - return code; - } - }, - }; const bundle = await build({ root, configFile: false, @@ -152,17 +145,69 @@ async function buildLegacyChunk(root, chunkName, code) { [chunkName]: VIRTUAL_ENTRY }, output: { - format: "es", + format: "esm", manualChunks: undefined - } + }, + makeAbsoluteExternalsRelative: false, }, }, plugins: [ - resolveEntryPlugin, + memoryBabelInputPlugin(VIRTUAL_ENTRY, root, code), babelPlugin ] }); const assets = Array.isArray(bundle.output) ? bundle.output : [bundle.output]; const mainChunk = assets.find(a => a.name === chunkName); - return mainChunk.code; + const babelCode = mainChunk.code; + const bundle2 = await rollup({ + plugins: [ + memoryBabelInputPlugin(VIRTUAL_ENTRY, root, babelCode), + overridesAsRollupPlugin(new Map( + [["safe-buffer", "./scripts/package-overrides/safe-buffer/index.js"], + ["buffer", "./scripts/package-overrides/buffer/index.js"]]), projectRootDir), + commonjs(), + nodeResolve(), + ], + input: { + [chunkName]: VIRTUAL_ENTRY + } + }); + const {output} = await bundle2.generate({ + format: 'iife', + name: `hydrogen` + }); + const bundledCode = output[0].code; + return bundledCode; +} + +function memoryBabelInputPlugin(entryName, dir, code) { + return { + name: "hydrogen:resolve-legacy-entry", + resolveId(id, importer) { + if (id === entryName) { + return id; + } else if (importer === entryName && id.startsWith("./")) { + return this.resolve(path.join(dir, id)); + } + }, + load(id) { + if (id === entryName) { + return code; + } + }, + } +} + +function overridesAsRollupPlugin(mapping, basedir) { + return { + name: "rewrite-imports", + async resolveId (source, importer) { + const target = mapping.get(source); + if (target) { + const resolvedTarget = await this.resolve(path.join(basedir, target)); + console.log("resolving", source, resolvedTarget); + return resolvedTarget; + } + } + }; } From 0f7a78ee25b84f3c16800633bdf6d1f9b0c5a674 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 11 Nov 2021 13:05:12 +0530 Subject: [PATCH 063/242] Make return type explicit --- 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 b0412b02..c33e529f 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -156,7 +156,7 @@ export class LogItem { } } - serialize(filter: LogFilter, parentStartTime: number | null = null, forced: boolean) { + serialize(filter: LogFilter, parentStartTime: number | null = null, forced: boolean): ISerializedItem | null { if (this._filterCreator) { try { filter = this._filterCreator(new LogFilter(filter), this); From 425a3c85a990ca775112d4b2877d78d388d5900d Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 11 Nov 2021 13:24:52 +0530 Subject: [PATCH 064/242] Make error prop private and expose via getter --- src/logging/LogItem.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index c33e529f..a464c285 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -59,7 +59,7 @@ export type LogCallback = (item: LogItem) => unknown; export class LogItem { public readonly start: number; public logLevel: LogLevel; - public error: Error | null; + private _error: Error | null; public end: number | null; private _values: LogItemValues; private _logger: BaseLogger; @@ -72,7 +72,7 @@ export class LogItem { this.end = null; // (l)abel this._values = typeof labelOrValues === "string" ? {l: labelOrValues} : labelOrValues; - this.error = null; + this._error = null; this.logLevel = logLevel; this._children = null; this._filterCreator = filterCreator; @@ -191,12 +191,12 @@ export class LogItem { // (l)evel l: this.logLevel }; - if (this.error) { + if (this._error) { // (e)rror item.e = { - stack: this.error.stack, - name: this.error.name, - message: this.error.message.split("\n")[0] + stack: this._error.stack, + name: this._error.name, + message: this._error.message.split("\n")[0] }; } if (forced) { @@ -266,7 +266,7 @@ export class LogItem { } catch(err: Error) { - this.error = err; + this._error = err; this.logLevel = LogLevel.Error; this.finish(); return err; @@ -290,4 +290,8 @@ export class LogItem { get logger() { return this._logger; } + + get error() { + return this._error; + } } From 09851600f7863ace096bb6adb476bb573aa7e745 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 11 Nov 2021 15:35:51 +0530 Subject: [PATCH 065/242] Remove unwanted types --- src/logging/LogItem.ts | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index a464c285..4289aafc 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -19,25 +19,6 @@ import {LogLevel, LogFilter} from "./LogFilter"; import type {LogLevelOrNull} from "./LogFilter"; import type {BaseLogger} from "./BaseLogger"; -type LogItemWithLabel = { - l: string; - [key: string]: unknown; -}; - -type LogItemNetwork = { - t: "network"; - method: string; - url: string; - [key: string]: unknown; -} - -type LogItemRef = { - ref: number; - [key: string]: unknown; -} - -type LogItemValues = LogItemWithLabel | LogItemNetwork | LogItemRef; - interface ISerializedItem { s: number; d: number | null; @@ -52,6 +33,16 @@ interface ISerializedItem { c?: Array; }; +type LogItemValues = { + l?: string; + t?: string; + id?: unknown; + status?: string | number; + refId?: number; + ref?: number; + [key: string]: any +} + export type LabelOrValues = string | LogItemValues; export type FilterCreator = ((filter: LogFilter, item: LogItem) => LogFilter) | null; export type LogCallback = (item: LogItem) => unknown; From eb7c5c44370d3fbc359d5832ea73e61dd36b991d Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 11 Nov 2021 16:08:25 +0530 Subject: [PATCH 066/242] Use undefined only instead of both undefined and null --- src/logging/BaseLogger.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 99a8f9b7..259c47eb 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -34,7 +34,7 @@ export abstract class BaseLogger { log(labelOrValues: LabelOrValues, logLevel: LogLevel = LogLevel.Info) { const item = new LogItem(labelOrValues, logLevel, null, this); item.end = item.start; - this._persistItem(item, null, false); + this._persistItem(item, undefined, false); } /** if item is a log item, wrap the callback in a child of it, otherwise start a new root log item. */ @@ -134,7 +134,7 @@ export abstract class BaseLogger { this._openItems.clear(); } - abstract _persistItem(item: LogItem, filter?: LogFilter | null, forced?: boolean): void; + abstract _persistItem(item: LogItem, filter?: LogFilter, forced?: boolean): void; abstract export(): void; From 9fed2ca41b28be42cc89f6a1260f9b94c4487182 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 11 Nov 2021 16:25:14 +0530 Subject: [PATCH 067/242] Use undefined instead of null --- src/logging/LogFilter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/logging/LogFilter.ts b/src/logging/LogFilter.ts index 476bca0e..4da7d457 100644 --- a/src/logging/LogFilter.ts +++ b/src/logging/LogFilter.ts @@ -30,7 +30,7 @@ export enum LogLevel { export type LogLevelOrNull = LogLevel | null; export class LogFilter { - private _min: LogLevelOrNull = null; + private _min?: LogLevel; private _parentFilter?: LogFilter; constructor(parentFilter?: LogFilter) { @@ -44,7 +44,7 @@ export class LogFilter { } } // neither our children or us have a loglevel high enough, filter out. - if (this._min !== null && !Array.isArray(children) && item.logLevel < this._min) { + if (this._min && !Array.isArray(children) && item.logLevel < this._min) { return false; } else { return true; From 2ddd2d16ed72b449236f1d25fbf834e8aa5ac979 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 11 Nov 2021 16:50:46 +0530 Subject: [PATCH 068/242] IDBLogger.js --> IDBLogger.ts --- src/logging/{IDBLogger.js => IDBLogger.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/logging/{IDBLogger.js => IDBLogger.ts} (100%) diff --git a/src/logging/IDBLogger.js b/src/logging/IDBLogger.ts similarity index 100% rename from src/logging/IDBLogger.js rename to src/logging/IDBLogger.ts From f3d0f88f957a88bd2ecc48907e4ed558a2328c38 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 12 Nov 2021 15:06:11 +0530 Subject: [PATCH 069/242] Make error public --- src/logging/LogItem.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 4289aafc..64ed6603 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -50,7 +50,7 @@ export type LogCallback = (item: LogItem) => unknown; export class LogItem { public readonly start: number; public logLevel: LogLevel; - private _error: Error | null; + public error: Error | null; public end: number | null; private _values: LogItemValues; private _logger: BaseLogger; @@ -63,7 +63,7 @@ export class LogItem { this.end = null; // (l)abel this._values = typeof labelOrValues === "string" ? {l: labelOrValues} : labelOrValues; - this._error = null; + this.error = null; this.logLevel = logLevel; this._children = null; this._filterCreator = filterCreator; @@ -182,12 +182,12 @@ export class LogItem { // (l)evel l: this.logLevel }; - if (this._error) { + if (this.error) { // (e)rror item.e = { - stack: this._error.stack, - name: this._error.name, - message: this._error.message.split("\n")[0] + stack: this.error.stack, + name: this.error.name, + message: this.error.message.split("\n")[0] }; } if (forced) { @@ -257,7 +257,7 @@ export class LogItem { } catch(err: Error) { - this._error = err; + this.error = err; this.logLevel = LogLevel.Error; this.finish(); return err; @@ -281,8 +281,4 @@ export class LogItem { get logger() { return this._logger; } - - get error() { - return this._error; - } } From 8c7a765e1114762a65be741407e16613e5012877 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 12 Nov 2021 15:06:21 +0530 Subject: [PATCH 070/242] Convert IDBLogger to ts --- src/logging/IDBLogger.ts | 25 +++++++++++++++++++++---- src/platform/web/Platform.js | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index 2360b54c..93ba9549 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -23,8 +23,21 @@ import { fetchResults, } from "../matrix/storage/idb/utils"; 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"; + +type QueuedItem = { + json: string; + id?: number; +} export class IDBLogger extends BaseLogger { + private readonly _name: string; + private readonly _limit: number; + private readonly _flushInterval: Interval; + private _queuedItems: QueuedItem[]; + constructor(options) { super(options); const {name, flushInterval = 60 * 1000, limit = 3000} = options; @@ -121,7 +134,7 @@ export class IDBLogger extends BaseLogger { try { const txn = db.transaction(["logs"], "readonly"); const logs = txn.objectStore("logs"); - const storedItems = await fetchResults(logs.openCursor(), () => false); + const storedItems: QueuedItem[] = await fetchResults(logs.openCursor(), () => false); const allItems = storedItems.concat(this._queuedItems); return new IDBLogExport(allItems, this, this._platform); } finally { @@ -154,7 +167,11 @@ export class IDBLogger extends BaseLogger { } class IDBLogExport { - constructor(items, logger, platform) { + private readonly _items: QueuedItem[]; + private readonly _logger: IDBLogger; + private readonly _platform: Platform; + + constructor(items: QueuedItem[], logger: IDBLogger, platform: Platform) { this._items = items; this._logger = logger; this._platform = platform; @@ -171,7 +188,7 @@ class IDBLogExport { return this._logger._removeItems(this._items); } - asBlob() { + asBlob(): BlobHandle { const log = { formatVersion: 1, appVersion: this._platform.updateService?.version, @@ -179,7 +196,7 @@ class IDBLogExport { }; const json = JSON.stringify(log); const buffer = this._platform.encoding.utf8.encode(json); - const blob = this._platform.createBlob(buffer, "application/json"); + const blob: BlobHandle = this._platform.createBlob(buffer, "application/json"); return blob; } } diff --git a/src/platform/web/Platform.js b/src/platform/web/Platform.js index 1530ed12..63cbac2e 100644 --- a/src/platform/web/Platform.js +++ b/src/platform/web/Platform.js @@ -21,7 +21,7 @@ import {SessionInfoStorage} from "../../matrix/sessioninfo/localstorage/SessionI import {SettingsStorage} from "./dom/SettingsStorage.js"; import {Encoding} from "./utils/Encoding.js"; import {OlmWorker} from "../../matrix/e2ee/OlmWorker.js"; -import {IDBLogger} from "../../logging/IDBLogger.js"; +import {IDBLogger} from "../../logging/IDBLogger"; import {ConsoleLogger} from "../../logging/ConsoleLogger.js"; import {RootView} from "./ui/RootView.js"; import {Clock} from "./dom/Clock.js"; From 29a826051475f61ea945fb5500eda4a12b280c26 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 12 Nov 2021 23:12:15 +0530 Subject: [PATCH 071/242] Add explicit types for return in methods --- src/logging/LogItem.ts | 35 +++++++++++++----------- src/matrix/storage/idb/StorageFactory.ts | 2 +- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 64ed6603..2909a84e 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -21,7 +21,7 @@ import type {BaseLogger} from "./BaseLogger"; interface ISerializedItem { s: number; - d: number | null; + d?: number; v: LogItemValues; l: LogLevel; e?: { @@ -70,7 +70,7 @@ export class LogItem { } /** start a new root log item and run it detached mode, see BaseLogger.runDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator) { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): LogItem { return this._logger.runDetached(labelOrValues, callback, logLevel, filterCreator); } @@ -83,7 +83,7 @@ export class LogItem { This is useful if the referenced operation can't be awaited. */ refDetached(logItem: LogItem, logLevel: LogLevelOrNull = null) { logItem.ensureRefId(); - return this.log({ref: logItem._values.refId as number}, logLevel); + this.log({ref: logItem._values.refId as number}, logLevel); } ensureRefId() { @@ -100,27 +100,30 @@ export class LogItem { return item.run(callback); } - get duration() { + get duration(): number | undefined{ if (this.end) { return this.end - this.start; } else { - return null; + return undefined; } } - durationWithoutType(type: string) { - if (this.duration) { - return this.duration - this.durationOfType(type); + durationWithoutType(type: string): number | undefined{ + const durationOfType = this.durationOfType(type); + if (this.duration && durationOfType) { + return this.duration - durationOfType; } - return null; } - durationOfType(type: string) { + durationOfType(type: string): number | undefined { if (this._values.t === type) { return this.duration; } else if (this._children) { return this._children.reduce((sum, c) => { - return sum + c.durationOfType(type); + const duration = c.durationOfType(type); + if (duration) { + return sum + duration; + } }, 0); } else { return 0; @@ -213,11 +216,11 @@ export class LogItem { * @param {Function} callback [description] * @return {[type]} [description] */ - run(callback: LogCallback) { + run(callback: LogCallback): unknown { if (this.end !== null) { console.trace("log item is finished, additional logs will likely not be recorded"); } - let result; + let result: unknown; try { result = callback(this); if (result instanceof Promise) { @@ -252,18 +255,18 @@ export class LogItem { } // expose log level without needing import everywhere - get level() { + get level(): typeof LogLevel { return LogLevel; } - catch(err: Error) { + catch(err: Error): Error { this.error = err; this.logLevel = LogLevel.Error; this.finish(); return err; } - child(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull, filterCreator: FilterCreator) { + child(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull, filterCreator: FilterCreator): LogItem { if (this.end !== null) { console.trace("log item is finished, additional logs will likely not be recorded"); } diff --git a/src/matrix/storage/idb/StorageFactory.ts b/src/matrix/storage/idb/StorageFactory.ts index 71201842..4ae55612 100644 --- a/src/matrix/storage/idb/StorageFactory.ts +++ b/src/matrix/storage/idb/StorageFactory.ts @@ -101,5 +101,5 @@ async function createStores(db: IDBDatabase, txn: IDBTransaction, oldVersion: nu const migrationFunc = schema[i]; await log.wrap(`v${i + 1}`, log => migrationFunc(db, txn, localStorage, log)); } - }); + }) as Promise; } From 8e42e3f21f23a85c65893a47a9868ccaedc67277 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 12 Nov 2021 23:17:21 +0530 Subject: [PATCH 072/242] Add types to returns in LogFilter.ts --- src/logging/LogFilter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/logging/LogFilter.ts b/src/logging/LogFilter.ts index 4da7d457..480e92db 100644 --- a/src/logging/LogFilter.ts +++ b/src/logging/LogFilter.ts @@ -37,7 +37,7 @@ export class LogFilter { this._parentFilter = parentFilter; } - filter(item: LogItem, children: Array | null) { + filter(item: LogItem, children: Array | null): boolean { if (this._parentFilter) { if (!this._parentFilter.filter(item, children)) { return false; @@ -52,7 +52,7 @@ export class LogFilter { } /* methods to build the filter */ - minLevel(logLevel: LogLevel) { + minLevel(logLevel: LogLevel): LogFilter { this._min = logLevel; return this; } From 67e8fc0c43ea2ed1508a0a4b3d751a4f9248c143 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 12 Nov 2021 23:27:25 +0530 Subject: [PATCH 073/242] Add return types to methods in BaseLogger --- src/logging/BaseLogger.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 259c47eb..9865355a 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -38,7 +38,7 @@ export abstract class BaseLogger { } /** if item is a log item, wrap the callback in a child of it, otherwise start a new root log item. */ - wrapOrRun(item: LogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null) { + wrapOrRun(item: LogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): unknown { if (item) { return item.wrap(labelOrValues, callback, logLevel, filterCreator); } else { @@ -51,7 +51,8 @@ export abstract class BaseLogger { Useful to pair with LogItem.refDetached. @return {LogItem} the log item added, useful to pass to LogItem.refDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null) { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): LogItem { + // todo: Remove jsdoc type? if (logLevel === null) { logLevel = LogLevel.Info; } @@ -63,7 +64,7 @@ export abstract class BaseLogger { /** run a callback wrapped in a log operation. Errors and duration are transparently logged, also for async operations. Whatever the callback returns is returned here. */ - run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null) { + run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): unknown { if (logLevel === null) { logLevel = LogLevel.Info; } @@ -71,7 +72,7 @@ export abstract class BaseLogger { return this._run(item, callback, logLevel!, filterCreator, true); } - _run(item: LogItem, callback: LogCallback, logLevel: LogLevel, filterCreator: FilterCreator, shouldThrow: boolean) { + _run(item: LogItem, callback: LogCallback, logLevel: LogLevel, filterCreator: FilterCreator, shouldThrow: boolean): unknown { this._openItems.add(item); const finishItem = () => { @@ -139,7 +140,7 @@ export abstract class BaseLogger { abstract export(): void; // expose log level without needing - get level() { + get level(): typeof LogLevel { return LogLevel; } @@ -147,7 +148,7 @@ export abstract class BaseLogger { return this._platform.clock.now(); } - _createRefId() { + _createRefId(): number { return Math.round(this._platform.random() * Number.MAX_SAFE_INTEGER); } } From 5efa27c2a3c2297885b99bdeb14ac60c8bd5d5be Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sun, 14 Nov 2021 15:48:59 +0530 Subject: [PATCH 074/242] Add more type annotations --- src/logging/IDBLogger.ts | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index 93ba9549..2ef5b551 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -26,6 +26,8 @@ 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 {LogItem} from "./LogItem"; +import type {LogFilter} from "./LogFilter"; type QueuedItem = { json: string; @@ -54,7 +56,7 @@ export class IDBLogger extends BaseLogger { this._flushInterval.dispose(); } - handleEvent(evt) { + handleEvent(evt: Event) { if (evt.type === "pagehide") { this._finishAllAndFlush(); } @@ -96,7 +98,7 @@ export class IDBLogger extends BaseLogger { this._persistQueuedItems(this._queuedItems); } - _loadQueuedItems() { + _loadQueuedItems(): QueuedItem[] { const key = `${this._name}_queuedItems`; try { const json = window.localStorage.getItem(key); @@ -110,18 +112,18 @@ export class IDBLogger extends BaseLogger { return []; } - _openDB() { + _openDB(): Promise { return openDatabase(this._name, db => db.createObjectStore("logs", {keyPath: "id", autoIncrement: true}), 1); } - _persistItem(logItem, filter, forced) { - const serializedItem = logItem.serialize(filter, forced); + _persistItem(logItem: LogItem, filter: LogFilter, forced: boolean) { + const serializedItem = logItem.serialize(filter, undefined, forced); this._queuedItems.push({ json: JSON.stringify(serializedItem) }); } - _persistQueuedItems(items) { + _persistQueuedItems(items: QueuedItem[]) { try { window.localStorage.setItem(`${this._name}_queuedItems`, JSON.stringify(items)); } catch (e) { @@ -129,7 +131,7 @@ export class IDBLogger extends BaseLogger { } } - async export() { + async export(): Promise { const db = await this._openDB(); try { const txn = db.transaction(["logs"], "readonly"); @@ -144,7 +146,7 @@ export class IDBLogger extends BaseLogger { } } - async _removeItems(items) { + async _removeItems(items: QueuedItem[]) { const db = await this._openDB(); try { const txn = db.transaction(["logs"], "readwrite"); @@ -177,7 +179,7 @@ class IDBLogExport { this._platform = platform; } - get count() { + get count(): number { return this._items.length; } @@ -195,7 +197,7 @@ class IDBLogExport { items: this._items.map(i => JSON.parse(i.json)) }; const json = JSON.stringify(log); - const buffer = this._platform.encoding.utf8.encode(json); + const buffer: Uint8Array = this._platform.encoding.utf8.encode(json); const blob: BlobHandle = this._platform.createBlob(buffer, "application/json"); return blob; } From 2d8b719ab0a5be648e5d29e6e228b4a538f9f64b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sun, 14 Nov 2021 15:55:42 +0530 Subject: [PATCH 075/242] Add void return types as well --- src/logging/IDBLogger.ts | 16 ++++++++-------- src/logging/LogItem.ts | 17 +++++++++-------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index 2ef5b551..4f6301ce 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -51,18 +51,18 @@ export class IDBLogger extends BaseLogger { this._flushInterval = this._platform.clock.createInterval(() => this._tryFlush(), flushInterval); } - dispose() { + dispose(): void { window.removeEventListener("pagehide", this, false); this._flushInterval.dispose(); } - handleEvent(evt: Event) { + handleEvent(evt: Event): void { if (evt.type === "pagehide") { this._finishAllAndFlush(); } } - async _tryFlush() { + async _tryFlush(): Promise { const db = await this._openDB(); try { const txn = db.transaction(["logs"], "readwrite"); @@ -92,7 +92,7 @@ export class IDBLogger extends BaseLogger { } } - _finishAllAndFlush() { + _finishAllAndFlush(): void { this._finishOpenItems(); this.log({l: "pagehide, closing logs", t: "navigation"}); this._persistQueuedItems(this._queuedItems); @@ -116,14 +116,14 @@ export class IDBLogger extends BaseLogger { return openDatabase(this._name, db => db.createObjectStore("logs", {keyPath: "id", autoIncrement: true}), 1); } - _persistItem(logItem: LogItem, filter: LogFilter, forced: boolean) { + _persistItem(logItem: LogItem, filter: LogFilter, forced: boolean): void { const serializedItem = logItem.serialize(filter, undefined, forced); this._queuedItems.push({ json: JSON.stringify(serializedItem) }); } - _persistQueuedItems(items: QueuedItem[]) { + _persistQueuedItems(items: QueuedItem[]): void { try { window.localStorage.setItem(`${this._name}_queuedItems`, JSON.stringify(items)); } catch (e) { @@ -146,7 +146,7 @@ export class IDBLogger extends BaseLogger { } } - async _removeItems(items: QueuedItem[]) { + async _removeItems(items: QueuedItem[]): Promise { const db = await this._openDB(); try { const txn = db.transaction(["logs"], "readwrite"); @@ -186,7 +186,7 @@ class IDBLogExport { /** * @return {Promise} */ - removeFromStore() { + removeFromStore(): Promise { return this._logger._removeItems(this._items); } diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 2909a84e..716a3e73 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -75,18 +75,18 @@ export class LogItem { } /** start a new detached root log item and log a reference to it from this item */ - wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator) { + wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): void { this.refDetached(this.runDetached(labelOrValues, callback, logLevel, filterCreator)); } /** logs a reference to a different log item, usually obtained from runDetached. This is useful if the referenced operation can't be awaited. */ - refDetached(logItem: LogItem, logLevel: LogLevelOrNull = null) { + refDetached(logItem: LogItem, logLevel: LogLevelOrNull = null): void { logItem.ensureRefId(); this.log({ref: logItem._values.refId as number}, logLevel); } - ensureRefId() { + ensureRefId(): void { if (!this._values.refId) { this.set("refId", this._logger._createRefId()); } @@ -95,7 +95,7 @@ export class LogItem { /** * Creates a new child item and runs it in `callback`. */ - wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null) { + wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): unknown { const item = this.child(labelOrValues, logLevel, filterCreator); return item.run(callback); } @@ -136,12 +136,12 @@ export class LogItem { * * Hence, the child item is not returned. */ - log(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull = null) { + log(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull = null): void { const item = this.child(labelOrValues, logLevel, null); item.end = item.start; } - set(key: string | object, value: unknown) { + set(key: string | object, value: unknown): void { if(typeof key === "object") { const values = key; Object.assign(this._values, values); @@ -150,6 +150,7 @@ export class LogItem { } } + // todo: null or undefined here? serialize(filter: LogFilter, parentStartTime: number | null = null, forced: boolean): ISerializedItem | null { if (this._filterCreator) { try { @@ -243,7 +244,7 @@ export class LogItem { * finished the item, recording the end time. After finishing, an item can't be modified anymore as it will be persisted. * @internal shouldn't typically be called by hand. allows to force finish if a promise is still running when closing the app */ - finish() { + finish(): void { if (this.end === null) { if (this._children !== null) { for(const c of this._children) { @@ -281,7 +282,7 @@ export class LogItem { return item; } - get logger() { + get logger(): BaseLogger { return this._logger; } } From 39d0708cca6c8fcbb9e91e398b1eaf0030e1488f Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sun, 14 Nov 2021 15:58:51 +0530 Subject: [PATCH 076/242] Add comment --- src/logging/IDBLogger.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index 4f6301ce..3283dd0d 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -154,7 +154,8 @@ export class IDBLogger extends BaseLogger { for (const item of items) { const queuedIdx = this._queuedItems.findIndex(i => i.id === item.id); if (queuedIdx === -1) { - logs.delete(item.id); + // todo: isn't id optional? do we need further checks here + logs.delete(item.id!); // resolve questionable use of non-null assertion operator? } else { this._queuedItems.splice(queuedIdx, 1); } From bba44abf529f665ad47e94e56d90c47fe96fba97 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sun, 14 Nov 2021 16:24:16 +0530 Subject: [PATCH 077/242] Convert console logger to ts --- .../{ConsoleLogger.js => ConsoleLogger.ts} | 44 ++++++++++--------- src/logging/LogItem.ts | 10 ++++- 2 files changed, 32 insertions(+), 22 deletions(-) rename src/logging/{ConsoleLogger.js => ConsoleLogger.ts} (58%) diff --git a/src/logging/ConsoleLogger.js b/src/logging/ConsoleLogger.ts similarity index 58% rename from src/logging/ConsoleLogger.js rename to src/logging/ConsoleLogger.ts index 4d3be73b..5b709bb1 100644 --- a/src/logging/ConsoleLogger.js +++ b/src/logging/ConsoleLogger.ts @@ -14,35 +14,37 @@ See the License for the specific language governing permissions and limitations under the License. */ import {BaseLogger} from "./BaseLogger"; +import type {LogItem, LogItemValues} from "./LogItem"; export class ConsoleLogger extends BaseLogger { - _persistItem(item) { + _persistItem(item: LogItem): void { printToConsole(item); } - export() { + export(): void { throw new Error("Cannot export from ConsoleLogger"); } } const excludedKeysFromTable = ["l", "id"]; -function filterValues(values) { +function filterValues(values: LogItemValues): LogItemValues | null { if (!values) { + // todo: is this check here unnecessary because LogItem will always have values? return null; } return Object.entries(values) .filter(([key]) => !excludedKeysFromTable.includes(key)) - .reduce((obj, [key, value]) => { + .reduce((obj: LogItemValues, [key, value]) => { obj = obj || {}; obj[key] = value; return obj; }, null); } -function printToConsole(item) { +function printToConsole(item: LogItem): void { const label = `${itemCaption(item)} (${item.duration}ms)`; - const filteredValues = filterValues(item._values); - const shouldGroup = item._children || filteredValues; + const filteredValues = filterValues(item.values); + const shouldGroup = item.children || filteredValues; if (shouldGroup) { if (item.error) { console.group(label); @@ -62,8 +64,8 @@ function printToConsole(item) { if (filteredValues) { console.table(filteredValues); } - if (item._children) { - for(const c of item._children) { + if (item.children) { + for(const c of item.children) { printToConsole(c); } } @@ -72,18 +74,18 @@ function printToConsole(item) { } } -function itemCaption(item) { - if (item._values.t === "network") { - return `${item._values.method} ${item._values.url}`; - } else if (item._values.l && typeof item._values.id !== "undefined") { - return `${item._values.l} ${item._values.id}`; - } else if (item._values.l && typeof item._values.status !== "undefined") { - return `${item._values.l} (${item._values.status})`; - } else if (item._values.l && item.error) { - return `${item._values.l} failed`; - } else if (typeof item._values.ref !== "undefined") { - return `ref ${item._values.ref}`; +function itemCaption(item: LogItem): string { + if (item.values.t === "network") { + return `${item.values.method} ${item.values.url}`; + } else if (item.values.l && typeof item.values.id !== "undefined") { + return `${item.values.l} ${item.values.id}`; + } else if (item.values.l && typeof item.values.status !== "undefined") { + return `${item.values.l} (${item.values.status})`; + } else if (item.values.l && item.error) { + return `${item.values.l} failed`; + } else if (typeof item.values.ref !== "undefined") { + return `ref ${item.values.ref}`; } else { - return item._values.l || item._values.type; + return item.values.l || item.values.type; } } diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 716a3e73..051b0353 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -33,7 +33,7 @@ interface ISerializedItem { c?: Array; }; -type LogItemValues = { +export type LogItemValues = { l?: string; t?: string; id?: unknown; @@ -285,4 +285,12 @@ export class LogItem { get logger(): BaseLogger { return this._logger; } + + get values(): LogItemValues { + return this._values; + } + + get children(): Array | null { + return this._children; + } } From a7d059b3ed304269296500e6997507b0a3b9ed3e Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sun, 14 Nov 2021 19:42:18 +0530 Subject: [PATCH 078/242] Fix imports --- src/matrix/storage/idb/QueryTarget.ts | 2 +- src/matrix/storage/idb/Storage.ts | 2 +- src/matrix/storage/idb/StorageFactory.ts | 4 ++-- src/matrix/storage/idb/Store.ts | 2 +- src/matrix/storage/idb/Transaction.ts | 4 ++-- src/matrix/storage/idb/schema.ts | 2 +- src/matrix/storage/idb/stores/SessionStore.ts | 2 +- src/matrix/storage/idb/stores/TimelineEventStore.ts | 2 +- src/platform/web/Platform.js | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/matrix/storage/idb/QueryTarget.ts b/src/matrix/storage/idb/QueryTarget.ts index 01f46e1a..03fe66bc 100644 --- a/src/matrix/storage/idb/QueryTarget.ts +++ b/src/matrix/storage/idb/QueryTarget.ts @@ -16,7 +16,7 @@ limitations under the License. import {iterateCursor, DONE, NOT_DONE, reqAsPromise} from "./utils"; import {StorageError} from "../common"; -import {LogItem} from "../../../logging/LogItem.js"; +import {LogItem} from "../../../logging/LogItem"; import {IDBKey} from "./Transaction"; // this is the part of the Transaction class API that is used here and in the Store subclass, diff --git a/src/matrix/storage/idb/Storage.ts b/src/matrix/storage/idb/Storage.ts index 53ee7bc0..728d4fca 100644 --- a/src/matrix/storage/idb/Storage.ts +++ b/src/matrix/storage/idb/Storage.ts @@ -18,7 +18,7 @@ import {IDOMStorage} from "./types"; import {Transaction} from "./Transaction"; import { STORE_NAMES, StoreNames, StorageError } from "../common"; import { reqAsPromise } from "./utils"; -import { BaseLogger } from "../../../logging/BaseLogger.js"; +import { BaseLogger } from "../../../logging/BaseLogger"; const WEBKITEARLYCLOSETXNBUG_BOGUS_KEY = "782rh281re38-boguskey"; diff --git a/src/matrix/storage/idb/StorageFactory.ts b/src/matrix/storage/idb/StorageFactory.ts index 4ae55612..f8cc192d 100644 --- a/src/matrix/storage/idb/StorageFactory.ts +++ b/src/matrix/storage/idb/StorageFactory.ts @@ -20,8 +20,8 @@ import { openDatabase, reqAsPromise } from "./utils"; import { exportSession, importSession, Export } from "./export"; import { schema } from "./schema"; import { detectWebkitEarlyCloseTxnBug } from "./quirks"; -import { BaseLogger } from "../../../logging/BaseLogger.js"; -import { LogItem } from "../../../logging/LogItem.js"; +import { BaseLogger } from "../../../logging/BaseLogger"; +import { LogItem } from "../../../logging/LogItem"; const sessionName = (sessionId: string) => `hydrogen_session_${sessionId}`; const openDatabaseWithSessionId = function(sessionId: string, idbFactory: IDBFactory, localStorage: IDOMStorage, log: LogItem) { diff --git a/src/matrix/storage/idb/Store.ts b/src/matrix/storage/idb/Store.ts index a4c80426..74de2afa 100644 --- a/src/matrix/storage/idb/Store.ts +++ b/src/matrix/storage/idb/Store.ts @@ -18,7 +18,7 @@ import {QueryTarget, IDBQuery, ITransaction} from "./QueryTarget"; import {IDBRequestError, IDBRequestAttemptError} from "./error"; import {reqAsPromise} from "./utils"; import {Transaction, IDBKey} from "./Transaction"; -import {LogItem} from "../../../logging/LogItem.js"; +import {LogItem} from "../../../logging/LogItem"; const LOG_REQUESTS = false; diff --git a/src/matrix/storage/idb/Transaction.ts b/src/matrix/storage/idb/Transaction.ts index 3bc4aed2..0d9e55a5 100644 --- a/src/matrix/storage/idb/Transaction.ts +++ b/src/matrix/storage/idb/Transaction.ts @@ -36,8 +36,8 @@ import {OutboundGroupSessionStore} from "./stores/OutboundGroupSessionStore"; import {GroupSessionDecryptionStore} from "./stores/GroupSessionDecryptionStore"; import {OperationStore} from "./stores/OperationStore"; import {AccountDataStore} from "./stores/AccountDataStore"; -import {LogItem} from "../../../logging/LogItem.js"; -import {BaseLogger} from "../../../logging/BaseLogger.js"; +import {LogItem} from "../../../logging/LogItem"; +import {BaseLogger} from "../../../logging/BaseLogger"; export type IDBKey = IDBValidKey | IDBKeyRange; diff --git a/src/matrix/storage/idb/schema.ts b/src/matrix/storage/idb/schema.ts index cd22d803..a9c4e2e4 100644 --- a/src/matrix/storage/idb/schema.ts +++ b/src/matrix/storage/idb/schema.ts @@ -11,7 +11,7 @@ import {SessionStore} from "./stores/SessionStore"; import {Store} from "./Store"; import {encodeScopeTypeKey} from "./stores/OperationStore"; import {MAX_UNICODE} from "./stores/common"; -import {LogItem} from "../../../logging/LogItem.js"; +import {LogItem} from "../../../logging/LogItem"; export type MigrationFunc = (db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: LogItem) => Promise | void; diff --git a/src/matrix/storage/idb/stores/SessionStore.ts b/src/matrix/storage/idb/stores/SessionStore.ts index 785835b8..6bf87e9b 100644 --- a/src/matrix/storage/idb/stores/SessionStore.ts +++ b/src/matrix/storage/idb/stores/SessionStore.ts @@ -16,7 +16,7 @@ limitations under the License. import {Store} from "../Store"; import {IDOMStorage} from "../types"; import {SESSION_E2EE_KEY_PREFIX} from "../../../e2ee/common.js"; -import {LogItem} from "../../../../logging/LogItem.js"; +import {LogItem} from "../../../../logging/LogItem"; import {parse, stringify} from "../../../../utils/typedJSON"; export interface SessionEntry { diff --git a/src/matrix/storage/idb/stores/TimelineEventStore.ts b/src/matrix/storage/idb/stores/TimelineEventStore.ts index 2087a39f..3c101701 100644 --- a/src/matrix/storage/idb/stores/TimelineEventStore.ts +++ b/src/matrix/storage/idb/stores/TimelineEventStore.ts @@ -20,7 +20,7 @@ import { encodeUint32, decodeUint32 } from "../utils"; import {KeyLimits} from "../../common"; import {Store} from "../Store"; import {TimelineEvent, StateEvent} from "../../types"; -import {LogItem} from "../../../../logging/LogItem.js"; +import {LogItem} from "../../../../logging/LogItem"; interface Annotation { count: number; diff --git a/src/platform/web/Platform.js b/src/platform/web/Platform.js index 63cbac2e..f6cd2895 100644 --- a/src/platform/web/Platform.js +++ b/src/platform/web/Platform.js @@ -22,7 +22,7 @@ import {SettingsStorage} from "./dom/SettingsStorage.js"; import {Encoding} from "./utils/Encoding.js"; import {OlmWorker} from "../../matrix/e2ee/OlmWorker.js"; import {IDBLogger} from "../../logging/IDBLogger"; -import {ConsoleLogger} from "../../logging/ConsoleLogger.js"; +import {ConsoleLogger} from "../../logging/ConsoleLogger"; import {RootView} from "./ui/RootView.js"; import {Clock} from "./dom/Clock.js"; import {ServiceWorkerHandler} from "./dom/ServiceWorkerHandler.js"; From 520e0f1b892299f98d31a6f05157d4b5d82afdb6 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 15 Nov 2021 17:29:08 +0530 Subject: [PATCH 079/242] Use interface ILogItem --- .../room/timeline/ReactionsViewModel.js | 2 +- src/logging/BaseLogger.ts | 12 +-- src/logging/ConsoleLogger.ts | 8 +- src/logging/IDBLogger.ts | 6 +- src/logging/LogFilter.ts | 4 +- src/logging/LogItem.ts | 38 ++++++-- src/logging/{NullLogger.js => NullLogger.ts} | 90 ++++++++++--------- src/logging/utils.js | 2 +- src/matrix/e2ee/megolm/Decryption.ts | 6 +- src/matrix/room/Invite.js | 2 +- src/matrix/room/sending/SendQueue.js | 2 +- src/matrix/room/timeline/Timeline.js | 2 +- .../room/timeline/persistence/GapWriter.js | 2 +- .../timeline/persistence/RelationWriter.js | 2 +- .../room/timeline/persistence/SyncWriter.js | 2 +- src/matrix/storage/idb/QueryTarget.ts | 6 +- src/matrix/storage/idb/StorageFactory.ts | 31 ++++--- src/matrix/storage/idb/Store.ts | 12 +-- src/matrix/storage/idb/Transaction.ts | 14 +-- src/matrix/storage/idb/schema.ts | 12 +-- src/matrix/storage/idb/stores/SessionStore.ts | 4 +- .../storage/idb/stores/TimelineEventStore.ts | 8 +- src/mocks/Storage.ts | 2 +- 23 files changed, 155 insertions(+), 114 deletions(-) rename src/logging/{NullLogger.js => NullLogger.ts} (57%) diff --git a/src/domain/session/room/timeline/ReactionsViewModel.js b/src/domain/session/room/timeline/ReactionsViewModel.js index 25d74b49..3a47aaa0 100644 --- a/src/domain/session/room/timeline/ReactionsViewModel.js +++ b/src/domain/session/room/timeline/ReactionsViewModel.js @@ -184,7 +184,7 @@ import {Clock as MockClock} from "../../../../mocks/Clock.js"; import {createMockStorage} from "../../../../mocks/Storage"; import {ListObserver} from "../../../../mocks/ListObserver.js"; import {createEvent, withTextBody, withContent} from "../../../../mocks/event.js"; -import {NullLogItem, NullLogger} from "../../../../logging/NullLogger.js"; +import {NullLogItem, NullLogger} from "../../../../logging/NullLogger"; import {HomeServer as MockHomeServer} from "../../../../mocks/HomeServer.js"; // other imports import {BaseMessageTile} from "./tiles/BaseMessageTile.js"; diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 9865355a..e420c0df 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -17,14 +17,14 @@ limitations under the License. import {LogItem} from "./LogItem"; import {LogLevel, LogFilter} from "./LogFilter"; -import type {FilterCreator, LabelOrValues, LogCallback} from "./LogItem"; +import type {FilterCreator, LabelOrValues, LogCallback, ILogItem} from "./LogItem"; import type {LogLevelOrNull} from "./LogFilter"; // todo: should this import be here just for getting the type? should it instead be done when Platform.js --> Platform.ts? import type {Platform} from "../platform/web/Platform.js"; export abstract class BaseLogger { - protected _openItems: Set = new Set(); + protected _openItems: Set = new Set(); protected _platform: Platform; constructor({platform}) { @@ -38,7 +38,7 @@ export abstract class BaseLogger { } /** if item is a log item, wrap the callback in a child of it, otherwise start a new root log item. */ - wrapOrRun(item: LogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): unknown { + wrapOrRun(item: ILogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): unknown { if (item) { return item.wrap(labelOrValues, callback, logLevel, filterCreator); } else { @@ -51,7 +51,7 @@ export abstract class BaseLogger { Useful to pair with LogItem.refDetached. @return {LogItem} the log item added, useful to pass to LogItem.refDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): LogItem { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): ILogItem { // todo: Remove jsdoc type? if (logLevel === null) { logLevel = LogLevel.Info; @@ -72,7 +72,7 @@ export abstract class BaseLogger { return this._run(item, callback, logLevel!, filterCreator, true); } - _run(item: LogItem, callback: LogCallback, logLevel: LogLevel, filterCreator: FilterCreator, shouldThrow: boolean): unknown { + _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, filterCreator: FilterCreator, shouldThrow: boolean): unknown { this._openItems.add(item); const finishItem = () => { @@ -135,7 +135,7 @@ export abstract class BaseLogger { this._openItems.clear(); } - abstract _persistItem(item: LogItem, filter?: LogFilter, forced?: boolean): void; + abstract _persistItem(item: ILogItem, filter?: LogFilter, forced?: boolean): void; abstract export(): void; diff --git a/src/logging/ConsoleLogger.ts b/src/logging/ConsoleLogger.ts index 5b709bb1..d8693e38 100644 --- a/src/logging/ConsoleLogger.ts +++ b/src/logging/ConsoleLogger.ts @@ -14,10 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ import {BaseLogger} from "./BaseLogger"; -import type {LogItem, LogItemValues} from "./LogItem"; +import type {ILogItem, LogItemValues} from "./LogItem"; export class ConsoleLogger extends BaseLogger { - _persistItem(item: LogItem): void { + _persistItem(item: ILogItem): void { printToConsole(item); } @@ -41,7 +41,7 @@ function filterValues(values: LogItemValues): LogItemValues | null { }, null); } -function printToConsole(item: LogItem): void { +function printToConsole(item: ILogItem): void { const label = `${itemCaption(item)} (${item.duration}ms)`; const filteredValues = filterValues(item.values); const shouldGroup = item.children || filteredValues; @@ -74,7 +74,7 @@ function printToConsole(item: LogItem): void { } } -function itemCaption(item: LogItem): string { +function itemCaption(item: ILogItem): string { if (item.values.t === "network") { return `${item.values.method} ${item.values.url}`; } else if (item.values.l && typeof item.values.id !== "undefined") { diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index 3283dd0d..960db0da 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 {LogItem} from "./LogItem"; +import type {ILogItem} from "./LogItem"; import type {LogFilter} from "./LogFilter"; type QueuedItem = { @@ -116,8 +116,8 @@ export class IDBLogger extends BaseLogger { return openDatabase(this._name, db => db.createObjectStore("logs", {keyPath: "id", autoIncrement: true}), 1); } - _persistItem(logItem: LogItem, filter: LogFilter, forced: boolean): void { - const serializedItem = logItem.serialize(filter, undefined, forced); + _persistItem(logItem: ILogItem, filter: LogFilter, forced: boolean): void { + const serializedItem = logItem.serialize(filter, null, forced); this._queuedItems.push({ json: JSON.stringify(serializedItem) }); diff --git a/src/logging/LogFilter.ts b/src/logging/LogFilter.ts index 480e92db..dc415ede 100644 --- a/src/logging/LogFilter.ts +++ b/src/logging/LogFilter.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type {LogItem} from "./LogItem"; +import type {ILogItem} from "./LogItem"; export enum LogLevel { All = 1, @@ -37,7 +37,7 @@ export class LogFilter { this._parentFilter = parentFilter; } - filter(item: LogItem, children: Array | null): boolean { + filter(item: ILogItem, children: Array | null): boolean { if (this._parentFilter) { if (!this._parentFilter.filter(item, children)) { return false; diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 051b0353..54957347 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -33,6 +33,30 @@ interface ISerializedItem { c?: Array; }; +export interface ILogItem { + logger: any; + level: typeof LogLevel; + duration?: number; + end?: number | null; + start?: number; + logLevel: LogLevel; + children: Array | null; + values: LogItemValues; + error: Error | null; + wrap(labelOrValues: LabelOrValues, callback: LogCallback, level: LogLevelOrNull, filterCreator: FilterCreator): unknown; + log(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull): void; + set(key: string | object, value: unknown): void; + run(callback: LogCallback): unknown; + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): ILogItem; + wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): void; + refDetached(logItem: ILogItem, logLevel: LogLevelOrNull): void; + ensureRefId(): void; + catch(err: Error): Error; + finish(): void; + child(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull, filterCreator: FilterCreator): ILogItem; + serialize(filter: LogFilter, parentStartTime: number | null, forced: boolean): ISerializedItem | null; +} + export type LogItemValues = { l?: string; t?: string; @@ -44,10 +68,10 @@ export type LogItemValues = { } export type LabelOrValues = string | LogItemValues; -export type FilterCreator = ((filter: LogFilter, item: LogItem) => LogFilter) | null; -export type LogCallback = (item: LogItem) => unknown; +export type FilterCreator = ((filter: LogFilter, item: ILogItem) => LogFilter) | null; +export type LogCallback = (item: ILogItem) => unknown; -export class LogItem { +export class LogItem implements ILogItem { public readonly start: number; public logLevel: LogLevel; public error: Error | null; @@ -70,7 +94,7 @@ export class LogItem { } /** start a new root log item and run it detached mode, see BaseLogger.runDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): LogItem { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): ILogItem { return this._logger.runDetached(labelOrValues, callback, logLevel, filterCreator); } @@ -81,9 +105,9 @@ export class LogItem { /** logs a reference to a different log item, usually obtained from runDetached. This is useful if the referenced operation can't be awaited. */ - refDetached(logItem: LogItem, logLevel: LogLevelOrNull = null): void { + refDetached(logItem: ILogItem, logLevel: LogLevelOrNull = null): void { logItem.ensureRefId(); - this.log({ref: logItem._values.refId as number}, logLevel); + this.log({ref: (logItem as LogItem)._values.refId}, logLevel); } ensureRefId(): void { @@ -267,7 +291,7 @@ export class LogItem { return err; } - child(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull, filterCreator: FilterCreator): LogItem { + child(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull, filterCreator: FilterCreator): ILogItem { if (this.end !== null) { console.trace("log item is finished, additional logs will likely not be recorded"); } diff --git a/src/logging/NullLogger.js b/src/logging/NullLogger.ts similarity index 57% rename from src/logging/NullLogger.js rename to src/logging/NullLogger.ts index 12eec5c9..285ea1e4 100644 --- a/src/logging/NullLogger.js +++ b/src/logging/NullLogger.ts @@ -14,18 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. */ import {LogLevel} from "./LogFilter"; +import type {ILogItem, LabelOrValues, LogCallback, LogItemValues} from "./LogItem"; -function noop () {} +function noop (): void {} export class NullLogger { - constructor() { - this.item = new NullLogItem(this); - } + public readonly item: ILogItem = new NullLogItem(this); - log() {} + log(): void {} - run(_, callback) { + run(_: null, callback) { return callback(this.item); } @@ -50,50 +49,61 @@ export class NullLogger { } } -export class NullLogItem { - constructor(logger) { +export class NullLogItem implements ILogItem { + public readonly logger: NullLogger; + public readonly logLevel: LogLevel; + public children: Array | null = null; + public values: LogItemValues; + public error: Error | null = null; + + constructor(logger: NullLogger) { this.logger = logger; } - wrap(_, callback) { + wrap(_: LabelOrValues, callback: LogCallback): unknown { return callback(this); } - log() {} - set() {} + log(): void {} + set(): void {} - runDetached(_, callback) { + runDetached(_: LabelOrValues, callback: LogCallback): ILogItem { new Promise(r => r(callback(this))).then(noop, noop); - } - - wrapDetached(_, callback) { - return this.refDetached(null, callback); - } - - run(callback) { - return callback(this); - } - - refDetached() {} - - ensureRefId() {} - - get level() { - return LogLevel; - } - - get duration() { - return 0; - } - - catch(err) { - return err; - } - - child() { return this; } - finish() {} + wrapDetached(_: LabelOrValues, _callback: LogCallback): void { + return this.refDetached(); + } + + run(callback: LogCallback): unknown { + return callback(this); + } + + refDetached(): void {} + + ensureRefId(): void {} + + get level(): typeof LogLevel { + return LogLevel; + } + + get duration(): 0 { + return 0; + } + + catch(err: Error): Error { + return err; + } + + child() { + return this; + } + + finish(): void {} + + serialize() { + return null; + } } export const Instance = new NullLogger(); diff --git a/src/logging/utils.js b/src/logging/utils.js index 3da9aa5d..659df055 100644 --- a/src/logging/utils.js +++ b/src/logging/utils.js @@ -1,7 +1,7 @@ // these are helper functions if you can't assume you always have a log item (e.g. some code paths call with one set, others don't) // if you know you always have a log item, better to use the methods on the log item than these utility functions. -import {Instance as NullLoggerInstance} from "./NullLogger.js"; +import {Instance as NullLoggerInstance} from "./NullLogger"; export function wrapOrRunNullLogger(logItem, labelOrValues, callback, logLevel = null, filterCreator = null) { if (logItem) { diff --git a/src/matrix/e2ee/megolm/Decryption.ts b/src/matrix/e2ee/megolm/Decryption.ts index 842d423d..4cb66971 100644 --- a/src/matrix/e2ee/megolm/Decryption.ts +++ b/src/matrix/e2ee/megolm/Decryption.ts @@ -26,7 +26,7 @@ import type {OlmWorker} from "../OlmWorker"; import type {Transaction} from "../../storage/idb/Transaction"; import type {TimelineEvent} from "../../storage/types"; import type {DecryptionResult} from "../DecryptionResult"; -import type {LogItem} from "../../../logging/LogItem"; +import type {ILogItem} from "../../../logging/LogItem"; export class Decryption { private keyLoader: KeyLoader; @@ -136,7 +136,7 @@ export class Decryption { * Extracts room keys from decrypted device messages. * The key won't be persisted yet, you need to call RoomKey.write for that. */ - roomKeysFromDeviceMessages(decryptionResults: DecryptionResult[], log: LogItem): IncomingRoomKey[] { + roomKeysFromDeviceMessages(decryptionResults: DecryptionResult[], log: ILogItem): IncomingRoomKey[] { const keys: IncomingRoomKey[] = []; for (const dr of decryptionResults) { if (dr.event?.type !== "m.room_key" || dr.event.content?.algorithm !== MEGOLM_ALGORITHM) { @@ -152,7 +152,7 @@ export class Decryption { log.logLevel = log.level.Warn; log.set("invalid", true); } - }, log.level.Detail); + }, log.level.Detail, null); } return keys; } diff --git a/src/matrix/room/Invite.js b/src/matrix/room/Invite.js index 1bf802dd..da721c77 100644 --- a/src/matrix/room/Invite.js +++ b/src/matrix/room/Invite.js @@ -244,7 +244,7 @@ export class Invite extends EventEmitter { } } -import {NullLogItem} from "../../logging/NullLogger.js"; +import {NullLogItem} from "../../logging/NullLogger"; import {Clock as MockClock} from "../../mocks/Clock.js"; import {default as roomInviteFixture} from "../../fixtures/matrix/invites/room.js"; import {default as dmInviteFixture} from "../../fixtures/matrix/invites/dm.js"; diff --git a/src/matrix/room/sending/SendQueue.js b/src/matrix/room/sending/SendQueue.js index 28408e34..896100c7 100644 --- a/src/matrix/room/sending/SendQueue.js +++ b/src/matrix/room/sending/SendQueue.js @@ -353,7 +353,7 @@ export class SendQueue { import {HomeServer as MockHomeServer} from "../../../mocks/HomeServer.js"; import {createMockStorage} from "../../../mocks/Storage"; import {ListObserver} from "../../../mocks/ListObserver.js"; -import {NullLogger, NullLogItem} from "../../../logging/NullLogger.js"; +import {NullLogger, NullLogItem} from "../../../logging/NullLogger"; import {createEvent, withTextBody, withTxnId} from "../../../mocks/event.js"; import {poll} from "../../../mocks/poll.js"; import {createAnnotation} from "../timeline/relations.js"; diff --git a/src/matrix/room/timeline/Timeline.js b/src/matrix/room/timeline/Timeline.js index 4e6fe40c..bd89ee8d 100644 --- a/src/matrix/room/timeline/Timeline.js +++ b/src/matrix/room/timeline/Timeline.js @@ -346,7 +346,7 @@ import {Clock as MockClock} from "../../../mocks/Clock.js"; import {createMockStorage} from "../../../mocks/Storage"; import {ListObserver} from "../../../mocks/ListObserver.js"; import {createEvent, withTextBody, withContent, withSender} from "../../../mocks/event.js"; -import {NullLogItem} from "../../../logging/NullLogger.js"; +import {NullLogItem} from "../../../logging/NullLogger"; import {EventEntry} from "./entries/EventEntry.js"; import {User} from "../../User.js"; import {PendingEvent} from "../sending/PendingEvent.js"; diff --git a/src/matrix/room/timeline/persistence/GapWriter.js b/src/matrix/room/timeline/persistence/GapWriter.js index 7794b797..3e520608 100644 --- a/src/matrix/room/timeline/persistence/GapWriter.js +++ b/src/matrix/room/timeline/persistence/GapWriter.js @@ -205,7 +205,7 @@ import {FragmentIdComparer} from "../FragmentIdComparer.js"; import {RelationWriter} from "./RelationWriter.js"; import {createMockStorage} from "../../../../mocks/Storage"; import {FragmentBoundaryEntry} from "../entries/FragmentBoundaryEntry.js"; -import {NullLogItem} from "../../../../logging/NullLogger.js"; +import {NullLogItem} from "../../../../logging/NullLogger"; import {TimelineMock, eventIds, eventId} from "../../../../mocks/TimelineMock.ts"; import {SyncWriter} from "./SyncWriter.js"; import {MemberWriter} from "./MemberWriter.js"; diff --git a/src/matrix/room/timeline/persistence/RelationWriter.js b/src/matrix/room/timeline/persistence/RelationWriter.js index c0d3d369..60a2b618 100644 --- a/src/matrix/room/timeline/persistence/RelationWriter.js +++ b/src/matrix/room/timeline/persistence/RelationWriter.js @@ -257,7 +257,7 @@ import {createMockStorage} from "../../../../mocks/Storage"; import {createEvent, withTextBody, withRedacts, withContent} from "../../../../mocks/event.js"; import {createAnnotation} from "../relations.js"; import {FragmentIdComparer} from "../FragmentIdComparer.js"; -import {NullLogItem} from "../../../../logging/NullLogger.js"; +import {NullLogItem} from "../../../../logging/NullLogger"; export function tests() { const fragmentIdComparer = new FragmentIdComparer([]); diff --git a/src/matrix/room/timeline/persistence/SyncWriter.js b/src/matrix/room/timeline/persistence/SyncWriter.js index 749c3392..dc5ae3a8 100644 --- a/src/matrix/room/timeline/persistence/SyncWriter.js +++ b/src/matrix/room/timeline/persistence/SyncWriter.js @@ -258,7 +258,7 @@ export class SyncWriter { import {createMockStorage} from "../../../../mocks/Storage"; import {createEvent, withTextBody} from "../../../../mocks/event.js"; -import {Instance as nullLogger} from "../../../../logging/NullLogger.js"; +import {Instance as nullLogger} from "../../../../logging/NullLogger"; export function tests() { const roomId = "!abc:hs.tld"; return { diff --git a/src/matrix/storage/idb/QueryTarget.ts b/src/matrix/storage/idb/QueryTarget.ts index 03fe66bc..7519beac 100644 --- a/src/matrix/storage/idb/QueryTarget.ts +++ b/src/matrix/storage/idb/QueryTarget.ts @@ -16,7 +16,7 @@ limitations under the License. import {iterateCursor, DONE, NOT_DONE, reqAsPromise} from "./utils"; import {StorageError} from "../common"; -import {LogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/LogItem"; import {IDBKey} from "./Transaction"; // this is the part of the Transaction class API that is used here and in the Store subclass, @@ -25,7 +25,7 @@ export interface ITransaction { idbFactory: IDBFactory; IDBKeyRange: typeof IDBKeyRange; databaseName: string; - addWriteError(error: StorageError, refItem: LogItem | undefined, operationName: string, keys: IDBKey[] | undefined); + addWriteError(error: StorageError, refItem: ILogItem | undefined, operationName: string, keys: IDBKey[] | undefined); } type Reducer = (acc: B, val: A) => B @@ -277,7 +277,7 @@ export function tests() { class MockTransaction extends MockIDBImpl { get databaseName(): string { return "mockdb"; } - addWriteError(error: StorageError, refItem: LogItem | undefined, operationName: string, keys: IDBKey[] | undefined) {} + addWriteError(error: StorageError, refItem: ILogItem | undefined, operationName: string, keys: IDBKey[] | undefined) {} } interface TestEntry { diff --git a/src/matrix/storage/idb/StorageFactory.ts b/src/matrix/storage/idb/StorageFactory.ts index f8cc192d..5ca6bce4 100644 --- a/src/matrix/storage/idb/StorageFactory.ts +++ b/src/matrix/storage/idb/StorageFactory.ts @@ -21,10 +21,10 @@ import { exportSession, importSession, Export } from "./export"; import { schema } from "./schema"; import { detectWebkitEarlyCloseTxnBug } from "./quirks"; import { BaseLogger } from "../../../logging/BaseLogger"; -import { LogItem } from "../../../logging/LogItem"; +import { ILogItem } from "../../../logging/LogItem"; const sessionName = (sessionId: string) => `hydrogen_session_${sessionId}`; -const openDatabaseWithSessionId = function(sessionId: string, idbFactory: IDBFactory, localStorage: IDOMStorage, log: LogItem) { +const openDatabaseWithSessionId = function(sessionId: string, idbFactory: IDBFactory, localStorage: IDOMStorage, log: ILogItem) { const create = (db, txn, oldVersion, version) => createStores(db, txn, oldVersion, version, localStorage, log); return openDatabase(sessionName(sessionId), create, schema.length, idbFactory); } @@ -63,7 +63,7 @@ export class StorageFactory { this._localStorage = localStorage; } - async create(sessionId: string, log: LogItem): Promise { + async create(sessionId: string, log: ILogItem): Promise { await this._serviceWorkerHandler?.preventConcurrentSessionAccess(sessionId); requestPersistedStorage().then(persisted => { // Firefox lies here though, and returns true even if the user denied the request @@ -83,23 +83,30 @@ export class StorageFactory { return reqAsPromise(req); } - async export(sessionId: string, log: LogItem): Promise { + async export(sessionId: string, log: ILogItem): Promise { const db = await openDatabaseWithSessionId(sessionId, this._idbFactory, this._localStorage, log); return await exportSession(db); } - async import(sessionId: string, data: Export, log: LogItem): Promise { + async import(sessionId: string, data: Export, log: ILogItem): Promise { const db = await openDatabaseWithSessionId(sessionId, this._idbFactory, this._localStorage, log); return await importSession(db, data); } } -async function createStores(db: IDBDatabase, txn: IDBTransaction, oldVersion: number | null, version: number, localStorage: IDOMStorage, log: LogItem): Promise { +async function createStores(db: IDBDatabase, txn: IDBTransaction, oldVersion: number | null, version: number, localStorage: IDOMStorage, log: ILogItem): Promise { const startIdx = oldVersion || 0; - return log.wrap({l: "storage migration", oldVersion, version}, async log => { - for(let i = startIdx; i < version; ++i) { - const migrationFunc = schema[i]; - await log.wrap(`v${i + 1}`, log => migrationFunc(db, txn, localStorage, log)); - } - }) as Promise; + return log.wrap( + { l: "storage migration", oldVersion, version }, + async (log) => { + for (let i = startIdx; i < version; ++i) { + const migrationFunc = schema[i]; + await log.wrap(`v${i + 1}`, (log) => + migrationFunc(db, txn, localStorage, log), null, null + ); + } + }, + null, + null + ) as Promise; } diff --git a/src/matrix/storage/idb/Store.ts b/src/matrix/storage/idb/Store.ts index 74de2afa..5a2a9abc 100644 --- a/src/matrix/storage/idb/Store.ts +++ b/src/matrix/storage/idb/Store.ts @@ -18,7 +18,7 @@ import {QueryTarget, IDBQuery, ITransaction} from "./QueryTarget"; import {IDBRequestError, IDBRequestAttemptError} from "./error"; import {reqAsPromise} from "./utils"; import {Transaction, IDBKey} from "./Transaction"; -import {LogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/LogItem"; const LOG_REQUESTS = false; @@ -145,7 +145,7 @@ export class Store extends QueryTarget { return new QueryTarget(new QueryTargetWrapper(this._idbStore.index(indexName)), this._transaction); } - put(value: T, log?: LogItem): void { + put(value: T, log?: ILogItem): void { // If this request fails, the error will bubble up to the transaction and abort it, // which is the behaviour we want. Therefore, it is ok to not create a promise for this // request and await it. @@ -160,13 +160,13 @@ export class Store extends QueryTarget { this._prepareErrorLog(request, log, "put", undefined, value); } - add(value: T, log?: LogItem): void { + add(value: T, log?: ILogItem): void { // ok to not monitor result of request, see comment in `put`. const request = this._idbStore.add(value); this._prepareErrorLog(request, log, "add", undefined, value); } - async tryAdd(value: T, log: LogItem): Promise { + async tryAdd(value: T, log: ILogItem): Promise { try { await reqAsPromise(this._idbStore.add(value)); return true; @@ -181,13 +181,13 @@ export class Store extends QueryTarget { } } - delete(keyOrKeyRange: IDBValidKey | IDBKeyRange, log?: LogItem): void { + delete(keyOrKeyRange: IDBValidKey | IDBKeyRange, log?: ILogItem): void { // ok to not monitor result of request, see comment in `put`. const request = this._idbStore.delete(keyOrKeyRange); this._prepareErrorLog(request, log, "delete", keyOrKeyRange, undefined); } - private _prepareErrorLog(request: IDBRequest, log: LogItem | undefined, operationName: string, key: IDBKey | undefined, value: T | undefined) { + private _prepareErrorLog(request: IDBRequest, log: ILogItem | undefined, operationName: string, key: IDBKey | undefined, value: T | undefined) { if (log) { log.ensureRefId(); } diff --git a/src/matrix/storage/idb/Transaction.ts b/src/matrix/storage/idb/Transaction.ts index 0d9e55a5..721ee711 100644 --- a/src/matrix/storage/idb/Transaction.ts +++ b/src/matrix/storage/idb/Transaction.ts @@ -36,7 +36,7 @@ import {OutboundGroupSessionStore} from "./stores/OutboundGroupSessionStore"; import {GroupSessionDecryptionStore} from "./stores/GroupSessionDecryptionStore"; import {OperationStore} from "./stores/OperationStore"; import {AccountDataStore} from "./stores/AccountDataStore"; -import {LogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/LogItem"; import {BaseLogger} from "../../../logging/BaseLogger"; export type IDBKey = IDBValidKey | IDBKeyRange; @@ -44,7 +44,7 @@ export type IDBKey = IDBValidKey | IDBKeyRange; class WriteErrorInfo { constructor( public readonly error: StorageError, - public readonly refItem: LogItem | undefined, + public readonly refItem: ILogItem | undefined, public readonly operationName: string, public readonly keys: IDBKey[] | undefined, ) {} @@ -169,7 +169,7 @@ export class Transaction { return this._store(StoreNames.accountData, idbStore => new AccountDataStore(idbStore)); } - async complete(log?: LogItem): Promise { + async complete(log?: ILogItem): Promise { try { await txnAsPromise(this._txn); } catch (err) { @@ -190,7 +190,7 @@ export class Transaction { return error; } - abort(log?: LogItem): void { + abort(log?: ILogItem): void { // TODO: should we wrap the exception in a StorageError? try { this._txn.abort(); @@ -202,14 +202,14 @@ export class Transaction { } } - addWriteError(error: StorageError, refItem: LogItem | undefined, operationName: string, keys: IDBKey[] | undefined) { + addWriteError(error: StorageError, refItem: ILogItem | undefined, operationName: string, keys: IDBKey[] | undefined) { // don't log subsequent `AbortError`s if (error.errcode !== "AbortError" || this._writeErrors.length === 0) { this._writeErrors.push(new WriteErrorInfo(error, refItem, operationName, keys)); } } - private _logWriteErrors(parentItem: LogItem | undefined) { + private _logWriteErrors(parentItem: ILogItem | undefined) { const callback = errorGroupItem => { // we don't have context when there is no parentItem, so at least log stores if (!parentItem) { @@ -226,7 +226,7 @@ export class Transaction { }; const label = `${this._writeErrors.length} storage write operation(s) failed`; if (parentItem) { - parentItem.wrap(label, callback); + parentItem.wrap(label, callback, null, null); } else { this.logger.run(label, callback); } diff --git a/src/matrix/storage/idb/schema.ts b/src/matrix/storage/idb/schema.ts index a9c4e2e4..62a4cea1 100644 --- a/src/matrix/storage/idb/schema.ts +++ b/src/matrix/storage/idb/schema.ts @@ -11,10 +11,10 @@ import {SessionStore} from "./stores/SessionStore"; import {Store} from "./Store"; import {encodeScopeTypeKey} from "./stores/OperationStore"; import {MAX_UNICODE} from "./stores/common"; -import {LogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/LogItem"; -export type MigrationFunc = (db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: LogItem) => Promise | void; +export type MigrationFunc = (db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: ILogItem) => Promise | void; // FUNCTIONS SHOULD ONLY BE APPENDED!! // the index in the array is the database version export const schema: MigrationFunc[] = [ @@ -166,7 +166,7 @@ function createTimelineRelationsStore(db: IDBDatabase) : void { } //v11 doesn't change the schema, but ensures all userIdentities have all the roomIds they should (see #470) -async function fixMissingRoomsInUserIdentities(db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: LogItem) { +async function fixMissingRoomsInUserIdentities(db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: ILogItem) { const roomSummaryStore = txn.objectStore("roomSummary"); const trackedRoomIds: string[] = []; await iterateCursor(roomSummaryStore.openCursor(), roomSummary => { @@ -196,7 +196,7 @@ async function fixMissingRoomsInUserIdentities(db: IDBDatabase, txn: IDBTransact const updatedIdentity = addRoomToIdentity(identity, userId, roomId); if (updatedIdentity) { log.log({l: `fixing up`, id: userId, - roomsBefore: originalRoomCount, roomsAfter: updatedIdentity.roomIds.length}); + roomsBefore: originalRoomCount, roomsAfter: updatedIdentity.roomIds.length}, null); userIdentitiesStore.put(updatedIdentity); foundMissing = true; } @@ -207,7 +207,7 @@ async function fixMissingRoomsInUserIdentities(db: IDBDatabase, txn: IDBTransact // so we'll create a new one on the next message that will be properly shared outboundGroupSessionsStore.delete(roomId); } - }); + }, null, null); } } @@ -220,7 +220,7 @@ async function changeSSSSKeyPrefix(db: IDBDatabase, txn: IDBTransaction) { } } // v13 -async function backupAndRestoreE2EEAccountToLocalStorage(db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: LogItem) { +async function backupAndRestoreE2EEAccountToLocalStorage(db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: ILogItem) { const session = txn.objectStore("session"); // the Store object gets passed in several things through the Transaction class (a wrapper around IDBTransaction), // the only thing we should need here is the databaseName though, so we mock it out. diff --git a/src/matrix/storage/idb/stores/SessionStore.ts b/src/matrix/storage/idb/stores/SessionStore.ts index 6bf87e9b..dd133b45 100644 --- a/src/matrix/storage/idb/stores/SessionStore.ts +++ b/src/matrix/storage/idb/stores/SessionStore.ts @@ -16,7 +16,7 @@ limitations under the License. import {Store} from "../Store"; import {IDOMStorage} from "../types"; import {SESSION_E2EE_KEY_PREFIX} from "../../../e2ee/common.js"; -import {LogItem} from "../../../../logging/LogItem"; +import {ILogItem} from "../../../../logging/LogItem"; import {parse, stringify} from "../../../../utils/typedJSON"; export interface SessionEntry { @@ -64,7 +64,7 @@ export class SessionStore { }); } - async tryRestoreE2EEIdentityFromLocalStorage(log: LogItem): Promise { + async tryRestoreE2EEIdentityFromLocalStorage(log: ILogItem): Promise { let success = false; const lsPrefix = this._localStorageKeyPrefix; const prefix = lsPrefix + SESSION_E2EE_KEY_PREFIX; diff --git a/src/matrix/storage/idb/stores/TimelineEventStore.ts b/src/matrix/storage/idb/stores/TimelineEventStore.ts index 3c101701..b3663c29 100644 --- a/src/matrix/storage/idb/stores/TimelineEventStore.ts +++ b/src/matrix/storage/idb/stores/TimelineEventStore.ts @@ -20,7 +20,7 @@ import { encodeUint32, decodeUint32 } from "../utils"; import {KeyLimits} from "../../common"; import {Store} from "../Store"; import {TimelineEvent, StateEvent} from "../../types"; -import {LogItem} from "../../../../logging/LogItem"; +import {ILogItem} from "../../../../logging/LogItem"; interface Annotation { count: number; @@ -286,7 +286,7 @@ export class TimelineEventStore { * * Returns if the event was not yet known and the entry was written. */ - tryInsert(entry: TimelineEventEntry, log: LogItem): Promise { + tryInsert(entry: TimelineEventEntry, log: ILogItem): Promise { (entry as TimelineEventStorageEntry).key = encodeKey(entry.roomId, entry.fragmentId, entry.eventIndex); (entry as TimelineEventStorageEntry).eventIdKey = encodeEventIdKey(entry.roomId, entry.event.event_id); return this._timelineStore.tryAdd(entry as TimelineEventStorageEntry, log); @@ -320,7 +320,7 @@ export class TimelineEventStore { import {createMockStorage} from "../../../../mocks/Storage"; import {createEvent, withTextBody} from "../../../../mocks/event.js"; import {createEventEntry} from "../../../room/timeline/persistence/common.js"; -import {Instance as logItem} from "../../../../logging/NullLogger.js"; +import {Instance as nullLogger} from "../../../../logging/NullLogger"; export function tests() { @@ -368,7 +368,7 @@ export function tests() { let eventKey = EventKey.defaultFragmentKey(109); for (const insertedId of insertedIds) { const entry = createEventEntry(eventKey.nextKey(), roomId, createEventWithId(insertedId)); - assert(await txn.timelineEvents.tryInsert(entry, logItem)); + assert(await txn.timelineEvents.tryInsert(entry, nullLogger.item)); eventKey = eventKey.nextKey(); } const eventKeyMap = await txn.timelineEvents.getEventKeysForIds(roomId, checkedIds); diff --git a/src/mocks/Storage.ts b/src/mocks/Storage.ts index 5dba796a..a5a30ffd 100644 --- a/src/mocks/Storage.ts +++ b/src/mocks/Storage.ts @@ -18,7 +18,7 @@ import {FDBFactory, FDBKeyRange} from "../../lib/fake-indexeddb/index.js"; import {StorageFactory} from "../matrix/storage/idb/StorageFactory"; import {IDOMStorage} from "../matrix/storage/idb/types"; import {Storage} from "../matrix/storage/idb/Storage"; -import {Instance as nullLogger} from "../logging/NullLogger.js"; +import {Instance as nullLogger} from "../logging/NullLogger"; import {openDatabase, CreateObjectStore} from "../matrix/storage/idb/utils"; export function createMockStorage(): Promise { From 30a384fe1e8ddcd7fe627cac55a663e7c6d7e8ea Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 15 Nov 2021 18:44:25 +0530 Subject: [PATCH 080/242] Make LogFilter optional --- src/logging/BaseLogger.ts | 18 +++++++++--------- src/logging/LogItem.ts | 16 ++++++++-------- src/matrix/e2ee/megolm/Decryption.ts | 2 +- src/matrix/storage/idb/StorageFactory.ts | 8 ++------ src/matrix/storage/idb/Transaction.ts | 2 +- src/matrix/storage/idb/schema.ts | 2 +- 6 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index e420c0df..28602b17 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -32,13 +32,13 @@ export abstract class BaseLogger { } log(labelOrValues: LabelOrValues, logLevel: LogLevel = LogLevel.Info) { - const item = new LogItem(labelOrValues, logLevel, null, this); + const item = new LogItem(labelOrValues, logLevel, this); item.end = item.start; this._persistItem(item, undefined, false); } /** if item is a log item, wrap the callback in a child of it, otherwise start a new root log item. */ - wrapOrRun(item: ILogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): unknown { + wrapOrRun(item: ILogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator?: FilterCreator): unknown { if (item) { return item.wrap(labelOrValues, callback, logLevel, filterCreator); } else { @@ -51,28 +51,28 @@ export abstract class BaseLogger { Useful to pair with LogItem.refDetached. @return {LogItem} the log item added, useful to pass to LogItem.refDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): ILogItem { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator?: FilterCreator): ILogItem { // todo: Remove jsdoc type? if (logLevel === null) { logLevel = LogLevel.Info; } - const item = new LogItem(labelOrValues, logLevel, null, this); - this._run(item, callback, logLevel!, filterCreator, false /* don't throw, nobody is awaiting */); + const item = new LogItem(labelOrValues, logLevel, this); + this._run(item, callback, logLevel!, false /* don't throw, nobody is awaiting */, filterCreator); return item; } /** run a callback wrapped in a log operation. Errors and duration are transparently logged, also for async operations. Whatever the callback returns is returned here. */ - run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): unknown { + run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator?: FilterCreator): unknown { if (logLevel === null) { logLevel = LogLevel.Info; } - const item = new LogItem(labelOrValues, logLevel, null, this); - return this._run(item, callback, logLevel!, filterCreator, true); + const item = new LogItem(labelOrValues, logLevel, this); + return this._run(item, callback, logLevel!, true, filterCreator); } - _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, filterCreator: FilterCreator, shouldThrow: boolean): unknown { + _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, shouldThrow: boolean, filterCreator?: FilterCreator): unknown { this._openItems.add(item); const finishItem = () => { diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 54957347..c40d7c08 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -43,7 +43,7 @@ export interface ILogItem { children: Array | null; values: LogItemValues; error: Error | null; - wrap(labelOrValues: LabelOrValues, callback: LogCallback, level: LogLevelOrNull, filterCreator: FilterCreator): unknown; + wrap(labelOrValues: LabelOrValues, callback: LogCallback, level: LogLevelOrNull, filterCreator?: FilterCreator): unknown; log(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull): void; set(key: string | object, value: unknown): void; run(callback: LogCallback): unknown; @@ -68,7 +68,7 @@ export type LogItemValues = { } export type LabelOrValues = string | LogItemValues; -export type FilterCreator = ((filter: LogFilter, item: ILogItem) => LogFilter) | null; +export type FilterCreator = ((filter: LogFilter, item: ILogItem) => LogFilter); export type LogCallback = (item: ILogItem) => unknown; export class LogItem implements ILogItem { @@ -78,10 +78,10 @@ export class LogItem implements ILogItem { public end: number | null; private _values: LogItemValues; private _logger: BaseLogger; - private _filterCreator: FilterCreator; + private _filterCreator?: FilterCreator; private _children: Array | null; - constructor(labelOrValues: LabelOrValues, logLevel: LogLevel, filterCreator: FilterCreator, logger: BaseLogger) { + constructor(labelOrValues: LabelOrValues, logLevel: LogLevel, logger: BaseLogger, filterCreator?: FilterCreator) { this._logger = logger; this.start = logger._now(); this.end = null; @@ -119,7 +119,7 @@ export class LogItem implements ILogItem { /** * Creates a new child item and runs it in `callback`. */ - wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): unknown { + wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator?: FilterCreator): unknown { const item = this.child(labelOrValues, logLevel, filterCreator); return item.run(callback); } @@ -161,7 +161,7 @@ export class LogItem implements ILogItem { * Hence, the child item is not returned. */ log(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull = null): void { - const item = this.child(labelOrValues, logLevel, null); + const item = this.child(labelOrValues, logLevel); item.end = item.start; } @@ -291,14 +291,14 @@ export class LogItem implements ILogItem { return err; } - child(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull, filterCreator: FilterCreator): ILogItem { + child(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull, filterCreator?: FilterCreator): ILogItem { if (this.end !== null) { console.trace("log item is finished, additional logs will likely not be recorded"); } if (!logLevel) { logLevel = this.logLevel || LogLevel.Info; } - const item = new LogItem(labelOrValues, logLevel, filterCreator, this._logger); + const item = new LogItem(labelOrValues, logLevel, this._logger, filterCreator); if (this._children === null) { this._children = []; } diff --git a/src/matrix/e2ee/megolm/Decryption.ts b/src/matrix/e2ee/megolm/Decryption.ts index 4cb66971..ee96eca1 100644 --- a/src/matrix/e2ee/megolm/Decryption.ts +++ b/src/matrix/e2ee/megolm/Decryption.ts @@ -152,7 +152,7 @@ export class Decryption { log.logLevel = log.level.Warn; log.set("invalid", true); } - }, log.level.Detail, null); + }, log.level.Detail); } return keys; } diff --git a/src/matrix/storage/idb/StorageFactory.ts b/src/matrix/storage/idb/StorageFactory.ts index 5ca6bce4..5c257bfb 100644 --- a/src/matrix/storage/idb/StorageFactory.ts +++ b/src/matrix/storage/idb/StorageFactory.ts @@ -101,12 +101,8 @@ async function createStores(db: IDBDatabase, txn: IDBTransaction, oldVersion: nu async (log) => { for (let i = startIdx; i < version; ++i) { const migrationFunc = schema[i]; - await log.wrap(`v${i + 1}`, (log) => - migrationFunc(db, txn, localStorage, log), null, null - ); + await log.wrap(`v${i + 1}`, (log) => migrationFunc(db, txn, localStorage, log), null); } }, - null, - null - ) as Promise; + null) as Promise; } diff --git a/src/matrix/storage/idb/Transaction.ts b/src/matrix/storage/idb/Transaction.ts index 721ee711..c68a1759 100644 --- a/src/matrix/storage/idb/Transaction.ts +++ b/src/matrix/storage/idb/Transaction.ts @@ -226,7 +226,7 @@ export class Transaction { }; const label = `${this._writeErrors.length} storage write operation(s) failed`; if (parentItem) { - parentItem.wrap(label, callback, null, null); + parentItem.wrap(label, callback, null); } else { this.logger.run(label, callback); } diff --git a/src/matrix/storage/idb/schema.ts b/src/matrix/storage/idb/schema.ts index 62a4cea1..b21bd30f 100644 --- a/src/matrix/storage/idb/schema.ts +++ b/src/matrix/storage/idb/schema.ts @@ -207,7 +207,7 @@ async function fixMissingRoomsInUserIdentities(db: IDBDatabase, txn: IDBTransact // so we'll create a new one on the next message that will be properly shared outboundGroupSessionsStore.delete(roomId); } - }, null, null); + }, null); } } From 7097ba07d168d1a4156099dd9967310aebfa415a Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 15 Nov 2021 18:59:33 +0530 Subject: [PATCH 081/242] Replace LogLabelOrNull type with undefined --- src/logging/BaseLogger.ts | 11 +++++------ src/logging/IDBLogger.ts | 1 + src/logging/LogFilter.ts | 2 -- src/logging/LogItem.ts | 25 ++++++++++++------------ src/matrix/storage/idb/StorageFactory.ts | 5 ++--- src/matrix/storage/idb/Transaction.ts | 2 +- src/matrix/storage/idb/schema.ts | 4 ++-- 7 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 28602b17..6c377d48 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -18,7 +18,6 @@ limitations under the License. import {LogItem} from "./LogItem"; import {LogLevel, LogFilter} from "./LogFilter"; import type {FilterCreator, LabelOrValues, LogCallback, ILogItem} from "./LogItem"; -import type {LogLevelOrNull} from "./LogFilter"; // todo: should this import be here just for getting the type? should it instead be done when Platform.js --> Platform.ts? import type {Platform} from "../platform/web/Platform.js"; @@ -38,7 +37,7 @@ export abstract class BaseLogger { } /** if item is a log item, wrap the callback in a child of it, otherwise start a new root log item. */ - wrapOrRun(item: ILogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator?: FilterCreator): unknown { + wrapOrRun(item: ILogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): unknown { if (item) { return item.wrap(labelOrValues, callback, logLevel, filterCreator); } else { @@ -51,9 +50,9 @@ export abstract class BaseLogger { Useful to pair with LogItem.refDetached. @return {LogItem} the log item added, useful to pass to LogItem.refDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator?: FilterCreator): ILogItem { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem { // todo: Remove jsdoc type? - if (logLevel === null) { + if (!logLevel) { logLevel = LogLevel.Info; } const item = new LogItem(labelOrValues, logLevel, this); @@ -64,8 +63,8 @@ export abstract class BaseLogger { /** run a callback wrapped in a log operation. Errors and duration are transparently logged, also for async operations. Whatever the callback returns is returned here. */ - run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator?: FilterCreator): unknown { - if (logLevel === null) { + run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): unknown { + if (!logLevel) { logLevel = LogLevel.Info; } const item = new LogItem(labelOrValues, logLevel, this); diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index 960db0da..d5ce2f9a 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -40,6 +40,7 @@ export class IDBLogger extends BaseLogger { private readonly _flushInterval: Interval; private _queuedItems: QueuedItem[]; + // todo: type constructor constructor(options) { super(options); const {name, flushInterval = 60 * 1000, limit = 3000} = options; diff --git a/src/logging/LogFilter.ts b/src/logging/LogFilter.ts index dc415ede..9968e63e 100644 --- a/src/logging/LogFilter.ts +++ b/src/logging/LogFilter.ts @@ -27,8 +27,6 @@ export enum LogLevel { Off } -export type LogLevelOrNull = LogLevel | null; - export class LogFilter { private _min?: LogLevel; private _parentFilter?: LogFilter; diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index c40d7c08..c0325ca7 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -16,7 +16,6 @@ limitations under the License. */ import {LogLevel, LogFilter} from "./LogFilter"; -import type {LogLevelOrNull} from "./LogFilter"; import type {BaseLogger} from "./BaseLogger"; interface ISerializedItem { @@ -43,17 +42,17 @@ export interface ILogItem { children: Array | null; values: LogItemValues; error: Error | null; - wrap(labelOrValues: LabelOrValues, callback: LogCallback, level: LogLevelOrNull, filterCreator?: FilterCreator): unknown; - log(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull): void; + wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): unknown; + log(labelOrValues: LabelOrValues, logLevel?: LogLevel): void; set(key: string | object, value: unknown): void; run(callback: LogCallback): unknown; - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): ILogItem; - wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): void; - refDetached(logItem: ILogItem, logLevel: LogLevelOrNull): void; + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; + wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): void; + refDetached(logItem: ILogItem, logLevel?: LogLevel): void; ensureRefId(): void; catch(err: Error): Error; finish(): void; - child(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull, filterCreator: FilterCreator): ILogItem; + child(labelOrValues: LabelOrValues, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; serialize(filter: LogFilter, parentStartTime: number | null, forced: boolean): ISerializedItem | null; } @@ -94,18 +93,18 @@ export class LogItem implements ILogItem { } /** start a new root log item and run it detached mode, see BaseLogger.runDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): ILogItem { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem { return this._logger.runDetached(labelOrValues, callback, logLevel, filterCreator); } /** start a new detached root log item and log a reference to it from this item */ - wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): void { + wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): void { this.refDetached(this.runDetached(labelOrValues, callback, logLevel, filterCreator)); } /** logs a reference to a different log item, usually obtained from runDetached. This is useful if the referenced operation can't be awaited. */ - refDetached(logItem: ILogItem, logLevel: LogLevelOrNull = null): void { + refDetached(logItem: ILogItem, logLevel?: LogLevel): void { logItem.ensureRefId(); this.log({ref: (logItem as LogItem)._values.refId}, logLevel); } @@ -119,7 +118,7 @@ export class LogItem implements ILogItem { /** * Creates a new child item and runs it in `callback`. */ - wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator?: FilterCreator): unknown { + wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): unknown { const item = this.child(labelOrValues, logLevel, filterCreator); return item.run(callback); } @@ -160,7 +159,7 @@ export class LogItem implements ILogItem { * * Hence, the child item is not returned. */ - log(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull = null): void { + log(labelOrValues: LabelOrValues, logLevel?: LogLevel): void { const item = this.child(labelOrValues, logLevel); item.end = item.start; } @@ -291,7 +290,7 @@ export class LogItem implements ILogItem { return err; } - child(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull, filterCreator?: FilterCreator): ILogItem { + child(labelOrValues: LabelOrValues, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem { if (this.end !== null) { console.trace("log item is finished, additional logs will likely not be recorded"); } diff --git a/src/matrix/storage/idb/StorageFactory.ts b/src/matrix/storage/idb/StorageFactory.ts index 5c257bfb..120f73f5 100644 --- a/src/matrix/storage/idb/StorageFactory.ts +++ b/src/matrix/storage/idb/StorageFactory.ts @@ -101,8 +101,7 @@ async function createStores(db: IDBDatabase, txn: IDBTransaction, oldVersion: nu async (log) => { for (let i = startIdx; i < version; ++i) { const migrationFunc = schema[i]; - await log.wrap(`v${i + 1}`, (log) => migrationFunc(db, txn, localStorage, log), null); + await log.wrap(`v${i + 1}`, (log) => migrationFunc(db, txn, localStorage, log)); } - }, - null) as Promise; + }) as Promise; } diff --git a/src/matrix/storage/idb/Transaction.ts b/src/matrix/storage/idb/Transaction.ts index c68a1759..4c3d2b5c 100644 --- a/src/matrix/storage/idb/Transaction.ts +++ b/src/matrix/storage/idb/Transaction.ts @@ -226,7 +226,7 @@ export class Transaction { }; const label = `${this._writeErrors.length} storage write operation(s) failed`; if (parentItem) { - parentItem.wrap(label, callback, null); + parentItem.wrap(label, callback); } else { this.logger.run(label, callback); } diff --git a/src/matrix/storage/idb/schema.ts b/src/matrix/storage/idb/schema.ts index b21bd30f..6250980d 100644 --- a/src/matrix/storage/idb/schema.ts +++ b/src/matrix/storage/idb/schema.ts @@ -196,7 +196,7 @@ async function fixMissingRoomsInUserIdentities(db: IDBDatabase, txn: IDBTransact const updatedIdentity = addRoomToIdentity(identity, userId, roomId); if (updatedIdentity) { log.log({l: `fixing up`, id: userId, - roomsBefore: originalRoomCount, roomsAfter: updatedIdentity.roomIds.length}, null); + roomsBefore: originalRoomCount, roomsAfter: updatedIdentity.roomIds.length}); userIdentitiesStore.put(updatedIdentity); foundMissing = true; } @@ -207,7 +207,7 @@ async function fixMissingRoomsInUserIdentities(db: IDBDatabase, txn: IDBTransact // so we'll create a new one on the next message that will be properly shared outboundGroupSessionsStore.delete(roomId); } - }, null); + }); } } From ba5f2032bafbb32a2700f5c8ee664be5b7ef348c Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 15 Nov 2021 19:17:49 +0530 Subject: [PATCH 082/242] Make properties in LogItem optional, not null --- src/logging/LogItem.ts | 29 +++++++++++++---------------- src/logging/NullLogger.ts | 4 ++-- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index c0325ca7..012abc57 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -36,12 +36,12 @@ export interface ILogItem { logger: any; level: typeof LogLevel; duration?: number; - end?: number | null; + end?: number; start?: number; logLevel: LogLevel; - children: Array | null; + children?: Array; values: LogItemValues; - error: Error | null; + error?: Error; wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): unknown; log(labelOrValues: LabelOrValues, logLevel?: LogLevel): void; set(key: string | object, value: unknown): void; @@ -73,22 +73,19 @@ export type LogCallback = (item: ILogItem) => unknown; export class LogItem implements ILogItem { public readonly start: number; public logLevel: LogLevel; - public error: Error | null; - public end: number | null; + public error?: Error; + public end?: number; private _values: LogItemValues; private _logger: BaseLogger; private _filterCreator?: FilterCreator; - private _children: Array | null; + private _children?: Array; constructor(labelOrValues: LabelOrValues, logLevel: LogLevel, logger: BaseLogger, filterCreator?: FilterCreator) { this._logger = logger; this.start = logger._now(); - this.end = null; // (l)abel this._values = typeof labelOrValues === "string" ? {l: labelOrValues} : labelOrValues; - this.error = null; this.logLevel = logLevel; - this._children = null; this._filterCreator = filterCreator; } @@ -183,7 +180,7 @@ export class LogItem implements ILogItem { } } let children: Array | null = null; - if (this._children !== null) { + if (this._children) { children = this._children.reduce((array: Array, c) => { const s = c.serialize(filter, this.start, false); if (s) { @@ -241,7 +238,7 @@ export class LogItem implements ILogItem { * @return {[type]} [description] */ run(callback: LogCallback): unknown { - if (this.end !== null) { + if (this.end) { console.trace("log item is finished, additional logs will likely not be recorded"); } let result: unknown; @@ -268,8 +265,8 @@ export class LogItem implements ILogItem { * @internal shouldn't typically be called by hand. allows to force finish if a promise is still running when closing the app */ finish(): void { - if (this.end === null) { - if (this._children !== null) { + if (!this.end) { + if (this._children) { for(const c of this._children) { c.finish(); } @@ -291,14 +288,14 @@ export class LogItem implements ILogItem { } child(labelOrValues: LabelOrValues, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem { - if (this.end !== null) { + if (this.end) { console.trace("log item is finished, additional logs will likely not be recorded"); } if (!logLevel) { logLevel = this.logLevel || LogLevel.Info; } const item = new LogItem(labelOrValues, logLevel, this._logger, filterCreator); - if (this._children === null) { + if (!this._children) { this._children = []; } this._children.push(item); @@ -313,7 +310,7 @@ export class LogItem implements ILogItem { return this._values; } - get children(): Array | null { + get children(): Array | undefined { return this._children; } } diff --git a/src/logging/NullLogger.ts b/src/logging/NullLogger.ts index 285ea1e4..601a1c39 100644 --- a/src/logging/NullLogger.ts +++ b/src/logging/NullLogger.ts @@ -52,9 +52,9 @@ export class NullLogger { export class NullLogItem implements ILogItem { public readonly logger: NullLogger; public readonly logLevel: LogLevel; - public children: Array | null = null; + public children?: Array; public values: LogItemValues; - public error: Error | null = null; + public error?: Error; constructor(logger: NullLogger) { this.logger = logger; From fe69f84c8537247d158661cdf1f5ec77e5857e79 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 15 Nov 2021 19:32:16 +0530 Subject: [PATCH 083/242] Use undefined in LogItem.serialize --- src/logging/IDBLogger.ts | 2 +- src/logging/LogItem.ts | 8 ++++---- src/logging/NullLogger.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index d5ce2f9a..dcfd3a64 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -118,7 +118,7 @@ export class IDBLogger extends BaseLogger { } _persistItem(logItem: ILogItem, filter: LogFilter, forced: boolean): void { - const serializedItem = logItem.serialize(filter, null, forced); + const serializedItem = logItem.serialize(filter, undefined, forced); this._queuedItems.push({ json: JSON.stringify(serializedItem) }); diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 012abc57..82f785e4 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -53,7 +53,7 @@ export interface ILogItem { catch(err: Error): Error; finish(): void; child(labelOrValues: LabelOrValues, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; - serialize(filter: LogFilter, parentStartTime: number | null, forced: boolean): ISerializedItem | null; + serialize(filter: LogFilter, parentStartTime: number | undefined, forced: boolean): ISerializedItem | undefined; } export type LogItemValues = { @@ -171,7 +171,7 @@ export class LogItem implements ILogItem { } // todo: null or undefined here? - serialize(filter: LogFilter, parentStartTime: number | null = null, forced: boolean): ISerializedItem | null { + serialize(filter: LogFilter, parentStartTime: number | undefined, forced: boolean): ISerializedItem | undefined { if (this._filterCreator) { try { filter = this._filterCreator(new LogFilter(filter), this); @@ -193,12 +193,12 @@ export class LogItem implements ILogItem { }, null); } if (filter && !filter.filter(this, children)) { - return null; + return; } // in (v)alues, (l)abel and (t)ype are also reserved. const item: ISerializedItem = { // (s)tart - s: parentStartTime === null ? this.start : this.start - parentStartTime, + s: parentStartTime? this.start - parentStartTime : this.start, // (d)uration d: this.duration, // (v)alues diff --git a/src/logging/NullLogger.ts b/src/logging/NullLogger.ts index 601a1c39..63e91f61 100644 --- a/src/logging/NullLogger.ts +++ b/src/logging/NullLogger.ts @@ -102,7 +102,7 @@ export class NullLogItem implements ILogItem { finish(): void {} serialize() { - return null; + return undefined; } } From 4c1d7a8f2d098a0fbfa850fd1f421e52f4d080a6 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 15 Nov 2021 22:47:38 +0530 Subject: [PATCH 084/242] Use generics over returning unknown --- src/logging/BaseLogger.ts | 9 +++++---- src/logging/LogItem.ts | 20 ++++++++++---------- src/logging/NullLogger.ts | 8 ++++---- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 6c377d48..a2463d3a 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -21,6 +21,7 @@ import type {FilterCreator, LabelOrValues, LogCallback, ILogItem} from "./LogIte // todo: should this import be here just for getting the type? should it instead be done when Platform.js --> Platform.ts? import type {Platform} from "../platform/web/Platform.js"; +type RunResult = T | void | Promise; export abstract class BaseLogger { protected _openItems: Set = new Set(); @@ -37,7 +38,7 @@ export abstract class BaseLogger { } /** if item is a log item, wrap the callback in a child of it, otherwise start a new root log item. */ - wrapOrRun(item: ILogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): unknown { + wrapOrRun(item: ILogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): RunResult { if (item) { return item.wrap(labelOrValues, callback, logLevel, filterCreator); } else { @@ -50,7 +51,7 @@ export abstract class BaseLogger { Useful to pair with LogItem.refDetached. @return {LogItem} the log item added, useful to pass to LogItem.refDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem { // todo: Remove jsdoc type? if (!logLevel) { logLevel = LogLevel.Info; @@ -63,7 +64,7 @@ export abstract class BaseLogger { /** run a callback wrapped in a log operation. Errors and duration are transparently logged, also for async operations. Whatever the callback returns is returned here. */ - run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): unknown { + run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): RunResult { if (!logLevel) { logLevel = LogLevel.Info; } @@ -71,7 +72,7 @@ export abstract class BaseLogger { return this._run(item, callback, logLevel!, true, filterCreator); } - _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, shouldThrow: boolean, filterCreator?: FilterCreator): unknown { + _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, shouldThrow: boolean, filterCreator?: FilterCreator): RunResult { this._openItems.add(item); const finishItem = () => { diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 82f785e4..4600b6d5 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -42,12 +42,12 @@ export interface ILogItem { children?: Array; values: LogItemValues; error?: Error; - wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): unknown; + wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T | Promise; log(labelOrValues: LabelOrValues, logLevel?: LogLevel): void; set(key: string | object, value: unknown): void; - run(callback: LogCallback): unknown; - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; - wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): void; + run(callback: LogCallback): T | Promise; + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; + wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): void; refDetached(logItem: ILogItem, logLevel?: LogLevel): void; ensureRefId(): void; catch(err: Error): Error; @@ -68,7 +68,7 @@ export type LogItemValues = { export type LabelOrValues = string | LogItemValues; export type FilterCreator = ((filter: LogFilter, item: ILogItem) => LogFilter); -export type LogCallback = (item: ILogItem) => unknown; +export type LogCallback = (item: ILogItem) => T; export class LogItem implements ILogItem { public readonly start: number; @@ -90,12 +90,12 @@ export class LogItem implements ILogItem { } /** start a new root log item and run it detached mode, see BaseLogger.runDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem { return this._logger.runDetached(labelOrValues, callback, logLevel, filterCreator); } /** start a new detached root log item and log a reference to it from this item */ - wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): void { + wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): void { this.refDetached(this.runDetached(labelOrValues, callback, logLevel, filterCreator)); } @@ -115,7 +115,7 @@ export class LogItem implements ILogItem { /** * Creates a new child item and runs it in `callback`. */ - wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): unknown { + wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T | Promise { const item = this.child(labelOrValues, logLevel, filterCreator); return item.run(callback); } @@ -237,11 +237,11 @@ export class LogItem implements ILogItem { * @param {Function} callback [description] * @return {[type]} [description] */ - run(callback: LogCallback): unknown { + run(callback: LogCallback): T | Promise { if (this.end) { console.trace("log item is finished, additional logs will likely not be recorded"); } - let result: unknown; + let result: T | Promise; try { result = callback(this); if (result instanceof Promise) { diff --git a/src/logging/NullLogger.ts b/src/logging/NullLogger.ts index 63e91f61..9db1eee4 100644 --- a/src/logging/NullLogger.ts +++ b/src/logging/NullLogger.ts @@ -60,22 +60,22 @@ export class NullLogItem implements ILogItem { this.logger = logger; } - wrap(_: LabelOrValues, callback: LogCallback): unknown { + wrap(_: LabelOrValues, callback: LogCallback): T | Promise { return callback(this); } log(): void {} set(): void {} - runDetached(_: LabelOrValues, callback: LogCallback): ILogItem { + runDetached(_: LabelOrValues, callback: LogCallback): ILogItem { new Promise(r => r(callback(this))).then(noop, noop); return this; } - wrapDetached(_: LabelOrValues, _callback: LogCallback): void { + wrapDetached(_: LabelOrValues, _callback: LogCallback): void { return this.refDetached(); } - run(callback: LogCallback): unknown { + run(callback: LogCallback): T | Promise { return callback(this); } From 4161d31642bc664ebaec9b3e51780635a5e88587 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 12:23:06 +0530 Subject: [PATCH 085/242] Convert NullLogger to typescript --- src/logging/NullLogger.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/logging/NullLogger.ts b/src/logging/NullLogger.ts index 9db1eee4..d1ac2a03 100644 --- a/src/logging/NullLogger.ts +++ b/src/logging/NullLogger.ts @@ -18,21 +18,20 @@ import type {ILogItem, LabelOrValues, LogCallback, LogItemValues} from "./LogIte function noop (): void {} - export class NullLogger { public readonly item: ILogItem = new NullLogItem(this); log(): void {} - run(_: null, callback) { + run(_, callback: LogCallback): T | Promise { return callback(this.item); } - wrapOrRun(item, _, callback) { + wrapOrRun(item: ILogItem, _, callback: LogCallback): T | Promise { if (item) { - return item.wrap(null, callback); + return item.wrap(_, callback); } else { - return this.run(null, callback); + return this.run(_, callback); } } @@ -40,11 +39,11 @@ export class NullLogger { new Promise(r => r(callback(this.item))).then(noop, noop); } - async export() { + async export(): Promise { return null; } - get level() { + get level(): typeof LogLevel { return LogLevel; } } @@ -63,6 +62,7 @@ export class NullLogItem implements ILogItem { wrap(_: LabelOrValues, callback: LogCallback): T | Promise { return callback(this); } + log(): void {} set(): void {} @@ -95,13 +95,13 @@ export class NullLogItem implements ILogItem { return err; } - child() { + child(): ILogItem { return this; } finish(): void {} - serialize() { + serialize(): undefined { return undefined; } } From 3ee160729883dd6ac71f1d1e05da112f18f54781 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 12:32:49 +0530 Subject: [PATCH 086/242] Convert utils to typescript --- src/logging/utils.js | 16 ---------------- src/logging/utils.ts | 18 ++++++++++++++++++ src/matrix/room/BaseRoom.js | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) delete mode 100644 src/logging/utils.js create mode 100644 src/logging/utils.ts diff --git a/src/logging/utils.js b/src/logging/utils.js deleted file mode 100644 index 659df055..00000000 --- a/src/logging/utils.js +++ /dev/null @@ -1,16 +0,0 @@ -// these are helper functions if you can't assume you always have a log item (e.g. some code paths call with one set, others don't) -// if you know you always have a log item, better to use the methods on the log item than these utility functions. - -import {Instance as NullLoggerInstance} from "./NullLogger"; - -export function wrapOrRunNullLogger(logItem, labelOrValues, callback, logLevel = null, filterCreator = null) { - if (logItem) { - return logItem.wrap(logItem, labelOrValues, callback, logLevel, filterCreator); - } else { - return NullLoggerInstance.run(null, callback); - } -} - -export function ensureLogItem(logItem) { - return logItem || NullLoggerInstance.item; -} diff --git a/src/logging/utils.ts b/src/logging/utils.ts new file mode 100644 index 00000000..61cbce80 --- /dev/null +++ b/src/logging/utils.ts @@ -0,0 +1,18 @@ +// these are helper functions if you can't assume you always have a log item (e.g. some code paths call with one set, others don't) +// if you know you always have a log item, better to use the methods on the log item than these utility functions. + +import {Instance as NullLoggerInstance} from "./NullLogger"; +import type {FilterCreator, ILogItem, LabelOrValues, LogCallback} from "./LogItem"; +import {LogLevel} from "./LogFilter"; + +export function wrapOrRunNullLogger(logItem: ILogItem | undefined, labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T | Promise { + if (logItem) { + return logItem.wrap(labelOrValues, callback, logLevel, filterCreator); + } else { + return NullLoggerInstance.run(null, callback); + } +} + +export function ensureLogItem(logItem: ILogItem): ILogItem { + return logItem || NullLoggerInstance.item; +} diff --git a/src/matrix/room/BaseRoom.js b/src/matrix/room/BaseRoom.js index 1aa8cb18..93973b71 100644 --- a/src/matrix/room/BaseRoom.js +++ b/src/matrix/room/BaseRoom.js @@ -27,7 +27,7 @@ import {Heroes} from "./members/Heroes.js"; import {EventEntry} from "./timeline/entries/EventEntry.js"; import {ObservedEventMap} from "./ObservedEventMap.js"; import {DecryptionSource} from "../e2ee/common.js"; -import {ensureLogItem} from "../../logging/utils.js"; +import {ensureLogItem} from "../../logging/utils"; import {PowerLevels} from "./PowerLevels.js"; import {RetainedObservableValue} from "../../observable/ObservableValue"; From 286747c23c01074b28ddf29f5e281addb1c31634 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 12:41:03 +0530 Subject: [PATCH 087/242] Add type annotation for ctor --- 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 dcfd3a64..c5fa2a52 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -41,7 +41,7 @@ export class IDBLogger extends BaseLogger { private _queuedItems: QueuedItem[]; // todo: type constructor - constructor(options) { + constructor(options: {name: string, flushInterval?: number, limit?: number, platform: Platform}) { super(options); const {name, flushInterval = 60 * 1000, limit = 3000} = options; this._name = name; From e339e730f413d30d3a2891dd5074783c8e817b34 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 12:42:50 +0530 Subject: [PATCH 088/242] Remove todo comment --- src/logging/IDBLogger.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index c5fa2a52..944116b8 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -40,7 +40,6 @@ export class IDBLogger extends BaseLogger { private readonly _flushInterval: Interval; private _queuedItems: QueuedItem[]; - // todo: type constructor constructor(options: {name: string, flushInterval?: number, limit?: number, platform: Platform}) { super(options); const {name, flushInterval = 60 * 1000, limit = 3000} = options; From 34a8463bf912af38a0708586de6bbcb107af8930 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 12:43:23 +0530 Subject: [PATCH 089/242] Fix jsdoc return type --- src/logging/BaseLogger.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index a2463d3a..f6c88aff 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -50,9 +50,8 @@ export abstract class BaseLogger { where the (async) result or errors are not propagated but still logged. Useful to pair with LogItem.refDetached. - @return {LogItem} the log item added, useful to pass to LogItem.refDetached */ + @return {ILogItem} the log item added, useful to pass to LogItem.refDetached */ runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem { - // todo: Remove jsdoc type? if (!logLevel) { logLevel = LogLevel.Info; } From 4704a70cb78d5c2c35e57c54248958ca9ad36956 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 13:06:47 +0530 Subject: [PATCH 090/242] Remove todo comment --- src/logging/BaseLogger.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index f6c88aff..ddf1b308 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -18,7 +18,6 @@ limitations under the License. import {LogItem} from "./LogItem"; import {LogLevel, LogFilter} from "./LogFilter"; import type {FilterCreator, LabelOrValues, LogCallback, ILogItem} from "./LogItem"; -// todo: should this import be here just for getting the type? should it instead be done when Platform.js --> Platform.ts? import type {Platform} from "../platform/web/Platform.js"; type RunResult = T | void | Promise; From 58105824d9669ed2fa9dafb9b76ee2c84965c311 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 13:08:13 +0530 Subject: [PATCH 091/242] Fix error in reduce --- src/logging/LogItem.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 4600b6d5..c12308ef 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -141,9 +141,7 @@ export class LogItem implements ILogItem { } else if (this._children) { return this._children.reduce((sum, c) => { const duration = c.durationOfType(type); - if (duration) { - return sum + duration; - } + return sum + (duration ?? 0); }, 0); } else { return 0; From 14eaa574342eca3cf6443fbdb0d9ed019bdeee8b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 16 Nov 2021 13:14:11 +0530 Subject: [PATCH 092/242] No need for type assertion here --- src/matrix/storage/idb/StorageFactory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/storage/idb/StorageFactory.ts b/src/matrix/storage/idb/StorageFactory.ts index 120f73f5..3c7e0e40 100644 --- a/src/matrix/storage/idb/StorageFactory.ts +++ b/src/matrix/storage/idb/StorageFactory.ts @@ -103,5 +103,5 @@ async function createStores(db: IDBDatabase, txn: IDBTransaction, oldVersion: nu const migrationFunc = schema[i]; await log.wrap(`v${i + 1}`, (log) => migrationFunc(db, txn, localStorage, log)); } - }) as Promise; + }); } From 8fce29caf7593c82677e35342e41d9e88d8a046b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 11:38:33 +0530 Subject: [PATCH 093/242] Explicitly check for undefined --- src/logging/LogFilter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging/LogFilter.ts b/src/logging/LogFilter.ts index 9968e63e..5f0e7ae7 100644 --- a/src/logging/LogFilter.ts +++ b/src/logging/LogFilter.ts @@ -42,7 +42,7 @@ export class LogFilter { } } // neither our children or us have a loglevel high enough, filter out. - if (this._min && !Array.isArray(children) && item.logLevel < this._min) { + if (this._min !== undefined && !Array.isArray(children) && item.logLevel < this._min) { return false; } else { return true; From b0ab8cd77f8ae373b07cb330e1f7881c17192253 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 11:40:38 +0530 Subject: [PATCH 094/242] Space before { --- src/logging/LogItem.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index c12308ef..717eadfd 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -120,7 +120,7 @@ export class LogItem implements ILogItem { return item.run(callback); } - get duration(): number | undefined{ + get duration(): number | undefined { if (this.end) { return this.end - this.start; } else { @@ -128,7 +128,7 @@ export class LogItem implements ILogItem { } } - durationWithoutType(type: string): number | undefined{ + durationWithoutType(type: string): number | undefined { const durationOfType = this.durationOfType(type); if (this.duration && durationOfType) { return this.duration - durationOfType; From 9c8f96e233e2bb16234d5a536d39d88932f0a9f0 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Wed, 17 Nov 2021 11:43:59 +0530 Subject: [PATCH 095/242] value is optional Co-authored-by: Bruno Windels --- 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 717eadfd..fd9fcb1d 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -159,7 +159,7 @@ export class LogItem implements ILogItem { item.end = item.start; } - set(key: string | object, value: unknown): void { + set(key: string | object, value?: unknown): void { if(typeof key === "object") { const values = key; Object.assign(this._values, values); From 835da58b53fe745de68741a548fd45d7695d6c15 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 11:59:50 +0530 Subject: [PATCH 096/242] Remove ! --- src/logging/BaseLogger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index ddf1b308..c9ce6aaf 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -55,7 +55,7 @@ export abstract class BaseLogger { logLevel = LogLevel.Info; } const item = new LogItem(labelOrValues, logLevel, this); - this._run(item, callback, logLevel!, false /* don't throw, nobody is awaiting */, filterCreator); + this._run(item, callback, logLevel, false /* don't throw, nobody is awaiting */, filterCreator); return item; } From 07a1130db33963ba4090657432aed766fd8af501 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 12:02:12 +0530 Subject: [PATCH 097/242] children can be array of ISerializedItem --- src/logging/LogFilter.ts | 4 ++-- src/logging/LogItem.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/logging/LogFilter.ts b/src/logging/LogFilter.ts index 5f0e7ae7..d0189631 100644 --- a/src/logging/LogFilter.ts +++ b/src/logging/LogFilter.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type {ILogItem} from "./LogItem"; +import type {ILogItem, ISerializedItem} from "./LogItem"; export enum LogLevel { All = 1, @@ -35,7 +35,7 @@ export class LogFilter { this._parentFilter = parentFilter; } - filter(item: ILogItem, children: Array | null): boolean { + filter(item: ILogItem, children: ISerializedItem[] | null): boolean { if (this._parentFilter) { if (!this._parentFilter.filter(item, children)) { return false; diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index fd9fcb1d..30a6294a 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -18,7 +18,7 @@ limitations under the License. import {LogLevel, LogFilter} from "./LogFilter"; import type {BaseLogger} from "./BaseLogger"; -interface ISerializedItem { +export interface ISerializedItem { s: number; d?: number; v: LogItemValues; From d01271fb150ba19f0183c25e3cd3ffaa78d8899e Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 13:22:19 +0530 Subject: [PATCH 098/242] _run return T or void depending on boolean --- src/logging/BaseLogger.ts | 26 +++++++++++++++----------- src/logging/LogItem.ts | 10 +++++----- src/logging/NullLogger.ts | 4 ++-- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index c9ce6aaf..999db4cf 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -20,8 +20,6 @@ import {LogLevel, LogFilter} from "./LogFilter"; import type {FilterCreator, LabelOrValues, LogCallback, ILogItem} from "./LogItem"; import type {Platform} from "../platform/web/Platform.js"; -type RunResult = T | void | Promise; - export abstract class BaseLogger { protected _openItems: Set = new Set(); protected _platform: Platform; @@ -37,7 +35,7 @@ export abstract class BaseLogger { } /** if item is a log item, wrap the callback in a child of it, otherwise start a new root log item. */ - wrapOrRun(item: ILogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): RunResult { + wrapOrRun(item: ILogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T { if (item) { return item.wrap(labelOrValues, callback, logLevel, filterCreator); } else { @@ -62,7 +60,7 @@ export abstract class BaseLogger { /** run a callback wrapped in a log operation. Errors and duration are transparently logged, also for async operations. Whatever the callback returns is returned here. */ - run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): RunResult { + run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T { if (!logLevel) { logLevel = LogLevel.Info; } @@ -70,7 +68,9 @@ export abstract class BaseLogger { return this._run(item, callback, logLevel!, true, filterCreator); } - _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, shouldThrow: boolean, filterCreator?: FilterCreator): RunResult { + _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, wantResult: true, filterCreator?: FilterCreator): T; + _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, wantResult: false, filterCreator?: FilterCreator): void; + _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, wantResult: boolean, filterCreator?: FilterCreator): T | void { this._openItems.add(item); const finishItem = () => { @@ -94,24 +94,28 @@ export abstract class BaseLogger { }; try { - const result = item.run(callback); + let result = item.run(callback); if (result instanceof Promise) { - return result.then(promiseResult => { + result = result.then(promiseResult => { finishItem(); return promiseResult; }, err => { finishItem(); - if (shouldThrow) { + if (wantResult) { throw err; } - }); - } else { + }) as unknown as T; + if (wantResult) { + return result; + } + } + if(wantResult) { finishItem(); return result; } } catch (err) { finishItem(); - if (shouldThrow) { + if (wantResult) { throw err; } } diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 30a6294a..c3d32ef5 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -42,10 +42,10 @@ export interface ILogItem { children?: Array; values: LogItemValues; error?: Error; - wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T | Promise; + wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T; log(labelOrValues: LabelOrValues, logLevel?: LogLevel): void; set(key: string | object, value: unknown): void; - run(callback: LogCallback): T | Promise; + run(callback: LogCallback): T; runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): void; refDetached(logItem: ILogItem, logLevel?: LogLevel): void; @@ -115,7 +115,7 @@ export class LogItem implements ILogItem { /** * Creates a new child item and runs it in `callback`. */ - wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T | Promise { + wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T { const item = this.child(labelOrValues, logLevel, filterCreator); return item.run(callback); } @@ -235,7 +235,7 @@ export class LogItem implements ILogItem { * @param {Function} callback [description] * @return {[type]} [description] */ - run(callback: LogCallback): T | Promise { + run(callback: LogCallback): T { if (this.end) { console.trace("log item is finished, additional logs will likely not be recorded"); } @@ -248,7 +248,7 @@ export class LogItem implements ILogItem { return promiseResult; }, err => { throw this.catch(err); - }); + }) as unknown as T; } else { this.finish(); return result; diff --git a/src/logging/NullLogger.ts b/src/logging/NullLogger.ts index d1ac2a03..eba453e6 100644 --- a/src/logging/NullLogger.ts +++ b/src/logging/NullLogger.ts @@ -59,7 +59,7 @@ export class NullLogItem implements ILogItem { this.logger = logger; } - wrap(_: LabelOrValues, callback: LogCallback): T | Promise { + wrap(_: LabelOrValues, callback: LogCallback): T { return callback(this); } @@ -75,7 +75,7 @@ export class NullLogItem implements ILogItem { return this.refDetached(); } - run(callback: LogCallback): T | Promise { + run(callback: LogCallback): T { return callback(this); } From 1942c31eff00b46451efc27d410ccf009548968d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 10:42:54 +0100 Subject: [PATCH 099/242] still finish item when not returning from sync callback --- src/logging/BaseLogger.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 999db4cf..f14caa5e 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -69,6 +69,7 @@ export abstract class BaseLogger { } _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, wantResult: true, filterCreator?: FilterCreator): T; + // we don't return if we don't throw, as we don't have anything to return when an error is caught but swallowed for the fire-and-forget case. _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, wantResult: false, filterCreator?: FilterCreator): void; _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, wantResult: boolean, filterCreator?: FilterCreator): T | void { this._openItems.add(item); @@ -108,10 +109,11 @@ export abstract class BaseLogger { if (wantResult) { return result; } - } - if(wantResult) { + } else { finishItem(); - return result; + if(wantResult) { + return result; + } } } catch (err) { finishItem(); From f93bdd962a8085d827cfc14bc5c3757f9d817b47 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 10:50:55 +0100 Subject: [PATCH 100/242] might as well use generic here --- src/logging/BaseLogger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index f14caa5e..4b04b510 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -48,7 +48,7 @@ export abstract class BaseLogger { Useful to pair with LogItem.refDetached. @return {ILogItem} the log item added, useful to pass to LogItem.refDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem { if (!logLevel) { logLevel = LogLevel.Info; } From 90d7b73dd4b6e328667f7e89132f9352d2d5b547 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 11:08:29 +0100 Subject: [PATCH 101/242] non-persisted queued items don't have an id yet, find them by ref equality --- src/logging/IDBLogger.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index 944116b8..ebcf2249 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -152,12 +152,14 @@ export class IDBLogger extends BaseLogger { const txn = db.transaction(["logs"], "readwrite"); const logs = txn.objectStore("logs"); for (const item of items) { - const queuedIdx = this._queuedItems.findIndex(i => i.id === item.id); - if (queuedIdx === -1) { - // todo: isn't id optional? do we need further checks here - logs.delete(item.id!); // resolve questionable use of non-null assertion operator? + if (typeof item.id === "number") { + logs.delete(item.id); } else { - this._queuedItems.splice(queuedIdx, 1); + // assume the (non-persisted) object in each array will be the same + const queuedIdx = this._queuedItems.indexOf(item); + if (queuedIdx === -1) { + this._queuedItems.splice(queuedIdx, 1); + } } } await txnAsPromise(txn); From 3ee7e73ff0530f33c4a3d1d95d287c831ba81cd9 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 11:08:44 +0100 Subject: [PATCH 102/242] item is optional here --- src/logging/BaseLogger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 4b04b510..3b2842ad 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -35,7 +35,7 @@ export abstract class BaseLogger { } /** if item is a log item, wrap the callback in a child of it, otherwise start a new root log item. */ - wrapOrRun(item: ILogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T { + wrapOrRun(item: ILogItem | undefined, labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T { if (item) { return item.wrap(labelOrValues, callback, logLevel, filterCreator); } else { From 1b13f32d94a17a198533fc001f331078388df7a0 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 17 Nov 2021 15:22:08 +0530 Subject: [PATCH 103/242] Remove resolved todo comment --- src/logging/LogItem.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index c3d32ef5..9521b67b 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -168,7 +168,6 @@ export class LogItem implements ILogItem { } } - // todo: null or undefined here? serialize(filter: LogFilter, parentStartTime: number | undefined, forced: boolean): ISerializedItem | undefined { if (this._filterCreator) { try { From 695996d6e2f5f66edc617aa4b9a0ef54bde630a7 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 11:38:17 +0100 Subject: [PATCH 104/242] add ILogger and ILogExport interface, to give export correct return type also move logging related types to own file --- src/logging/BaseLogger.ts | 6 +- src/logging/ConsoleLogger.ts | 6 +- src/logging/IDBLogger.ts | 6 +- src/logging/LogFilter.ts | 2 +- src/logging/LogItem.ts | 53 +---------- src/logging/NullLogger.ts | 15 ++-- src/logging/types.ts | 87 +++++++++++++++++++ src/logging/utils.ts | 2 +- src/matrix/e2ee/megolm/Decryption.ts | 2 +- src/matrix/storage/idb/QueryTarget.ts | 2 +- src/matrix/storage/idb/Storage.ts | 6 +- src/matrix/storage/idb/StorageFactory.ts | 3 +- src/matrix/storage/idb/Store.ts | 2 +- src/matrix/storage/idb/Transaction.ts | 5 +- src/matrix/storage/idb/schema.ts | 2 +- src/matrix/storage/idb/stores/SessionStore.ts | 2 +- .../storage/idb/stores/TimelineEventStore.ts | 2 +- 17 files changed, 119 insertions(+), 84 deletions(-) create mode 100644 src/logging/types.ts diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 3b2842ad..7d015262 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -17,10 +17,10 @@ limitations under the License. import {LogItem} from "./LogItem"; import {LogLevel, LogFilter} from "./LogFilter"; -import type {FilterCreator, LabelOrValues, LogCallback, ILogItem} from "./LogItem"; +import type {ILogger, ILogExport, FilterCreator, LabelOrValues, LogCallback, ILogItem} from "./types"; import type {Platform} from "../platform/web/Platform.js"; -export abstract class BaseLogger { +export abstract class BaseLogger implements ILogger { protected _openItems: Set = new Set(); protected _platform: Platform; @@ -141,7 +141,7 @@ export abstract class BaseLogger { abstract _persistItem(item: ILogItem, filter?: LogFilter, forced?: boolean): void; - abstract export(): void; + abstract export(): Promise; // expose log level without needing get level(): typeof LogLevel { diff --git a/src/logging/ConsoleLogger.ts b/src/logging/ConsoleLogger.ts index d8693e38..20fdf6a6 100644 --- a/src/logging/ConsoleLogger.ts +++ b/src/logging/ConsoleLogger.ts @@ -14,15 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ import {BaseLogger} from "./BaseLogger"; -import type {ILogItem, LogItemValues} from "./LogItem"; +import type {ILogItem, LogItemValues, ILogExport} from "./types"; export class ConsoleLogger extends BaseLogger { _persistItem(item: ILogItem): void { printToConsole(item); } - export(): void { - throw new Error("Cannot export from ConsoleLogger"); + async export(): Promise { + return undefined; } } diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index ebcf2249..621359dc 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} from "./LogItem"; +import type {ILogItem, ILogExport} from "./types"; import type {LogFilter} from "./LogFilter"; type QueuedItem = { @@ -131,7 +131,7 @@ export class IDBLogger extends BaseLogger { } } - async export(): Promise { + async export(): Promise { const db = await this._openDB(); try { const txn = db.transaction(["logs"], "readonly"); @@ -171,7 +171,7 @@ export class IDBLogger extends BaseLogger { } } -class IDBLogExport { +class IDBLogExport implements ILogExport { private readonly _items: QueuedItem[]; private readonly _logger: IDBLogger; private readonly _platform: Platform; diff --git a/src/logging/LogFilter.ts b/src/logging/LogFilter.ts index d0189631..8611d5f3 100644 --- a/src/logging/LogFilter.ts +++ b/src/logging/LogFilter.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type {ILogItem, ISerializedItem} from "./LogItem"; +import type {ILogItem, ISerializedItem} from "./types"; export enum LogLevel { All = 1, diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 9521b67b..7774dd41 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -17,58 +17,7 @@ limitations under the License. import {LogLevel, LogFilter} from "./LogFilter"; import type {BaseLogger} from "./BaseLogger"; - -export interface ISerializedItem { - s: number; - d?: number; - v: LogItemValues; - l: LogLevel; - e?: { - stack?: string; - name: string; - message: string; - }; - f?: boolean; - c?: Array; -}; - -export interface ILogItem { - logger: any; - level: typeof LogLevel; - duration?: number; - end?: number; - start?: number; - logLevel: LogLevel; - children?: Array; - values: LogItemValues; - error?: Error; - wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T; - log(labelOrValues: LabelOrValues, logLevel?: LogLevel): void; - set(key: string | object, value: unknown): void; - run(callback: LogCallback): T; - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; - wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): void; - refDetached(logItem: ILogItem, logLevel?: LogLevel): void; - ensureRefId(): void; - catch(err: Error): Error; - finish(): void; - child(labelOrValues: LabelOrValues, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; - serialize(filter: LogFilter, parentStartTime: number | undefined, forced: boolean): ISerializedItem | undefined; -} - -export type LogItemValues = { - l?: string; - t?: string; - id?: unknown; - status?: string | number; - refId?: number; - ref?: number; - [key: string]: any -} - -export type LabelOrValues = string | LogItemValues; -export type FilterCreator = ((filter: LogFilter, item: ILogItem) => LogFilter); -export type LogCallback = (item: ILogItem) => T; +import type {ISerializedItem, ILogItem, LogItemValues, LabelOrValues, FilterCreator, LogCallback} from "./types"; export class LogItem implements ILogItem { public readonly start: number; diff --git a/src/logging/NullLogger.ts b/src/logging/NullLogger.ts index eba453e6..ed12cd78 100644 --- a/src/logging/NullLogger.ts +++ b/src/logging/NullLogger.ts @@ -14,20 +14,20 @@ See the License for the specific language governing permissions and limitations under the License. */ import {LogLevel} from "./LogFilter"; -import type {ILogItem, LabelOrValues, LogCallback, LogItemValues} from "./LogItem"; +import type {ILogger, ILogExport, ILogItem, LabelOrValues, LogCallback, LogItemValues} from "./types"; function noop (): void {} -export class NullLogger { +export class NullLogger implements ILogger { public readonly item: ILogItem = new NullLogItem(this); log(): void {} - run(_, callback: LogCallback): T | Promise { + run(_, callback: LogCallback): T { return callback(this.item); } - wrapOrRun(item: ILogItem, _, callback: LogCallback): T | Promise { + wrapOrRun(item: ILogItem | undefined, _, callback: LogCallback): T { if (item) { return item.wrap(_, callback); } else { @@ -35,12 +35,13 @@ export class NullLogger { } } - runDetached(_, callback) { + runDetached(_, callback): ILogItem { new Promise(r => r(callback(this.item))).then(noop, noop); + return this.item; } - async export(): Promise { - return null; + async export(): Promise { + return undefined; } get level(): typeof LogLevel { diff --git a/src/logging/types.ts b/src/logging/types.ts new file mode 100644 index 00000000..6a29a7a2 --- /dev/null +++ b/src/logging/types.ts @@ -0,0 +1,87 @@ +/* +Copyright 2020 Bruno Windels +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 {LogLevel, LogFilter} from "./LogFilter"; +import type {BaseLogger} from "./BaseLogger"; +import type {BlobHandle} from "../platform/web/dom/BlobHandle.js"; + +export interface ISerializedItem { + s: number; + d?: number; + v: LogItemValues; + l: LogLevel; + e?: { + stack?: string; + name: string; + message: string; + }; + f?: boolean; + c?: Array; +}; + +export interface ILogItem { + logger: any; + level: typeof LogLevel; + duration?: number; + end?: number; + start?: number; + logLevel: LogLevel; + children?: Array; + values: LogItemValues; + error?: Error; + wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T; + log(labelOrValues: LabelOrValues, logLevel?: LogLevel): void; + set(key: string | object, value: unknown): void; + run(callback: LogCallback): T; + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; + wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): void; + refDetached(logItem: ILogItem, logLevel?: LogLevel): void; + ensureRefId(): void; + catch(err: Error): Error; + finish(): void; + child(labelOrValues: LabelOrValues, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; + serialize(filter: LogFilter, parentStartTime: number | undefined, forced: boolean): ISerializedItem | undefined; +} + +export interface ILogger { + log(labelOrValues: LabelOrValues, logLevel?: LogLevel): void; + wrapOrRun(item: ILogItem | undefined, labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T; + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; + run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T; + export(): Promise; + get level(): typeof LogLevel; +} + +export interface ILogExport { + get count(): number; + removeFromStore(): Promise; + asBlob(): BlobHandle; +} + +export type LogItemValues = { + l?: string; + t?: string; + id?: unknown; + status?: string | number; + refId?: number; + ref?: number; + [key: string]: any +} + +export type LabelOrValues = string | LogItemValues; +export type FilterCreator = ((filter: LogFilter, item: ILogItem) => LogFilter); +export type LogCallback = (item: ILogItem) => T; diff --git a/src/logging/utils.ts b/src/logging/utils.ts index 61cbce80..2b32454d 100644 --- a/src/logging/utils.ts +++ b/src/logging/utils.ts @@ -2,7 +2,7 @@ // if you know you always have a log item, better to use the methods on the log item than these utility functions. import {Instance as NullLoggerInstance} from "./NullLogger"; -import type {FilterCreator, ILogItem, LabelOrValues, LogCallback} from "./LogItem"; +import type {FilterCreator, ILogItem, LabelOrValues, LogCallback} from "./types"; import {LogLevel} from "./LogFilter"; export function wrapOrRunNullLogger(logItem: ILogItem | undefined, labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T | Promise { diff --git a/src/matrix/e2ee/megolm/Decryption.ts b/src/matrix/e2ee/megolm/Decryption.ts index ee96eca1..e139e8c9 100644 --- a/src/matrix/e2ee/megolm/Decryption.ts +++ b/src/matrix/e2ee/megolm/Decryption.ts @@ -26,7 +26,7 @@ import type {OlmWorker} from "../OlmWorker"; import type {Transaction} from "../../storage/idb/Transaction"; import type {TimelineEvent} from "../../storage/types"; import type {DecryptionResult} from "../DecryptionResult"; -import type {ILogItem} from "../../../logging/LogItem"; +import type {ILogItem} from "../../../logging/types"; export class Decryption { private keyLoader: KeyLoader; diff --git a/src/matrix/storage/idb/QueryTarget.ts b/src/matrix/storage/idb/QueryTarget.ts index 7519beac..5bea1139 100644 --- a/src/matrix/storage/idb/QueryTarget.ts +++ b/src/matrix/storage/idb/QueryTarget.ts @@ -16,7 +16,7 @@ limitations under the License. import {iterateCursor, DONE, NOT_DONE, reqAsPromise} from "./utils"; import {StorageError} from "../common"; -import {ILogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/types"; import {IDBKey} from "./Transaction"; // this is the part of the Transaction class API that is used here and in the Store subclass, diff --git a/src/matrix/storage/idb/Storage.ts b/src/matrix/storage/idb/Storage.ts index 728d4fca..6f3ed8ad 100644 --- a/src/matrix/storage/idb/Storage.ts +++ b/src/matrix/storage/idb/Storage.ts @@ -18,7 +18,7 @@ import {IDOMStorage} from "./types"; import {Transaction} from "./Transaction"; import { STORE_NAMES, StoreNames, StorageError } from "../common"; import { reqAsPromise } from "./utils"; -import { BaseLogger } from "../../../logging/BaseLogger"; +import { ILogger } from "../../../logging/types"; const WEBKITEARLYCLOSETXNBUG_BOGUS_KEY = "782rh281re38-boguskey"; @@ -26,13 +26,13 @@ export class Storage { private _db: IDBDatabase; private _hasWebkitEarlyCloseTxnBug: boolean; - readonly logger: BaseLogger; + readonly logger: ILogger; readonly idbFactory: IDBFactory readonly IDBKeyRange: typeof IDBKeyRange; readonly storeNames: typeof StoreNames; readonly localStorage: IDOMStorage; - constructor(idbDatabase: IDBDatabase, idbFactory: IDBFactory, _IDBKeyRange: typeof IDBKeyRange, hasWebkitEarlyCloseTxnBug: boolean, localStorage: IDOMStorage, logger: BaseLogger) { + constructor(idbDatabase: IDBDatabase, idbFactory: IDBFactory, _IDBKeyRange: typeof IDBKeyRange, hasWebkitEarlyCloseTxnBug: boolean, localStorage: IDOMStorage, logger: ILogger) { this._db = idbDatabase; this.idbFactory = idbFactory; this.IDBKeyRange = _IDBKeyRange; diff --git a/src/matrix/storage/idb/StorageFactory.ts b/src/matrix/storage/idb/StorageFactory.ts index 3c7e0e40..5cb1b6e5 100644 --- a/src/matrix/storage/idb/StorageFactory.ts +++ b/src/matrix/storage/idb/StorageFactory.ts @@ -20,8 +20,7 @@ import { openDatabase, reqAsPromise } from "./utils"; import { exportSession, importSession, Export } from "./export"; import { schema } from "./schema"; import { detectWebkitEarlyCloseTxnBug } from "./quirks"; -import { BaseLogger } from "../../../logging/BaseLogger"; -import { ILogItem } from "../../../logging/LogItem"; +import { ILogItem } from "../../../logging/types"; const sessionName = (sessionId: string) => `hydrogen_session_${sessionId}`; const openDatabaseWithSessionId = function(sessionId: string, idbFactory: IDBFactory, localStorage: IDOMStorage, log: ILogItem) { diff --git a/src/matrix/storage/idb/Store.ts b/src/matrix/storage/idb/Store.ts index 5a2a9abc..07cc90b0 100644 --- a/src/matrix/storage/idb/Store.ts +++ b/src/matrix/storage/idb/Store.ts @@ -18,7 +18,7 @@ import {QueryTarget, IDBQuery, ITransaction} from "./QueryTarget"; import {IDBRequestError, IDBRequestAttemptError} from "./error"; import {reqAsPromise} from "./utils"; import {Transaction, IDBKey} from "./Transaction"; -import {ILogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/types"; const LOG_REQUESTS = false; diff --git a/src/matrix/storage/idb/Transaction.ts b/src/matrix/storage/idb/Transaction.ts index 4c3d2b5c..80894105 100644 --- a/src/matrix/storage/idb/Transaction.ts +++ b/src/matrix/storage/idb/Transaction.ts @@ -36,8 +36,7 @@ import {OutboundGroupSessionStore} from "./stores/OutboundGroupSessionStore"; import {GroupSessionDecryptionStore} from "./stores/GroupSessionDecryptionStore"; import {OperationStore} from "./stores/OperationStore"; import {AccountDataStore} from "./stores/AccountDataStore"; -import {ILogItem} from "../../../logging/LogItem"; -import {BaseLogger} from "../../../logging/BaseLogger"; +import type {ILogger, ILogItem} from "../../../logging/types"; export type IDBKey = IDBValidKey | IDBKeyRange; @@ -77,7 +76,7 @@ export class Transaction { return this._storage.databaseName; } - get logger(): BaseLogger { + get logger(): ILogger { return this._storage.logger; } diff --git a/src/matrix/storage/idb/schema.ts b/src/matrix/storage/idb/schema.ts index 6250980d..ad3e5896 100644 --- a/src/matrix/storage/idb/schema.ts +++ b/src/matrix/storage/idb/schema.ts @@ -11,7 +11,7 @@ import {SessionStore} from "./stores/SessionStore"; import {Store} from "./Store"; import {encodeScopeTypeKey} from "./stores/OperationStore"; import {MAX_UNICODE} from "./stores/common"; -import {ILogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/types"; export type MigrationFunc = (db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: ILogItem) => Promise | void; diff --git a/src/matrix/storage/idb/stores/SessionStore.ts b/src/matrix/storage/idb/stores/SessionStore.ts index dd133b45..7faedc41 100644 --- a/src/matrix/storage/idb/stores/SessionStore.ts +++ b/src/matrix/storage/idb/stores/SessionStore.ts @@ -16,8 +16,8 @@ limitations under the License. import {Store} from "../Store"; import {IDOMStorage} from "../types"; import {SESSION_E2EE_KEY_PREFIX} from "../../../e2ee/common.js"; -import {ILogItem} from "../../../../logging/LogItem"; import {parse, stringify} from "../../../../utils/typedJSON"; +import type {ILogItem} from "../../../../logging/types"; export interface SessionEntry { key: string; diff --git a/src/matrix/storage/idb/stores/TimelineEventStore.ts b/src/matrix/storage/idb/stores/TimelineEventStore.ts index b3663c29..bb6f652f 100644 --- a/src/matrix/storage/idb/stores/TimelineEventStore.ts +++ b/src/matrix/storage/idb/stores/TimelineEventStore.ts @@ -20,7 +20,7 @@ import { encodeUint32, decodeUint32 } from "../utils"; import {KeyLimits} from "../../common"; import {Store} from "../Store"; import {TimelineEvent, StateEvent} from "../../types"; -import {ILogItem} from "../../../../logging/LogItem"; +import {ILogItem} from "../../../../logging/types"; interface Annotation { count: number; From 5f362cbdbde6b17cfe28e6b39e38d8e8a2245b9a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 11:54:29 +0100 Subject: [PATCH 105/242] remove dead code --- src/logging/ConsoleLogger.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/logging/ConsoleLogger.ts b/src/logging/ConsoleLogger.ts index 20fdf6a6..f2a2efd1 100644 --- a/src/logging/ConsoleLogger.ts +++ b/src/logging/ConsoleLogger.ts @@ -28,10 +28,6 @@ export class ConsoleLogger extends BaseLogger { const excludedKeysFromTable = ["l", "id"]; function filterValues(values: LogItemValues): LogItemValues | null { - if (!values) { - // todo: is this check here unnecessary because LogItem will always have values? - return null; - } return Object.entries(values) .filter(([key]) => !excludedKeysFromTable.includes(key)) .reduce((obj: LogItemValues, [key, value]) => { From b1d20178f816addce705fa143f87a8d1009f013e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 12:37:50 +0100 Subject: [PATCH 106/242] add explicit void return type --- src/logging/BaseLogger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 7d015262..6ff50b98 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -28,7 +28,7 @@ export abstract class BaseLogger implements ILogger { this._platform = platform; } - log(labelOrValues: LabelOrValues, logLevel: LogLevel = LogLevel.Info) { + log(labelOrValues: LabelOrValues, logLevel: LogLevel = LogLevel.Info): void { const item = new LogItem(labelOrValues, logLevel, this); item.end = item.start; this._persistItem(item, undefined, false); From 276d8d4a42c4532fc6fcecb6dbe5b4b4f219a18f Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 12:39:57 +0100 Subject: [PATCH 107/242] check for undefined, no need for ! --- src/logging/BaseLogger.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 6ff50b98..2f7389ab 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -61,11 +61,11 @@ export abstract class BaseLogger implements ILogger { Errors and duration are transparently logged, also for async operations. Whatever the callback returns is returned here. */ run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T { - if (!logLevel) { + if (logLevel === undefined) { logLevel = LogLevel.Info; } const item = new LogItem(labelOrValues, logLevel, this); - return this._run(item, callback, logLevel!, true, filterCreator); + return this._run(item, callback, logLevel, true, filterCreator); } _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, wantResult: true, filterCreator?: FilterCreator): T; From 46dd78162fa9f6f467193e381e287319064c0c4a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 12:54:32 +0100 Subject: [PATCH 108/242] no need to dig into internals here --- 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 7774dd41..1d9ce20b 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -52,7 +52,7 @@ export class LogItem implements ILogItem { This is useful if the referenced operation can't be awaited. */ refDetached(logItem: ILogItem, logLevel?: LogLevel): void { logItem.ensureRefId(); - this.log({ref: (logItem as LogItem)._values.refId}, logLevel); + this.log({ref: logItem.values.refId}, logLevel); } ensureRefId(): void { From 74fb15e426c549f3ff3d29c8d9aead918298fac4 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 12:54:44 +0100 Subject: [PATCH 109/242] add future todo note --- src/logging/IDBLogger.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index 621359dc..96147ca1 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -51,6 +51,7 @@ export class IDBLogger extends BaseLogger { this._flushInterval = this._platform.clock.createInterval(() => this._tryFlush(), flushInterval); } + // TODO: move dispose to ILogger, listen to pagehide elsewhere and call dispose from there, which calls _finishAllAndFlush dispose(): void { window.removeEventListener("pagehide", this, false); this._flushInterval.dispose(); From afc538e87598a7bfa82c5158ce5f2c8d20353131 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 12:58:08 +0100 Subject: [PATCH 110/242] explicitly check for type, rather than truthy --- 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 1d9ce20b..0e5b0ecb 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -144,7 +144,7 @@ export class LogItem implements ILogItem { // in (v)alues, (l)abel and (t)ype are also reserved. const item: ISerializedItem = { // (s)tart - s: parentStartTime? this.start - parentStartTime : this.start, + s: typeof parentStartTime === "number" ? this.start - parentStartTime : this.start, // (d)uration d: this.duration, // (v)alues From 526a81826936eb23454ffbeccb17043bb65de69e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 13:42:49 +0100 Subject: [PATCH 111/242] only used internally --- src/logging/types.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/logging/types.ts b/src/logging/types.ts index 6a29a7a2..280b5606 100644 --- a/src/logging/types.ts +++ b/src/logging/types.ts @@ -46,7 +46,6 @@ export interface ILogItem { wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T; log(labelOrValues: LabelOrValues, logLevel?: LogLevel): void; set(key: string | object, value: unknown): void; - run(callback: LogCallback): T; runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): void; refDetached(logItem: ILogItem, logLevel?: LogLevel): void; From 42e5fb33ba9071cc8f0b47e2a335ac40299dbc47 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 13:50:56 +0100 Subject: [PATCH 112/242] remove more non-public methods from ILogItem interface --- src/logging/BaseLogger.ts | 8 ++++---- src/logging/LogItem.ts | 2 +- src/logging/types.ts | 2 -- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 2f7389ab..7112c948 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -21,7 +21,7 @@ import type {ILogger, ILogExport, FilterCreator, LabelOrValues, LogCallback, ILo import type {Platform} from "../platform/web/Platform.js"; export abstract class BaseLogger implements ILogger { - protected _openItems: Set = new Set(); + protected _openItems: Set = new Set(); protected _platform: Platform; constructor({platform}) { @@ -68,10 +68,10 @@ export abstract class BaseLogger implements ILogger { return this._run(item, callback, logLevel, true, filterCreator); } - _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, wantResult: true, filterCreator?: FilterCreator): T; + _run(item: LogItem, callback: LogCallback, logLevel: LogLevel, wantResult: true, filterCreator?: FilterCreator): T; // we don't return if we don't throw, as we don't have anything to return when an error is caught but swallowed for the fire-and-forget case. - _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, wantResult: false, filterCreator?: FilterCreator): void; - _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, wantResult: boolean, filterCreator?: FilterCreator): T | void { + _run(item: LogItem, callback: LogCallback, logLevel: LogLevel, wantResult: false, filterCreator?: FilterCreator): void; + _run(item: LogItem, callback: LogCallback, logLevel: LogLevel, wantResult: boolean, filterCreator?: FilterCreator): T | void { this._openItems.add(item); const finishItem = () => { diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 0e5b0ecb..4fb8daa0 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -233,7 +233,7 @@ export class LogItem implements ILogItem { return err; } - child(labelOrValues: LabelOrValues, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem { + child(labelOrValues: LabelOrValues, logLevel?: LogLevel, filterCreator?: FilterCreator): LogItem { if (this.end) { console.trace("log item is finished, additional logs will likely not be recorded"); } diff --git a/src/logging/types.ts b/src/logging/types.ts index 280b5606..f90572e5 100644 --- a/src/logging/types.ts +++ b/src/logging/types.ts @@ -51,8 +51,6 @@ export interface ILogItem { refDetached(logItem: ILogItem, logLevel?: LogLevel): void; ensureRefId(): void; catch(err: Error): Error; - finish(): void; - child(labelOrValues: LabelOrValues, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; serialize(filter: LogFilter, parentStartTime: number | undefined, forced: boolean): ISerializedItem | undefined; } From fde0163b978dcc1d9dfc969ad3547c8212514a23 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 13:53:27 +0100 Subject: [PATCH 113/242] remove unneeded union type and simplify code --- src/logging/LogItem.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 4fb8daa0..f9262db7 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -187,9 +187,8 @@ export class LogItem implements ILogItem { if (this.end) { console.trace("log item is finished, additional logs will likely not be recorded"); } - let result: T | Promise; try { - result = callback(this); + const result = callback(this); if (result instanceof Promise) { return result.then(promiseResult => { this.finish(); From 41a10d9697c8424ec93ca8d2d1820705cfab1161 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 13:56:20 +0100 Subject: [PATCH 114/242] explicitly check for undefined --- 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 f9262db7..cd5a5a8b 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -184,7 +184,7 @@ export class LogItem implements ILogItem { * @return {[type]} [description] */ run(callback: LogCallback): T { - if (this.end) { + if (this.end !== undefined) { console.trace("log item is finished, additional logs will likely not be recorded"); } try { From 4030a4918d13ebfa72f7d1f7205546fa3fda6a12 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 13:57:11 +0100 Subject: [PATCH 115/242] explicitly check for undefined --- 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 cd5a5a8b..da009b06 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -210,7 +210,7 @@ export class LogItem implements ILogItem { * @internal shouldn't typically be called by hand. allows to force finish if a promise is still running when closing the app */ finish(): void { - if (!this.end) { + if (this.end === undefined) { if (this._children) { for(const c of this._children) { c.finish(); From b5e9eb26baf4a0dd71f0d9c69a898fd747f59a71 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 14:33:58 +0100 Subject: [PATCH 116/242] reduce size of ILogItem interface further --- src/logging/BaseLogger.ts | 2 +- src/logging/ConsoleLogger.ts | 5 +++-- src/logging/types.ts | 12 +++++------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 7112c948..723c2f17 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -139,7 +139,7 @@ export abstract class BaseLogger implements ILogger { this._openItems.clear(); } - abstract _persistItem(item: ILogItem, filter?: LogFilter, forced?: boolean): void; + abstract _persistItem(item: LogItem, filter?: LogFilter, forced?: boolean): void; abstract export(): Promise; diff --git a/src/logging/ConsoleLogger.ts b/src/logging/ConsoleLogger.ts index f2a2efd1..f48c72b2 100644 --- a/src/logging/ConsoleLogger.ts +++ b/src/logging/ConsoleLogger.ts @@ -14,10 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ import {BaseLogger} from "./BaseLogger"; +import {LogItem} from "./LogItem"; import type {ILogItem, LogItemValues, ILogExport} from "./types"; export class ConsoleLogger extends BaseLogger { - _persistItem(item: ILogItem): void { + _persistItem(item: LogItem): void { printToConsole(item); } @@ -37,7 +38,7 @@ function filterValues(values: LogItemValues): LogItemValues | null { }, null); } -function printToConsole(item: ILogItem): void { +function printToConsole(item: LogItem): void { const label = `${itemCaption(item)} (${item.duration}ms)`; const filteredValues = filterValues(item.values); const shouldGroup = item.children || filteredValues; diff --git a/src/logging/types.ts b/src/logging/types.ts index f90572e5..01755960 100644 --- a/src/logging/types.ts +++ b/src/logging/types.ts @@ -34,15 +34,13 @@ export interface ISerializedItem { }; export interface ILogItem { - logger: any; - level: typeof LogLevel; - duration?: number; - end?: number; - start?: number; logLevel: LogLevel; - children?: Array; - values: LogItemValues; error?: Error; + readonly logger: ILogger; + readonly level: typeof LogLevel; + readonly end?: number; + readonly start?: number; + readonly values: LogItemValues; wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T; log(labelOrValues: LabelOrValues, logLevel?: LogLevel): void; set(key: string | object, value: unknown): void; From 692ae25e76efd348f84e2946e6c2945c56467524 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 14:35:26 +0100 Subject: [PATCH 117/242] remove unused method --- src/logging/NullLogger.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/logging/NullLogger.ts b/src/logging/NullLogger.ts index ed12cd78..5ec38aa9 100644 --- a/src/logging/NullLogger.ts +++ b/src/logging/NullLogger.ts @@ -76,10 +76,6 @@ export class NullLogItem implements ILogItem { return this.refDetached(); } - run(callback: LogCallback): T { - return callback(this); - } - refDetached(): void {} ensureRefId(): void {} From 0a433b90e3ff1b5797c0de2b7b303ce4bf2bd6fe Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Nov 2021 15:09:25 +0100 Subject: [PATCH 118/242] packages processed by post-install need to be in dependencies, or the script fails --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b391a3c0..60b9e55c 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,6 @@ "finalhandler": "^1.1.1", "impunity": "^1.0.1", "mdn-polyfills": "^5.20.0", - "node-html-parser": "^4.0.0", "postcss": "^8.1.1", "postcss-css-variables": "^0.17.0", "postcss-flexbugs-fixes": "^4.2.1", @@ -55,6 +54,7 @@ "xxhashjs": "^0.2.2" }, "dependencies": { + "node-html-parser": "^4.0.0", "@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.3.tgz", "@rollup/plugin-commonjs": "^15.0.0", "@rollup/plugin-json": "^4.1.0", From 7772643b0d34357dd7c9aa08c0689164c6ddf862 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 15 Nov 2021 12:45:27 +0530 Subject: [PATCH 119/242] 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 120/242] 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 121/242] 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 122/242] 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 123/242] 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 124/242] 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 125/242] 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 126/242] 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 127/242] 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 128/242] 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 129/242] 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 130/242] 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 131/242] 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 132/242] 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 133/242] 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 134/242] 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 135/242] 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 136/242] 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 137/242] 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 138/242] 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 139/242] 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 140/242] 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 141/242] 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 142/242] 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 143/242] 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 144/242] 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 6980921dab5381448381c5b5d32e513946cf9493 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 18 Nov 2021 14:16:10 +0000 Subject: [PATCH 145/242] some impl notes for SDK --- doc/impl-thoughts/SDK.md | 97 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 doc/impl-thoughts/SDK.md diff --git a/doc/impl-thoughts/SDK.md b/doc/impl-thoughts/SDK.md new file mode 100644 index 00000000..0faea2f2 --- /dev/null +++ b/doc/impl-thoughts/SDK.md @@ -0,0 +1,97 @@ +SDK: + + - we need to compile src/lib.ts to javascript, with a d.ts file generated as well. We need to compile to javascript once for cjs and once of es modules. The package.json looks like this: + +we don't need to bundle for the sdk case! we might need to do some transpilation to just plain ES6 (e.g. don't assume ?. and ??) we could use a browserslist query for this e.g. `node 14`. esbuild seems to support this as well, tldraw uses esbuild for their build. + +one advantage of not bundling the files for the sdk is that you can still use import overrides in the consuming project build settings. is that an idiomatic way of doing things though? + + + +``` +"main": "./dist/index.cjs", + "exports": { + "import": "./dist/index.mjs", + "require": "./dist/index.cjs" + }, + "types": "dist/index.d.ts", +``` + +this way we will support typescript, non-esm javascript and esm javascript using libhydrogen as an SDK + +got this from https://medium.com/dazn-tech/publishing-npm-packages-as-native-es-modules-41ffbc0a9dea + +how about the assets? + +we also need to build the app + +we need to be able to version libhydrogen independently from hydrogen the app? as any api breaking changes will need a major version increase. we probably want to end up with a monorepo where the app uses the sdk as well and we just use the local code with yarn link? + +## Assets + +we want to provide scss/sass files, but also css that can be included +https://github.com/webpack/webpack/issues/7353 seems to imply that we just need to include the assets in the published files and from there on it is the consumer of libhydrogen's problem. + + +how does all of this tie in with vite? + + +we want to have hydrogenapp be a consumer of libhydrogen, potentially as two packages in a monorepo ... but we want the SDK to expose views and stylesheets... without having an index.html (which would be in hydrogenapp). this seems a bit odd...? + +what would be in hydrogenapp actually? just an index.html file? + +I'm not sure it makes sense to have them be 2 different packages in a monorepo, they should really be two artifacts from the same directory. + +the stylesheets included in libhydrogen are from the same main.css file as is used in the app + +https://www.freecodecamp.org/news/build-a-css-library-with-vitejs/ + +basically, we import the sass file from src/lib.ts so it is included in the assets there too, and we also create a plugin that emits a file for every sass file as suggested in the link above? + +we probably want two different build commands for the app and the sdk though, we could have a parent vite config that both build configs extend from? + + +### Dependency assets +our dependencies should not be bundled for the SDK case. So if we import aesjs, it would be up to the build system of the consuming project to make that import work. + +the paths.ts thingy ... we want to make it easy for people to setup the assets for our dependencies (olm), some assets are also part of the sdk itself. it might make sense to make all of the assets there part of the sdk (e.g. bundle olm.wasm and friends?) although shipping crypto, etc ... + +perhaps we should have an include file per build system that treats own assets and dep assets the same by including the package name as wel for our own deps: +```js +import _downloadSandboxPath from "@matrix-org/hydrogen-sdk/download-sandbox.html?url"; +import _serviceWorkerPath from "@matrix-org/hydrogen-sdk/sw.js?url"; // not yet sure this is the way to do it +import olmWasmPath from "@matrix-org/olm/olm.wasm?url"; +import olmJsPath from "@matrix-org/olm/olm.js?url"; +import olmLegacyJsPath from "@matrix-org/olm/olm_legacy.js?url"; + +export const olmPaths = { + wasm: olmWasmPath, + legacyBundle: olmLegacyJsPath, + wasmBundle: olmJsPath, +}; + +export const downloadSandboxPath = _downloadSandboxPath; +``` + +we could put this file per build system, as ESM, in dist as well so you can include it to get the paths + + +## Tooling + + - `vite` a more high-level build tool that takes your index.html and turns it into optimized assets that you can host for production, as well as a very fast dev server. is used to have good default settings for our tools, typescript support, and also deals with asset compiling. good dev server. Would be nice to have the same tool for dev and prod. vite has good support for using `import` for anything that is not javascript, where we had an issue with `snowpack` (to get the prod path of an asset). + - `rollup`: inlines + - `lerna` is used to handle multi-package monorepos + - `esbuild`: a js/ts build tool that we could use for building the lower level sdk where no other assets are involved, `vite` uses it for fast dev builds (`rollup` for prod). For now we won't extract a lower level sdk though. + + +## TODO + + - finish vite app build (without IE11 for now?) + - create vite config to build src/lib.ts in cjs and esm, inheriting from a common base config with the app config + - this will create a dist folder with + - the whole source tree in es and cjs format + - an es file to import get the asset paths as they are expected by Platform, per build system + - assets from hydrogen itself: + - css files and any resource used therein + - download-sandbox.html + - a type declaration file (index.d.ts) From f23227fc8b385bc9d72f7b51c272a59f4fef9e2b Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 19 Nov 2021 10:22:59 +0100 Subject: [PATCH 146/242] use latest version of impunity with support for multiple entry points --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b391a3c0..7f584ee3 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.1", + "impunity": "^1.0.3", "mdn-polyfills": "^5.20.0", "node-html-parser": "^4.0.0", "postcss": "^8.1.1", From ec71e30ecb76551ec6fdb2e3c96ae3aee8eae9e0 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 19 Nov 2021 10:23:18 +0100 Subject: [PATCH 147/242] add Platform as entry point so also platform dependant code gets searched for tests --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7f584ee3..d7d0bc5d 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "lint": "eslint --cache src/", "lint-ts": "eslint src/ -c .ts-eslintrc.js --ext .ts", "lint-ci": "eslint src/", - "test": "impunity --entry-point src/main.js --force-esm-dirs lib/ src/", + "test": "impunity --entry-point src/main.js src/platform/web/Platform.js --force-esm-dirs lib/ src/", "start": "snowpack dev --port 3000", "build": "node --experimental-modules scripts/build.mjs", "postinstall": "node ./scripts/post-install.js" From f1a6a4924ec1a0c703f8437a228df1e2d9b850e0 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 19 Nov 2021 10:23:59 +0100 Subject: [PATCH 148/242] commit yarn.lock too --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index fc159a40..830a5cd5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3021,10 +3021,10 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -impunity@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/impunity/-/impunity-1.0.1.tgz#e1d19c468bd7b8ae3dc7ad44ccbe81f17c626fde" - integrity sha512-MbQ6+UcLNdpMZPBYvr0OLY3pQCr8UMjMK45YCIrRFsZUO9hj/eMurLjpjiO3HBgCkZcw+5FlU6JCHjm5Q3u7mw== +impunity@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/impunity/-/impunity-1.0.3.tgz#1e9972d137f0e0dbed4d39e6eca6c238a29b6526" + integrity sha512-D3XT8ED/AX5mbSQdAf0nz+65ilZE/q17Yykx8g7FqlnKjDdoowFv9kxdS4tOggPrJY/5lAfE86/ZFa878VpZBw== dependencies: colors "^1.3.3" commander "^6.1.0" From d4e923f9de02168e2e049cf83932aaf41a0ac8cc Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sat, 24 Jul 2021 13:42:57 +0530 Subject: [PATCH 149/242] Remove code from loadList We don't need this method so best to leave it empty. Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/LazyListView.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index 4426d97c..b6b4b0d1 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -168,6 +168,8 @@ export class LazyListView extends ListView { mount() { const root = super.mount(); + this._subscription = this._list.subscribe(this); + this._childInstances = []; this._parent = el("div", {className: "LazyListParent"}, root); /* Hooking to scroll events can be expensive. @@ -181,17 +183,12 @@ export class LazyListView extends ListView { update(attributes) { this._renderRange = null; super.update(attributes); + this._childInstances = []; this._initialRender(); } loadList() { - if (!this._list) { return; } - this._subscription = this._list.subscribe(this); - this._childInstances = []; - /* - super.loadList() would render the entire list at this point. - We instead lazy render a part of the list in _renderIfNeeded - */ + // We don't render the entire list; so nothing to see here. } _removeChild(child) { From 1a28b4f887eb49841e53e5ee078aa9bc1f6d93f8 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sun, 25 Jul 2021 19:48:51 +0530 Subject: [PATCH 150/242] WIP --- src/platform/web/ui/general/LazyListView.js | 38 +++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index b6b4b0d1..a8c686eb 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -19,6 +19,11 @@ import {mountView} from "./utils"; import {ListView} from "./ListView"; import {insertAt} from "./utils"; +class ScrollDirection { + static get downwards() { return 1; } + static get upwards() { return -1; } +} + class ItemRange { constructor(topCount, renderCount, bottomCount) { this.topCount = topCount; @@ -56,6 +61,10 @@ class ItemRange { ); } + get lastIndex() { + return this.topCount + this.renderCount; + } + totalSize() { return this.topCount + this.renderCount + this.bottomCount; } @@ -69,6 +78,23 @@ class ItemRange { */ return idx - this.topCount; } + + scrollDirectionTo(range) { + return range.bottomCount < this.bottomCount ? ScrollDirection.downwards : ScrollDirection.upwards; + } + + diff(range) { + const diffResult = {}; + if (this.scrollDirectionTo(range) === ScrollDirection.downwards) { + diffResult.toRemove = { start: this.topCount, end: range.topCount - 1 }; + diffResult.toAdd = { start: this.lastIndex + 1, end: range.lastIndex }; + } + else { + diffResult.toRemove = { start: range.lastIndex + 1, end: this.lastIndex }; + diffResult.toAdd = { start: range.topCount, end: this.topCount - 1 }; + } + return diffResult; + } } export class LazyListView extends ListView { @@ -101,6 +127,9 @@ export class LazyListView extends ListView { // only update render Range if the new range + overflowMargin isn't contained by the old anymore // or if we are force rendering if (forceRender || !this._renderRange.contains(intersectRange)) { + console.log("new", renderRange); + console.log("current", this._renderRange); + console.log("diff", this._renderRange.diff(renderRange)); this._renderRange = renderRange; this._renderElementsInRange(); } @@ -146,13 +175,18 @@ export class LazyListView extends ListView { return null; } - _renderElementsInRange() { + _adjustPadding() { + + } + + _renderElementsInRange(range) { const { topCount, renderCount, bottomCount } = this._renderRange; + const renderedItems = this._itemsFromList(topCount, topCount + renderCount); const paddingTop = topCount * this._itemHeight; const paddingBottom = bottomCount * this._itemHeight; - const renderedItems = this._itemsFromList(topCount, topCount + renderCount); this._root.style.paddingTop = `${paddingTop}px`; this._root.style.paddingBottom = `${paddingBottom}px`; + for (const child of this._childInstances) { this._removeChild(child); } From 61402e798e878da08d5b3d4e6873f047790bd67a Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 27 Jul 2021 13:24:36 +0530 Subject: [PATCH 151/242] WIP 2 --- src/platform/web/ui/general/LazyListView.js | 88 +++++++++++++++------ 1 file changed, 64 insertions(+), 24 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index a8c686eb..299e511c 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -84,16 +84,17 @@ class ItemRange { } diff(range) { - const diffResult = {}; - if (this.scrollDirectionTo(range) === ScrollDirection.downwards) { - diffResult.toRemove = { start: this.topCount, end: range.topCount - 1 }; - diffResult.toAdd = { start: this.lastIndex + 1, end: range.lastIndex }; + const scrollDirection = this.scrollDirectionTo(range); + let toRemove, toAdd; + if (scrollDirection === ScrollDirection.downwards) { + toRemove = { start: this.topCount, end: range.topCount - 1 }; + toAdd = { start: this.lastIndex, end: range.lastIndex }; } else { - diffResult.toRemove = { start: range.lastIndex + 1, end: this.lastIndex }; - diffResult.toAdd = { start: range.topCount, end: this.topCount - 1 }; + toRemove = { start: range.lastIndex, end: this.lastIndex }; + toAdd = { start: range.topCount, end: this.topCount - 1 }; } - return diffResult; + return { toRemove, toAdd, scrollDirection }; } } @@ -130,8 +131,7 @@ export class LazyListView extends ListView { console.log("new", renderRange); console.log("current", this._renderRange); console.log("diff", this._renderRange.diff(renderRange)); - this._renderRange = renderRange; - this._renderElementsInRange(); + this._renderElementsInRange(renderRange); } } @@ -149,7 +149,18 @@ export class LazyListView extends ListView { const range = this._getVisibleRange(); const renderRange = range.expand(this._overflowItems); this._renderRange = renderRange; - this._renderElementsInRange(); + + const { topCount, renderCount } = this._renderRange; + const renderedItems = this._itemsFromList(topCount, topCount + renderCount); + this._adjustPadding(renderRange); + this._childInstances = []; + const fragment = document.createDocumentFragment(); + for (const item of renderedItems) { + const view = this._childCreator(item); + this._childInstances.push(view); + fragment.appendChild(mountView(view, this._mountArgs)); + } + this._root.appendChild(fragment); } _itemsFromList(start, end) { @@ -175,29 +186,58 @@ export class LazyListView extends ListView { return null; } - _adjustPadding() { - - } - - _renderElementsInRange(range) { - const { topCount, renderCount, bottomCount } = this._renderRange; - const renderedItems = this._itemsFromList(topCount, topCount + renderCount); + _adjustPadding(range) { + const { topCount, bottomCount } = range; const paddingTop = topCount * this._itemHeight; const paddingBottom = bottomCount * this._itemHeight; this._root.style.paddingTop = `${paddingTop}px`; this._root.style.paddingBottom = `${paddingBottom}px`; + } - for (const child of this._childInstances) { - this._removeChild(child); - } - this._childInstances = []; + _renderedFragment(items, childInstanceModifier) { const fragment = document.createDocumentFragment(); - for (const item of renderedItems) { + for (const item of items) { const view = this._childCreator(item); - this._childInstances.push(view); + childInstanceModifier(view); fragment.appendChild(mountView(view, this._mountArgs)); } - this._root.appendChild(fragment); + return fragment; + } + + _renderElementsInRange(range) { + const diff = this._renderRange.diff(range); + const {start, end} = diff.toAdd; + const renderedItems = this._itemsFromList(start, end); + this._adjustPadding(range); + + if (diff.scrollDirection === ScrollDirection.downwards) { + const {start, end} = diff.toRemove; + this._childInstances.splice(0, end - start + 1) + .forEach(child => this._removeChild(child)); + const fragment = this._renderedFragment(renderedItems, view => this._childInstances.push(view)); + this._root.appendChild(fragment); + } + else { + const {start, end} = diff.toRemove; + const normalizedStart = this._renderRange.normalize(start); + this._childInstances.splice(normalizedStart, end - start + 1) + .forEach(child => this._removeChild(child)); + const fragment = this._renderedFragment(renderedItems, view => this._childInstances.unshift(view)); + this._root.insertBefore(fragment, this._root.firstChild); + } + this._renderRange = range; + // for (const child of this._childInstances) { + // this._removeChild(child); + // } + // this._childInstances = []; + + // const fragment = document.createDocumentFragment(); + // for (const item of renderedItems) { + // const view = this._childCreator(item); + // this._childInstances.push(view); + // fragment.appendChild(mountView(view, this._mountArgs)); + // } + // this._root.appendChild(fragment); } mount() { From 168312627df2cc3512f7f986489e44ed8085f1c5 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 9 Aug 2021 14:21:42 +0530 Subject: [PATCH 152/242] Render only diff of ranges Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/LazyListView.js | 52 ++++++++++++--------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index 299e511c..ffd834eb 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -83,18 +83,40 @@ class ItemRange { return range.bottomCount < this.bottomCount ? ScrollDirection.downwards : ScrollDirection.upwards; } + /** + * Check if this range intersects with another range + * @param {ItemRange} range The range to check against + * @param {ScrollDirection} scrollDirection + * @returns {Boolean} + */ + intersects(range) { + return !!Math.max(0, Math.min(this.lastIndex, range.lastIndex) - Math.max(this.topCount, range.topCount)); + } + diff(range) { + /** + * Range-1 + * |----------------------| + * Range-2 + * |---------------------| + * <-------><------------><-------> + * bisect-1 intersection bisect-2 + */ const scrollDirection = this.scrollDirectionTo(range); - let toRemove, toAdd; - if (scrollDirection === ScrollDirection.downwards) { - toRemove = { start: this.topCount, end: range.topCount - 1 }; - toAdd = { start: this.lastIndex, end: range.lastIndex }; + if (!this.intersects(range)) { + // There is no intersection between the ranges; which can happen if you scroll really fast + // In this case, we need to do full render of the new range + const toRemove = { start: this.topCount, end: this.lastIndex }; + const toAdd = { start: range.topCount, end: range.lastIndex }; + return {toRemove, toAdd, scrollDirection}; } - else { - toRemove = { start: range.lastIndex, end: this.lastIndex }; - toAdd = { start: range.topCount, end: this.topCount - 1 }; - } - return { toRemove, toAdd, scrollDirection }; + const bisection1 = {start: Math.min(this.topCount, range.topCount), end: Math.max(this.topCount, range.topCount) - 1}; + const bisection2 = {start: Math.min(this.lastIndex, range.lastIndex), end: Math.max(this.lastIndex, range.lastIndex)}; + // When scrolling down, bisection1 needs to be removed and bisection2 needs to be added + // When scrolling up, vice versa + const toRemove = scrollDirection === ScrollDirection.downwards ? bisection1 : bisection2; + const toAdd = scrollDirection === ScrollDirection.downwards ? bisection2 : bisection1; + return {toAdd, toRemove, scrollDirection}; } } @@ -226,18 +248,6 @@ export class LazyListView extends ListView { this._root.insertBefore(fragment, this._root.firstChild); } this._renderRange = range; - // for (const child of this._childInstances) { - // this._removeChild(child); - // } - // this._childInstances = []; - - // const fragment = document.createDocumentFragment(); - // for (const item of renderedItems) { - // const view = this._childCreator(item); - // this._childInstances.push(view); - // fragment.appendChild(mountView(view, this._mountArgs)); - // } - // this._root.appendChild(fragment); } mount() { From a02b6b68d3a81de9c5f06382a161cb3042bb34cf Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 9 Aug 2021 14:35:10 +0530 Subject: [PATCH 153/242] Move common code from if-else Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/LazyListView.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index ffd834eb..f0de677c 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -173,7 +173,7 @@ export class LazyListView extends ListView { this._renderRange = renderRange; const { topCount, renderCount } = this._renderRange; - const renderedItems = this._itemsFromList(topCount, topCount + renderCount); + const renderedItems = this._itemsFromList({ start: topCount, end: topCount + renderCount}); this._adjustPadding(renderRange); this._childInstances = []; const fragment = document.createDocumentFragment(); @@ -185,7 +185,7 @@ export class LazyListView extends ListView { this._root.appendChild(fragment); } - _itemsFromList(start, end) { + _itemsFromList({start, end}) { const array = []; let i = 0; for (const item of this._list) { @@ -228,22 +228,18 @@ export class LazyListView extends ListView { _renderElementsInRange(range) { const diff = this._renderRange.diff(range); - const {start, end} = diff.toAdd; - const renderedItems = this._itemsFromList(start, end); + const renderedItems = this._itemsFromList(diff.toAdd); this._adjustPadding(range); + const {start, end} = diff.toRemove; + const normalizedStart = this._renderRange.normalize(start); + this._childInstances.splice(normalizedStart, end - start + 1).forEach(child => this._removeChild(child)); + if (diff.scrollDirection === ScrollDirection.downwards) { - const {start, end} = diff.toRemove; - this._childInstances.splice(0, end - start + 1) - .forEach(child => this._removeChild(child)); const fragment = this._renderedFragment(renderedItems, view => this._childInstances.push(view)); this._root.appendChild(fragment); } else { - const {start, end} = diff.toRemove; - const normalizedStart = this._renderRange.normalize(start); - this._childInstances.splice(normalizedStart, end - start + 1) - .forEach(child => this._removeChild(child)); const fragment = this._renderedFragment(renderedItems, view => this._childInstances.unshift(view)); this._root.insertBefore(fragment, this._root.firstChild); } From 587dd3848e6517fb04c9eadcb091aaea3e275f53 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 9 Aug 2021 15:04:17 +0530 Subject: [PATCH 154/242] Use existing render function for initial render Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/LazyListView.js | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index f0de677c..aa38a4fb 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -168,21 +168,10 @@ export class LazyListView extends ListView { this._height = this._parent.clientHeight; if (this._height === 0) { console.error("LazyListView could not calculate parent height."); } - const range = this._getVisibleRange(); - const renderRange = range.expand(this._overflowItems); - this._renderRange = renderRange; - - const { topCount, renderCount } = this._renderRange; - const renderedItems = this._itemsFromList({ start: topCount, end: topCount + renderCount}); - this._adjustPadding(renderRange); - this._childInstances = []; - const fragment = document.createDocumentFragment(); - for (const item of renderedItems) { - const view = this._childCreator(item); - this._childInstances.push(view); - fragment.appendChild(mountView(view, this._mountArgs)); - } - this._root.appendChild(fragment); + const initialRange = this._getVisibleRange(); + const initialRenderRange = initialRange.expand(this._overflowItems); + this._renderRange = new ItemRange(0, 0, 0); + this._renderElementsInRange(initialRenderRange); } _itemsFromList({start, end}) { From 83ff2dd810066c263d9b07faa66efd7d97cc20f9 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 10 Aug 2021 14:37:33 +0530 Subject: [PATCH 155/242] Fix onAdd Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/LazyListView.js | 29 +++++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index aa38a4fb..c4a1c6b9 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -43,6 +43,8 @@ class ItemRange { } containsIndex(idx) { + // TODO: Replace by lastIndex + // TODO: Should idx be <= since lastIndex is not rendered? return idx >= this.topCount && idx <= (this.topCount + this.renderCount); } @@ -170,7 +172,7 @@ export class LazyListView extends ListView { if (this._height === 0) { console.error("LazyListView could not calculate parent height."); } const initialRange = this._getVisibleRange(); const initialRenderRange = initialRange.expand(this._overflowItems); - this._renderRange = new ItemRange(0, 0, 0); + this._renderRange = new ItemRange(0, 0, initialRange.bottomCount + 1); this._renderElementsInRange(initialRenderRange); } @@ -219,7 +221,6 @@ export class LazyListView extends ListView { const diff = this._renderRange.diff(range); const renderedItems = this._itemsFromList(diff.toAdd); this._adjustPadding(range); - const {start, end} = diff.toRemove; const normalizedStart = this._renderRange.normalize(start); this._childInstances.splice(normalizedStart, end - start + 1).forEach(child => this._removeChild(child)); @@ -265,9 +266,27 @@ export class LazyListView extends ListView { child.unmount(); } - // If size of the list changes, re-render - onAdd() { - this._renderIfNeeded(true); + onAdd(idx, value) { + const {topCount, renderCount, bottomCount} = this._renderRange; + if (this._renderRange.containsIndex(idx)) { + const normalizedIdx = this._renderRange.normalize(idx); + if (bottomCount === 0) { + // We're completely scrolled; so the extra element needs to be removed from top + this._removeChild(this._childInstances.shift()); + this._renderRange = new ItemRange(topCount + 1, renderCount, bottomCount); + } + else { + // Remove the last element, render the new element + this._removeChild(this._childInstances.pop()); + this._renderRange = new ItemRange(topCount, renderCount, bottomCount + 1); + } + super.onAdd(normalizedIdx, value); + } + else { + this._renderRange = idx < topCount ? new ItemRange(topCount + 1, renderCount, bottomCount): + new ItemRange(topCount, renderCount, bottomCount + 1); + } + this._adjustPadding(this._renderRange); } onRemove() { From 1165683f69badc40e4354eeb6729ac796a77d551 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 10 Aug 2021 18:44:00 +0530 Subject: [PATCH 156/242] Fix onRemove Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/LazyListView.js | 25 +++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index c4a1c6b9..d94487ba 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -289,8 +289,29 @@ export class LazyListView extends ListView { this._adjustPadding(this._renderRange); } - onRemove() { - this._renderIfNeeded(true); + onRemove(idx, value) { + const {topCount, renderCount, bottomCount} = this._renderRange; + if (this._renderRange.containsIndex(idx)) { + const normalizedIdx = this._renderRange.normalize(idx); + super.onRemove(normalizedIdx, value); + if (bottomCount === 0) { + const child = this._childCreator(this._itemAtIndex(topCount - 1)); + this._childInstances.unshift(child); + this._root.insertBefore(mountView(child, this._mountArgs), this._root.firstChild); + this._renderRange = new ItemRange(topCount - 1, renderCount, bottomCount); + } + else { + const child = this._childCreator(this._itemAtIndex(this._renderRange.lastIndex - 1)); + this._childInstances.push(child); + this._root.appendChild(mountView(child, this._mountArgs)); + this._renderRange = new ItemRange(topCount, renderCount, bottomCount - 1); + } + } + else { + this._renderRange = idx < topCount ? new ItemRange(topCount - 1, renderCount, bottomCount): + new ItemRange(topCount, renderCount, bottomCount - 1); + } + this._adjustPadding(this._renderRange); } onUpdate(idx, value, params) { From 3ae52ea1ca0c37767d9703ca8bbf49ec9930a21f Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 11 Aug 2021 12:23:26 +0530 Subject: [PATCH 157/242] Fix bug in onAdd and onRemove Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/LazyListView.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index d94487ba..b0d28c51 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -271,9 +271,15 @@ export class LazyListView extends ListView { if (this._renderRange.containsIndex(idx)) { const normalizedIdx = this._renderRange.normalize(idx); if (bottomCount === 0) { - // We're completely scrolled; so the extra element needs to be removed from top - this._removeChild(this._childInstances.shift()); - this._renderRange = new ItemRange(topCount + 1, renderCount, bottomCount); + /* + If we're at the bottom of the list, we need to render the additional item + without removing another item from the list. + We can't increment topCount because the index topCount is not affected by the + add operation (and any modification will thus break ItemRange.normalize()). + We can't increment bottomCount because there's not enough items left to trigger + a further render. + */ + this._renderRange = new ItemRange(topCount, renderCount + 1, bottomCount); } else { // Remove the last element, render the new element @@ -295,10 +301,8 @@ export class LazyListView extends ListView { const normalizedIdx = this._renderRange.normalize(idx); super.onRemove(normalizedIdx, value); if (bottomCount === 0) { - const child = this._childCreator(this._itemAtIndex(topCount - 1)); - this._childInstances.unshift(child); - this._root.insertBefore(mountView(child, this._mountArgs), this._root.firstChild); - this._renderRange = new ItemRange(topCount - 1, renderCount, bottomCount); + // See onAdd for explanation + this._renderRange = new ItemRange(topCount, renderCount - 1, bottomCount); } else { const child = this._childCreator(this._itemAtIndex(this._renderRange.lastIndex - 1)); From e10b494f0ca859aaa27b53e999b4205490925346 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 11 Aug 2021 12:30:38 +0530 Subject: [PATCH 158/242] Improve containsIndex Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/LazyListView.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index b0d28c51..2c070d95 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -43,9 +43,7 @@ class ItemRange { } containsIndex(idx) { - // TODO: Replace by lastIndex - // TODO: Should idx be <= since lastIndex is not rendered? - return idx >= this.topCount && idx <= (this.topCount + this.renderCount); + return idx >= this.topCount && idx < this.lastIndex; } expand(amount) { From da715c70b0ec3b5f53b0db6ff437c3cda358f8b2 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 11 Aug 2021 12:37:07 +0530 Subject: [PATCH 159/242] Remove forceRender Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/LazyListView.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index 2c070d95..00e9b9d8 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -139,17 +139,12 @@ export class LazyListView extends ListView { return new ItemRange(topCount, renderCount, bottomCount); } - _renderIfNeeded(forceRender = false) { - /* - forceRender only because we don't optimize onAdd/onRemove yet. - Ideally, onAdd/onRemove should only render whatever has changed + update padding + update renderRange - */ + _renderIfNeeded() { const range = this._getVisibleRange(); const intersectRange = range.expand(this._overflowMargin); const renderRange = range.expand(this._overflowItems); // only update render Range if the new range + overflowMargin isn't contained by the old anymore - // or if we are force rendering - if (forceRender || !this._renderRange.contains(intersectRange)) { + if (!this._renderRange.contains(intersectRange)) { console.log("new", renderRange); console.log("current", this._renderRange); console.log("diff", this._renderRange.diff(renderRange)); From aee135a6cdaaad5a3a9a52fdf5da9e8f48f66da6 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 11 Aug 2021 12:45:45 +0530 Subject: [PATCH 160/242] Jsdoc fix Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/LazyListView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index 00e9b9d8..f1fc533e 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -87,7 +87,7 @@ class ItemRange { * Check if this range intersects with another range * @param {ItemRange} range The range to check against * @param {ScrollDirection} scrollDirection - * @returns {Boolean} + * @returns {boolean} */ intersects(range) { return !!Math.max(0, Math.min(this.lastIndex, range.lastIndex) - Math.max(this.topCount, range.topCount)); From 5d54285640934b5a3cb8b728de684d2140e622c7 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 11 Aug 2021 12:52:38 +0530 Subject: [PATCH 161/242] Move ItemRange to separate file Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/ItemRange.js | 116 ++++++++++++++++++++ src/platform/web/ui/general/LazyListView.js | 102 +---------------- 2 files changed, 117 insertions(+), 101 deletions(-) create mode 100644 src/platform/web/ui/general/ItemRange.js diff --git a/src/platform/web/ui/general/ItemRange.js b/src/platform/web/ui/general/ItemRange.js new file mode 100644 index 00000000..ab6b23b0 --- /dev/null +++ b/src/platform/web/ui/general/ItemRange.js @@ -0,0 +1,116 @@ +/* +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. +*/ + +export class ScrollDirection { + static get downwards() { return 1; } + static get upwards() { return -1; } +} + +export class ItemRange { + constructor(topCount, renderCount, bottomCount) { + this.topCount = topCount; + this.renderCount = renderCount; + this.bottomCount = bottomCount; + } + + contains(range) { + // don't contain empty ranges + // as it will prevent clearing the list + // once it is scrolled far enough out of view + if (!range.renderCount && this.renderCount) { + return false; + } + return range.topCount >= this.topCount && + (range.topCount + range.renderCount) <= (this.topCount + this.renderCount); + } + + containsIndex(idx) { + return idx >= this.topCount && idx < this.lastIndex; + } + + expand(amount) { + // don't expand ranges that won't render anything + if (this.renderCount === 0) { + return this; + } + + const topGrow = Math.min(amount, this.topCount); + const bottomGrow = Math.min(amount, this.bottomCount); + return new ItemRange( + this.topCount - topGrow, + this.renderCount + topGrow + bottomGrow, + this.bottomCount - bottomGrow, + ); + } + + get lastIndex() { + return this.topCount + this.renderCount; + } + + totalSize() { + return this.topCount + this.renderCount + this.bottomCount; + } + + normalize(idx) { + /* + map index from list to index in rendered range + eg: if the index range of this._list is [0, 200] and we have rendered + elements in range [50, 60] then index 50 in list must map to index 0 + in DOM tree/childInstance array. + */ + return idx - this.topCount; + } + + scrollDirectionTo(range) { + return range.bottomCount < this.bottomCount ? ScrollDirection.downwards : ScrollDirection.upwards; + } + + /** + * Check if this range intersects with another range + * @param {ItemRange} range The range to check against + * @param {ScrollDirection} scrollDirection + * @returns {boolean} + */ + intersects(range) { + return !!Math.max(0, Math.min(this.lastIndex, range.lastIndex) - Math.max(this.topCount, range.topCount)); + } + + diff(range) { + /** + * Range-1 + * |----------------------| + * Range-2 + * |---------------------| + * <-------><------------><-------> + * bisect-1 intersection bisect-2 + */ + const scrollDirection = this.scrollDirectionTo(range); + if (!this.intersects(range)) { + // There is no intersection between the ranges; which can happen if you scroll really fast + // In this case, we need to do full render of the new range + const toRemove = { start: this.topCount, end: this.lastIndex }; + const toAdd = { start: range.topCount, end: range.lastIndex }; + return {toRemove, toAdd, scrollDirection}; + } + const bisection1 = {start: Math.min(this.topCount, range.topCount), end: Math.max(this.topCount, range.topCount) - 1}; + const bisection2 = {start: Math.min(this.lastIndex, range.lastIndex), end: Math.max(this.lastIndex, range.lastIndex)}; + // When scrolling down, bisection1 needs to be removed and bisection2 needs to be added + // When scrolling up, vice versa + const toRemove = scrollDirection === ScrollDirection.downwards ? bisection1 : bisection2; + const toAdd = scrollDirection === ScrollDirection.downwards ? bisection2 : bisection1; + return {toAdd, toRemove, scrollDirection}; + } +} diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index f1fc533e..6864172c 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -18,107 +18,7 @@ import {el} from "./html"; import {mountView} from "./utils"; import {ListView} from "./ListView"; import {insertAt} from "./utils"; - -class ScrollDirection { - static get downwards() { return 1; } - static get upwards() { return -1; } -} - -class ItemRange { - constructor(topCount, renderCount, bottomCount) { - this.topCount = topCount; - this.renderCount = renderCount; - this.bottomCount = bottomCount; - } - - contains(range) { - // don't contain empty ranges - // as it will prevent clearing the list - // once it is scrolled far enough out of view - if (!range.renderCount && this.renderCount) { - return false; - } - return range.topCount >= this.topCount && - (range.topCount + range.renderCount) <= (this.topCount + this.renderCount); - } - - containsIndex(idx) { - return idx >= this.topCount && idx < this.lastIndex; - } - - expand(amount) { - // don't expand ranges that won't render anything - if (this.renderCount === 0) { - return this; - } - - const topGrow = Math.min(amount, this.topCount); - const bottomGrow = Math.min(amount, this.bottomCount); - return new ItemRange( - this.topCount - topGrow, - this.renderCount + topGrow + bottomGrow, - this.bottomCount - bottomGrow, - ); - } - - get lastIndex() { - return this.topCount + this.renderCount; - } - - totalSize() { - return this.topCount + this.renderCount + this.bottomCount; - } - - normalize(idx) { - /* - map index from list to index in rendered range - eg: if the index range of this._list is [0, 200] and we have rendered - elements in range [50, 60] then index 50 in list must map to index 0 - in DOM tree/childInstance array. - */ - return idx - this.topCount; - } - - scrollDirectionTo(range) { - return range.bottomCount < this.bottomCount ? ScrollDirection.downwards : ScrollDirection.upwards; - } - - /** - * Check if this range intersects with another range - * @param {ItemRange} range The range to check against - * @param {ScrollDirection} scrollDirection - * @returns {boolean} - */ - intersects(range) { - return !!Math.max(0, Math.min(this.lastIndex, range.lastIndex) - Math.max(this.topCount, range.topCount)); - } - - diff(range) { - /** - * Range-1 - * |----------------------| - * Range-2 - * |---------------------| - * <-------><------------><-------> - * bisect-1 intersection bisect-2 - */ - const scrollDirection = this.scrollDirectionTo(range); - if (!this.intersects(range)) { - // There is no intersection between the ranges; which can happen if you scroll really fast - // In this case, we need to do full render of the new range - const toRemove = { start: this.topCount, end: this.lastIndex }; - const toAdd = { start: range.topCount, end: range.lastIndex }; - return {toRemove, toAdd, scrollDirection}; - } - const bisection1 = {start: Math.min(this.topCount, range.topCount), end: Math.max(this.topCount, range.topCount) - 1}; - const bisection2 = {start: Math.min(this.lastIndex, range.lastIndex), end: Math.max(this.lastIndex, range.lastIndex)}; - // When scrolling down, bisection1 needs to be removed and bisection2 needs to be added - // When scrolling up, vice versa - const toRemove = scrollDirection === ScrollDirection.downwards ? bisection1 : bisection2; - const toAdd = scrollDirection === ScrollDirection.downwards ? bisection2 : bisection1; - return {toAdd, toRemove, scrollDirection}; - } -} +import {ItemRange, ScrollDirection} from "./ItemRange.js"; export class LazyListView extends ListView { constructor({itemHeight, overflowMargin = 5, overflowItems = 20,...options}, childCreator) { From 33ac34b04e05eced0ffec18cf9f985e7e74d5e20 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sun, 15 Aug 2021 20:48:51 +0530 Subject: [PATCH 162/242] Do not break onListChanged Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/LazyListView.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index 6864172c..c064a2b5 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -162,6 +162,7 @@ export class LazyListView extends ListView { onAdd(idx, value) { const {topCount, renderCount, bottomCount} = this._renderRange; if (this._renderRange.containsIndex(idx)) { + this.onBeforeListChanged(); const normalizedIdx = this._renderRange.normalize(idx); if (bottomCount === 0) { /* @@ -179,7 +180,8 @@ export class LazyListView extends ListView { this._removeChild(this._childInstances.pop()); this._renderRange = new ItemRange(topCount, renderCount, bottomCount + 1); } - super.onAdd(normalizedIdx, value); + super.onAdd(normalizedIdx, value, true); + this.onListChanged(); } else { this._renderRange = idx < topCount ? new ItemRange(topCount + 1, renderCount, bottomCount): @@ -191,8 +193,9 @@ export class LazyListView extends ListView { onRemove(idx, value) { const {topCount, renderCount, bottomCount} = this._renderRange; if (this._renderRange.containsIndex(idx)) { + this.onBeforeListChanged(); const normalizedIdx = this._renderRange.normalize(idx); - super.onRemove(normalizedIdx, value); + super.onRemove(normalizedIdx, value, true); if (bottomCount === 0) { // See onAdd for explanation this._renderRange = new ItemRange(topCount, renderCount - 1, bottomCount); @@ -203,6 +206,7 @@ export class LazyListView extends ListView { this._root.appendChild(mountView(child, this._mountArgs)); this._renderRange = new ItemRange(topCount, renderCount, bottomCount - 1); } + this.onListChanged(); } else { this._renderRange = idx < topCount ? new ItemRange(topCount - 1, renderCount, bottomCount): From bbeb909bdc233a2e874e5855ef69d70493db12d4 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sun, 15 Aug 2021 21:07:40 +0530 Subject: [PATCH 163/242] Use createEnum Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/ItemRange.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/platform/web/ui/general/ItemRange.js b/src/platform/web/ui/general/ItemRange.js index ab6b23b0..53627aa4 100644 --- a/src/platform/web/ui/general/ItemRange.js +++ b/src/platform/web/ui/general/ItemRange.js @@ -14,10 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -export class ScrollDirection { - static get downwards() { return 1; } - static get upwards() { return -1; } -} +import {createEnum} from "../../../../utils/enum.js"; + +export const ScrollDirection = createEnum("upwards", "downwards"); export class ItemRange { constructor(topCount, renderCount, bottomCount) { From d625d57aa4ec89dbf4b37a1ea27f3a3c2989db73 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 16 Aug 2021 15:28:57 +0530 Subject: [PATCH 164/242] Fix lastIndex Signed-off-by: RMidhunSuresh --- src/platform/web/ui/general/ItemRange.js | 6 +++--- src/platform/web/ui/general/LazyListView.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/platform/web/ui/general/ItemRange.js b/src/platform/web/ui/general/ItemRange.js index 53627aa4..494f5dcb 100644 --- a/src/platform/web/ui/general/ItemRange.js +++ b/src/platform/web/ui/general/ItemRange.js @@ -37,7 +37,7 @@ export class ItemRange { } containsIndex(idx) { - return idx >= this.topCount && idx < this.lastIndex; + return idx >= this.topCount && idx <= this.lastIndex; } expand(amount) { @@ -56,7 +56,7 @@ export class ItemRange { } get lastIndex() { - return this.topCount + this.renderCount; + return this.topCount + this.renderCount - 1; } totalSize() { @@ -105,7 +105,7 @@ export class ItemRange { return {toRemove, toAdd, scrollDirection}; } const bisection1 = {start: Math.min(this.topCount, range.topCount), end: Math.max(this.topCount, range.topCount) - 1}; - const bisection2 = {start: Math.min(this.lastIndex, range.lastIndex), end: Math.max(this.lastIndex, range.lastIndex)}; + const bisection2 = {start: Math.min(this.lastIndex, range.lastIndex) + 1, end: Math.max(this.lastIndex, range.lastIndex)}; // When scrolling down, bisection1 needs to be removed and bisection2 needs to be added // When scrolling up, vice versa const toRemove = scrollDirection === ScrollDirection.downwards ? bisection1 : bisection2; diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/LazyListView.js index c064a2b5..3213ffee 100644 --- a/src/platform/web/ui/general/LazyListView.js +++ b/src/platform/web/ui/general/LazyListView.js @@ -73,7 +73,7 @@ export class LazyListView extends ListView { const array = []; let i = 0; for (const item of this._list) { - if (i >= start && i < end) { + if (i >= start && i <= end) { array.push(item); } i = i + 1; @@ -201,7 +201,7 @@ export class LazyListView extends ListView { this._renderRange = new ItemRange(topCount, renderCount - 1, bottomCount); } else { - const child = this._childCreator(this._itemAtIndex(this._renderRange.lastIndex - 1)); + const child = this._childCreator(this._itemAtIndex(this._renderRange.lastIndex)); this._childInstances.push(child); this._root.appendChild(mountView(child, this._mountArgs)); this._renderRange = new ItemRange(topCount, renderCount, bottomCount - 1); From 4a64d0ee171b442b3b4f1354b3ef641b2a25cd86 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 19 Nov 2021 22:49:46 +0100 Subject: [PATCH 165/242] WIP --- src/platform/web/ui/general/ItemRange.js | 115 ---------- src/platform/web/ui/general/ItemRange.ts | 210 ++++++++++++++++++ src/platform/web/ui/general/LazyListView.ts | 200 +++++++++++++++++ src/platform/web/ui/general/ListView.ts | 53 +++-- .../{LazyListView.js => foo-LazyListView.js} | 0 src/platform/web/ui/general/utils.ts | 4 + .../ui/session/rightpanel/MemberListView.js | 2 +- 7 files changed, 450 insertions(+), 134 deletions(-) delete mode 100644 src/platform/web/ui/general/ItemRange.js create mode 100644 src/platform/web/ui/general/ItemRange.ts create mode 100644 src/platform/web/ui/general/LazyListView.ts rename src/platform/web/ui/general/{LazyListView.js => foo-LazyListView.js} (100%) diff --git a/src/platform/web/ui/general/ItemRange.js b/src/platform/web/ui/general/ItemRange.js deleted file mode 100644 index 494f5dcb..00000000 --- a/src/platform/web/ui/general/ItemRange.js +++ /dev/null @@ -1,115 +0,0 @@ -/* -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 {createEnum} from "../../../../utils/enum.js"; - -export const ScrollDirection = createEnum("upwards", "downwards"); - -export class ItemRange { - constructor(topCount, renderCount, bottomCount) { - this.topCount = topCount; - this.renderCount = renderCount; - this.bottomCount = bottomCount; - } - - contains(range) { - // don't contain empty ranges - // as it will prevent clearing the list - // once it is scrolled far enough out of view - if (!range.renderCount && this.renderCount) { - return false; - } - return range.topCount >= this.topCount && - (range.topCount + range.renderCount) <= (this.topCount + this.renderCount); - } - - containsIndex(idx) { - return idx >= this.topCount && idx <= this.lastIndex; - } - - expand(amount) { - // don't expand ranges that won't render anything - if (this.renderCount === 0) { - return this; - } - - const topGrow = Math.min(amount, this.topCount); - const bottomGrow = Math.min(amount, this.bottomCount); - return new ItemRange( - this.topCount - topGrow, - this.renderCount + topGrow + bottomGrow, - this.bottomCount - bottomGrow, - ); - } - - get lastIndex() { - return this.topCount + this.renderCount - 1; - } - - totalSize() { - return this.topCount + this.renderCount + this.bottomCount; - } - - normalize(idx) { - /* - map index from list to index in rendered range - eg: if the index range of this._list is [0, 200] and we have rendered - elements in range [50, 60] then index 50 in list must map to index 0 - in DOM tree/childInstance array. - */ - return idx - this.topCount; - } - - scrollDirectionTo(range) { - return range.bottomCount < this.bottomCount ? ScrollDirection.downwards : ScrollDirection.upwards; - } - - /** - * Check if this range intersects with another range - * @param {ItemRange} range The range to check against - * @param {ScrollDirection} scrollDirection - * @returns {boolean} - */ - intersects(range) { - return !!Math.max(0, Math.min(this.lastIndex, range.lastIndex) - Math.max(this.topCount, range.topCount)); - } - - diff(range) { - /** - * Range-1 - * |----------------------| - * Range-2 - * |---------------------| - * <-------><------------><-------> - * bisect-1 intersection bisect-2 - */ - const scrollDirection = this.scrollDirectionTo(range); - if (!this.intersects(range)) { - // There is no intersection between the ranges; which can happen if you scroll really fast - // In this case, we need to do full render of the new range - const toRemove = { start: this.topCount, end: this.lastIndex }; - const toAdd = { start: range.topCount, end: range.lastIndex }; - return {toRemove, toAdd, scrollDirection}; - } - const bisection1 = {start: Math.min(this.topCount, range.topCount), end: Math.max(this.topCount, range.topCount) - 1}; - const bisection2 = {start: Math.min(this.lastIndex, range.lastIndex) + 1, end: Math.max(this.lastIndex, range.lastIndex)}; - // When scrolling down, bisection1 needs to be removed and bisection2 needs to be added - // When scrolling up, vice versa - const toRemove = scrollDirection === ScrollDirection.downwards ? bisection1 : bisection2; - const toAdd = scrollDirection === ScrollDirection.downwards ? bisection2 : bisection1; - return {toAdd, toRemove, scrollDirection}; - } -} diff --git a/src/platform/web/ui/general/ItemRange.ts b/src/platform/web/ui/general/ItemRange.ts new file mode 100644 index 00000000..66db6078 --- /dev/null +++ b/src/platform/web/ui/general/ItemRange.ts @@ -0,0 +1,210 @@ +/* +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. +*/ + +// start is included in the range, +// end is excluded, +// so [2, 2[ means an empty range +class Range { + constructor( + public readonly start: number, + public readonly end: number + ) {} + + get length() { + return this.end - this.start; + } + + contains(range: Range): boolean { + return range.start >= this.start && range.end <= this.end; + } + + containsIndex(idx: number): boolean { + return idx >= this.start && idx < this.end; + } + + intersects(range: Range): boolean { + return range.start < this.end && this.start < range.end; + } + + forEach(callback: ((i: number) => void)) { + for (let i = this.start; i < this.end; i += 1) { + callback(i); + } + } + + forEachInIterator(it: IterableIterator, callback: ((T, i: number) => void)) { + let i = 0; + for (i = 0; i < this.start; i += 1) { + it.next(); + } + for (i = 0; i < this.length; i += 1) { + const result = it.next(); + if (result.done) { + break; + } else { + callback(result.value, this.start + i); + } + } + } + + [Symbol.iterator](): Iterator { + return new RangeIterator(this); + } +} + +class RangeIterator implements Iterator { + private idx: number; + constructor(private readonly range: Range) { + this.idx = range.start - 1; + } + + next(): IteratorResult { + if (this.idx < (this.range.end - 1)) { + this.idx += 1; + return {value: this.idx, done: false}; + } else { + return {value: undefined, done: true}; + } + } +} + +export function tests() { + return { + "length": assert => { + const a = new Range(2, 5); + assert.equal(a.length, 3); + }, + "iterator": assert => { + assert.deepEqual(Array.from(new Range(2, 5)), [2, 3, 4]); + }, + "containsIndex": assert => { + const a = new Range(2, 5); + assert.equal(a.containsIndex(0), false); + assert.equal(a.containsIndex(1), false); + assert.equal(a.containsIndex(2), true); + assert.equal(a.containsIndex(3), true); + assert.equal(a.containsIndex(4), true); + assert.equal(a.containsIndex(5), false); + assert.equal(a.containsIndex(6), false); + }, + "intersects returns false for touching ranges": assert => { + const a = new Range(2, 5); + const b = new Range(5, 10); + assert.equal(a.intersects(b), false); + assert.equal(b.intersects(a), false); + }, + "intersects returns false": assert => { + const a = new Range(2, 5); + const b = new Range(50, 100); + assert.equal(a.intersects(b), false); + assert.equal(b.intersects(a), false); + }, + "intersects returns true for 1 overlapping item": assert => { + const a = new Range(2, 5); + const b = new Range(4, 10); + assert.equal(a.intersects(b), true); + assert.equal(b.intersects(a), true); + }, + "contains beyond left edge": assert => { + const a = new Range(2, 5); + const b = new Range(1, 3); + assert.equal(a.contains(b), false); + }, + "contains at left edge": assert => { + const a = new Range(2, 5); + const b = new Range(2, 3); + assert.equal(a.contains(b), true); + }, + "contains between edges": assert => { + const a = new Range(2, 5); + const b = new Range(3, 4); + assert.equal(a.contains(b), true); + }, + "contains at right edge": assert => { + const a = new Range(2, 5); + const b = new Range(3, 5); + assert.equal(a.contains(b), true); + }, + "contains beyond right edge": assert => { + const a = new Range(2, 5); + const b = new Range(4, 6); + assert.equal(a.contains(b), false); + }, + "contains for non-intersecting ranges": assert => { + const a = new Range(2, 5); + const b = new Range(5, 6); + assert.equal(a.contains(b), false); + }, + "forEachInIterator with more values available": assert => { + const callbackValues: {v: string, i: number}[] = []; + const values = ["a", "b", "c", "d", "e", "f"]; + const it = values[Symbol.iterator](); + new Range(2, 5).forEachInIterator(it, (v, i) => callbackValues.push({v, i})); + assert.deepEqual(callbackValues, [ + {v: "c", i: 2}, + {v: "d", i: 3}, + {v: "e", i: 4}, + ]); + }, + "forEachInIterator with fewer values available": assert => { + const callbackValues: {v: string, i: number}[] = []; + const values = ["a", "b", "c"]; + const it = values[Symbol.iterator](); + new Range(2, 5).forEachInIterator(it, (v, i) => callbackValues.push({v, i})); + assert.deepEqual(callbackValues, [ + {v: "c", i: 2}, + ]); + }, + }; +} + +export class ItemRange extends Range { + constructor( + start: number, + end: number, + public readonly totalLength: number + ) { + super(start, end); + } + + + expand(amount: number): ItemRange { + // don't expand ranges that won't render anything + if (this.length === 0) { + return this; + } + + const topGrow = Math.min(amount, this.start); + const bottomGrow = Math.min(amount, this.totalLength - this.end); + return new ItemRange( + this.start - topGrow, + this.end + topGrow + bottomGrow, + this.totalLength, + ); + } + + static fromViewport(listLength: number, itemHeight: number, listHeight: number, scrollTop: number) { + const topCount = Math.min(Math.max(0, Math.floor(scrollTop / itemHeight)), listLength); + const itemsAfterTop = listLength - topCount; + const visibleItems = listHeight !== 0 ? Math.ceil(listHeight / itemHeight) : 0; + const renderCount = Math.min(visibleItems, itemsAfterTop); + return new ItemRange(topCount, topCount + renderCount, listLength); + } + + missingFrom() { + + } +} diff --git a/src/platform/web/ui/general/LazyListView.ts b/src/platform/web/ui/general/LazyListView.ts new file mode 100644 index 00000000..65c53c2d --- /dev/null +++ b/src/platform/web/ui/general/LazyListView.ts @@ -0,0 +1,200 @@ +/* +Copyright 2020 Bruno Windels + +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 {tag} from "./html"; +import {removeChildren, mountView} from "./utils"; +import {ItemRange} from "./ItemRange"; +import {ListView, IOptions as IParentOptions} from "./ListView"; +import {IView} from "./types"; + +export interface IOptions extends IParentOptions { + itemHeight: number; + overflowMargin?: number; + overflowItems?: number; +} + +export class LazyListView extends ListView { + private renderRange?: ItemRange; + private height?: number; + private itemHeight: number; + private overflowItems: number; + private scrollContainer?: Element; + + constructor( + {itemHeight, overflowMargin = 5, overflowItems = 20,...options}: IOptions, + childCreator: (value: T) => V + ) { + super(options, childCreator); + this.itemHeight = itemHeight; + this.overflowItems = overflowItems; + // TODO: this.overflowMargin = overflowMargin; + } + + handleEvent(e: Event) { + if (e.type === "scroll") { + this.handleScroll(); + } else { + super.handleEvent(e); + } + } + + handleScroll() { + const visibleRange = this._getVisibleRange(); + // don't contain empty ranges + // as it will prevent clearing the list + // once it is scrolled far enough out of view + if (visibleRange.length !== 0 && !this.renderRange!.contains(visibleRange)) { + const prevRenderRange = this.renderRange!; + this.renderRange = visibleRange.expand(this.overflowItems); + this.renderUpdate(prevRenderRange, this.renderRange); + } + } + + override async loadList() { + /* + Wait two frames for the return from mount() to be inserted into DOM. + This should be enough, but if this gives us trouble we can always use + MutationObserver. + */ + await new Promise(r => requestAnimationFrame(r)); + await new Promise(r => requestAnimationFrame(r)); + + if (!this._list) { + return; + } + const visibleRange = this._getVisibleRange(); + this.renderRange = visibleRange.expand(this.overflowItems); + this._childInstances = []; + this._subscription = this._list.subscribe(this); + this.reRenderFullRange(this.renderRange); + } + + private _getVisibleRange() { + const {clientHeight, scrollTop} = this.root()!; + if (clientHeight === 0) { + throw new Error("LazyListView height is 0"); + } + return ItemRange.fromViewport(this._list.length, this.itemHeight, clientHeight, scrollTop); + } + + private reRenderFullRange(range: ItemRange) { + removeChildren(this._listElement!); + const fragment = document.createDocumentFragment(); + const it = this._list[Symbol.iterator](); + this._childInstances!.length = 0; + range.forEachInIterator(it, item => { + const child = this._childCreator(item); + this._childInstances!.push(child); + fragment.appendChild(mountView(child, this._mountArgs)); + }); + this._listElement!.appendChild(fragment); + this.adjustPadding(range); + } + + private renderUpdate(prevRange: ItemRange, newRange: ItemRange) { + if (newRange.intersects(prevRange)) { + for (const idxInList of prevRange) { + // TODO: we need to make sure we keep childInstances in order so the indices lign up. + // Perhaps we should join both ranges and see in which range it appears and either add or remove? + if (!newRange.containsIndex(idxInList)) { + const localIdx = idxInList - prevRange.start; + this.removeChild(localIdx); + } + } + const addedRange = newRange.missingFrom(prevRange); + addedRange.forEachInIterator(this._list[Symbol.iterator](), (item, idxInList) => { + const localIdx = idxInList - newRange.start; + this.addChild(localIdx, item); + }); + this.adjustPadding(newRange); + } else { + this.reRenderFullRange(newRange); + } + } + + private adjustPadding(range: ItemRange) { + const paddingTop = range.start * this.itemHeight; + const paddingBottom = (range.totalLength - range.end) * this.itemHeight; + const style = this.scrollContainer!.style; + style.paddingTop = `${paddingTop}px`; + style.paddingBottom = `${paddingBottom}px`; + } + + mount() { + const listElement = super.mount(); + this.scrollContainer = tag.div({className: "LazyListParent"}, listElement); + /* + Hooking to scroll events can be expensive. + Do we need to do more (like event throttling)? + */ + this.scrollContainer.addEventListener("scroll", this); + return this.scrollContainer; + } + + unmount() { + this.root()!.removeEventListener("scroll", this); + this.scrollContainer = undefined; + super.unmount(); + } + + root(): Element | undefined { + return this.scrollContainer; + } + + private get _listElement(): Element | undefined { + return super.root(); + } + + onAdd(idx: number, value: T) { + // TODO: update totalLength in renderRange + const result = this.renderRange!.queryAdd(idx); + if (result.addIdx !== -1) { + this.addChild(result.addIdx, value); + } + if (result.removeIdx !== -1) { + this.removeChild(result.removeIdx); + } + } + + onRemove(idx: number, value: T) { + // TODO: update totalLength in renderRange + const result = this.renderRange!.queryRemove(idx); + if (result.removeIdx !== -1) { + this.removeChild(result.removeIdx); + } + if (result.addIdx !== -1) { + this.addChild(result.addIdx, value); + } + } + + onMove(fromIdx: number, toIdx: number, value: T) { + const result = this.renderRange!.queryMove(fromIdx, toIdx); + if (result.moveFromIdx !== -1 && result.moveToIdx !== -1) { + this.moveChild(result.moveFromIdx, result.moveToIdx); + } else if (result.removeIdx !== -1) { + this.removeChild(result.removeIdx); + } else if (result.addIdx !== -1) { + this.addChild(result.addIdx, value); + } + } + + onUpdate(i: number, value: T, params: any) { + const updateIdx = this.renderRange!.queryUpdate(i); + if (updateIdx !== -1) { + this.updateChild(updateIdx, value, params); + } + } +} diff --git a/src/platform/web/ui/general/ListView.ts b/src/platform/web/ui/general/ListView.ts index f76bd961..9d639098 100644 --- a/src/platform/web/ui/general/ListView.ts +++ b/src/platform/web/ui/general/ListView.ts @@ -17,10 +17,10 @@ limitations under the License. import {el} from "./html"; import {mountView, insertAt} from "./utils"; import {SubscriptionHandle} from "../../../../observable/BaseObservable"; -import {BaseObservableList as ObservableList} from "../../../../observable/list/BaseObservableList"; +import {BaseObservableList as ObservableList, IListObserver} from "../../../../observable/list/BaseObservableList"; import {IView, IMountArgs} from "./types"; -interface IOptions { +export interface IOptions { list: ObservableList, onItemClick?: (childView: V, evt: UIEvent) => void, className?: string, @@ -28,17 +28,17 @@ interface IOptions { parentProvidesUpdates?: boolean } -export class ListView implements IView { +export class ListView implements IView, IListObserver { private _onItemClick?: (childView: V, evt: UIEvent) => void; - private _list: ObservableList; private _className?: string; private _tagName: string; private _root?: Element; - private _subscription?: SubscriptionHandle; - private _childCreator: (value: T) => V; - private _childInstances?: V[]; - private _mountArgs: IMountArgs; + protected _subscription?: SubscriptionHandle; + protected _childCreator: (value: T) => V; + protected _mountArgs: IMountArgs; + protected _list: ObservableList; + protected _childInstances?: V[]; constructor( {list, onItemClick, className, tagName = "ul", parentProvidesUpdates = true}: IOptions, @@ -145,31 +145,48 @@ export class ListView implements IView { } onAdd(idx: number, value: T) { - const child = this._childCreator(value); - this._childInstances!.splice(idx, 0, child); - insertAt(this._root!, idx, mountView(child, this._mountArgs)); + this.addChild(idx, value); } onRemove(idx: number, value: T) { - const [child] = this._childInstances!.splice(idx, 1); + this.removeChild(idx); + } + + onMove(fromIdx: number, toIdx: number, value: T) { + this.moveChild(fromIdx, toIdx); + } + + onUpdate(i: number, value: T, params: any) { + this.updateChild(i, value, params); + } + + protected addChild(childIdx: number, value: T) { + const child = this._childCreator(value); + this._childInstances!.splice(childIdx, 0, child); + insertAt(this._root!, childIdx, mountView(child, this._mountArgs)); + } + + protected removeChild(childIdx: number) { + const [child] = this._childInstances!.splice(childIdx, 1); child.root()!.remove(); child.unmount(); } - onMove(fromIdx: number, toIdx: number, value: T) { - const [child] = this._childInstances!.splice(fromIdx, 1); - this._childInstances!.splice(toIdx, 0, child); + protected moveChild(fromChildIdx: number, toChildIdx: number) { + const [child] = this._childInstances!.splice(fromChildIdx, 1); + this._childInstances!.splice(toChildIdx, 0, child); child.root()!.remove(); - insertAt(this._root!, toIdx, child.root()! as Element); + insertAt(this._root!, toChildIdx, child.root()! as Element); } - onUpdate(i: number, value: T, params: any) { + protected updateChild(childIdx: number, value: T, params: any) { if (this._childInstances) { - const instance = this._childInstances![i]; + const instance = this._childInstances![childIdx]; instance && instance.update(value, params); } } + // TODO: is this the list or view index? protected recreateItem(index: number, value: T) { if (this._childInstances) { const child = this._childCreator(value); diff --git a/src/platform/web/ui/general/LazyListView.js b/src/platform/web/ui/general/foo-LazyListView.js similarity index 100% rename from src/platform/web/ui/general/LazyListView.js rename to src/platform/web/ui/general/foo-LazyListView.js diff --git a/src/platform/web/ui/general/utils.ts b/src/platform/web/ui/general/utils.ts index 7eb1d7f9..f8d407e9 100644 --- a/src/platform/web/ui/general/utils.ts +++ b/src/platform/web/ui/general/utils.ts @@ -50,3 +50,7 @@ export function insertAt(parentNode: Element, idx: number, childNode: Node): voi parentNode.insertBefore(childNode, nextDomNode); } } + +export function removeChildren(parentNode: Element): void { + parentNode.innerHTML = ''; +} diff --git a/src/platform/web/ui/session/rightpanel/MemberListView.js b/src/platform/web/ui/session/rightpanel/MemberListView.js index 6c3d252e..6096f919 100644 --- a/src/platform/web/ui/session/rightpanel/MemberListView.js +++ b/src/platform/web/ui/session/rightpanel/MemberListView.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {LazyListView} from "../../general/LazyListView.js"; +import {LazyListView} from "../../general/LazyListView"; import {MemberTileView} from "./MemberTileView.js"; export class MemberListView extends LazyListView{ From cf9f43ab9ebea291af1d6478c44b6f6d30293f74 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 22 Nov 2021 20:35:57 +0100 Subject: [PATCH 166/242] WIP2 --- src/observable/list/ObservableArray.js | 8 + src/platform/web/ui/general/LazyListView.ts | 92 ++-- src/platform/web/ui/general/ListRange.ts | 440 ++++++++++++++++++ .../web/ui/general/{ItemRange.ts => Range.ts} | 105 +++-- 4 files changed, 555 insertions(+), 90 deletions(-) create mode 100644 src/platform/web/ui/general/ListRange.ts rename src/platform/web/ui/general/{ItemRange.ts => Range.ts} (78%) diff --git a/src/observable/list/ObservableArray.js b/src/observable/list/ObservableArray.js index 5d9f5c12..053e7320 100644 --- a/src/observable/list/ObservableArray.js +++ b/src/observable/list/ObservableArray.js @@ -44,6 +44,14 @@ export class ObservableArray extends BaseObservableList { this.emitAdd(idx, item); } + move(fromIdx, toIdx) { + if (fromIdx < this._items.length && toIdx < this._items.length) { + const item = this._items.splice(fromIdx, 1); + this._items.splice(toIdx, 0, item); + this.emitMove(fromIdx, toIdx, item); + } + } + update(idx, item, params = null) { if (idx < this._items.length) { this._items[idx] = item; diff --git a/src/platform/web/ui/general/LazyListView.ts b/src/platform/web/ui/general/LazyListView.ts index 65c53c2d..f8aa80cc 100644 --- a/src/platform/web/ui/general/LazyListView.ts +++ b/src/platform/web/ui/general/LazyListView.ts @@ -16,7 +16,7 @@ limitations under the License. import {tag} from "./html"; import {removeChildren, mountView} from "./utils"; -import {ItemRange} from "./ItemRange"; +import {ListRange, ResultType, AddRemoveResult} from "./ListRange"; import {ListView, IOptions as IParentOptions} from "./ListView"; import {IView} from "./types"; @@ -27,11 +27,11 @@ export interface IOptions extends IParentOptions { } export class LazyListView extends ListView { - private renderRange?: ItemRange; + private renderRange?: ListRange; private height?: number; private itemHeight: number; private overflowItems: number; - private scrollContainer?: Element; + private scrollContainer?: HTMLElement; constructor( {itemHeight, overflowMargin = 5, overflowItems = 20,...options}: IOptions, @@ -87,10 +87,10 @@ export class LazyListView extends ListView { if (clientHeight === 0) { throw new Error("LazyListView height is 0"); } - return ItemRange.fromViewport(this._list.length, this.itemHeight, clientHeight, scrollTop); + return ListRange.fromViewport(this._list.length, this.itemHeight, clientHeight, scrollTop); } - private reRenderFullRange(range: ItemRange) { + private reRenderFullRange(range: ListRange) { removeChildren(this._listElement!); const fragment = document.createDocumentFragment(); const it = this._list[Symbol.iterator](); @@ -104,20 +104,22 @@ export class LazyListView extends ListView { this.adjustPadding(range); } - private renderUpdate(prevRange: ItemRange, newRange: ItemRange) { + private renderUpdate(prevRange: ListRange, newRange: ListRange) { if (newRange.intersects(prevRange)) { - for (const idxInList of prevRange) { - // TODO: we need to make sure we keep childInstances in order so the indices lign up. - // Perhaps we should join both ranges and see in which range it appears and either add or remove? + // remove children in reverse order so child index isn't affected by previous removals + for (const idxInList of prevRange.reverseIterable()) { if (!newRange.containsIndex(idxInList)) { const localIdx = idxInList - prevRange.start; this.removeChild(localIdx); } } - const addedRange = newRange.missingFrom(prevRange); - addedRange.forEachInIterator(this._list[Symbol.iterator](), (item, idxInList) => { - const localIdx = idxInList - newRange.start; - this.addChild(localIdx, item); + // use forEachInIterator instead of for loop as we need to advance + // the list iterator to the start of the range first + newRange.forEachInIterator(this._list[Symbol.iterator](), (item, idxInList) => { + if (!prevRange.containsIndex(idxInList)) { + const localIdx = idxInList - newRange.start; + this.addChild(localIdx, item); + } }); this.adjustPadding(newRange); } else { @@ -125,7 +127,7 @@ export class LazyListView extends ListView { } } - private adjustPadding(range: ItemRange) { + private adjustPadding(range: ListRange) { const paddingTop = range.start * this.itemHeight; const paddingBottom = (range.totalLength - range.end) * this.itemHeight; const style = this.scrollContainer!.style; @@ -135,11 +137,7 @@ export class LazyListView extends ListView { mount() { const listElement = super.mount(); - this.scrollContainer = tag.div({className: "LazyListParent"}, listElement); - /* - Hooking to scroll events can be expensive. - Do we need to do more (like event throttling)? - */ + this.scrollContainer = tag.div({className: "LazyListParent"}, listElement) as HTMLElement; this.scrollContainer.addEventListener("scroll", this); return this.scrollContainer; } @@ -159,42 +157,46 @@ export class LazyListView extends ListView { } onAdd(idx: number, value: T) { - // TODO: update totalLength in renderRange - const result = this.renderRange!.queryAdd(idx); - if (result.addIdx !== -1) { - this.addChild(result.addIdx, value); - } - if (result.removeIdx !== -1) { - this.removeChild(result.removeIdx); - } + const result = this.renderRange!.queryAdd(idx, value, this._list); + this.applyRemoveAddResult(result); } onRemove(idx: number, value: T) { - // TODO: update totalLength in renderRange - const result = this.renderRange!.queryRemove(idx); - if (result.removeIdx !== -1) { - this.removeChild(result.removeIdx); - } - if (result.addIdx !== -1) { - this.addChild(result.addIdx, value); - } + const result = this.renderRange!.queryRemove(idx, this._list); + this.applyRemoveAddResult(result); } onMove(fromIdx: number, toIdx: number, value: T) { - const result = this.renderRange!.queryMove(fromIdx, toIdx); - if (result.moveFromIdx !== -1 && result.moveToIdx !== -1) { - this.moveChild(result.moveFromIdx, result.moveToIdx); - } else if (result.removeIdx !== -1) { - this.removeChild(result.removeIdx); - } else if (result.addIdx !== -1) { - this.addChild(result.addIdx, value); + const result = this.renderRange!.queryMove(fromIdx, toIdx, value, this._list); + if (result) { + if (result.type === ResultType.Move) { + this.moveChild( + this.renderRange!.toLocalIndex(result.fromIdx), + this.renderRange!.toLocalIndex(result.toIdx) + ); + } else { + this.applyRemoveAddResult(result); + } } } onUpdate(i: number, value: T, params: any) { - const updateIdx = this.renderRange!.queryUpdate(i); - if (updateIdx !== -1) { - this.updateChild(updateIdx, value, params); + if (this.renderRange!.containsIndex(i)) { + this.updateChild(this.renderRange!.toLocalIndex(i), value, params); + } + } + + private applyRemoveAddResult(result: AddRemoveResult) { + // order is important here, the new range can have a different start + if (result.type === ResultType.Remove || result.type === ResultType.RemoveAndAdd) { + this.removeChild(this.renderRange!.toLocalIndex(result.removeIdx)); + } + if (result.newRange) { + this.renderRange = result.newRange; + this.adjustPadding(this.renderRange) + } + if (result.type === ResultType.Add || result.type === ResultType.RemoveAndAdd) { + this.addChild(this.renderRange!.toLocalIndex(result.addIdx), result.value); } } } diff --git a/src/platform/web/ui/general/ListRange.ts b/src/platform/web/ui/general/ListRange.ts new file mode 100644 index 00000000..7ccd5726 --- /dev/null +++ b/src/platform/web/ui/general/ListRange.ts @@ -0,0 +1,440 @@ +/* +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 {Range, RangeZone} from "./Range"; + +function skipOnIterator(it: Iterator, pos: number): boolean { + let i = 0; + while (i < pos) { + i += 1; + if(it.next().done) { + return false; + } + } + return true; +} + +function getIteratorValueAtIdx(it: Iterator, idx: number): undefined | T { + if (skipOnIterator(it, idx)) { + const result = it.next(); + if (!result.done) { + return result.value; + } + } + return undefined; +} + +export enum ResultType { + Move, + Add, + Remove, + RemoveAndAdd, + UpdateRange +} + +export interface MoveResult { + type: ResultType.Move; + fromIdx: number; + toIdx: number +} + +interface AddResult { + type: ResultType.Add; + newRange?: ListRange; + /** the list index of an item to add */ + addIdx: number; + /** the value to add at addIdx */ + value: T +} + +interface RemoveResult { + type: ResultType.Remove; + newRange?: ListRange; + /** the list index of an item to remove, before the add or remove event has been taken into account */ + removeIdx: number; +} + +interface RemoveAndAddResult { + type: ResultType.RemoveAndAdd; + newRange?: ListRange; + /** the list index of an item to remove, before the add or remove event has been taken into account */ + removeIdx: number; + /** the list index of an item to add */ + addIdx: number; + /** the value to add at addIdx */ + value: T; +} + +interface UpdateRangeResult { + type: ResultType.UpdateRange; + newRange?: ListRange; +} + +export type AddRemoveResult = AddResult | RemoveResult | RemoveAndAddResult | UpdateRangeResult; + +export class ListRange extends Range { + constructor( + start: number, + end: number, + private _totalLength: number, + private _viewportItemCount: number = end - start + ) { + super(start, end); + } + + expand(amount: number): ListRange { + // don't expand ranges that won't render anything + if (this.length === 0) { + return this; + } + const newStart = Math.max(0, this.start - amount); + const newEnd = Math.min(this.totalLength, this.end + amount); + return new ListRange( + newStart, + newEnd, + this.totalLength, + this._viewportItemCount + ); + } + + get totalLength(): number { + return this._totalLength; + } + + get viewportItemCount(): number { + return this._viewportItemCount; + } + + static fromViewport(listLength: number, itemHeight: number, listHeight: number, scrollTop: number) { + const topCount = Math.min(Math.max(0, Math.floor(scrollTop / itemHeight)), listLength); + const itemsAfterTop = listLength - topCount; + const viewportItemCount = listHeight !== 0 ? Math.ceil(listHeight / itemHeight) : 0; + const renderCount = Math.min(viewportItemCount, itemsAfterTop); + return new ListRange(topCount, topCount + renderCount, listLength, viewportItemCount); + } + + queryAdd(idx: number, value: T, list: Iterable): AddRemoveResult { + const maxAddIdx = this.viewportItemCount > this.length ? this.end : this.end - 1; + if (idx <= maxAddIdx) { + // use maxAddIdx to allow to grow the range by one at a time + // if the viewport isn't filled yet + const addIdx = this.clampIndex(idx, this.maxAddIdx); + const addValue = addIdx === idx ? value : getIteratorValueAtIdx(list[Symbol.iterator](), addIdx)!; + return this.createAddResult(addIdx, addValue); + } else { + // if the add happened after the range, we only update the range with the new length + return {type: ResultType.UpdateRange, newRange: this.derive(1, 0)}; + } + } + + queryRemove(idx: number, list: Iterable): AddRemoveResult { + if (idx < this.end) { + const removeIdx = this.clampIndex(idx); + return this.createRemoveResult(removeIdx, list); + } else { + return {type: ResultType.UpdateRange, newRange: this.derive(-1, 0)}; + } + } + + queryMove(fromIdx: number, toIdx: number, value: T, list: Iterable): MoveResult | AddRemoveResult | undefined { + const fromZone = this.getIndexZone(fromIdx); + const toZone = this.getIndexZone(toIdx); + if (fromZone === toZone) { + if (fromZone === RangeZone.Before || fromZone === RangeZone.After) { + return; + } else if (fromZone === RangeZone.Inside) { + return {type: ResultType.Move, fromIdx, toIdx}; + } + } else { + // TODO + const addIdx = this.clampIndex(toIdx); + const removeIdx = this.clampIndex(fromIdx); + const addValue = addIdx === toIdx ? value : getIteratorValueAtIdx(list[Symbol.iterator](), addIdx)!; + return {type: ResultType.RemoveAndAdd, removeIdx, addIdx, value: addValue}; + } + } + + private createAddResult(addIdx: number, value: T): AddRemoveResult { + // if the view port isn't filled yet, we don't remove + if (this.viewportItemCount > this.length) { + return {type: ResultType.Add, addIdx, value, newRange: this.derive(1, 1)}; + } else { + const removeIdx = this.clampIndex(Number.MAX_SAFE_INTEGER); + return {type: ResultType.RemoveAndAdd, removeIdx, addIdx, value, newRange: this.derive(1, 0)}; + } + } + + private createRemoveResult(removeIdx: number, list: Iterable): AddRemoveResult { + if (this.end < this.totalLength) { + // we have items below the range, we can add one from there to fill the viewport + const addIdx = this.clampIndex(Number.MAX_SAFE_INTEGER); + // we assume the value has already been removed from the list, + // so we can just look up the next value which is already at the same idx + const value = getIteratorValueAtIdx(list[Symbol.iterator](), addIdx)!; + return {type: ResultType.RemoveAndAdd, removeIdx, value, addIdx, newRange: this.derive(-1, 0)}; + } else if (this.start !== 0) { + // move the range 1 item up so we still display a viewport full of items + const newRange = this.derive(-1, 0, 1); + const addIdx = newRange.start; + // we assume the value has already been removed from the list, + // so we can just look up the next value which is already at the same idx + const value = getIteratorValueAtIdx(list[Symbol.iterator](), addIdx)!; + return {type: ResultType.RemoveAndAdd, removeIdx, value, addIdx, newRange}; + } else { + // we can't add at the bottom nor top, already constrained + return {type: ResultType.Remove, removeIdx, newRange: this.derive(-1, 0)}; + } + } + + private derive(totalLengthInc: number, viewportItemCountDecr: number, startDecr: number = 0): ListRange { + return new ListRange( + this.start - startDecr, + this.end - startDecr + viewportItemCountDecr, + this.totalLength + totalLengthInc, + this.viewportItemCount + ); + } +} + +import {ObservableArray} from "../../../../observable/list/ObservableArray.js"; + +export function tests() { + return { + "fromViewport": assert => { + const range = ListRange.fromViewport(10, 20, 90, 30); + assert.equal(range.start, 1); + assert.equal(range.end, 6); + assert.equal(range.totalLength, 10); + }, + "fromViewport at end": assert => { + const itemHeight = 20; + const range = ListRange.fromViewport(10, itemHeight, 3 * itemHeight, 7 * itemHeight); + assert.equal(range.start, 7); + assert.equal(range.end, 10); + assert.equal(range.totalLength, 10); + }, + "fromViewport with not enough items to fill viewport": assert => { + const itemHeight = 20; + const range = ListRange.fromViewport(5, itemHeight, 8 * itemHeight, 0); + assert.equal(range.start, 0); + assert.equal(range.end, 5); + assert.equal(range.totalLength, 5); + assert.equal(range.length, 5); + assert.equal(range.viewportItemCount, 8); + }, + "expand at start of list": assert => { + const range = new ListRange(1, 5, 10); + const expanded = range.expand(2); + assert.equal(expanded.start, 0); + assert.equal(expanded.end, 7); + assert.equal(expanded.totalLength, 10); + assert.equal(expanded.length, 7); + }, + "expand at end of list": assert => { + const range = new ListRange(7, 9, 10); + const expanded = range.expand(2); + assert.equal(expanded.start, 5); + assert.equal(expanded.end, 10); + assert.equal(expanded.totalLength, 10); + assert.equal(expanded.length, 5); + }, + "expand in middle of list": assert => { + const range = new ListRange(4, 6, 10); + const expanded = range.expand(2); + assert.equal(expanded.start, 2); + assert.equal(expanded.end, 8); + assert.equal(expanded.totalLength, 10); + assert.equal(expanded.length, 6); + }, + "queryAdd with addition before range": assert => { + const list = new ObservableArray(["b", "c", "d", "e"]); + const range = new ListRange(1, 3, list.length); + let added = false; + list.subscribe({ + onAdd(idx, value) { + added = true; + const result = range.queryAdd(idx, value, list); + assert.deepEqual(result, { + type: ResultType.RemoveAndAdd, + removeIdx: 2, + addIdx: 1, + value: "b", + newRange: new ListRange(1, 3, 5) + }); + } + }); + list.insert(0, "a"); + assert(added); + }, + "queryAdd with addition within range": assert => { + const list = new ObservableArray(["a", "b", "d", "e"]); + const range = new ListRange(1, 3, list.length); + let added = false; + list.subscribe({ + onAdd(idx, value) { + added = true; + const result = range.queryAdd(idx, value, list); + assert.deepEqual(result, { + type: ResultType.RemoveAndAdd, + removeIdx: 2, + addIdx: 2, + value: "c", + newRange: new ListRange(1, 3, 5) + }); + } + }); + list.insert(2, "c"); + assert(added); + }, + "queryAdd with addition after range": assert => { + const list = new ObservableArray(["a", "b", "c", "d"]); + const range = new ListRange(1, 3, list.length); + let added = false; + list.subscribe({ + onAdd(idx, value) { + added = true; + const result = range.queryAdd(idx, value, list); + assert.deepEqual(result, { + type: ResultType.UpdateRange, + newRange: new ListRange(1, 3, 5) + }); + } + }); + list.insert(4, "e"); + assert(added); + }, + "queryAdd with too few items to fill viewport grows the range": assert => { + const list = new ObservableArray(["a", "b", "d"]); + const viewportItemCount = 4; + const range = new ListRange(0, 3, list.length, viewportItemCount); + let added = false; + list.subscribe({ + onAdd(idx, value) { + added = true; + const result = range.queryAdd(idx, value, list); + assert.deepEqual(result, { + type: ResultType.Add, + newRange: new ListRange(0, 4, 4), + addIdx: 2, + value: "c" + }); + } + }); + list.insert(2, "c"); + assert(added); + }, + "queryRemove with removal before range": assert => { + const list = new ObservableArray(["a", "b", "c", "d", "e"]); + const range = new ListRange(1, 3, list.length); + let removed = false; + list.subscribe({ + onRemove(idx) { + removed = true; + const result = range.queryRemove(idx, list); + assert.deepEqual(result, { + type: ResultType.RemoveAndAdd, + removeIdx: 1, + addIdx: 2, + value: "d", + newRange: new ListRange(1, 3, 4) + }); + } + }); + list.remove(0); + assert(removed); + }, + "queryRemove with removal within range": assert => { + const list = new ObservableArray(["a", "b", "c", "d", "e"]); + const range = new ListRange(1, 3, list.length); + let removed = false; + list.subscribe({ + onRemove(idx) { + removed = true; + const result = range.queryRemove(idx, list); + assert.deepEqual(result, { + type: ResultType.RemoveAndAdd, + removeIdx: 2, + addIdx: 2, + value: "d", + newRange: new ListRange(1, 3, 4) + }); + assert.equal(list.length, 4); + } + }); + list.remove(2); + assert(removed); + }, + "queryRemove with removal after range": assert => { + const list = new ObservableArray(["a", "b", "c", "d", "e"]); + const range = new ListRange(1, 3, list.length); + let removed = false; + list.subscribe({ + onRemove(idx) { + removed = true; + const result = range.queryRemove(idx, list); + assert.deepEqual(result, { + type: ResultType.UpdateRange, + newRange: new ListRange(1, 3, 4) + }); + } + }); + list.remove(3); + assert(removed); + }, + "queryRemove at bottom of range moves range one up": assert => { + const list = new ObservableArray(["a", "b", "c"]); + const range = new ListRange(1, 3, list.length); + let removed = false; + list.subscribe({ + onRemove(idx) { + removed = true; + const result = range.queryRemove(idx, list); + assert.deepEqual(result, { + newRange: new ListRange(0, 2, 2), + type: ResultType.RemoveAndAdd, + removeIdx: 2, + addIdx: 0, + value: "a" + }); + } + }); + list.remove(2); + assert(removed); + }, + + "queryMove with move inside range": assert => { + const list = new ObservableArray(["a", "b", "c", "d", "e"]); + const range = new ListRange(1, 4, list.length); + let moved = false; + list.subscribe({ + onMove(fromIdx, toIdx, value) { + moved = true; + const result = range.queryMove(fromIdx, toIdx, value, list); + assert.deepEqual(result, { + type: ResultType.Move, + fromIdx: 2, + toIdx: 3 + }); + } + }); + list.move(2, 3); + assert(moved); + }, + + }; +} + +// TODO: test with view larger than space needed by list diff --git a/src/platform/web/ui/general/ItemRange.ts b/src/platform/web/ui/general/Range.ts similarity index 78% rename from src/platform/web/ui/general/ItemRange.ts rename to src/platform/web/ui/general/Range.ts index 66db6078..16dc0a33 100644 --- a/src/platform/web/ui/general/ItemRange.ts +++ b/src/platform/web/ui/general/Range.ts @@ -17,7 +17,7 @@ limitations under the License. // start is included in the range, // end is excluded, // so [2, 2[ means an empty range -class Range { +export class Range { constructor( public readonly start: number, public readonly end: number @@ -35,14 +35,12 @@ class Range { return idx >= this.start && idx < this.end; } - intersects(range: Range): boolean { - return range.start < this.end && this.start < range.end; + toLocalIndex(idx: number) { + return idx - this.start; } - forEach(callback: ((i: number) => void)) { - for (let i = this.start; i < this.end; i += 1) { - callback(i); - } + intersects(range: Range): boolean { + return range.start < this.end && this.start < range.end; } forEachInIterator(it: IterableIterator, callback: ((T, i: number) => void)) { @@ -63,6 +61,30 @@ class Range { [Symbol.iterator](): Iterator { return new RangeIterator(this); } + + reverseIterable(): Iterable { + return new ReverseRangeIterator(this); + } + + clampIndex(idx: number, end = this.end - 1) { + return Math.min(Math.max(this.start, idx), end); + } + + getIndexZone(idx): RangeZone { + if (idx < this.start) { + return RangeZone.Before; + } else if (idx < this.end) { + return RangeZone.Inside; + } else { + return RangeZone.After; + } + } +} + +export enum RangeZone { + Before = 1, + Inside, + After } class RangeIterator implements Iterator { @@ -81,6 +103,26 @@ class RangeIterator implements Iterator { } } +class ReverseRangeIterator implements Iterable, Iterator { + private idx: number; + constructor(private readonly range: Range) { + this.idx = range.end; + } + + [Symbol.iterator]() { + return this; + } + + next(): IteratorResult { + if (this.idx > this.range.start) { + this.idx -= 1; + return {value: this.idx, done: false}; + } else { + return {value: undefined, done: true}; + } + } +} + export function tests() { return { "length": assert => { @@ -90,6 +132,9 @@ export function tests() { "iterator": assert => { assert.deepEqual(Array.from(new Range(2, 5)), [2, 3, 4]); }, + "reverseIterable": assert => { + assert.deepEqual(Array.from(new Range(2, 5).reverseIterable()), [4, 3, 2]); + }, "containsIndex": assert => { const a = new Range(2, 5); assert.equal(a.containsIndex(0), false); @@ -168,43 +213,13 @@ export function tests() { {v: "c", i: 2}, ]); }, + "clampIndex": assert => { + assert.equal(new Range(2, 5).clampIndex(0), 2); + assert.equal(new Range(2, 5).clampIndex(2), 2); + assert.equal(new Range(2, 5).clampIndex(3), 3); + assert.equal(new Range(2, 5).clampIndex(4), 4); + assert.equal(new Range(2, 5).clampIndex(5), 4); + assert.equal(new Range(2, 5).clampIndex(10), 4); + } }; } - -export class ItemRange extends Range { - constructor( - start: number, - end: number, - public readonly totalLength: number - ) { - super(start, end); - } - - - expand(amount: number): ItemRange { - // don't expand ranges that won't render anything - if (this.length === 0) { - return this; - } - - const topGrow = Math.min(amount, this.start); - const bottomGrow = Math.min(amount, this.totalLength - this.end); - return new ItemRange( - this.start - topGrow, - this.end + topGrow + bottomGrow, - this.totalLength, - ); - } - - static fromViewport(listLength: number, itemHeight: number, listHeight: number, scrollTop: number) { - const topCount = Math.min(Math.max(0, Math.floor(scrollTop / itemHeight)), listLength); - const itemsAfterTop = listLength - topCount; - const visibleItems = listHeight !== 0 ? Math.ceil(listHeight / itemHeight) : 0; - const renderCount = Math.min(visibleItems, itemsAfterTop); - return new ItemRange(topCount, topCount + renderCount, listLength); - } - - missingFrom() { - - } -} From 3aa3b7e1600e342cd3f02b1486c540ff86342e9b Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 08:30:52 +0100 Subject: [PATCH 167/242] fix end growing larger than totalLength when range shrinks in case of remove --- src/platform/web/ui/general/ListRange.ts | 47 +++++++++++++++++------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/platform/web/ui/general/ListRange.ts b/src/platform/web/ui/general/ListRange.ts index 7ccd5726..a85a7323 100644 --- a/src/platform/web/ui/general/ListRange.ts +++ b/src/platform/web/ui/general/ListRange.ts @@ -131,12 +131,12 @@ export class ListRange extends Range { if (idx <= maxAddIdx) { // use maxAddIdx to allow to grow the range by one at a time // if the viewport isn't filled yet - const addIdx = this.clampIndex(idx, this.maxAddIdx); + const addIdx = this.clampIndex(idx, maxAddIdx); const addValue = addIdx === idx ? value : getIteratorValueAtIdx(list[Symbol.iterator](), addIdx)!; return this.createAddResult(addIdx, addValue); } else { // if the add happened after the range, we only update the range with the new length - return {type: ResultType.UpdateRange, newRange: this.derive(1, 0)}; + return {type: ResultType.UpdateRange, newRange: this.deriveRange(1, 0)}; } } @@ -145,7 +145,7 @@ export class ListRange extends Range { const removeIdx = this.clampIndex(idx); return this.createRemoveResult(removeIdx, list); } else { - return {type: ResultType.UpdateRange, newRange: this.derive(-1, 0)}; + return {type: ResultType.UpdateRange, newRange: this.deriveRange(-1, 0)}; } } @@ -170,10 +170,10 @@ export class ListRange extends Range { private createAddResult(addIdx: number, value: T): AddRemoveResult { // if the view port isn't filled yet, we don't remove if (this.viewportItemCount > this.length) { - return {type: ResultType.Add, addIdx, value, newRange: this.derive(1, 1)}; + return {type: ResultType.Add, addIdx, value, newRange: this.deriveRange(1, 1)}; } else { const removeIdx = this.clampIndex(Number.MAX_SAFE_INTEGER); - return {type: ResultType.RemoveAndAdd, removeIdx, addIdx, value, newRange: this.derive(1, 0)}; + return {type: ResultType.RemoveAndAdd, removeIdx, addIdx, value, newRange: this.deriveRange(1, 0)}; } } @@ -184,10 +184,10 @@ export class ListRange extends Range { // we assume the value has already been removed from the list, // so we can just look up the next value which is already at the same idx const value = getIteratorValueAtIdx(list[Symbol.iterator](), addIdx)!; - return {type: ResultType.RemoveAndAdd, removeIdx, value, addIdx, newRange: this.derive(-1, 0)}; + return {type: ResultType.RemoveAndAdd, removeIdx, value, addIdx, newRange: this.deriveRange(-1, 0)}; } else if (this.start !== 0) { // move the range 1 item up so we still display a viewport full of items - const newRange = this.derive(-1, 0, 1); + const newRange = this.deriveRange(-1, 0, 1); const addIdx = newRange.start; // we assume the value has already been removed from the list, // so we can just look up the next value which is already at the same idx @@ -195,15 +195,19 @@ export class ListRange extends Range { return {type: ResultType.RemoveAndAdd, removeIdx, value, addIdx, newRange}; } else { // we can't add at the bottom nor top, already constrained - return {type: ResultType.Remove, removeIdx, newRange: this.derive(-1, 0)}; + return {type: ResultType.Remove, removeIdx, newRange: this.deriveRange(-1, 0)}; } } - private derive(totalLengthInc: number, viewportItemCountDecr: number, startDecr: number = 0): ListRange { + private deriveRange(totalLengthInc: number, viewportItemCountDecr: number, startDecr: number = 0): ListRange { + const start = this.start - startDecr; + const totalLength = this.totalLength + totalLengthInc; + // prevent end being larger than totalLength + const end = Math.min(Math.max(start, this.end - startDecr + viewportItemCountDecr), totalLength); return new ListRange( - this.start - startDecr, - this.end - startDecr + viewportItemCountDecr, - this.totalLength + totalLengthInc, + start, + end, + totalLength, this.viewportItemCount ); } @@ -414,7 +418,24 @@ export function tests() { list.remove(2); assert(removed); }, - + "queryRemove with range on full length shrinks range": assert => { + const list = new ObservableArray(["a", "b", "c"]); + const range = new ListRange(0, 3, list.length); + let removed = false; + list.subscribe({ + onRemove(idx) { + removed = true; + const result = range.queryRemove(idx, list); + assert.deepEqual(result, { + newRange: new ListRange(0, 2, 2, 3), + type: ResultType.Remove, + removeIdx: 2, + }); + } + }); + list.remove(2); + assert(removed); + }, "queryMove with move inside range": assert => { const list = new ObservableArray(["a", "b", "c", "d", "e"]); const range = new ListRange(1, 4, list.length); From c22718811fa351e0dfa3e447673bffaebab1df6e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 08:56:33 +0100 Subject: [PATCH 168/242] more tests for queryMove --- src/observable/list/ObservableArray.js | 2 +- src/platform/web/ui/general/ListRange.ts | 97 +++++++++++++++++++++++- 2 files changed, 96 insertions(+), 3 deletions(-) diff --git a/src/observable/list/ObservableArray.js b/src/observable/list/ObservableArray.js index 053e7320..afdaba37 100644 --- a/src/observable/list/ObservableArray.js +++ b/src/observable/list/ObservableArray.js @@ -46,7 +46,7 @@ export class ObservableArray extends BaseObservableList { move(fromIdx, toIdx) { if (fromIdx < this._items.length && toIdx < this._items.length) { - const item = this._items.splice(fromIdx, 1); + const [item] = this._items.splice(fromIdx, 1); this._items.splice(toIdx, 0, item); this.emitMove(fromIdx, toIdx, item); } diff --git a/src/platform/web/ui/general/ListRange.ts b/src/platform/web/ui/general/ListRange.ts index a85a7323..3604e5f8 100644 --- a/src/platform/web/ui/general/ListRange.ts +++ b/src/platform/web/ui/general/ListRange.ts @@ -454,8 +454,101 @@ export function tests() { list.move(2, 3); assert(moved); }, + "queryMove with move from before to inside range": assert => { + const list = new ObservableArray(["a", "b", "c", "d", "e"]); + const range = new ListRange(2, 5, list.length); + let moved = false; + list.subscribe({ + onMove(fromIdx, toIdx, value) { + moved = true; + const result = range.queryMove(fromIdx, toIdx, value, list); + assert.deepEqual(result, { + type: ResultType.RemoveAndAdd, + removeIdx: 2, + addIdx: 3, + value: "a" + }); + } + }); + list.move(0, 3); // move "a" to after "d" + assert(moved); + }, + "queryMove with move from after to inside range": assert => { + const list = new ObservableArray(["a", "b", "c", "d", "e"]); + const range = new ListRange(0, 3, list.length); + let moved = false; + list.subscribe({ + onMove(fromIdx, toIdx, value) { + moved = true; + const result = range.queryMove(fromIdx, toIdx, value, list); + assert.deepEqual(result, { + type: ResultType.RemoveAndAdd, + removeIdx: 2, + addIdx: 1, + value: "e" + }); + } + }); + list.move(4, 1); // move "e" to before "b" + assert(moved); + }, + "queryMove with move inside range to after": assert => { + const list = new ObservableArray(["a", "b", "c", "d", "e"]); + const range = new ListRange(0, 3, list.length); + let moved = false; + list.subscribe({ + onMove(fromIdx, toIdx, value) { + moved = true; + const result = range.queryMove(fromIdx, toIdx, value, list); + assert.deepEqual(result, { + type: ResultType.RemoveAndAdd, + removeIdx: 1, + addIdx: 2, + value: "d" + }); + } + }); + list.move(1, 3); // move "b" to after "d" + assert(moved); + }, + "queryMove with move inside range to before": assert => { + const list = new ObservableArray(["a", "b", "c", "d", "e"]); + const range = new ListRange(2, 5, list.length); + let moved = false; + list.subscribe({ + onMove(fromIdx, toIdx, value) { + moved = true; + const result = range.queryMove(fromIdx, toIdx, value, list); + assert.deepEqual(result, { + type: ResultType.RemoveAndAdd, + removeIdx: 3, + addIdx: 2, + value: "b" + }); + } + }); + list.move(3, 0); // move "d" to before "a" + assert(moved); + }, + "queryMove with move from before range to after": assert => { + const list = new ObservableArray(["a", "b", "c", "d", "e"]); + const range = new ListRange(1, 4, list.length); + let moved = false; + list.subscribe({ + onMove(fromIdx, toIdx, value) { + moved = true; + const result = range.queryMove(fromIdx, toIdx, value, list); + assert.deepEqual(result, { + type: ResultType.RemoveAndAdd, + removeIdx: 1, + addIdx: 3, + value: "e" + }); + } + }); + list.move(0, 4); // move "a" to after "e" + assert(moved); + }, }; } - -// TODO: test with view larger than space needed by list From 7897ea88cd71ce4ea04cfa95119489a60811cefa Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 14:24:43 +0100 Subject: [PATCH 169/242] add some spaces and comments --- src/platform/web/ui/general/LazyListView.ts | 2 +- src/platform/web/ui/general/ListRange.ts | 2 ++ src/platform/web/ui/session/rightpanel/MemberListView.js | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.ts b/src/platform/web/ui/general/LazyListView.ts index f8aa80cc..2d8891ce 100644 --- a/src/platform/web/ui/general/LazyListView.ts +++ b/src/platform/web/ui/general/LazyListView.ts @@ -34,7 +34,7 @@ export class LazyListView extends ListView { private scrollContainer?: HTMLElement; constructor( - {itemHeight, overflowMargin = 5, overflowItems = 20,...options}: IOptions, + {itemHeight, overflowMargin = 5, overflowItems = 20, ...options}: IOptions, childCreator: (value: T) => V ) { super(options, childCreator); diff --git a/src/platform/web/ui/general/ListRange.ts b/src/platform/web/ui/general/ListRange.ts index 3604e5f8..2b70a987 100644 --- a/src/platform/web/ui/general/ListRange.ts +++ b/src/platform/web/ui/general/ListRange.ts @@ -67,6 +67,8 @@ interface RemoveResult { removeIdx: number; } +// need to repeat the fields from RemoveResult and AddResult here +// to make the discriminated union work interface RemoveAndAddResult { type: ResultType.RemoveAndAdd; newRange?: ListRange; diff --git a/src/platform/web/ui/session/rightpanel/MemberListView.js b/src/platform/web/ui/session/rightpanel/MemberListView.js index 6096f919..a4a4e78c 100644 --- a/src/platform/web/ui/session/rightpanel/MemberListView.js +++ b/src/platform/web/ui/session/rightpanel/MemberListView.js @@ -17,7 +17,7 @@ limitations under the License. import {LazyListView} from "../../general/LazyListView"; import {MemberTileView} from "./MemberTileView.js"; -export class MemberListView extends LazyListView{ +export class MemberListView extends LazyListView { constructor(vm) { super({ list: vm.memberTileViewModels, From c64a9c1e23d64f198bb688c776b880c8ab4394e3 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 14:25:00 +0100 Subject: [PATCH 170/242] snowpack/esbuild 0.9 doesn't support override keyword --- src/platform/web/ui/general/LazyListView.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/platform/web/ui/general/LazyListView.ts b/src/platform/web/ui/general/LazyListView.ts index 2d8891ce..deceac08 100644 --- a/src/platform/web/ui/general/LazyListView.ts +++ b/src/platform/web/ui/general/LazyListView.ts @@ -63,7 +63,8 @@ export class LazyListView extends ListView { } } - override async loadList() { + // override + async loadList() { /* Wait two frames for the return from mount() to be inserted into DOM. This should be enough, but if this gives us trouble we can always use From 4be2f12a14ee8b571c19ac82af20067c25a66d4f Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 14:25:22 +0100 Subject: [PATCH 171/242] subscribe before calling list.length --- src/platform/web/ui/general/LazyListView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/web/ui/general/LazyListView.ts b/src/platform/web/ui/general/LazyListView.ts index deceac08..a29e434c 100644 --- a/src/platform/web/ui/general/LazyListView.ts +++ b/src/platform/web/ui/general/LazyListView.ts @@ -76,10 +76,10 @@ export class LazyListView extends ListView { if (!this._list) { return; } + this._subscription = this._list.subscribe(this); const visibleRange = this._getVisibleRange(); this.renderRange = visibleRange.expand(this.overflowItems); this._childInstances = []; - this._subscription = this._list.subscribe(this); this.reRenderFullRange(this.renderRange); } From 9557178ffbb7303b1a74d3a46d03616e3256c9b5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 14:25:35 +0100 Subject: [PATCH 172/242] padding needs to be on ul, not scroll container, or the list blows up --- src/platform/web/ui/general/LazyListView.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.ts b/src/platform/web/ui/general/LazyListView.ts index a29e434c..4686c5ea 100644 --- a/src/platform/web/ui/general/LazyListView.ts +++ b/src/platform/web/ui/general/LazyListView.ts @@ -131,7 +131,7 @@ export class LazyListView extends ListView { private adjustPadding(range: ListRange) { const paddingTop = range.start * this.itemHeight; const paddingBottom = (range.totalLength - range.end) * this.itemHeight; - const style = this.scrollContainer!.style; + const style = this._listElement!.style; style.paddingTop = `${paddingTop}px`; style.paddingBottom = `${paddingBottom}px`; } @@ -153,8 +153,8 @@ export class LazyListView extends ListView { return this.scrollContainer; } - private get _listElement(): Element | undefined { - return super.root(); + private get _listElement(): HTMLElement | undefined { + return super.root() as HTMLElement | undefined; } onAdd(idx: number, value: T) { From 35fb84c2759b34dc7ef26dfa894b8d4ab700373b Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 14:26:15 +0100 Subject: [PATCH 173/242] remove old js lazylist --- .../web/ui/general/foo-LazyListView.js | 287 ------------------ 1 file changed, 287 deletions(-) delete mode 100644 src/platform/web/ui/general/foo-LazyListView.js diff --git a/src/platform/web/ui/general/foo-LazyListView.js b/src/platform/web/ui/general/foo-LazyListView.js deleted file mode 100644 index 3213ffee..00000000 --- a/src/platform/web/ui/general/foo-LazyListView.js +++ /dev/null @@ -1,287 +0,0 @@ -/* -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 {el} from "./html"; -import {mountView} from "./utils"; -import {ListView} from "./ListView"; -import {insertAt} from "./utils"; -import {ItemRange, ScrollDirection} from "./ItemRange.js"; - -export class LazyListView extends ListView { - constructor({itemHeight, overflowMargin = 5, overflowItems = 20,...options}, childCreator) { - super(options, childCreator); - this._itemHeight = itemHeight; - this._overflowMargin = overflowMargin; - this._overflowItems = overflowItems; - } - - _getVisibleRange() { - const length = this._list ? this._list.length : 0; - const scrollTop = this._parent.scrollTop; - const topCount = Math.min(Math.max(0, Math.floor(scrollTop / this._itemHeight)), length); - const itemsAfterTop = length - topCount; - const visibleItems = this._height !== 0 ? Math.ceil(this._height / this._itemHeight) : 0; - const renderCount = Math.min(visibleItems, itemsAfterTop); - const bottomCount = itemsAfterTop - renderCount; - return new ItemRange(topCount, renderCount, bottomCount); - } - - _renderIfNeeded() { - const range = this._getVisibleRange(); - const intersectRange = range.expand(this._overflowMargin); - const renderRange = range.expand(this._overflowItems); - // only update render Range if the new range + overflowMargin isn't contained by the old anymore - if (!this._renderRange.contains(intersectRange)) { - console.log("new", renderRange); - console.log("current", this._renderRange); - console.log("diff", this._renderRange.diff(renderRange)); - this._renderElementsInRange(renderRange); - } - } - - async _initialRender() { - /* - Wait two frames for the return from mount() to be inserted into DOM. - This should be enough, but if this gives us trouble we can always use - MutationObserver. - */ - await new Promise(r => requestAnimationFrame(r)); - await new Promise(r => requestAnimationFrame(r)); - - this._height = this._parent.clientHeight; - if (this._height === 0) { console.error("LazyListView could not calculate parent height."); } - const initialRange = this._getVisibleRange(); - const initialRenderRange = initialRange.expand(this._overflowItems); - this._renderRange = new ItemRange(0, 0, initialRange.bottomCount + 1); - this._renderElementsInRange(initialRenderRange); - } - - _itemsFromList({start, end}) { - const array = []; - let i = 0; - for (const item of this._list) { - if (i >= start && i <= end) { - array.push(item); - } - i = i + 1; - } - return array; - } - - _itemAtIndex(idx) { - let i = 0; - for (const item of this._list) { - if (i === idx) { - return item; - } - i = i + 1; - } - return null; - } - - _adjustPadding(range) { - const { topCount, bottomCount } = range; - const paddingTop = topCount * this._itemHeight; - const paddingBottom = bottomCount * this._itemHeight; - this._root.style.paddingTop = `${paddingTop}px`; - this._root.style.paddingBottom = `${paddingBottom}px`; - } - - _renderedFragment(items, childInstanceModifier) { - const fragment = document.createDocumentFragment(); - for (const item of items) { - const view = this._childCreator(item); - childInstanceModifier(view); - fragment.appendChild(mountView(view, this._mountArgs)); - } - return fragment; - } - - _renderElementsInRange(range) { - const diff = this._renderRange.diff(range); - const renderedItems = this._itemsFromList(diff.toAdd); - this._adjustPadding(range); - const {start, end} = diff.toRemove; - const normalizedStart = this._renderRange.normalize(start); - this._childInstances.splice(normalizedStart, end - start + 1).forEach(child => this._removeChild(child)); - - if (diff.scrollDirection === ScrollDirection.downwards) { - const fragment = this._renderedFragment(renderedItems, view => this._childInstances.push(view)); - this._root.appendChild(fragment); - } - else { - const fragment = this._renderedFragment(renderedItems, view => this._childInstances.unshift(view)); - this._root.insertBefore(fragment, this._root.firstChild); - } - this._renderRange = range; - } - - mount() { - const root = super.mount(); - this._subscription = this._list.subscribe(this); - this._childInstances = []; - this._parent = el("div", {className: "LazyListParent"}, root); - /* - Hooking to scroll events can be expensive. - Do we need to do more (like event throttling)? - */ - this._parent.addEventListener("scroll", () => this._renderIfNeeded()); - this._initialRender(); - return this._parent; - } - - update(attributes) { - this._renderRange = null; - super.update(attributes); - this._childInstances = []; - this._initialRender(); - } - - loadList() { - // We don't render the entire list; so nothing to see here. - } - - _removeChild(child) { - child.root().remove(); - child.unmount(); - } - - onAdd(idx, value) { - const {topCount, renderCount, bottomCount} = this._renderRange; - if (this._renderRange.containsIndex(idx)) { - this.onBeforeListChanged(); - const normalizedIdx = this._renderRange.normalize(idx); - if (bottomCount === 0) { - /* - If we're at the bottom of the list, we need to render the additional item - without removing another item from the list. - We can't increment topCount because the index topCount is not affected by the - add operation (and any modification will thus break ItemRange.normalize()). - We can't increment bottomCount because there's not enough items left to trigger - a further render. - */ - this._renderRange = new ItemRange(topCount, renderCount + 1, bottomCount); - } - else { - // Remove the last element, render the new element - this._removeChild(this._childInstances.pop()); - this._renderRange = new ItemRange(topCount, renderCount, bottomCount + 1); - } - super.onAdd(normalizedIdx, value, true); - this.onListChanged(); - } - else { - this._renderRange = idx < topCount ? new ItemRange(topCount + 1, renderCount, bottomCount): - new ItemRange(topCount, renderCount, bottomCount + 1); - } - this._adjustPadding(this._renderRange); - } - - onRemove(idx, value) { - const {topCount, renderCount, bottomCount} = this._renderRange; - if (this._renderRange.containsIndex(idx)) { - this.onBeforeListChanged(); - const normalizedIdx = this._renderRange.normalize(idx); - super.onRemove(normalizedIdx, value, true); - if (bottomCount === 0) { - // See onAdd for explanation - this._renderRange = new ItemRange(topCount, renderCount - 1, bottomCount); - } - else { - const child = this._childCreator(this._itemAtIndex(this._renderRange.lastIndex)); - this._childInstances.push(child); - this._root.appendChild(mountView(child, this._mountArgs)); - this._renderRange = new ItemRange(topCount, renderCount, bottomCount - 1); - } - this.onListChanged(); - } - else { - this._renderRange = idx < topCount ? new ItemRange(topCount - 1, renderCount, bottomCount): - new ItemRange(topCount, renderCount, bottomCount - 1); - } - this._adjustPadding(this._renderRange); - } - - onUpdate(idx, value, params) { - if (this._renderRange.containsIndex(idx)) { - const normalizedIdx = this._renderRange.normalize(idx); - super.onUpdate(normalizedIdx, value, params); - } - } - - recreateItem(idx, value) { - if (this._renderRange.containsIndex(idx)) { - const normalizedIdx = this._renderRange.normalize(idx); - super.recreateItem(normalizedIdx, value) - } - } - - /** - * Render additional element from top or bottom to offset the outgoing element - */ - _renderExtraOnMove(fromIdx, toIdx) { - const {topCount, renderCount} = this._renderRange; - if (toIdx < fromIdx) { - // Element is moved up the list, so render element from top boundary - const index = topCount; - const child = this._childCreator(this._itemAtIndex(index)); - this._childInstances.unshift(child); - this._root.insertBefore(mountView(child, this._mountArgs), this._root.firstChild); - } - else { - // Element is moved down the list, so render element from bottom boundary - const index = topCount + renderCount - 1; - const child = this._childCreator(this._itemAtIndex(index)); - this._childInstances.push(child); - this._root.appendChild(mountView(child, this._mountArgs)); - } - } - - /** - * Remove an element from top or bottom to make space for the incoming element - */ - _removeElementOnMove(fromIdx, toIdx) { - // If element comes from the bottom, remove element at bottom and vice versa - const child = toIdx < fromIdx ? this._childInstances.pop() : this._childInstances.shift(); - this._removeChild(child); - } - - onMove(fromIdx, toIdx, value) { - const fromInRange = this._renderRange.containsIndex(fromIdx); - const toInRange = this._renderRange.containsIndex(toIdx); - const normalizedFromIdx = this._renderRange.normalize(fromIdx); - const normalizedToIdx = this._renderRange.normalize(toIdx); - if (fromInRange && toInRange) { - super.onMove(normalizedFromIdx, normalizedToIdx, value); - } - else if (fromInRange && !toInRange) { - this.onBeforeListChanged(); - const [child] = this._childInstances.splice(normalizedFromIdx, 1); - this._removeChild(child); - this._renderExtraOnMove(fromIdx, toIdx); - this.onListChanged(); - } - else if (!fromInRange && toInRange) { - this.onBeforeListChanged(); - const child = this._childCreator(value); - this._removeElementOnMove(fromIdx, toIdx); - this._childInstances.splice(normalizedToIdx, 0, child); - insertAt(this._root, normalizedToIdx, mountView(child, this._mountArgs)); - this.onListChanged(); - } - } - -} From e34a92e2ec2917addede180d12f1a34b0d39181d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 14:30:11 +0100 Subject: [PATCH 174/242] fix copyright --- src/platform/web/ui/general/LazyListView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/web/ui/general/LazyListView.ts b/src/platform/web/ui/general/LazyListView.ts index 4686c5ea..81b57264 100644 --- a/src/platform/web/ui/general/LazyListView.ts +++ b/src/platform/web/ui/general/LazyListView.ts @@ -1,5 +1,5 @@ /* -Copyright 2020 Bruno Windels +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. From 7b38df45da8d9e6e66e1a15c87082274cf813f02 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 14:31:23 +0100 Subject: [PATCH 175/242] i think this is fine now? --- src/platform/web/ui/general/ListRange.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platform/web/ui/general/ListRange.ts b/src/platform/web/ui/general/ListRange.ts index 2b70a987..80cd17e8 100644 --- a/src/platform/web/ui/general/ListRange.ts +++ b/src/platform/web/ui/general/ListRange.ts @@ -161,7 +161,6 @@ export class ListRange extends Range { return {type: ResultType.Move, fromIdx, toIdx}; } } else { - // TODO const addIdx = this.clampIndex(toIdx); const removeIdx = this.clampIndex(fromIdx); const addValue = addIdx === toIdx ? value : getIteratorValueAtIdx(list[Symbol.iterator](), addIdx)!; From e4be1702c4f6a0cd952c05bc053986622086d911 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 14:32:42 +0100 Subject: [PATCH 176/242] add comment for future test --- src/platform/web/ui/general/ListRange.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/platform/web/ui/general/ListRange.ts b/src/platform/web/ui/general/ListRange.ts index 80cd17e8..4f62ba21 100644 --- a/src/platform/web/ui/general/ListRange.ts +++ b/src/platform/web/ui/general/ListRange.ts @@ -550,6 +550,7 @@ export function tests() { list.move(0, 4); // move "a" to after "e" assert(moved); }, - + // would be good to test here what multiple mutations look like with executing the result of queryXXX + // on an array, much like we do in the view. }; } From f444160c6a29b4766551a20c7364df001a78789a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 14:33:27 +0100 Subject: [PATCH 177/242] feels ok without overflow margin for now --- src/platform/web/ui/general/LazyListView.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/platform/web/ui/general/LazyListView.ts b/src/platform/web/ui/general/LazyListView.ts index 81b57264..1696f044 100644 --- a/src/platform/web/ui/general/LazyListView.ts +++ b/src/platform/web/ui/general/LazyListView.ts @@ -22,7 +22,6 @@ import {IView} from "./types"; export interface IOptions extends IParentOptions { itemHeight: number; - overflowMargin?: number; overflowItems?: number; } @@ -34,13 +33,12 @@ export class LazyListView extends ListView { private scrollContainer?: HTMLElement; constructor( - {itemHeight, overflowMargin = 5, overflowItems = 20, ...options}: IOptions, + {itemHeight, overflowItems = 20, ...options}: IOptions, childCreator: (value: T) => V ) { super(options, childCreator); this.itemHeight = itemHeight; this.overflowItems = overflowItems; - // TODO: this.overflowMargin = overflowMargin; } handleEvent(e: Event) { From 91f2a96403e466be902d5a1e4015dd5d421cb8ae Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 24 Nov 2021 13:40:04 +0530 Subject: [PATCH 178/242] 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 179/242] 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 180/242] 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 181/242] 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 182/242] 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 183/242] 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 184/242] 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 185/242] 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 186/242] 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 229c584138a1928a3bb764293330a84aac3baad5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 25 Nov 2021 15:38:13 +0100 Subject: [PATCH 187/242] don't fail login if dehydrated devices are not supported --- src/matrix/SessionContainer.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 3e3dab66..91418b0d 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -329,7 +329,16 @@ export class SessionContainer { request: this._platform.request, }); const olm = await this._olmPromise; - const encryptedDehydratedDevice = await getDehydratedDevice(hsApi, olm, this._platform, log); + let encryptedDehydratedDevice; + try { + encryptedDehydratedDevice = await getDehydratedDevice(hsApi, olm, this._platform, log); + } catch (err) { + if (err instanceof HomeServerError) { + log.set("not_supported", true); + } else { + throw err; + } + } if (encryptedDehydratedDevice) { let resolveStageFinish; const promiseStageFinish = new Promise(r => resolveStageFinish = r); From ae7d4d07dfbcbfbe82972594dad62bf571cb8757 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 25 Nov 2021 15:42:36 +0100 Subject: [PATCH 188/242] use .name so we don't need an import --- src/matrix/SessionContainer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 91418b0d..d8977dde 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -333,7 +333,7 @@ export class SessionContainer { try { encryptedDehydratedDevice = await getDehydratedDevice(hsApi, olm, this._platform, log); } catch (err) { - if (err instanceof HomeServerError) { + if (err.name === "HomeServerError") { log.set("not_supported", true); } else { throw err; From 876fcf532f86dcc10aef65a5ce087deac3545022 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 26 Nov 2021 09:12:08 +0100 Subject: [PATCH 189/242] release v0.2.22 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3211bf4f..6479bee1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hydrogen-web", - "version": "0.2.21", + "version": "0.2.22", "description": "A javascript matrix client prototype, trying to minize RAM usage by offloading as much as possible to IndexedDB", "main": "src/lib.ts", "directories": { From 2802164bb4f416d6d59c3b9bfb8ec2d9cbbb78d9 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 26 Nov 2021 12:45:40 +0100 Subject: [PATCH 190/242] update to version that doesn't use a bash script anymore, which doesnt work on macos --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 6479bee1..848e4104 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.3", + "impunity": "^1.0.7", "mdn-polyfills": "^5.20.0", "postcss": "^8.1.1", "postcss-css-variables": "^0.17.0", diff --git a/yarn.lock b/yarn.lock index 830a5cd5..52661eff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3021,10 +3021,10 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -impunity@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/impunity/-/impunity-1.0.3.tgz#1e9972d137f0e0dbed4d39e6eca6c238a29b6526" - integrity sha512-D3XT8ED/AX5mbSQdAf0nz+65ilZE/q17Yykx8g7FqlnKjDdoowFv9kxdS4tOggPrJY/5lAfE86/ZFa878VpZBw== +impunity@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/impunity/-/impunity-1.0.7.tgz#b1484678ca82b7fce7750ab085a418302ce5883d" + integrity sha512-DIPr9toJHP8s/SMe6efOzhfGtiCbEniPO4JtHk6CvSZqtEPZpkF31l8TUrG8XTYxU1lBFwlkFi7RZ681YWdBrQ== dependencies: colors "^1.3.3" commander "^6.1.0" From d981a852397b825f136e75d0a22efa3552fafaf8 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 29 Nov 2021 11:43:43 +0530 Subject: [PATCH 191/242] 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 192/242] 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 a134e48ebb8792d46774620652a93af2e7c6b822 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 29 Nov 2021 10:49:26 +0100 Subject: [PATCH 193/242] update impunity to 1.0.8 to run tests on node >= 16.12 --- package.json | 4 +- yarn.lock | 133 +++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 120 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 848e4104..8cda0543 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.7", + "impunity": "^1.0.8", "mdn-polyfills": "^5.20.0", "postcss": "^8.1.1", "postcss-css-variables": "^0.17.0", @@ -54,7 +54,6 @@ "xxhashjs": "^0.2.2" }, "dependencies": { - "node-html-parser": "^4.0.0", "@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.3.tgz", "@rollup/plugin-commonjs": "^15.0.0", "@rollup/plugin-json": "^4.1.0", @@ -65,6 +64,7 @@ "bs58": "^4.0.1", "dompurify": "^2.3.0", "es6-promise": "https://github.com/bwindels/es6-promise.git#bwindels/expose-flush", + "node-html-parser": "^4.0.0", "rollup": "^2.26.4", "text-encoding": "^0.7.0" } diff --git a/yarn.lock b/yarn.lock index 52661eff..64926972 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2293,17 +2293,120 @@ es-module-lexer@^0.6.0: version "4.2.8" resolved "https://github.com/bwindels/es6-promise.git#112f78f5829e627055b0ff56a52fecb63f6003b1" -esbuild-node-loader@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/esbuild-node-loader/-/esbuild-node-loader-0.3.1.tgz#fa761e020eff316549ddc3c51a25ec9ffc159ff2" - integrity sha512-75xPOySulti9R5LwYOMmKiwHyXGr/f89I7UkHolLxRqeBiUNqcyCmNTjv+fO2WV9G3f7LDKVZJlbWoYh5LBpfQ== - dependencies: - esbuild "^0.12.6" +esbuild-android-arm64@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.13.15.tgz#3fc3ff0bab76fe35dd237476b5d2b32bb20a3d44" + integrity sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg== -esbuild@^0.12.6: - version "0.12.20" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.12.20.tgz#4d3c9d83c99a4031e027b42a4c398c23b6827cb0" - integrity sha512-u7+0qTo9Z64MD9PhooEngCmzyEYJ6ovFhPp8PLNh3UasR5Ihjv6HWVXqm8uHmasdQlpsAf0IsY4U0YVUfCpt4Q== +esbuild-darwin-64@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.13.15.tgz#8e9169c16baf444eacec60d09b24d11b255a8e72" + integrity sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ== + +esbuild-darwin-arm64@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.15.tgz#1b07f893b632114f805e188ddfca41b2b778229a" + integrity sha512-i1FZssTVxUqNlJ6cBTj5YQj4imWy3m49RZRnHhLpefFIh0To05ow9DTrXROTE1urGTQCloFUXTX8QfGJy1P8dQ== + +esbuild-freebsd-64@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.15.tgz#0b8b7eca1690c8ec94c75680c38c07269c1f4a85" + integrity sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA== + +esbuild-freebsd-arm64@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.15.tgz#2e1a6c696bfdcd20a99578b76350b41db1934e52" + integrity sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ== + +esbuild-linux-32@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.13.15.tgz#6fd39f36fc66dd45b6b5f515728c7bbebc342a69" + integrity sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g== + +esbuild-linux-64@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.13.15.tgz#9cb8e4bcd7574e67946e4ee5f1f1e12386bb6dd3" + integrity sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA== + +esbuild-linux-arm64@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.15.tgz#3891aa3704ec579a1b92d2a586122e5b6a2bfba1" + integrity sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA== + +esbuild-linux-arm@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.13.15.tgz#8a00e99e6a0c6c9a6b7f334841364d8a2b4aecfe" + integrity sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA== + +esbuild-linux-mips64le@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.15.tgz#36b07cc47c3d21e48db3bb1f4d9ef8f46aead4f7" + integrity sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg== + +esbuild-linux-ppc64le@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.15.tgz#f7e6bba40b9a11eb9dcae5b01550ea04670edad2" + integrity sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ== + +esbuild-netbsd-64@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.15.tgz#a2fedc549c2b629d580a732d840712b08d440038" + integrity sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w== + +esbuild-node-loader@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/esbuild-node-loader/-/esbuild-node-loader-0.6.3.tgz#3b90012f8bc2fcbb2ef76a659482c2c99840c5e8" + integrity sha512-Bf6o8SiMMh5+r20jsjAThNOtzo3t8Ye4Qdzz+twWHnxu28SdkGUr5ahq8iX0qbd+I9ge8sLNX7oQoNW1YzHlqA== + dependencies: + esbuild "^0.13.12" + +esbuild-openbsd-64@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.15.tgz#b22c0e5806d3a1fbf0325872037f885306b05cd7" + integrity sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g== + +esbuild-sunos-64@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.13.15.tgz#d0b6454a88375ee8d3964daeff55c85c91c7cef4" + integrity sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw== + +esbuild-windows-32@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.13.15.tgz#c96d0b9bbb52f3303322582ef8e4847c5ad375a7" + integrity sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw== + +esbuild-windows-64@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.13.15.tgz#1f79cb9b1e1bb02fb25cd414cb90d4ea2892c294" + integrity sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ== + +esbuild-windows-arm64@0.13.15: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.15.tgz#482173070810df22a752c686509c370c3be3b3c3" + integrity sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA== + +esbuild@^0.13.12: + version "0.13.15" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.13.15.tgz#db56a88166ee373f87dbb2d8798ff449e0450cdf" + integrity sha512-raCxt02HBKv8RJxE8vkTSCXGIyKHdEdGfUmiYb8wnabnaEmHzyW7DCHb5tEN0xU8ryqg5xw54mcwnYkC4x3AIw== + optionalDependencies: + esbuild-android-arm64 "0.13.15" + esbuild-darwin-64 "0.13.15" + esbuild-darwin-arm64 "0.13.15" + esbuild-freebsd-64 "0.13.15" + esbuild-freebsd-arm64 "0.13.15" + esbuild-linux-32 "0.13.15" + esbuild-linux-64 "0.13.15" + esbuild-linux-arm "0.13.15" + esbuild-linux-arm64 "0.13.15" + esbuild-linux-mips64le "0.13.15" + esbuild-linux-ppc64le "0.13.15" + esbuild-netbsd-64 "0.13.15" + esbuild-openbsd-64 "0.13.15" + esbuild-sunos-64 "0.13.15" + esbuild-windows-32 "0.13.15" + esbuild-windows-64 "0.13.15" + esbuild-windows-arm64 "0.13.15" esbuild@~0.9.0: version "0.9.7" @@ -3021,14 +3124,14 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -impunity@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/impunity/-/impunity-1.0.7.tgz#b1484678ca82b7fce7750ab085a418302ce5883d" - integrity sha512-DIPr9toJHP8s/SMe6efOzhfGtiCbEniPO4JtHk6CvSZqtEPZpkF31l8TUrG8XTYxU1lBFwlkFi7RZ681YWdBrQ== +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== dependencies: colors "^1.3.3" commander "^6.1.0" - esbuild-node-loader "^0.3.1" + esbuild-node-loader "^0.6.3" imurmurhash@^0.1.4: version "0.1.4" From 3322827979bc7068dc9f457476ea682667c7370c Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 08:04:45 +0100 Subject: [PATCH 194/242] 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 195/242] 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 196/242] 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 197/242] 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 198/242] 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 199/242] 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 200/242] 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 201/242] 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 202/242] 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 203/242] 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 75bf410320c88bebcb6cdfb68a2b35a7897de0be Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 1 Dec 2021 13:30:17 +0100 Subject: [PATCH 204/242] correct path of main.js for tests --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 37685f05..2728935c 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "lint": "eslint --cache src/", "lint-ts": "eslint src/ -c .ts-eslintrc.js --ext .ts", "lint-ci": "eslint src/", - "test": "impunity --entry-point src/main.js src/platform/web/Platform.js --force-esm-dirs lib/ src/ --root-dir src/", + "test": "impunity --entry-point src/platform/web/main.js src/platform/web/Platform.js --force-esm-dirs lib/ src/ --root-dir src/", "start": "vite --port 3000", "build": "vite build" }, From de24034b224303eaaefe29ec5b171f5019ca749a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 1 Dec 2021 13:30:58 +0100 Subject: [PATCH 205/242] remove secondary theme as vite puts them in one bundle --- src/platform/web/index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/platform/web/index.html b/src/platform/web/index.html index a99edde8..aa0a7c49 100644 --- a/src/platform/web/index.html +++ b/src/platform/web/index.html @@ -12,8 +12,7 @@ - - + diff --git a/src/platform/web/sdk/paths/vite.ts b/src/platform/web/sdk/paths/vite.ts index 6739f8d8..0a3ddedd 100644 --- a/src/platform/web/sdk/paths/vite.ts +++ b/src/platform/web/sdk/paths/vite.ts @@ -17,3 +17,6 @@ export const olmPaths = { export const downloadSandboxPath = _downloadSandboxPath; export const workerPath = _workerPath; +// the service worker is generated by the build as an unhashed asset, +// we don't use it at development time, so don't use import for the path +export const serviceWorkerPath = "sw.js"; From 155cd4c9bd0de51e551bc5d635e3d8eab8394edb Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 6 Dec 2021 13:49:14 +0100 Subject: [PATCH 222/242] make olmPath absolute if it isn't already --- src/platform/web/Platform.js | 12 ++++++++++-- vite.config.js | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/platform/web/Platform.js b/src/platform/web/Platform.js index 96f76abc..1b08d83d 100644 --- a/src/platform/web/Platform.js +++ b/src/platform/web/Platform.js @@ -80,8 +80,16 @@ function relPath(path, basePath) { async function loadOlmWorker(config) { const workerPool = new WorkerPool(config.worker, 4); await workerPool.init(); - const path = relPath(config.olm.legacyBundle, config.worker); - await workerPool.sendAll({type: "load_olm", path}); + let olmPath = config.olm.legacyBundle; + // convert olm path to absolute path + if (!olmPath.startsWith("/")) { + olmPath = new URL(olmPath, document.location.href).pathname; + console.log("olmPath", config.olm.legacyBundle, olmPath); + } + await workerPool.sendAll({ + type: "load_olm", + path: olmPath + }); const olmWorker = new OlmWorker(workerPool); return olmWorker; } diff --git a/vite.config.js b/vite.config.js index 72c81bac..caae8f4b 100644 --- a/vite.config.js +++ b/vite.config.js @@ -20,6 +20,7 @@ let polyfillRef; export default { public: false, root: "src/platform/web", + base: "./", server: { hmr: false }, From 91e69a2bd0c193818228280b4b7d33d2fca0f49d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 6 Dec 2021 15:25:44 +0100 Subject: [PATCH 223/242] fix icons in manifest not being found --- scripts/build-plugins/manifest.js | 5 ++++- vite.config.js | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/build-plugins/manifest.js b/scripts/build-plugins/manifest.js index 560bce68..b79af2b2 100644 --- a/scripts/build-plugins/manifest.js +++ b/scripts/build-plugins/manifest.js @@ -32,7 +32,10 @@ module.exports = function injectWebManifest(manifestFile) { name: path.basename(iconFileName), source: imgData }); - icon.src = this.getFileName(ref); + // we take the basename as getFileName gives the filename + // relative to the output dir, but the manifest is an asset + // just like they icon, so we assume they end up in the same dir + icon.src = path.basename(this.getFileName(ref)); } const outputName = path.basename(absoluteManifestFile); const manifestRef = this.emitFile({ diff --git a/vite.config.js b/vite.config.js index caae8f4b..28f9f5a6 100644 --- a/vite.config.js +++ b/vite.config.js @@ -47,6 +47,8 @@ export default { // }, "hydrogen-legacy", [ // './legacy-polyfill', // ]), + // important this comes before service worker + // otherwise the manifest and the icons it refers to won't be cached injectWebManifest("assets/manifest.json"), injectServiceWorker("sw.js"), ], From 0e2a22f509248bfdced509f56e2c21014ac285a0 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 6 Dec 2021 15:34:39 +0100 Subject: [PATCH 224/242] also look in chunks for cacheable assets for service worker --- scripts/build-plugins/service-worker.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/scripts/build-plugins/service-worker.js b/scripts/build-plugins/service-worker.js index 155c798b..987debbe 100644 --- a/scripts/build-plugins/service-worker.js +++ b/scripts/build-plugins/service-worker.js @@ -22,19 +22,17 @@ module.exports = function injectServiceWorker(swFile) { }, generateBundle: async function(_, bundle) { const absoluteSwFile = path.resolve(root, swFile); - const packageManifest = path.resolve(path.join(__dirname, "../../package.json")); let swSource = await fs.readFile(absoluteSwFile, {encoding: "utf8"}); - const assets = Object.values(bundle).filter(a => a.type === "asset"); - const cachedFileNames = assets.map(o => o.fileName).filter(fileName => fileName !== "index.html"); - const r = Object.entries(bundle).find(([key, asset]) => key.includes("index.html")); - const index = assets.find(o => o.fileName === "index.html"); + const index = bundle["index.html"]; if (!index) { - console.log("index not found", index, r); + console.log("index not found", index); } const uncachedFileContentMap = { "index.html": index.source, "sw.js": swSource }; + const assets = Object.values(bundle); + const cachedFileNames = assets.map(o => o.fileName).filter(fileName => fileName !== "index.html"); const globalHash = getBuildHash(cachedFileNames, uncachedFileContentMap); swSource = await buildServiceWorker(swSource, version, globalHash, assets); const outputName = path.basename(absoluteSwFile); From 5bd28da4f3f1c4b81a7673534204ae3312042a9f Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 6 Dec 2021 15:35:08 +0100 Subject: [PATCH 225/242] loading olm from the worker was broken, reading the wrong global --- src/platform/web/worker/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/web/worker/main.js b/src/platform/web/worker/main.js index db8d84e9..9b5560ca 100644 --- a/src/platform/web/worker/main.js +++ b/src/platform/web/worker/main.js @@ -108,7 +108,7 @@ class MessageHandler { self.window = self; self.document = {}; self.importScripts(path); - const olm = self.olm_exports; + const olm = self.Olm; await olm.init(); this._olm = olm; }); From c87628b614a3a8fbf336c6e1ac8df92d69bd86a9 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 6 Dec 2021 15:38:01 +0100 Subject: [PATCH 226/242] cleanup --- src/platform/web/Platform.js | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/platform/web/Platform.js b/src/platform/web/Platform.js index 1b08d83d..787c1c90 100644 --- a/src/platform/web/Platform.js +++ b/src/platform/web/Platform.js @@ -67,28 +67,21 @@ async function loadOlm(olmPaths) { } return null; } - -// make path relative to basePath, -// assuming it and basePath are relative to document -function relPath(path, basePath) { - const idx = basePath.lastIndexOf("/"); - const dir = idx === -1 ? "" : basePath.slice(0, idx); - const dirCount = dir.length ? dir.split("/").length : 0; - return "../".repeat(dirCount) + path; +// turn asset path to absolute path if it isn't already +// so it can be loaded independent of base +function assetAbsPath(assetPath) { + if (!assetPath.startsWith("/")) { + return new URL(assetPath, document.location.href).pathname; + } + return assetPath; } async function loadOlmWorker(config) { const workerPool = new WorkerPool(config.worker, 4); await workerPool.init(); - let olmPath = config.olm.legacyBundle; - // convert olm path to absolute path - if (!olmPath.startsWith("/")) { - olmPath = new URL(olmPath, document.location.href).pathname; - console.log("olmPath", config.olm.legacyBundle, olmPath); - } await workerPool.sendAll({ type: "load_olm", - path: olmPath + path: assetAbsPath(config.olm.legacyBundle) }); const olmWorker = new OlmWorker(workerPool); return olmWorker; From c8b0354d0774dd11dc0311a39ed079e5aac3aed2 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 8 Dec 2021 18:00:27 +0100 Subject: [PATCH 227/242] dont use lookbehind in regular expressions, safari & older firefoxes choke on them --- codestyle.md | 2 ++ src/platform/web/Platform.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/codestyle.md b/codestyle.md index c0e0e363..656a6845 100644 --- a/codestyle.md +++ b/codestyle.md @@ -8,3 +8,5 @@ otherwise it becomes hard to remember what was a default/named export - should we return promises from storage mutation calls? probably not, as we don't await them anywhere. only read calls should return promises? - we don't anymore + - don't use these features, as they are not widely enough supported. + - [lookbehind in regular expressions](https://caniuse.com/js-regexp-lookbehind) diff --git a/src/platform/web/Platform.js b/src/platform/web/Platform.js index 787c1c90..78332e59 100644 --- a/src/platform/web/Platform.js +++ b/src/platform/web/Platform.js @@ -163,7 +163,7 @@ export class Platform { // 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=).+/, ""); + item.e.stack = item.e.stack.replace(/(?<=\/\?loginToken=).+/, "?loginToken="); } return item; }; From 4c2c99fc07547904050e51d6563f266d9700b047 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 8 Dec 2021 18:05:57 +0100 Subject: [PATCH 228/242] actually remove lookbehind --- src/platform/web/Platform.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/web/Platform.js b/src/platform/web/Platform.js index 78332e59..b23faa6a 100644 --- a/src/platform/web/Platform.js +++ b/src/platform/web/Platform.js @@ -163,7 +163,7 @@ export class Platform { // 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=).+/, "?loginToken="); + item.e.stack = item.e.stack.replace(/\/\?loginToken=(.+)/, "?loginToken="); } return item; }; From fb8149b6cf53f8a624c00756546065740a2f36f3 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 8 Dec 2021 18:29:07 +0100 Subject: [PATCH 229/242] add base to manifest path, just for completeness --- scripts/build-plugins/manifest.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/build-plugins/manifest.js b/scripts/build-plugins/manifest.js index b79af2b2..e7c2c536 100644 --- a/scripts/build-plugins/manifest.js +++ b/scripts/build-plugins/manifest.js @@ -3,12 +3,14 @@ const path = require('path'); module.exports = function injectWebManifest(manifestFile) { let root; + let base; let manifestHref; return { name: "hydrogen:injectWebManifest", apply: "build", configResolved: config => { root = config.root; + base = config.base; }, transformIndexHtml: { transform(html) { @@ -43,7 +45,7 @@ module.exports = function injectWebManifest(manifestFile) { name: outputName, source: JSON.stringify(manifest) }); - manifestHref = this.getFileName(manifestRef); + manifestHref = base + this.getFileName(manifestRef); } }; } From 180681b602a70d2c2d821e462901ba14030faaa1 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 8 Dec 2021 18:29:32 +0100 Subject: [PATCH 230/242] manifest ends up in assets folder, index.html in parent folder --- src/platform/web/assets/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/web/assets/manifest.json b/src/platform/web/assets/manifest.json index 92dde01a..e8d897b2 100644 --- a/src/platform/web/assets/manifest.json +++ b/src/platform/web/assets/manifest.json @@ -3,7 +3,7 @@ "short_name": "Hydrogen", "display": "standalone", "description": "Lightweight matrix client with legacy and mobile browser support", - "start_url": "index.html", + "start_url": "../index.html", "icons": [ {"src": "icon.png", "sizes": "384x384", "type": "image/png"}, {"src": "icon-maskable.png", "sizes": "384x384", "type": "image/png", "purpose": "maskable"} From c344032c0a17cf679f3a847d131f95275c36d349 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 9 Dec 2021 11:39:28 +0100 Subject: [PATCH 231/242] transpile service worker and cleanup build plugin --- scripts/build-plugins/service-worker.js | 50 ++++++++++++------------- vite.config.js | 2 +- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/scripts/build-plugins/service-worker.js b/scripts/build-plugins/service-worker.js index 987debbe..e7a77048 100644 --- a/scripts/build-plugins/service-worker.js +++ b/scripts/build-plugins/service-worker.js @@ -8,42 +8,42 @@ function contentHash(str) { return hasher.digest(); } -module.exports = function injectServiceWorker(swFile) { +module.exports = function injectServiceWorker(swFile, otherUncachedFiles) { + const swName = path.basename(swFile); let root; let version; - let manifestHref; + return { name: "hydrogen:injectServiceWorker", apply: "build", enforce: "post", + buildStart() { + this.emitFile({ + type: "chunk", + fileName: swName, + id: swFile, + }); + }, configResolved: config => { root = config.root; version = JSON.parse(config.define.HYDROGEN_VERSION); // unquote }, - generateBundle: async function(_, bundle) { - const absoluteSwFile = path.resolve(root, swFile); - let swSource = await fs.readFile(absoluteSwFile, {encoding: "utf8"}); - const index = bundle["index.html"]; - if (!index) { - console.log("index not found", index); - } - const uncachedFileContentMap = { - "index.html": index.source, - "sw.js": swSource - }; + generateBundle: async function(options, bundle) { + const uncachedFileNames = [swName].concat(otherUncachedFiles); + const uncachedFileContentMap = uncachedFileNames.reduce((map, fileName) => { + const chunkOrAsset = bundle[fileName]; + if (!chunkOrAsset) { + throw new Error("could not get content for uncached asset or chunk " + fileName); + } + map[fileName] = chunkOrAsset.source || chunkOrAsset.code; + return map; + }, {}); const assets = Object.values(bundle); - const cachedFileNames = assets.map(o => o.fileName).filter(fileName => fileName !== "index.html"); + const cachedFileNames = assets.map(o => o.fileName).filter(fileName => !uncachedFileContentMap[fileName]); const globalHash = getBuildHash(cachedFileNames, uncachedFileContentMap); - swSource = await buildServiceWorker(swSource, version, globalHash, assets); - const outputName = path.basename(absoluteSwFile); - // TODO: do normal build transformations for service worker too, - // I think if we emit it as a chunk rather than an asset it would - // but we can't emit chunks anymore in generateBundle I think ... - this.emitFile({ - type: "asset", - fileName: outputName, - source: swSource - }); + const sw = bundle[swName]; + sw.code = replaceConstsInServiceWorker(sw.code, version, globalHash, assets); + console.log(`\nBuilt ${version} (${globalHash})`); } }; } @@ -75,7 +75,7 @@ function isPreCached(asset) { fileName.endsWith(".js") && !NON_PRECACHED_JS.includes(path.basename(name)); } -async function buildServiceWorker(swSource, version, globalHash, assets) { +function replaceConstsInServiceWorker(swSource, version, globalHash, assets) { const unhashedPreCachedAssets = []; const hashedPreCachedAssets = []; const hashedCachedOnRequestAssets = []; diff --git a/vite.config.js b/vite.config.js index 28f9f5a6..ef41babf 100644 --- a/vite.config.js +++ b/vite.config.js @@ -50,7 +50,7 @@ export default { // important this comes before service worker // otherwise the manifest and the icons it refers to won't be cached injectWebManifest("assets/manifest.json"), - injectServiceWorker("sw.js"), + injectServiceWorker("./src/platform/web/sw.js", ["index.html"]), ], define: { "HYDROGEN_VERSION": JSON.stringify(version) From 8e4da396ea39467bf28a1fe8ad979c1fde6415dc Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 9 Dec 2021 12:15:17 +0100 Subject: [PATCH 232/242] replace global hash in given chunks --- .eslintrc.js | 3 ++- scripts/build-plugins/service-worker.js | 14 +++++++++++++- src/platform/web/ui/login/common.js | 4 ++-- vite.config.js | 9 +++++++-- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 3817d7b1..5341c4e0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -15,6 +15,7 @@ module.exports = { "no-unused-vars": "warn" }, "globals": { - "HYDROGEN_VERSION": "readonly" + "HYDROGEN_VERSION": "readonly", + "HYDROGEN_GLOBAL_HASH": "readonly" } }; diff --git a/scripts/build-plugins/service-worker.js b/scripts/build-plugins/service-worker.js index e7a77048..541fdcad 100644 --- a/scripts/build-plugins/service-worker.js +++ b/scripts/build-plugins/service-worker.js @@ -8,7 +8,7 @@ function contentHash(str) { return hasher.digest(); } -module.exports = function injectServiceWorker(swFile, otherUncachedFiles) { +module.exports = function injectServiceWorker(swFile, otherUncachedFiles, globalHashChunkReplaceMap) { const swName = path.basename(swFile); let root; let version; @@ -43,6 +43,7 @@ module.exports = function injectServiceWorker(swFile, otherUncachedFiles) { const globalHash = getBuildHash(cachedFileNames, uncachedFileContentMap); const sw = bundle[swName]; sw.code = replaceConstsInServiceWorker(sw.code, version, globalHash, assets); + replaceGlobalHashPlaceholderInChunks(assets, globalHashChunkReplaceMap, globalHash); console.log(`\nBuilt ${version} (${globalHash})`); } }; @@ -115,3 +116,14 @@ function replaceConstsInServiceWorker(swSource, version, globalHash, assets) { swSource = replaceStringInSource("NOTIFICATION_BADGE_ICON", assets.find(a => a.name === "icon.png").fileName); return swSource; } + +function replaceGlobalHashPlaceholderInChunks(assets, globalHashChunkReplaceMap, globalHash) { + for (const [name, placeholder] of Object.entries(globalHashChunkReplaceMap)) { + const chunk = assets.find(a => a.type === "chunk" && a.name === name); + if (!chunk) { + throw new Error(`could not find chunk ${name} to replace global hash placeholder`); + } + console.log(placeholder, globalHash); + chunk.code = chunk.code.replaceAll(placeholder, `"${globalHash}"`); + } +} diff --git a/src/platform/web/ui/login/common.js b/src/platform/web/ui/login/common.js index 73da92c9..a247a2ba 100644 --- a/src/platform/web/ui/login/common.js +++ b/src/platform/web/ui/login/common.js @@ -15,10 +15,10 @@ limitations under the License. */ export function hydrogenGithubLink(t) { - if (HYDROGEN_VERSION) { + if (HYDROGEN_VERSION && HYDROGEN_GLOBAL_HASH) { return t.a({target: "_blank", href: `https://github.com/vector-im/hydrogen-web/releases/tag/v${HYDROGEN_VERSION}`}, - `Hydrogen v${HYDROGEN_VERSION} (${window.HYDROGEN_GLOBAL_HASH}) on Github`); + `Hydrogen v${HYDROGEN_VERSION} (${HYDROGEN_GLOBAL_HASH}) on Github`); } else { return t.a({target: "_blank", href: "https://github.com/vector-im/hydrogen-web"}, "Hydrogen on Github"); diff --git a/vite.config.js b/vite.config.js index ef41babf..9a4e66f9 100644 --- a/vite.config.js +++ b/vite.config.js @@ -4,6 +4,7 @@ const flexbugsFixes = require("postcss-flexbugs-fixes"); const fs = require("fs"); const path = require("path"); +const GLOBAL_HASH_PLACEHOLDER = "hydrogen-global-hash-placeholder-4cf32306-5d61-4262-9a57-c9983f472c3c"; const injectWebManifest = require("./scripts/build-plugins/manifest"); const injectServiceWorker = require("./scripts/build-plugins/service-worker"); @@ -50,10 +51,14 @@ export default { // important this comes before service worker // otherwise the manifest and the icons it refers to won't be cached injectWebManifest("assets/manifest.json"), - injectServiceWorker("./src/platform/web/sw.js", ["index.html"]), + injectServiceWorker("./src/platform/web/sw.js", ["index.html"], { + // replace global hash placeholder in index chunk + "index": JSON.stringify(GLOBAL_HASH_PLACEHOLDER) + }), ], define: { - "HYDROGEN_VERSION": JSON.stringify(version) + "HYDROGEN_VERSION": JSON.stringify(version), + "HYDROGEN_GLOBAL_HASH": JSON.stringify(GLOBAL_HASH_PLACEHOLDER) }, css: { postcss: { From 14dffa4ad492c61a588f49053d014b1d26577851 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 9 Dec 2021 12:21:34 +0100 Subject: [PATCH 233/242] remove leftover logging --- scripts/build-plugins/service-worker.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/build-plugins/service-worker.js b/scripts/build-plugins/service-worker.js index 541fdcad..e86bf27c 100644 --- a/scripts/build-plugins/service-worker.js +++ b/scripts/build-plugins/service-worker.js @@ -123,7 +123,6 @@ function replaceGlobalHashPlaceholderInChunks(assets, globalHashChunkReplaceMap, if (!chunk) { throw new Error(`could not find chunk ${name} to replace global hash placeholder`); } - console.log(placeholder, globalHash); chunk.code = chunk.code.replaceAll(placeholder, `"${globalHash}"`); } } From f934262e35e48efb23c2eff3ad1181a5d19803a5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 9 Dec 2021 12:22:17 +0100 Subject: [PATCH 234/242] also use global hash var here --- src/platform/web/dom/ServiceWorkerHandler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/web/dom/ServiceWorkerHandler.js b/src/platform/web/dom/ServiceWorkerHandler.js index 08c687c9..c7ba663a 100644 --- a/src/platform/web/dom/ServiceWorkerHandler.js +++ b/src/platform/web/dom/ServiceWorkerHandler.js @@ -185,7 +185,7 @@ export class ServiceWorkerHandler { } get buildHash() { - return window.HYDROGEN_GLOBAL_HASH; + return HYDROGEN_GLOBAL_HASH; } async preventConcurrentSessionAccess(sessionId) { From a4fac68393e3a905b824b8ed1b6a7c7b427bbf30 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 9 Dec 2021 14:36:12 +0100 Subject: [PATCH 235/242] use same method for setting version and build hash placeholder in sw also better naming in service worker plugin --- scripts/build-plugins/service-worker.js | 46 +++++++++++++------------ src/platform/web/sw.js | 6 ++-- vite.config.js | 5 +-- 3 files changed, 27 insertions(+), 30 deletions(-) diff --git a/scripts/build-plugins/service-worker.js b/scripts/build-plugins/service-worker.js index e86bf27c..a6817278 100644 --- a/scripts/build-plugins/service-worker.js +++ b/scripts/build-plugins/service-worker.js @@ -8,7 +8,7 @@ function contentHash(str) { return hasher.digest(); } -module.exports = function injectServiceWorker(swFile, otherUncachedFiles, globalHashChunkReplaceMap) { +module.exports = function injectServiceWorker(swFile, otherUnhashedFiles, globalHashPlaceholderLiteral, chunkNamesWithGlobalHash) { const swName = path.basename(swFile); let root; let version; @@ -29,8 +29,8 @@ module.exports = function injectServiceWorker(swFile, otherUncachedFiles, global version = JSON.parse(config.define.HYDROGEN_VERSION); // unquote }, generateBundle: async function(options, bundle) { - const uncachedFileNames = [swName].concat(otherUncachedFiles); - const uncachedFileContentMap = uncachedFileNames.reduce((map, fileName) => { + const unhashedFilenames = [swName].concat(otherUnhashedFiles); + const unhashedFileContentMap = unhashedFilenames.reduce((map, fileName) => { const chunkOrAsset = bundle[fileName]; if (!chunkOrAsset) { throw new Error("could not get content for uncached asset or chunk " + fileName); @@ -39,21 +39,21 @@ module.exports = function injectServiceWorker(swFile, otherUncachedFiles, global return map; }, {}); const assets = Object.values(bundle); - const cachedFileNames = assets.map(o => o.fileName).filter(fileName => !uncachedFileContentMap[fileName]); - const globalHash = getBuildHash(cachedFileNames, uncachedFileContentMap); + const hashedFileNames = assets.map(o => o.fileName).filter(fileName => !unhashedFileContentMap[fileName]); + const globalHash = getBuildHash(hashedFileNames, unhashedFileContentMap); const sw = bundle[swName]; - sw.code = replaceConstsInServiceWorker(sw.code, version, globalHash, assets); - replaceGlobalHashPlaceholderInChunks(assets, globalHashChunkReplaceMap, globalHash); + sw.code = replaceCacheFilenamesInServiceWorker(sw, unhashedFilenames, assets); + replaceGlobalHashPlaceholderInChunks(assets, chunkNamesWithGlobalHash, globalHashPlaceholderLiteral, `"${globalHash}"`); console.log(`\nBuilt ${version} (${globalHash})`); } }; } -function getBuildHash(cachedFileNames, uncachedFileContentMap) { - const unhashedHashes = Object.entries(uncachedFileContentMap).map(([fileName, content]) => { +function getBuildHash(hashedFileNames, unhashedFileContentMap) { + const unhashedHashes = Object.entries(unhashedFileContentMap).map(([fileName, content]) => { return `${fileName}-${contentHash(Buffer.from(content))}`; }); - const globalHashAssets = cachedFileNames.concat(unhashedHashes); + const globalHashAssets = hashedFileNames.concat(unhashedHashes); globalHashAssets.sort(); return contentHash(globalHashAssets.join(",")).toString(); } @@ -76,19 +76,24 @@ function isPreCached(asset) { fileName.endsWith(".js") && !NON_PRECACHED_JS.includes(path.basename(name)); } -function replaceConstsInServiceWorker(swSource, version, globalHash, assets) { +function replaceCacheFilenamesInServiceWorker(swChunk, unhashedFilenames, assets) { + let swSource = swChunk.code; const unhashedPreCachedAssets = []; const hashedPreCachedAssets = []; const hashedCachedOnRequestAssets = []; for (const asset of assets) { - const {name: unresolved, fileName: resolved} = asset; - if (!unresolved || resolved === unresolved) { - unhashedPreCachedAssets.push(resolved); + const {name, fileName} = asset; + // the service worker should not be cached at all, + // it's how updates happen + if (fileName === swChunk.fileName) { + continue; + } else if (unhashedFilenames.includes(fileName)) { + unhashedPreCachedAssets.push(fileName); } else if (isPreCached(asset)) { - hashedPreCachedAssets.push(resolved); + hashedPreCachedAssets.push(fileName); } else { - hashedCachedOnRequestAssets.push(resolved); + hashedCachedOnRequestAssets.push(fileName); } } @@ -107,9 +112,6 @@ function replaceConstsInServiceWorker(swSource, version, globalHash, assets) { return newSource; }; - // write service worker - swSource = swSource.replace(`"%%VERSION%%"`, `"${version}"`); - swSource = swSource.replace(`"%%GLOBAL_HASH%%"`, `"${globalHash}"`); swSource = replaceArrayInSource("UNHASHED_PRECACHED_ASSETS", unhashedPreCachedAssets); swSource = replaceArrayInSource("HASHED_PRECACHED_ASSETS", hashedPreCachedAssets); swSource = replaceArrayInSource("HASHED_CACHED_ON_REQUEST_ASSETS", hashedCachedOnRequestAssets); @@ -117,12 +119,12 @@ function replaceConstsInServiceWorker(swSource, version, globalHash, assets) { return swSource; } -function replaceGlobalHashPlaceholderInChunks(assets, globalHashChunkReplaceMap, globalHash) { - for (const [name, placeholder] of Object.entries(globalHashChunkReplaceMap)) { +function replaceGlobalHashPlaceholderInChunks(assets, chunkNamesWithGlobalHash, globalHashPlaceholderLiteral, globalHashLiteral) { + for (const name of chunkNamesWithGlobalHash) { const chunk = assets.find(a => a.type === "chunk" && a.name === name); if (!chunk) { throw new Error(`could not find chunk ${name} to replace global hash placeholder`); } - chunk.code = chunk.code.replaceAll(placeholder, `"${globalHash}"`); + chunk.code = chunk.code.replaceAll(globalHashPlaceholderLiteral, globalHashLiteral); } } diff --git a/src/platform/web/sw.js b/src/platform/web/sw.js index 1dbe21f9..3404275d 100644 --- a/src/platform/web/sw.js +++ b/src/platform/web/sw.js @@ -15,13 +15,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -const VERSION = "%%VERSION%%"; -const GLOBAL_HASH = "%%GLOBAL_HASH%%"; const UNHASHED_PRECACHED_ASSETS = []; const HASHED_PRECACHED_ASSETS = []; const HASHED_CACHED_ON_REQUEST_ASSETS = []; const NOTIFICATION_BADGE_ICON = "assets/icon.png"; -const unhashedCacheName = `hydrogen-assets-${GLOBAL_HASH}`; +const unhashedCacheName = `hydrogen-assets-${HYDROGEN_GLOBAL_HASH}`; const hashedCacheName = `hydrogen-assets`; const mediaThumbnailCacheName = `hydrogen-media-thumbnails-v2`; @@ -175,7 +173,7 @@ self.addEventListener('message', (event) => { } else { switch (event.data?.type) { case "version": - reply({version: VERSION, buildHash: GLOBAL_HASH}); + reply({version: HYDROGEN_VERSION, buildHash: HYDROGEN_GLOBAL_HASH}); break; case "skipWaiting": self.skipWaiting(); diff --git a/vite.config.js b/vite.config.js index 9a4e66f9..d9599cc4 100644 --- a/vite.config.js +++ b/vite.config.js @@ -51,10 +51,7 @@ export default { // important this comes before service worker // otherwise the manifest and the icons it refers to won't be cached injectWebManifest("assets/manifest.json"), - injectServiceWorker("./src/platform/web/sw.js", ["index.html"], { - // replace global hash placeholder in index chunk - "index": JSON.stringify(GLOBAL_HASH_PLACEHOLDER) - }), + injectServiceWorker("./src/platform/web/sw.js", ["index.html"], JSON.stringify(GLOBAL_HASH_PLACEHOLDER), ["index", "sw"]), ], define: { "HYDROGEN_VERSION": JSON.stringify(version), From 23e0d3f2ff4a15d8b804c28a915cec53ddaf16ab Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 9 Dec 2021 15:13:05 +0100 Subject: [PATCH 236/242] get notification badge icon url through import now we transpile the sw --- scripts/build-plugins/service-worker.js | 1 - src/platform/web/sw.js | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/build-plugins/service-worker.js b/scripts/build-plugins/service-worker.js index a6817278..bd7d29d0 100644 --- a/scripts/build-plugins/service-worker.js +++ b/scripts/build-plugins/service-worker.js @@ -115,7 +115,6 @@ function replaceCacheFilenamesInServiceWorker(swChunk, unhashedFilenames, assets swSource = replaceArrayInSource("UNHASHED_PRECACHED_ASSETS", unhashedPreCachedAssets); swSource = replaceArrayInSource("HASHED_PRECACHED_ASSETS", hashedPreCachedAssets); swSource = replaceArrayInSource("HASHED_CACHED_ON_REQUEST_ASSETS", hashedCachedOnRequestAssets); - swSource = replaceStringInSource("NOTIFICATION_BADGE_ICON", assets.find(a => a.name === "icon.png").fileName); return swSource; } diff --git a/src/platform/web/sw.js b/src/platform/web/sw.js index 3404275d..6b864444 100644 --- a/src/platform/web/sw.js +++ b/src/platform/web/sw.js @@ -15,10 +15,12 @@ See the License for the specific language governing permissions and limitations under the License. */ +import NOTIFICATION_BADGE_ICON from "./assets/icon.png?url"; +// replaced by the service worker build plugin const UNHASHED_PRECACHED_ASSETS = []; const HASHED_PRECACHED_ASSETS = []; const HASHED_CACHED_ON_REQUEST_ASSETS = []; -const NOTIFICATION_BADGE_ICON = "assets/icon.png"; + const unhashedCacheName = `hydrogen-assets-${HYDROGEN_GLOBAL_HASH}`; const hashedCacheName = `hydrogen-assets`; const mediaThumbnailCacheName = `hydrogen-media-thumbnails-v2`; From 9a82f88e1f72acb68117efb6bd754c4553c5ef6e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 9 Dec 2021 15:13:19 +0100 Subject: [PATCH 237/242] log swSource as build fails in CI --- scripts/build-plugins/service-worker.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build-plugins/service-worker.js b/scripts/build-plugins/service-worker.js index bd7d29d0..78d34b7f 100644 --- a/scripts/build-plugins/service-worker.js +++ b/scripts/build-plugins/service-worker.js @@ -100,14 +100,14 @@ function replaceCacheFilenamesInServiceWorker(swChunk, unhashedFilenames, assets const replaceArrayInSource = (name, value) => { const newSource = swSource.replace(`${name} = []`, `${name} = ${JSON.stringify(value)}`); if (newSource === swSource) { - throw new Error(`${name} was not found in the service worker source`); + throw new Error(`${name} was not found in the service worker source: ` + swSource); } return newSource; }; const replaceStringInSource = (name, value) => { const newSource = swSource.replace(new RegExp(`${name}\\s=\\s"[^"]*"`), `${name} = ${JSON.stringify(value)}`); if (newSource === swSource) { - throw new Error(`${name} was not found in the service worker source`); + throw new Error(`${name} was not found in the service worker source: ` + swSource); } return newSource; }; From 62827b92b7a9c2d60ab082e0246fc579dd7ab7dd Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 9 Dec 2021 16:37:31 +0100 Subject: [PATCH 238/242] implement placeholder replacement so it still works with minification --- .eslintrc.js | 8 +- scripts/build-plugins/service-worker.js | 97 ++++++++------ src/platform/web/Platform.js | 2 +- src/platform/web/dom/ServiceWorkerHandler.js | 4 +- src/platform/web/sw.js | 10 +- src/platform/web/ui/login/common.js | 6 +- vite.config.js | 128 +++++++++---------- 7 files changed, 142 insertions(+), 113 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 5341c4e0..cb28f4c8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -15,7 +15,11 @@ module.exports = { "no-unused-vars": "warn" }, "globals": { - "HYDROGEN_VERSION": "readonly", - "HYDROGEN_GLOBAL_HASH": "readonly" + "DEFINE_VERSION": "readonly", + "DEFINE_GLOBAL_HASH": "readonly", + // only available in sw.js + "DEFINE_UNHASHED_PRECACHED_ASSETS": "readonly", + "DEFINE_HASHED_PRECACHED_ASSETS": "readonly", + "DEFINE_HASHED_CACHED_ON_REQUEST_ASSETS": "readonly" } }; diff --git a/scripts/build-plugins/service-worker.js b/scripts/build-plugins/service-worker.js index 78d34b7f..19ae793f 100644 --- a/scripts/build-plugins/service-worker.js +++ b/scripts/build-plugins/service-worker.js @@ -8,7 +8,7 @@ function contentHash(str) { return hasher.digest(); } -module.exports = function injectServiceWorker(swFile, otherUnhashedFiles, globalHashPlaceholderLiteral, chunkNamesWithGlobalHash) { +function injectServiceWorker(swFile, otherUnhashedFiles, placeholdersPerChunk) { const swName = path.basename(swFile); let root; let version; @@ -26,7 +26,7 @@ module.exports = function injectServiceWorker(swFile, otherUnhashedFiles, global }, configResolved: config => { root = config.root; - version = JSON.parse(config.define.HYDROGEN_VERSION); // unquote + version = JSON.parse(config.define.DEFINE_VERSION); // unquote }, generateBundle: async function(options, bundle) { const unhashedFilenames = [swName].concat(otherUnhashedFiles); @@ -41,9 +41,11 @@ module.exports = function injectServiceWorker(swFile, otherUnhashedFiles, global const assets = Object.values(bundle); const hashedFileNames = assets.map(o => o.fileName).filter(fileName => !unhashedFileContentMap[fileName]); const globalHash = getBuildHash(hashedFileNames, unhashedFileContentMap); - const sw = bundle[swName]; - sw.code = replaceCacheFilenamesInServiceWorker(sw, unhashedFilenames, assets); - replaceGlobalHashPlaceholderInChunks(assets, chunkNamesWithGlobalHash, globalHashPlaceholderLiteral, `"${globalHash}"`); + const placeholderValues = { + DEFINE_GLOBAL_HASH: `"${globalHash}"`, + ...getCacheFileNamePlaceholderValues(swName, unhashedFilenames, assets, placeholdersPerChunk) + }; + replacePlaceholdersInChunks(assets, placeholdersPerChunk, placeholderValues); console.log(`\nBuilt ${version} (${globalHash})`); } }; @@ -76,8 +78,7 @@ function isPreCached(asset) { fileName.endsWith(".js") && !NON_PRECACHED_JS.includes(path.basename(name)); } -function replaceCacheFilenamesInServiceWorker(swChunk, unhashedFilenames, assets) { - let swSource = swChunk.code; +function getCacheFileNamePlaceholderValues(swName, unhashedFilenames, assets) { const unhashedPreCachedAssets = []; const hashedPreCachedAssets = []; const hashedCachedOnRequestAssets = []; @@ -86,7 +87,7 @@ function replaceCacheFilenamesInServiceWorker(swChunk, unhashedFilenames, assets const {name, fileName} = asset; // the service worker should not be cached at all, // it's how updates happen - if (fileName === swChunk.fileName) { + if (fileName === swName) { continue; } else if (unhashedFilenames.includes(fileName)) { unhashedPreCachedAssets.push(fileName); @@ -97,33 +98,57 @@ function replaceCacheFilenamesInServiceWorker(swChunk, unhashedFilenames, assets } } - const replaceArrayInSource = (name, value) => { - const newSource = swSource.replace(`${name} = []`, `${name} = ${JSON.stringify(value)}`); - if (newSource === swSource) { - throw new Error(`${name} was not found in the service worker source: ` + swSource); - } - return newSource; - }; - const replaceStringInSource = (name, value) => { - const newSource = swSource.replace(new RegExp(`${name}\\s=\\s"[^"]*"`), `${name} = ${JSON.stringify(value)}`); - if (newSource === swSource) { - throw new Error(`${name} was not found in the service worker source: ` + swSource); - } - return newSource; - }; - - swSource = replaceArrayInSource("UNHASHED_PRECACHED_ASSETS", unhashedPreCachedAssets); - swSource = replaceArrayInSource("HASHED_PRECACHED_ASSETS", hashedPreCachedAssets); - swSource = replaceArrayInSource("HASHED_CACHED_ON_REQUEST_ASSETS", hashedCachedOnRequestAssets); - return swSource; -} - -function replaceGlobalHashPlaceholderInChunks(assets, chunkNamesWithGlobalHash, globalHashPlaceholderLiteral, globalHashLiteral) { - for (const name of chunkNamesWithGlobalHash) { - const chunk = assets.find(a => a.type === "chunk" && a.name === name); - if (!chunk) { - throw new Error(`could not find chunk ${name} to replace global hash placeholder`); - } - chunk.code = chunk.code.replaceAll(globalHashPlaceholderLiteral, globalHashLiteral); + return { + DEFINE_UNHASHED_PRECACHED_ASSETS: JSON.stringify(unhashedPreCachedAssets), + DEFINE_HASHED_PRECACHED_ASSETS: JSON.stringify(hashedPreCachedAssets), + DEFINE_HASHED_CACHED_ON_REQUEST_ASSETS: JSON.stringify(hashedCachedOnRequestAssets) } } + +function replacePlaceholdersInChunks(assets, placeholdersPerChunk, placeholderValues) { + for (const [name, placeholderMap] of Object.entries(placeholdersPerChunk)) { + const chunk = assets.find(a => a.type === "chunk" && a.name === name); + if (!chunk) { + throw new Error(`could not find chunk ${name} to replace placeholders`); + } + for (const [placeholderName, placeholderLiteral] of Object.entries(placeholderMap)) { + const replacedValue = placeholderValues[placeholderName]; + const oldCode = chunk.code; + chunk.code = chunk.code.replaceAll(placeholderLiteral, replacedValue); + if (chunk.code === oldCode) { + throw new Error(`Could not replace ${placeholderName} in ${name}, looking for literal ${placeholderLiteral}:\n${chunk.code}`); + } + } + } +} + +/** creates a value to be include in the `define` build settings, + * but can be replace at the end of the build in certain chunks. + * We need this for injecting the global build hash and the final + * filenames in the service worker and index chunk. + * These values are only known in the generateBundle step, so we + * replace them by unique strings wrapped in a prompt call so no + * transformation will touch them (minifying, ...) and we can do a + * string replacement still at the end of the build. */ +function definePlaceholderValue(mode, name, devValue) { + if (mode === "production") { + // note that `prompt(...)` will never be in the final output, it's replaced by the final value + // once we know at the end of the build what it is and just used as a temporary value during the build + // as something that will not be transformed. + // I first considered Symbol but it's not inconceivable that babel would transform this. + return `prompt(${JSON.stringify(name)})`; + } else { + return JSON.stringify(devValue); + } +} + +function createPlaceholderValues(mode) { + return { + DEFINE_GLOBAL_HASH: definePlaceholderValue(mode, "DEFINE_GLOBAL_HASH", null), + DEFINE_UNHASHED_PRECACHED_ASSETS: definePlaceholderValue(mode, "UNHASHED_PRECACHED_ASSETS", []), + DEFINE_HASHED_PRECACHED_ASSETS: definePlaceholderValue(mode, "HASHED_PRECACHED_ASSETS", []), + DEFINE_HASHED_CACHED_ON_REQUEST_ASSETS: definePlaceholderValue(mode, "HASHED_CACHED_ON_REQUEST_ASSETS", []), + }; +} + +module.exports = {injectServiceWorker, createPlaceholderValues}; diff --git a/src/platform/web/Platform.js b/src/platform/web/Platform.js index b23faa6a..569daeb4 100644 --- a/src/platform/web/Platform.js +++ b/src/platform/web/Platform.js @@ -277,7 +277,7 @@ export class Platform { } get version() { - return HYDROGEN_VERSION; + return DEFINE_VERSION; } dispose() { diff --git a/src/platform/web/dom/ServiceWorkerHandler.js b/src/platform/web/dom/ServiceWorkerHandler.js index c7ba663a..0bb8c725 100644 --- a/src/platform/web/dom/ServiceWorkerHandler.js +++ b/src/platform/web/dom/ServiceWorkerHandler.js @@ -181,11 +181,11 @@ export class ServiceWorkerHandler { } get version() { - return HYDROGEN_VERSION; + return DEFINE_VERSION; } get buildHash() { - return HYDROGEN_GLOBAL_HASH; + return DEFINE_GLOBAL_HASH; } async preventConcurrentSessionAccess(sessionId) { diff --git a/src/platform/web/sw.js b/src/platform/web/sw.js index 6b864444..c5f69438 100644 --- a/src/platform/web/sw.js +++ b/src/platform/web/sw.js @@ -17,11 +17,11 @@ limitations under the License. import NOTIFICATION_BADGE_ICON from "./assets/icon.png?url"; // replaced by the service worker build plugin -const UNHASHED_PRECACHED_ASSETS = []; -const HASHED_PRECACHED_ASSETS = []; -const HASHED_CACHED_ON_REQUEST_ASSETS = []; +const UNHASHED_PRECACHED_ASSETS = DEFINE_UNHASHED_PRECACHED_ASSETS; +const HASHED_PRECACHED_ASSETS = DEFINE_HASHED_PRECACHED_ASSETS; +const HASHED_CACHED_ON_REQUEST_ASSETS = DEFINE_HASHED_CACHED_ON_REQUEST_ASSETS; -const unhashedCacheName = `hydrogen-assets-${HYDROGEN_GLOBAL_HASH}`; +const unhashedCacheName = `hydrogen-assets-${DEFINE_GLOBAL_HASH}`; const hashedCacheName = `hydrogen-assets`; const mediaThumbnailCacheName = `hydrogen-media-thumbnails-v2`; @@ -175,7 +175,7 @@ self.addEventListener('message', (event) => { } else { switch (event.data?.type) { case "version": - reply({version: HYDROGEN_VERSION, buildHash: HYDROGEN_GLOBAL_HASH}); + reply({version: DEFINE_VERSION, buildHash: DEFINE_GLOBAL_HASH}); break; case "skipWaiting": self.skipWaiting(); diff --git a/src/platform/web/ui/login/common.js b/src/platform/web/ui/login/common.js index a247a2ba..948eff34 100644 --- a/src/platform/web/ui/login/common.js +++ b/src/platform/web/ui/login/common.js @@ -15,10 +15,10 @@ limitations under the License. */ export function hydrogenGithubLink(t) { - if (HYDROGEN_VERSION && HYDROGEN_GLOBAL_HASH) { + if (DEFINE_VERSION && DEFINE_GLOBAL_HASH) { return t.a({target: "_blank", - href: `https://github.com/vector-im/hydrogen-web/releases/tag/v${HYDROGEN_VERSION}`}, - `Hydrogen v${HYDROGEN_VERSION} (${HYDROGEN_GLOBAL_HASH}) on Github`); + href: `https://github.com/vector-im/hydrogen-web/releases/tag/v${DEFINE_VERSION}`}, + `Hydrogen v${DEFINE_VERSION} (${DEFINE_GLOBAL_HASH}) on Github`); } else { return t.a({target: "_blank", href: "https://github.com/vector-im/hydrogen-web"}, "Hydrogen on Github"); diff --git a/vite.config.js b/vite.config.js index d9599cc4..6d092052 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,78 +1,78 @@ const cssvariables = require("postcss-css-variables"); -const autoprefixer = require("autoprefixer"); +//const autoprefixer = require("autoprefixer"); const flexbugsFixes = require("postcss-flexbugs-fixes"); const fs = require("fs"); const path = require("path"); -const GLOBAL_HASH_PLACEHOLDER = "hydrogen-global-hash-placeholder-4cf32306-5d61-4262-9a57-c9983f472c3c"; const injectWebManifest = require("./scripts/build-plugins/manifest"); -const injectServiceWorker = require("./scripts/build-plugins/service-worker"); +const {injectServiceWorker, createPlaceholderValues} = require("./scripts/build-plugins/service-worker"); // const legacyBuild = require("./scripts/build-plugins/legacy-build"); - -// we could also just import {version} from "../../package.json" where needed, -// but this won't work in the service worker yet as it is not transformed yet -// TODO: we should emit a chunk early on and then transform the asset again once we know all the other assets to cache +const {defineConfig} = require('vite'); const version = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8")).version; -const {defineConfig} = require("vite"); -let polyfillSrc; -let polyfillRef; -export default { - public: false, - root: "src/platform/web", - base: "./", - server: { - hmr: false - }, - resolve: { - alias: { - // these should only be imported by the base-x package in any runtime code - // and works in the browser with a Uint8Array shim, - // rather than including a ton of polyfill code - "safe-buffer": "./scripts/package-overrides/safe-buffer/index.js", - "buffer": "./scripts/package-overrides/buffer/index.js", +export default defineConfig(({mode}) => { + const definePlaceholders = createPlaceholderValues(mode); + return { + public: false, + root: "src/platform/web", + base: "./", + server: { + hmr: false + }, + resolve: { + alias: { + // these should only be imported by the base-x package in any runtime code + // and works in the browser with a Uint8Array shim, + // rather than including a ton of polyfill code + "safe-buffer": "./scripts/package-overrides/safe-buffer/index.js", + "buffer": "./scripts/package-overrides/buffer/index.js", + } + }, + build: { + outDir: "../../../target", + emptyOutDir: true, + minify: false, + sourcemap: false, + assetsInlineLimit: 0, + polyfillModulePreload: false, + }, + plugins: [ + // legacyBuild(scriptTagPath(path.join(__dirname, "src/platform/web/index.html"), 0), { + // "./Platform": "./LegacyPlatform" + // }, "hydrogen-legacy", [ + // './legacy-polyfill', + // ]), + // important this comes before service worker + // otherwise the manifest and the icons it refers to won't be cached + injectWebManifest("assets/manifest.json"), + injectServiceWorker("./src/platform/web/sw.js", ["index.html"], { + // placeholders to replace at end of build by chunk name + "index": {DEFINE_GLOBAL_HASH: definePlaceholders.DEFINE_GLOBAL_HASH}, + "sw": definePlaceholders + }), + ], + define: { + DEFINE_VERSION: JSON.stringify(version), + ...definePlaceholders + }, + css: { + postcss: { + plugins: [ + cssvariables({ + preserve: (declaration) => { + return declaration.value.indexOf("var(--ios-") == 0; + } + }), + // the grid option creates some source fragment that causes the vite warning reporter to crash because + // it wants to log a warning on a line that does not exist in the source fragment. + // autoprefixer({overrideBrowserslist: ["IE 11"], grid: "no-autoplace"}), + flexbugsFixes() + ] + } } - }, - build: { - outDir: "../../../target", - emptyOutDir: true, - minify: true, - sourcemap: false, - assetsInlineLimit: 0, - polyfillModulePreload: false, - }, - plugins: [ - // legacyBuild(scriptTagPath(path.join(__dirname, "src/platform/web/index.html"), 0), { - // "./Platform": "./LegacyPlatform" - // }, "hydrogen-legacy", [ - // './legacy-polyfill', - // ]), - // important this comes before service worker - // otherwise the manifest and the icons it refers to won't be cached - injectWebManifest("assets/manifest.json"), - injectServiceWorker("./src/platform/web/sw.js", ["index.html"], JSON.stringify(GLOBAL_HASH_PLACEHOLDER), ["index", "sw"]), - ], - define: { - "HYDROGEN_VERSION": JSON.stringify(version), - "HYDROGEN_GLOBAL_HASH": JSON.stringify(GLOBAL_HASH_PLACEHOLDER) - }, - css: { - postcss: { - plugins: [ - cssvariables({ - preserve: (declaration) => { - return declaration.value.indexOf("var(--ios-") == 0; - } - }), - // the grid option creates some source fragment that causes the vite warning reporter to crash because - // it wants to log a warning on a line that does not exist in the source fragment. - // autoprefixer({overrideBrowserslist: ["IE 11"], grid: "no-autoplace"}), - flexbugsFixes() - ] - } - } -}; + }; +}); function scriptTagPath(htmlFile, index) { return `${htmlFile}?html-proxy&index=${index}.js`; From dea7e7b4f5aa97b42624df60b5d9a1c9147e6850 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 9 Dec 2021 16:42:35 +0100 Subject: [PATCH 239/242] enable minification and source maps --- vite.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vite.config.js b/vite.config.js index 6d092052..c7c91a68 100644 --- a/vite.config.js +++ b/vite.config.js @@ -32,8 +32,8 @@ export default defineConfig(({mode}) => { build: { outDir: "../../../target", emptyOutDir: true, - minify: false, - sourcemap: false, + minify: true, + sourcemap: true, assetsInlineLimit: 0, polyfillModulePreload: false, }, From d9ff4a8484ced141e003f1773fcf9ac8ff17b1cc Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 9 Dec 2021 17:12:08 +0100 Subject: [PATCH 240/242] sw.js is not part of the sdk yet, so just put the path in index.html --- src/platform/web/index.html | 4 ++-- src/platform/web/sdk/paths/vite.ts | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/platform/web/index.html b/src/platform/web/index.html index 3b0e6e72..f7aeeed7 100644 --- a/src/platform/web/index.html +++ b/src/platform/web/index.html @@ -19,7 +19,7 @@ import {main} from "./main"; import {Platform} from "./Platform"; import configJSON from "./assets/config.json?raw"; - import {olmPaths, downloadSandboxPath, workerPath, serviceWorkerPath} from "./sdk/paths/vite"; + import {olmPaths, downloadSandboxPath, workerPath} from "./sdk/paths/vite"; const paths = { olm: olmPaths, downloadSandbox: downloadSandboxPath, @@ -27,7 +27,7 @@ ...JSON.parse(configJSON) }; if (import.meta.env.PROD) { - paths.serviceWorker = serviceWorkerPath; + paths.serviceWorker = "sw.js"; } const platform = new Platform( document.body, diff --git a/src/platform/web/sdk/paths/vite.ts b/src/platform/web/sdk/paths/vite.ts index 0a3ddedd..6739f8d8 100644 --- a/src/platform/web/sdk/paths/vite.ts +++ b/src/platform/web/sdk/paths/vite.ts @@ -17,6 +17,3 @@ export const olmPaths = { export const downloadSandboxPath = _downloadSandboxPath; export const workerPath = _workerPath; -// the service worker is generated by the build as an unhashed asset, -// we don't use it at development time, so don't use import for the path -export const serviceWorkerPath = "sw.js"; From 5c5193ef486f2fc8749aa51f4ffee62201b686f0 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 9 Dec 2021 18:04:11 +0100 Subject: [PATCH 241/242] remove old build system and unused dependencies some of these are for the ie11 legacy build, which has been postponed. They will be brougth back when we bring back the legacy build --- package.json | 18 - scripts/build-plugins/legacy-build.js | 213 --- scripts/build.mjs | 578 -------- scripts/common.mjs | 12 - scripts/deploy.sh | 6 - scripts/serve-local.js | 43 - snowpack.config.js | 37 - yarn.lock | 1928 +------------------------ 8 files changed, 12 insertions(+), 2823 deletions(-) delete mode 100644 scripts/build-plugins/legacy-build.js delete mode 100644 scripts/build.mjs delete mode 100644 scripts/common.mjs delete mode 100755 scripts/deploy.sh delete mode 100644 scripts/serve-local.js delete mode 100644 snowpack.config.js diff --git a/package.json b/package.json index adf2ae22..d90747ab 100644 --- a/package.json +++ b/package.json @@ -25,35 +25,17 @@ }, "homepage": "https://github.com/vector-im/hydrogen-web/#readme", "devDependencies": { - "@babel/core": "^7.11.1", - "@babel/plugin-transform-runtime": "^7.15.8", - "@babel/preset-env": "^7.11.0", - "@babel/standalone": "^7.15.8", - "@rollup/plugin-babel": "^5.1.0", - "@rollup/plugin-commonjs": "^15.0.0", - "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-multi-entry": "^4.0.0", - "@rollup/plugin-node-resolve": "^9.0.0", - "@rollup/pluginutils": "^4.1.1", "@typescript-eslint/eslint-plugin": "^4.29.2", "@typescript-eslint/parser": "^4.29.2", - "@vitejs/plugin-legacy": "^1.6.1", - "autoprefixer": "^10.4.0", - "cheerio": "^1.0.0-rc.3", - "commander": "^6.0.0", "core-js": "^3.6.5", "eslint": "^7.32.0", "fake-indexeddb": "^3.1.2", - "finalhandler": "^1.1.1", "impunity": "^1.0.9", "mdn-polyfills": "^5.20.0", "node-html-parser": "^4.0.0", "postcss-css-variables": "^0.18.0", "postcss-flexbugs-fixes": "^5.0.2", "regenerator-runtime": "^0.13.7", - "rollup": "^2.26.4", - "rollup-plugin-cleanup": "^3.1.1", - "serve-static": "^1.13.2", "typescript": "^4.3.5", "vite": "^2.6.14", "xxhashjs": "^0.2.2" diff --git a/scripts/build-plugins/legacy-build.js b/scripts/build-plugins/legacy-build.js deleted file mode 100644 index f7f641a3..00000000 --- a/scripts/build-plugins/legacy-build.js +++ /dev/null @@ -1,213 +0,0 @@ -const path = require("path"); -const {build} = require("vite"); -const {babel, getBabelOutputPlugin} = require('@rollup/plugin-babel'); -const {createFilter} = require("@rollup/pluginutils"); -const { rollup } = require('rollup'); -const { nodeResolve } = require('@rollup/plugin-node-resolve'); -const commonjs = require('@rollup/plugin-commonjs'); - -const VIRTUAL_ENTRY = "hydrogen:legacy-entry"; -const NODE_MODULES_NEEDING_TRANSPILATION = ["es6-promise"]; - -module.exports = function legacyBuild(entryModuleId, entryImportReplacements, chunkName, extraImports) { - let parentRoot; - let code; - let legacyBundleRef; - let legacyBundleFileName; - return { - name: "hydrogen:legacyBuild", - apply: "build", - configResolved: config => { - parentRoot = config.root; - }, - async moduleParsed(info) { - if (info.id === entryModuleId) { - code = info.code; - } - }, - async buildEnd() { - if (!code) { - throw new Error("couldnt find entry"); - } - for (const [importSource, newImportSource] of Object.entries(entryImportReplacements)) { - code = replaceImport(this, code, importSource, newImportSource); - } - code = prependExtraImports(code, extraImports); - const bundleCode = await buildLegacyChunk(parentRoot, chunkName, code); - legacyBundleRef = this.emitFile({ - type: "asset", - source: bundleCode, - name: `${chunkName}.js` - }); - }, - generateBundle() { - if (!legacyBundleRef) { - throw new Error("no bundle"); - } - legacyBundleFileName = this.getFileName(legacyBundleRef); - }, - transformIndexHtml: { - transform(html) { - if (!legacyBundleFileName) { - throw new Error("no bundle"); - } - return [{ - tag: "script", - attrs: {type: "text/javascript", nomodule: true, src: legacyBundleFileName}, - injectTo: "head" - }]; - }, - }, - } -} - -/** we replace the imports ourselves instead of relying on rollup-alias or similar, because - * we only want to replace imports in the entry module, not anywhere in the import tree. - * This allows to create sub classes for the legacy build that can still import - * the non-legacy class as a base class, like LegacyPlatform does with Platform.*/ -function replaceImport(pluginCtx, code, importSource, newImportSource) { - const ast = pluginCtx.parse(code); - for (const node of ast.body) { - if (node.type === "ImportDeclaration") { - const sourceNode = node.source; - if (sourceNode.value === importSource) { - code = code.substr(0, sourceNode.start) + JSON.stringify(newImportSource) + code.substr(sourceNode.end); - return code; - } - } - } - throw new Error(`Could not find import ${JSON.stringify(importSource)} to replace`); -} - -function prependExtraImports(code, extraImports) { - return extraImports.map(i => `import ${JSON.stringify(i)};`).join("\n") + code; -} - -async function buildLegacyChunk(root, chunkName, code) { - const projectRootDir = path.resolve(path.join(root, "../../..")); - const nodeModulesDir = path.join(projectRootDir, "node_modules"); - const defaultFilter = createFilter([], [], {resolve: projectRootDir}); - const transpiledModuleDirs = NODE_MODULES_NEEDING_TRANSPILATION.map(m => { - return path.join(nodeModulesDir, m); - }); - - const filterModule = id => { - if (!defaultFilter(id)) { - return false; - } - if (id.endsWith("?url") || id.endsWith("?raw")) { - // TODO is this needed - return true; - } - if (transpiledModuleDirs.some(d => id.startsWith(d))) { - return true; - } - if (id.startsWith(nodeModulesDir)) { - return false; - } - return true; - }; - // compile down to whatever IE 11 needs - const babelPlugin = getBabelOutputPlugin({ - babelrc: false, - compact: false, - extensions: [".js", ".ts"], - // babelHelpers: 'bundled', - presets: [ - [ - "@babel/preset-env", - { - modules: false, - useBuiltIns: "usage", - corejs: "3.4", - targets: "IE 11", - // we provide our own promise polyfill (es6-promise) - // with support for synchronous flushing of - // the queue for idb where needed - exclude: ["es.promise", "es.promise.all-settled", "es.promise.finally"] - } - ] - ] - }); - const bundle = await build({ - root, - configFile: false, - logLevel: 'error', - build: { - write: false, - minify: false, - target: "esnext", - assetsInlineLimit: 0, - polyfillModulePreload: false, - rollupOptions: { - external: id => !filterModule(id), - input: { - [chunkName]: VIRTUAL_ENTRY - }, - output: { - format: "esm", - manualChunks: undefined - }, - makeAbsoluteExternalsRelative: false, - }, - }, - plugins: [ - memoryBabelInputPlugin(VIRTUAL_ENTRY, root, code), - babelPlugin - ] - }); - const assets = Array.isArray(bundle.output) ? bundle.output : [bundle.output]; - const mainChunk = assets.find(a => a.name === chunkName); - const babelCode = mainChunk.code; - const bundle2 = await rollup({ - plugins: [ - memoryBabelInputPlugin(VIRTUAL_ENTRY, root, babelCode), - overridesAsRollupPlugin(new Map( - [["safe-buffer", "./scripts/package-overrides/safe-buffer/index.js"], - ["buffer", "./scripts/package-overrides/buffer/index.js"]]), projectRootDir), - commonjs(), - nodeResolve(), - ], - input: { - [chunkName]: VIRTUAL_ENTRY - } - }); - const {output} = await bundle2.generate({ - format: 'iife', - name: `hydrogen` - }); - const bundledCode = output[0].code; - return bundledCode; -} - -function memoryBabelInputPlugin(entryName, dir, code) { - return { - name: "hydrogen:resolve-legacy-entry", - resolveId(id, importer) { - if (id === entryName) { - return id; - } else if (importer === entryName && id.startsWith("./")) { - return this.resolve(path.join(dir, id)); - } - }, - load(id) { - if (id === entryName) { - return code; - } - }, - } -} - -function overridesAsRollupPlugin(mapping, basedir) { - return { - name: "rewrite-imports", - async resolveId (source, importer) { - const target = mapping.get(source); - if (target) { - const resolvedTarget = await this.resolve(path.join(basedir, target)); - console.log("resolving", source, resolvedTarget); - return resolvedTarget; - } - } - }; -} diff --git a/scripts/build.mjs b/scripts/build.mjs deleted file mode 100644 index 0674cb93..00000000 --- a/scripts/build.mjs +++ /dev/null @@ -1,578 +0,0 @@ -/* -Copyright 2020 Bruno Windels -Copyright 2020 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 {build as snowpackBuild, loadConfiguration} from "snowpack" -import cheerio from "cheerio"; -import fsRoot from "fs"; -const fs = fsRoot.promises; -import path from "path"; -import xxhash from 'xxhashjs'; -import { rollup } from 'rollup'; -import postcss from "postcss"; -import postcssImport from "postcss-import"; -import { fileURLToPath } from 'url'; -import { dirname } from 'path'; -import commander from "commander"; -// needed for legacy bundle -import babel from '@rollup/plugin-babel'; -// needed to find the polyfill modules in the main-legacy.js bundle -import { nodeResolve } from '@rollup/plugin-node-resolve'; -// needed because some of the polyfills are written as commonjs modules -import commonjs from '@rollup/plugin-commonjs'; -// multi-entry plugin so we can add polyfill file to main -import multi from '@rollup/plugin-multi-entry'; -import removeJsComments from 'rollup-plugin-cleanup'; -// replace urls of asset names with content hashed version -import postcssUrl from "postcss-url"; - -import cssvariables from "postcss-css-variables"; -import autoprefixer from "autoprefixer"; -import flexbugsFixes from "postcss-flexbugs-fixes"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); -const projectDir = path.join(__dirname, "../"); -const snowpackOutPath = path.join(projectDir, "snowpack-build-output"); -const cssSrcDir = path.join(projectDir, "src/platform/web/ui/css/"); -const snowpackConfig = await loadConfiguration({buildOptions: {out: snowpackOutPath}}, "snowpack.config.js"); -const snowpackOutDir = snowpackConfig.buildOptions.out.substring(projectDir.length); -const srcDir = path.join(projectDir, `${snowpackOutDir}/src/`); -const isPathInSrcDir = path => path.startsWith(srcDir); - -const parameters = new commander.Command(); -parameters - .option("--modern-only", "don't make a legacy build") - .option("--override-imports ", "pass in a file to override import paths, see doc/SKINNING.md") - .option("--override-css
", "pass in an alternative main css file") -parameters.parse(process.argv); - -/** - * We use Snowpack to handle the translation of TypeScript - * into JavaScript. We thus can't bundle files straight from - * the src directory, since some of them are TypeScript, and since - * they may import Node modules. We thus bundle files after they - * have been processed by Snowpack. This function returns paths - * to the files that have already been pre-processed in this manner. - */ -function srcPath(src) { - return path.join(snowpackOutDir, 'src', src); -} - -async function build({modernOnly, overrideImports, overrideCss}) { - await snowpackBuild({config: snowpackConfig}); - // get version number - const version = JSON.parse(await fs.readFile(path.join(projectDir, "package.json"), "utf8")).version; - let importOverridesMap; - if (overrideImports) { - importOverridesMap = await readImportOverrides(overrideImports); - } - const devHtml = await fs.readFile(path.join(snowpackOutPath, "index.html"), "utf8"); - const doc = cheerio.load(devHtml); - const themes = []; - findThemes(doc, themeName => { - themes.push(themeName); - }); - // clear target dir - const targetDir = path.join(projectDir, "target/"); - await removeDirIfExists(targetDir); - await createDirs(targetDir, themes); - const assets = new AssetMap(targetDir); - // copy olm assets - const olmAssets = await copyFolder(path.join(projectDir, "lib/olm/"), assets.directory); - assets.addSubMap(olmAssets); - await assets.write(`hydrogen.js`, await buildJs(srcPath("main.js"), [srcPath("platform/web/Platform.js")], importOverridesMap)); - if (!modernOnly) { - await assets.write(`hydrogen-legacy.js`, await buildJsLegacy(srcPath("main.js"), [ - srcPath('platform/web/legacy-polyfill.js'), - srcPath('platform/web/LegacyPlatform.js') - ], importOverridesMap)); - await assets.write(`worker.js`, await buildJsLegacy(srcPath("platform/web/worker/main.js"), [srcPath('platform/web/worker/polyfill.js')])); - } - // copy over non-theme assets - const baseConfig = JSON.parse(await fs.readFile(path.join(projectDir, "assets/config.json"), {encoding: "utf8"})); - const downloadSandbox = "download-sandbox.html"; - let downloadSandboxHtml = await fs.readFile(path.join(projectDir, `assets/${downloadSandbox}`)); - await assets.write(downloadSandbox, downloadSandboxHtml); - // creates the directories where the theme css bundles are placed in, - // and writes to assets, so the build bundles can translate them, so do it first - await copyThemeAssets(themes, assets); - await buildCssBundles(buildCssLegacy, themes, assets, overrideCss); - await buildManifest(assets); - // all assets have been added, create a hash from all assets name to cache unhashed files like index.html - assets.addToHashForAll("index.html", devHtml); - let swSource = await fs.readFile(path.join(snowpackOutPath, "sw.js"), "utf8"); - assets.addToHashForAll("sw.js", swSource); - - const globalHash = assets.hashForAll(); - - await buildServiceWorker(swSource, version, globalHash, assets); - await buildHtml(doc, version, baseConfig, globalHash, modernOnly, assets); - await removeDirIfExists(snowpackOutPath); - console.log(`built hydrogen ${version} (${globalHash}) successfully with ${assets.size} files`); -} - -async function findThemes(doc, callback) { - doc("link[rel~=stylesheet][title]").each((i, el) => { - const theme = doc(el); - const href = theme.attr("href"); - const themesPrefix = "/themes/"; - const prefixIdx = href.indexOf(themesPrefix); - if (prefixIdx !== -1) { - const themeNameStart = prefixIdx + themesPrefix.length; - const themeNameEnd = href.indexOf("/", themeNameStart); - const themeName = href.substr(themeNameStart, themeNameEnd - themeNameStart); - callback(themeName, theme); - } - }); -} - -async function createDirs(targetDir, themes) { - await fs.mkdir(targetDir); - const themeDir = path.join(targetDir, "themes"); - await fs.mkdir(themeDir); - for (const theme of themes) { - await fs.mkdir(path.join(themeDir, theme)); - } -} - -async function copyThemeAssets(themes, assets) { - for (const theme of themes) { - const themeDstFolder = path.join(assets.directory, `themes/${theme}`); - const themeSrcFolder = path.join(cssSrcDir, `themes/${theme}`); - const themeAssets = await copyFolder(themeSrcFolder, themeDstFolder, file => { - return !file.endsWith(".css"); - }); - assets.addSubMap(themeAssets); - } - return assets; -} - -async function buildHtml(doc, version, baseConfig, globalHash, modernOnly, assets) { - // transform html file - // change path to main.css to css bundle - doc("link[rel=stylesheet]:not([title])").attr("href", assets.resolve(`hydrogen.css`)); - // adjust file name of icon on iOS - doc("link[rel=apple-touch-icon]").attr("href", assets.resolve(`icon-maskable.png`)); - // change paths to all theme stylesheets - findThemes(doc, (themeName, theme) => { - theme.attr("href", assets.resolve(`themes/${themeName}/bundle.css`)); - }); - const configJSON = JSON.stringify(Object.assign({}, baseConfig, { - worker: assets.has("worker.js") ? assets.resolve(`worker.js`) : null, - downloadSandbox: assets.resolve("download-sandbox.html"), - serviceWorker: "sw.js", - olm: { - wasm: assets.resolve("olm.wasm"), - legacyBundle: assets.resolve("olm_legacy.js"), - wasmBundle: assets.resolve("olm.js"), - } - })); - const modernScript = `import {main, Platform} from "./${assets.resolve(`hydrogen.js`)}"; main(new Platform(document.body, ${configJSON}));`; - const mainScripts = [ - `` - ]; - if (!modernOnly) { - const legacyScript = `hydrogen.main(new hydrogen.Platform(document.body, ${configJSON}));`; - mainScripts.push( - ``, - `` - ); - } - doc("script#main").replaceWith(mainScripts.join("")); - - const versionScript = doc("script#version"); - versionScript.attr("type", "text/javascript"); - let vSource = versionScript.contents().text(); - vSource = vSource.replace(`"%%VERSION%%"`, `"${version}"`); - vSource = vSource.replace(`"%%GLOBAL_HASH%%"`, `"${globalHash}"`); - versionScript.text(wrapWithLicenseComments(vSource)); - doc("head").append(``); - await assets.writeUnhashed("index.html", doc.html()); -} - -async function buildJs(mainFile, extraFiles, importOverrides) { - // create js bundle - const plugins = [multi(), removeJsComments({comments: "none"})]; - if (importOverrides) { - plugins.push(overridesAsRollupPlugin(importOverrides)); - } - const bundle = await rollup({ - // for fake-indexeddb, so usage for tests only doesn't put it in bundle - treeshake: {moduleSideEffects: isPathInSrcDir}, - input: extraFiles.concat(mainFile), - plugins - }); - const {output} = await bundle.generate({ - format: 'es', - // TODO: can remove this? - name: `hydrogen` - }); - const code = output[0].code; - return wrapWithLicenseComments(code); -} - -async function buildJsLegacy(mainFile, extraFiles, importOverrides) { - // compile down to whatever IE 11 needs - const babelPlugin = babel.babel({ - babelHelpers: 'bundled', - exclude: 'node_modules/**', - presets: [ - [ - "@babel/preset-env", - { - useBuiltIns: "entry", - corejs: "3.4", - targets: "IE 11", - // we provide our own promise polyfill (es6-promise) - // with support for synchronous flushing of - // the queue for idb where needed - exclude: ["es.promise", "es.promise.all-settled", "es.promise.finally"] - } - ] - ] - }); - const plugins = [multi(), commonjs()]; - if (importOverrides) { - plugins.push(overridesAsRollupPlugin(importOverrides)); - } - plugins.push(nodeResolve(), babelPlugin); - // create js bundle - const rollupConfig = { - // for fake-indexeddb, so usage for tests only doesn't put it in bundle - treeshake: {moduleSideEffects: isPathInSrcDir}, - // important the extraFiles come first, - // so polyfills are available in the global scope - // if needed for the mainfile - input: extraFiles.concat(mainFile), - plugins - }; - const bundle = await rollup(rollupConfig); - const {output} = await bundle.generate({ - format: 'iife', - name: `hydrogen` - }); - const code = output[0].code; - return wrapWithLicenseComments(code); -} - -function wrapWithLicenseComments(code) { - // Add proper license comments to make GNU LibreJS accept the file - const start = '// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7&dn=apache-2.0.txt Apache-2.0'; - const end = '// @license-end'; - return `${start}\n${code}\n${end}`; -} - -const NON_PRECACHED_JS = [ - "hydrogen-legacy.js", - "olm_legacy.js", - "worker.js" -]; - -function isPreCached(asset) { - return asset.endsWith(".svg") || - asset.endsWith(".png") || - asset.endsWith(".css") || - asset.endsWith(".wasm") || - asset.endsWith(".html") || - // most environments don't need the worker - asset.endsWith(".js") && !NON_PRECACHED_JS.includes(asset); -} - -async function buildManifest(assets) { - const webManifest = JSON.parse(await fs.readFile(path.join(projectDir, "assets/manifest.json"), "utf8")); - // copy manifest icons - for (const icon of webManifest.icons) { - let iconData = await fs.readFile(path.join(projectDir, icon.src)); - const iconTargetPath = path.basename(icon.src); - icon.src = await assets.write(iconTargetPath, iconData); - } - await assets.write("manifest.json", JSON.stringify(webManifest)); -} - -async function buildServiceWorker(swSource, version, globalHash, assets) { - const unhashedPreCachedAssets = ["index.html"]; - const hashedPreCachedAssets = []; - const hashedCachedOnRequestAssets = []; - - for (const [unresolved, resolved] of assets) { - if (unresolved === resolved) { - unhashedPreCachedAssets.push(resolved); - } else if (isPreCached(unresolved)) { - hashedPreCachedAssets.push(resolved); - } else { - hashedCachedOnRequestAssets.push(resolved); - } - } - - const replaceArrayInSource = (name, value) => { - const newSource = swSource.replace(`${name} = []`, `${name} = ${JSON.stringify(value)}`); - if (newSource === swSource) { - throw new Error(`${name} was not found in the service worker source`); - } - return newSource; - }; - const replaceStringInSource = (name, value) => { - const newSource = swSource.replace(new RegExp(`${name}\\s=\\s"[^"]*"`), `${name} = ${JSON.stringify(value)}`); - if (newSource === swSource) { - throw new Error(`${name} was not found in the service worker source`); - } - return newSource; - }; - - // write service worker - swSource = swSource.replace(`"%%VERSION%%"`, `"${version}"`); - swSource = swSource.replace(`"%%GLOBAL_HASH%%"`, `"${globalHash}"`); - swSource = replaceArrayInSource("UNHASHED_PRECACHED_ASSETS", unhashedPreCachedAssets); - swSource = replaceArrayInSource("HASHED_PRECACHED_ASSETS", hashedPreCachedAssets); - swSource = replaceArrayInSource("HASHED_CACHED_ON_REQUEST_ASSETS", hashedCachedOnRequestAssets); - swSource = replaceStringInSource("NOTIFICATION_BADGE_ICON", assets.resolve("icon.png")); - - // service worker should not have a hashed name as it is polled by the browser for updates - await assets.writeUnhashed("sw.js", swSource); -} - -async function buildCssBundles(buildFn, themes, assets, mainCssFile = null) { - if (!mainCssFile) { - mainCssFile = path.join(cssSrcDir, "main.css"); - } - const bundleCss = await buildFn(mainCssFile); - await assets.write(`hydrogen.css`, bundleCss); - for (const theme of themes) { - const themeRelPath = `themes/${theme}/`; - const themeRoot = path.join(cssSrcDir, themeRelPath); - const assetUrlMapper = ({absolutePath}) => { - if (!absolutePath.startsWith(themeRoot)) { - throw new Error("resource is out of theme directory: " + absolutePath); - } - const relPath = absolutePath.substr(themeRoot.length); - const hashedDstPath = assets.resolve(path.join(themeRelPath, relPath)); - if (hashedDstPath) { - return hashedDstPath.substr(themeRelPath.length); - } - }; - const themeCss = await buildFn(path.join(themeRoot, `theme.css`), assetUrlMapper); - await assets.write(path.join(themeRelPath, `bundle.css`), themeCss); - } -} - -// async function buildCss(entryPath, urlMapper = null) { -// const preCss = await fs.readFile(entryPath, "utf8"); -// const options = [postcssImport]; -// if (urlMapper) { -// options.push(postcssUrl({url: urlMapper})); -// } -// const cssBundler = postcss(options); -// const result = await cssBundler.process(preCss, {from: entryPath}); -// return result.css; -// } - -async function buildCssLegacy(entryPath, urlMapper = null) { - const preCss = await fs.readFile(entryPath, "utf8"); - const options = [ - postcssImport, - cssvariables({ - preserve: (declaration) => { - return declaration.value.indexOf("var(--ios-") == 0; - } - }), - autoprefixer({overrideBrowserslist: ["IE 11"], grid: "no-autoplace"}), - flexbugsFixes() - ]; - if (urlMapper) { - options.push(postcssUrl({url: urlMapper})); - } - const cssBundler = postcss(options); - const result = await cssBundler.process(preCss, {from: entryPath}); - return result.css; -} - -async function removeDirIfExists(targetDir) { - try { - await fs.rmdir(targetDir, {recursive: true}); - } catch (err) { - if (err.code !== "ENOENT") { - throw err; - } - } -} - -async function copyFolder(srcRoot, dstRoot, filter, assets = null) { - assets = assets || new AssetMap(dstRoot); - const dirEnts = await fs.readdir(srcRoot, {withFileTypes: true}); - for (const dirEnt of dirEnts) { - const dstPath = path.join(dstRoot, dirEnt.name); - const srcPath = path.join(srcRoot, dirEnt.name); - if (dirEnt.isDirectory()) { - await fs.mkdir(dstPath); - await copyFolder(srcPath, dstPath, filter, assets); - } else if ((dirEnt.isFile() || dirEnt.isSymbolicLink()) && (!filter || filter(srcPath))) { - const content = await fs.readFile(srcPath); - await assets.write(dstPath, content); - } - } - return assets; -} - -function contentHash(str) { - var hasher = new xxhash.h32(0); - hasher.update(str); - return hasher.digest(); -} - -class AssetMap { - constructor(targetDir) { - // remove last / if any, so substr in create works well - this._targetDir = path.resolve(targetDir); - this._assets = new Map(); - // hashes for unhashed resources so changes in these resources also contribute to the hashForAll - this._unhashedHashes = []; - } - - _toRelPath(resourcePath) { - let relPath = resourcePath; - if (path.isAbsolute(resourcePath)) { - if (!resourcePath.startsWith(this._targetDir)) { - throw new Error(`absolute path ${resourcePath} that is not within target dir ${this._targetDir}`); - } - relPath = resourcePath.substr(this._targetDir.length + 1); // + 1 for the / - } - return relPath; - } - - _create(resourcePath, content) { - const relPath = this._toRelPath(resourcePath); - const hash = contentHash(Buffer.from(content)); - const dir = path.dirname(relPath); - const extname = path.extname(relPath); - const basename = path.basename(relPath, extname); - const dstRelPath = path.join(dir, `${basename}-${hash}${extname}`); - this._assets.set(relPath, dstRelPath); - return dstRelPath; - } - - async write(resourcePath, content) { - const relPath = this._create(resourcePath, content); - const fullPath = path.join(this.directory, relPath); - if (typeof content === "string") { - await fs.writeFile(fullPath, content, "utf8"); - } else { - await fs.writeFile(fullPath, content); - } - return relPath; - } - - async writeUnhashed(resourcePath, content) { - const relPath = this._toRelPath(resourcePath); - this._assets.set(relPath, relPath); - const fullPath = path.join(this.directory, relPath); - if (typeof content === "string") { - await fs.writeFile(fullPath, content, "utf8"); - } else { - await fs.writeFile(fullPath, content); - } - return relPath; - } - - get directory() { - return this._targetDir; - } - - resolve(resourcePath) { - const relPath = this._toRelPath(resourcePath); - const result = this._assets.get(relPath); - if (!result) { - throw new Error(`unknown path: ${relPath}, only know ${Array.from(this._assets.keys()).join(", ")}`); - } - return result; - } - - addSubMap(assetMap) { - if (!assetMap.directory.startsWith(this.directory)) { - throw new Error(`map directory doesn't start with this directory: ${assetMap.directory} ${this.directory}`); - } - const relSubRoot = assetMap.directory.substr(this.directory.length + 1); - for (const [key, value] of assetMap._assets.entries()) { - this._assets.set(path.join(relSubRoot, key), path.join(relSubRoot, value)); - } - } - - [Symbol.iterator]() { - return this._assets.entries(); - } - - isUnhashed(relPath) { - const resolvedPath = this._assets.get(relPath); - if (!resolvedPath) { - throw new Error("Unknown asset: " + relPath); - } - return relPath === resolvedPath; - } - - get size() { - return this._assets.size; - } - - has(relPath) { - return this._assets.has(relPath); - } - - hashForAll() { - const globalHashAssets = Array.from(this).map(([, resolved]) => resolved); - globalHashAssets.push(...this._unhashedHashes); - globalHashAssets.sort(); - return contentHash(globalHashAssets.join(",")); - } - - addToHashForAll(resourcePath, content) { - this._unhashedHashes.push(`${resourcePath}-${contentHash(Buffer.from(content))}`); - } -} - -async function readImportOverrides(filename) { - const json = await fs.readFile(filename, "utf8"); - const mapping = new Map(Object.entries(JSON.parse(json))); - return { - basedir: path.dirname(path.resolve(filename))+path.sep, - mapping - }; -} - -function overridesAsRollupPlugin(importOverrides) { - const {mapping, basedir} = importOverrides; - return { - name: "rewrite-imports", - resolveId (source, importer) { - let file; - if (source.startsWith(path.sep)) { - file = source; - } else { - file = path.join(path.dirname(importer), source); - } - if (file.startsWith(basedir)) { - const searchPath = file.substr(basedir.length); - const replacingPath = mapping.get(searchPath); - if (replacingPath) { - console.info(`replacing ${searchPath} with ${replacingPath}`); - return path.join(basedir, replacingPath); - } - } - return null; - } - }; -} - -build(parameters).catch(err => console.error(err)); diff --git a/scripts/common.mjs b/scripts/common.mjs deleted file mode 100644 index e135022a..00000000 --- a/scripts/common.mjs +++ /dev/null @@ -1,12 +0,0 @@ -import fsRoot from "fs"; -const fs = fsRoot.promises; - -export async function removeDirIfExists(targetDir) { - try { - await fs.rmdir(targetDir, {recursive: true}); - } catch (err) { - if (err.code !== "ENOENT") { - throw err; - } - } -} diff --git a/scripts/deploy.sh b/scripts/deploy.sh deleted file mode 100755 index 8027b1d8..00000000 --- a/scripts/deploy.sh +++ /dev/null @@ -1,6 +0,0 @@ -git checkout gh-pages -cp -R target/* . -git add $(find . -maxdepth 1 -type f) -git add themes -git commit -m "update hydrogen" -git checkout master diff --git a/scripts/serve-local.js b/scripts/serve-local.js deleted file mode 100644 index ae07d180..00000000 --- a/scripts/serve-local.js +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright 2020 Bruno Windels - -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. -*/ - -const finalhandler = require('finalhandler') -const http = require('http') -const serveStatic = require('serve-static') -const path = require('path'); - -// Serve up parent directory with cache disabled -const serve = serveStatic( - path.resolve(__dirname, "../"), - { - etag: false, - setHeaders: res => { - res.setHeader("Pragma", "no-cache"); - res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); - res.setHeader("Expires", "Wed, 21 Oct 2015 07:28:00 GMT"); - }, - index: ['index.html', 'index.htm'] - } -); - -// Create server -const server = http.createServer(function onRequest (req, res) { - console.log(req.method, req.url); - serve(req, res, finalhandler(req, res)) -}); - -// Listen -server.listen(3000); diff --git a/snowpack.config.js b/snowpack.config.js deleted file mode 100644 index 68f33242..00000000 --- a/snowpack.config.js +++ /dev/null @@ -1,37 +0,0 @@ -// Snowpack Configuration File -// See all supported options: https://www.snowpack.dev/reference/configuration - -/** @type {import("snowpack").SnowpackUserConfig } */ -module.exports = { - mount: { - // More specific paths before less specific paths (if they overlap) - "src/platform/web/docroot": "/", - "src": "/src", - "lib": {url: "/lib", static: true }, - "assets": "/assets", - /* ... */ - }, - exclude: [ - /* Avoid scanning scripts which use dev-dependencies and pull in babel, rollup, etc. */ - '**/node_modules/**/*', - '**/scripts/**', - '**/target/**', - '**/prototypes/**', - '**/src/platform/web/legacy-polyfill.js', - '**/src/platform/web/worker/polyfill.js' - ], - plugins: [ - /* ... */ - ], - packageOptions: { - /* ... */ - }, - devOptions: { - open: "none", - hmr: false, - /* ... */ - }, - buildOptions: { - /* ... */ - }, -}; diff --git a/yarn.lock b/yarn.lock index 10a18ec8..87d39fac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,350 +9,11 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" - integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== - dependencies: - "@babel/highlight" "^7.10.4" - -"@babel/code-frame@^7.14.5": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.15.8.tgz#45990c47adadb00c03677baa89221f7cc23d2503" - integrity sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg== - dependencies: - "@babel/highlight" "^7.14.5" - -"@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" - integrity sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ== - dependencies: - browserslist "^4.12.0" - invariant "^2.2.4" - semver "^5.5.0" - -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" - integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== - -"@babel/core@^7.11.1": - version "7.11.1" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.1.tgz#2c55b604e73a40dc21b0e52650b11c65cf276643" - integrity sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.0" - "@babel/helper-module-transforms" "^7.11.0" - "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.11.1" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.11.0" - "@babel/types" "^7.11.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.19" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/generator@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" - integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== - dependencies: - "@babel/types" "^7.11.0" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.15.4": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.8.tgz#fa56be6b596952ceb231048cf84ee499a19c0cd1" - integrity sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g== - dependencies: - "@babel/types" "^7.15.6" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/helper-annotate-as-pure@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" - integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA== - dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" - integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-compilation-targets@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" - integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== - dependencies: - "@babel/compat-data" "^7.10.4" - browserslist "^4.12.0" - invariant "^2.2.4" - levenary "^1.1.1" - semver "^5.5.0" - -"@babel/helper-compilation-targets@^7.13.0": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz#cf6d94f30fbefc139123e27dd6b02f65aeedb7b9" - integrity sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ== - dependencies: - "@babel/compat-data" "^7.15.0" - "@babel/helper-validator-option" "^7.14.5" - browserslist "^4.16.6" - semver "^6.3.0" - -"@babel/helper-create-class-features-plugin@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" - integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== - dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-member-expression-to-functions" "^7.10.5" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.10.4" - -"@babel/helper-create-regexp-features-plugin@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" - integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-regex" "^7.10.4" - regexpu-core "^4.7.0" - -"@babel/helper-define-map@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" - integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== - dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/types" "^7.10.5" - lodash "^4.17.19" - -"@babel/helper-define-polyfill-provider@^0.2.2": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz#0525edec5094653a282688d34d846e4c75e9c0b6" - integrity sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew== - dependencies: - "@babel/helper-compilation-targets" "^7.13.0" - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/traverse" "^7.13.0" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - semver "^6.1.2" - -"@babel/helper-explode-assignable-expression@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz#40a1cd917bff1288f699a94a75b37a1a2dbd8c7c" - integrity sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A== - dependencies: - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-function-name@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" - integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== - dependencies: - "@babel/helper-get-function-arity" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-function-name@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz#845744dafc4381a4a5fb6afa6c3d36f98a787ebc" - integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw== - dependencies: - "@babel/helper-get-function-arity" "^7.15.4" - "@babel/template" "^7.15.4" - "@babel/types" "^7.15.4" - -"@babel/helper-get-function-arity@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" - integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== - dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-get-function-arity@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz#098818934a137fce78b536a3e015864be1e2879b" - integrity sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-hoist-variables@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" - integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== - dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-hoist-variables@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz#09993a3259c0e918f99d104261dfdfc033f178df" - integrity sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" - integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== - dependencies: - "@babel/types" "^7.11.0" - -"@babel/helper-module-imports@^7.10.4": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz#90538e60b672ecf1b448f5f4f5433d37e79a3ec3" - integrity sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz#e18007d230632dea19b47853b984476e7b4e103f" - integrity sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" - integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== - dependencies: - "@babel/helper-module-imports" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" - "@babel/helper-simple-access" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/template" "^7.10.4" - "@babel/types" "^7.11.0" - lodash "^4.17.19" - -"@babel/helper-optimise-call-expression@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" - integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== - dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" - integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== - -"@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" - integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== - -"@babel/helper-regex@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" - integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== - dependencies: - lodash "^4.17.19" - -"@babel/helper-remap-async-to-generator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz#fce8bea4e9690bbe923056ded21e54b4e8b68ed5" - integrity sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-wrap-function" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-replace-supers@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" - integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.10.4" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-simple-access@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" - integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== - dependencies: - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-skip-transparent-expression-wrappers@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" - integrity sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q== - dependencies: - "@babel/types" "^7.11.0" - -"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" - integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== - dependencies: - "@babel/types" "^7.11.0" - -"@babel/helper-split-export-declaration@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz#aecab92dcdbef6a10aa3b62ab204b085f776e257" - integrity sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7": +"@babel/helper-validator-identifier@^7.10.4": version "7.15.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== -"@babel/helper-validator-identifier@^7.14.5": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" - integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== - -"@babel/helper-validator-option@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" - integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== - -"@babel/helper-wrap-function@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" - integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== - dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helpers@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" - integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== - dependencies: - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - "@babel/highlight@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" @@ -362,649 +23,6 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/highlight@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" - integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== - dependencies: - "@babel/helper-validator-identifier" "^7.14.5" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.11.1": - version "7.11.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.3.tgz#9e1eae46738bcd08e23e867bab43e7b95299a8f9" - integrity sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA== - -"@babel/parser@^7.15.4": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.8.tgz#7bacdcbe71bdc3ff936d510c15dcea7cf0b99016" - integrity sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA== - -"@babel/plugin-proposal-async-generator-functions@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" - integrity sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-remap-async-to-generator" "^7.10.4" - "@babel/plugin-syntax-async-generators" "^7.8.0" - -"@babel/plugin-proposal-class-properties@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" - integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-proposal-dynamic-import@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e" - integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - -"@babel/plugin-proposal-export-namespace-from@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz#570d883b91031637b3e2958eea3c438e62c05f54" - integrity sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-proposal-json-strings@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" - integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.0" - -"@babel/plugin-proposal-logical-assignment-operators@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz#9f80e482c03083c87125dee10026b58527ea20c8" - integrity sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" - integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - -"@babel/plugin-proposal-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" - integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-object-rest-spread@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" - integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.10.4" - -"@babel/plugin-proposal-optional-catch-binding@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" - integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - -"@babel/plugin-proposal-optional-chaining@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" - integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - -"@babel/plugin-proposal-private-methods@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" - integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-proposal-unicode-property-regex@^7.10.4", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" - integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-async-generators@^7.8.0": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c" - integrity sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-dynamic-import@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-export-namespace-from@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" - integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-json-strings@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-top-level-await@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d" - integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-arrow-functions@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" - integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-async-to-generator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" - integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ== - dependencies: - "@babel/helper-module-imports" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-remap-async-to-generator" "^7.10.4" - -"@babel/plugin-transform-block-scoped-functions@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" - integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-block-scoping@^7.10.4": - version "7.11.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz#5b7efe98852bef8d652c0b28144cd93a9e4b5215" - integrity sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-classes@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" - integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-define-map" "^7.10.4" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.10.4" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" - integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-destructuring@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" - integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-dotall-regex@^7.10.4", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" - integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-duplicate-keys@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" - integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-exponentiation-operator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" - integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-for-of@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" - integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-function-name@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" - integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg== - dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" - integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-member-expression-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" - integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-modules-amd@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" - integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw== - dependencies: - "@babel/helper-module-transforms" "^7.10.5" - "@babel/helper-plugin-utils" "^7.10.4" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-commonjs@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" - integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== - dependencies: - "@babel/helper-module-transforms" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-simple-access" "^7.10.4" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-systemjs@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" - integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw== - dependencies: - "@babel/helper-hoist-variables" "^7.10.4" - "@babel/helper-module-transforms" "^7.10.5" - "@babel/helper-plugin-utils" "^7.10.4" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-umd@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" - integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA== - dependencies: - "@babel/helper-module-transforms" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" - integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" - -"@babel/plugin-transform-new-target@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" - integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-object-super@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" - integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" - -"@babel/plugin-transform-parameters@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" - integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw== - dependencies: - "@babel/helper-get-function-arity" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-property-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" - integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-regenerator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" - integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw== - dependencies: - regenerator-transform "^0.14.2" - -"@babel/plugin-transform-reserved-words@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" - integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-runtime@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.8.tgz#9d15b1e94e1c7f6344f65a8d573597d93c6cd886" - integrity sha512-+6zsde91jMzzvkzuEA3k63zCw+tm/GvuuabkpisgbDMTPQsIMHllE3XczJFFtEHLjjhKQFZmGQVRdELetlWpVw== - dependencies: - "@babel/helper-module-imports" "^7.15.4" - "@babel/helper-plugin-utils" "^7.14.5" - babel-plugin-polyfill-corejs2 "^0.2.2" - babel-plugin-polyfill-corejs3 "^0.2.5" - babel-plugin-polyfill-regenerator "^0.2.2" - semver "^6.3.0" - -"@babel/plugin-transform-shorthand-properties@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" - integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-spread@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" - integrity sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" - -"@babel/plugin-transform-sticky-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" - integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-regex" "^7.10.4" - -"@babel/plugin-transform-template-literals@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" - integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-typeof-symbol@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" - integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-unicode-escapes@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" - integrity sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-unicode-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" - integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/preset-env@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.0.tgz#860ee38f2ce17ad60480c2021ba9689393efb796" - integrity sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg== - dependencies: - "@babel/compat-data" "^7.11.0" - "@babel/helper-compilation-targets" "^7.10.4" - "@babel/helper-module-imports" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-proposal-async-generator-functions" "^7.10.4" - "@babel/plugin-proposal-class-properties" "^7.10.4" - "@babel/plugin-proposal-dynamic-import" "^7.10.4" - "@babel/plugin-proposal-export-namespace-from" "^7.10.4" - "@babel/plugin-proposal-json-strings" "^7.10.4" - "@babel/plugin-proposal-logical-assignment-operators" "^7.11.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" - "@babel/plugin-proposal-numeric-separator" "^7.10.4" - "@babel/plugin-proposal-object-rest-spread" "^7.11.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" - "@babel/plugin-proposal-optional-chaining" "^7.11.0" - "@babel/plugin-proposal-private-methods" "^7.10.4" - "@babel/plugin-proposal-unicode-property-regex" "^7.10.4" - "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-class-properties" "^7.10.4" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.0" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.10.4" - "@babel/plugin-transform-arrow-functions" "^7.10.4" - "@babel/plugin-transform-async-to-generator" "^7.10.4" - "@babel/plugin-transform-block-scoped-functions" "^7.10.4" - "@babel/plugin-transform-block-scoping" "^7.10.4" - "@babel/plugin-transform-classes" "^7.10.4" - "@babel/plugin-transform-computed-properties" "^7.10.4" - "@babel/plugin-transform-destructuring" "^7.10.4" - "@babel/plugin-transform-dotall-regex" "^7.10.4" - "@babel/plugin-transform-duplicate-keys" "^7.10.4" - "@babel/plugin-transform-exponentiation-operator" "^7.10.4" - "@babel/plugin-transform-for-of" "^7.10.4" - "@babel/plugin-transform-function-name" "^7.10.4" - "@babel/plugin-transform-literals" "^7.10.4" - "@babel/plugin-transform-member-expression-literals" "^7.10.4" - "@babel/plugin-transform-modules-amd" "^7.10.4" - "@babel/plugin-transform-modules-commonjs" "^7.10.4" - "@babel/plugin-transform-modules-systemjs" "^7.10.4" - "@babel/plugin-transform-modules-umd" "^7.10.4" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4" - "@babel/plugin-transform-new-target" "^7.10.4" - "@babel/plugin-transform-object-super" "^7.10.4" - "@babel/plugin-transform-parameters" "^7.10.4" - "@babel/plugin-transform-property-literals" "^7.10.4" - "@babel/plugin-transform-regenerator" "^7.10.4" - "@babel/plugin-transform-reserved-words" "^7.10.4" - "@babel/plugin-transform-shorthand-properties" "^7.10.4" - "@babel/plugin-transform-spread" "^7.11.0" - "@babel/plugin-transform-sticky-regex" "^7.10.4" - "@babel/plugin-transform-template-literals" "^7.10.4" - "@babel/plugin-transform-typeof-symbol" "^7.10.4" - "@babel/plugin-transform-unicode-escapes" "^7.10.4" - "@babel/plugin-transform-unicode-regex" "^7.10.4" - "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.11.0" - browserslist "^4.12.0" - core-js-compat "^3.6.2" - invariant "^2.2.2" - levenary "^1.1.1" - semver "^5.5.0" - -"@babel/preset-modules@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" - integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/runtime@^7.8.4": - version "7.11.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" - integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/standalone@^7.15.7", "@babel/standalone@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.15.8.tgz#3cb40b81892a702968a3e0bba2bdd1115f034876" - integrity sha512-EF2uQLeuwflnPRGetWH2Z400ITOSK7YbkXIKxY91EWSiOJ8xsbupT3sx3sFRwVyQgjsHSILFDzLcSo/rGspLhQ== - -"@babel/template@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" - integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/parser" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/template@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" - integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/parser" "^7.15.4" - "@babel/types" "^7.15.4" - -"@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" - integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.0" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.11.0" - "@babel/types" "^7.11.0" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.19" - -"@babel/traverse@^7.13.0": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d" - integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/generator" "^7.15.4" - "@babel/helper-function-name" "^7.15.4" - "@babel/helper-hoist-variables" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" - "@babel/parser" "^7.15.4" - "@babel/types" "^7.15.4" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@^7.10.4", "@babel/types@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba" - integrity sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg== - dependencies: - "@babel/helper-validator-identifier" "^7.15.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.4.4": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" - integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== - dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - lodash "^4.17.19" - to-fast-properties "^2.0.0" - -"@babel/types@^7.15.4", "@babel/types@^7.15.6": - version "7.15.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f" - integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig== - dependencies: - "@babel/helper-validator-identifier" "^7.14.9" - to-fast-properties "^2.0.0" - "@eslint/eslintrc@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" @@ -1059,103 +77,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@rollup/plugin-babel@^5.1.0": - version "5.3.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz#9cb1c5146ddd6a4968ad96f209c50c62f92f9879" - integrity sha512-9uIC8HZOnVLrLHxayq/PTzw+uS25E14KPUBh5ktF+18Mjo5yK0ToMMx6epY0uEgkjwJw0aBW4x2horYXh8juWw== - dependencies: - "@babel/helper-module-imports" "^7.10.4" - "@rollup/pluginutils" "^3.1.0" - -"@rollup/plugin-commonjs@^15.0.0": - version "15.0.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-15.0.0.tgz#690d15a9d54ba829db93555bff9b98ff34e08574" - integrity sha512-8uAdikHqVyrT32w1zB9VhW6uGwGjhKgnDNP4pQJsjdnyF4FgCj6/bmv24c7v2CuKhq32CcyCwRzMPEElaKkn0w== - dependencies: - "@rollup/pluginutils" "^3.1.0" - commondir "^1.0.1" - estree-walker "^2.0.1" - glob "^7.1.6" - is-reference "^1.2.1" - magic-string "^0.25.7" - resolve "^1.17.0" - -"@rollup/plugin-json@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3" - integrity sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw== - dependencies: - "@rollup/pluginutils" "^3.0.8" - -"@rollup/plugin-multi-entry@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-multi-entry/-/plugin-multi-entry-4.0.0.tgz#8e105f16ec1bb26639eb3302c8db5665f44b9939" - integrity sha512-1Sw86rwFxrNS7ECY3iSZ7T940xKnruNGpmQDgSDVTp+VTa1g5cPXNzBgp+IoOer41CiVeGFLwYwvicVoJLHEDQ== - dependencies: - "@rollup/plugin-virtual" "^2.0.3" - matched "^5.0.0" - -"@rollup/plugin-node-resolve@^9.0.0": - version "9.0.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-9.0.0.tgz#39bd0034ce9126b39c1699695f440b4b7d2b62e6" - integrity sha512-gPz+utFHLRrd41WMP13Jq5mqqzHL3OXrfj3/MkSyB6UBIcuNt9j60GCbarzMzdf1VHFpOxfQh/ez7wyadLMqkg== - dependencies: - "@rollup/pluginutils" "^3.1.0" - "@types/resolve" "1.17.1" - builtin-modules "^3.1.0" - deepmerge "^4.2.2" - is-module "^1.0.0" - resolve "^1.17.0" - -"@rollup/plugin-virtual@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@rollup/plugin-virtual/-/plugin-virtual-2.0.3.tgz#0afc88d75c1e1378ab290b8e9898d4edb5be0d74" - integrity sha512-pw6ziJcyjZtntQ//bkad9qXaBx665SgEL8C8KI5wO8G5iU5MPxvdWrQyVaAvjojGm9tJoS8M9Z/EEepbqieYmw== - -"@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" - integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== - dependencies: - "@types/estree" "0.0.39" - estree-walker "^1.0.1" - picomatch "^2.2.2" - -"@rollup/pluginutils@^4.1.1": - version "4.1.1" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.1.tgz#1d4da86dd4eded15656a57d933fda2b9a08d47ec" - integrity sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ== - dependencies: - estree-walker "^2.0.1" - picomatch "^2.2.2" - -"@types/estree@*": - version "0.0.45" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884" - integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g== - -"@types/estree@0.0.39": - version "0.0.39" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" - integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== - "@types/json-schema@^7.0.7": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== -"@types/node@*": - version "14.10.3" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.3.tgz#5ae1f119c96643fc9b19b2d1a83bfa2ec3dbb7ea" - integrity sha512-zdN0hor7TLkjAdKTnYW+Y22oIhUUpil5ZD1V1OFq0CR0CLKw+NdR6dkziTfkWRLo6sKzisayoj/GNpNbe4LY9Q== - -"@types/resolve@1.17.1": - version "1.17.1" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" - integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== - dependencies: - "@types/node" "*" - "@typescript-eslint/eslint-plugin@^4.29.2": version "4.29.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.2.tgz#f54dc0a32b8f61c6024ab8755da05363b733838d" @@ -1225,17 +151,6 @@ "@typescript-eslint/types" "4.29.2" eslint-visitor-keys "^2.0.0" -"@vitejs/plugin-legacy@^1.6.1": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@vitejs/plugin-legacy/-/plugin-legacy-1.6.1.tgz#45f0e006de2d25758151b098b8dcb912c62a95dc" - integrity sha512-isBi2ti+AlCZUpfA1P6L8gseltBy/qi6Rsi92aDzeL2elpwXgN4Hv/xLS2UUSSj9F0mFmxXCYPWlBPaJnlYamQ== - dependencies: - "@babel/standalone" "^7.15.7" - core-js "^3.18.1" - magic-string "^0.25.7" - regenerator-runtime "^0.13.9" - systemjs "^6.10.3" - acorn-jsx@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" @@ -1317,49 +232,6 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== -autoprefixer@^10.4.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.0.tgz#c3577eb32a1079a440ec253e404eaf1eb21388c8" - integrity sha512-7FdJ1ONtwzV1G43GDD0kpVMn/qbiNqyOPMFTX5nRffI+7vgWoFEc6DcXOxHJxrWNDXrZh18eDsZjvZGUljSRGA== - dependencies: - browserslist "^4.17.5" - caniuse-lite "^1.0.30001272" - fraction.js "^4.1.1" - normalize-range "^0.1.2" - picocolors "^1.0.0" - postcss-value-parser "^4.1.0" - -babel-plugin-dynamic-import-node@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" - integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== - dependencies: - object.assign "^4.1.0" - -babel-plugin-polyfill-corejs2@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz#e9124785e6fd94f94b618a7954e5693053bf5327" - integrity sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ== - dependencies: - "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.2.2" - semver "^6.1.1" - -babel-plugin-polyfill-corejs3@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz#2779846a16a1652244ae268b1e906ada107faf92" - integrity sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" - core-js-compat "^3.16.2" - -babel-plugin-polyfill-regenerator@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz#b310c8d642acada348c1fa3b3e6ce0e851bee077" - integrity sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" - balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -1382,7 +254,7 @@ base64-arraybuffer@^0.2.0: resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz#4b944fac0191aa5907afe2d8c999ccc57ce80f45" integrity sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ== -boolbase@^1.0.0, boolbase@~1.0.0: +boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= @@ -1402,49 +274,6 @@ braces@^3.0.1: dependencies: fill-range "^7.0.1" -browserslist@^4.12.0, browserslist@^4.8.5: - version "4.14.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.0.tgz#2908951abfe4ec98737b72f34c3bcedc8d43b000" - integrity sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ== - dependencies: - caniuse-lite "^1.0.30001111" - electron-to-chromium "^1.3.523" - escalade "^3.0.2" - node-releases "^1.1.60" - -browserslist@^4.16.6: - version "4.16.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" - integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== - dependencies: - caniuse-lite "^1.0.30001219" - colorette "^1.2.2" - electron-to-chromium "^1.3.723" - escalade "^3.1.1" - node-releases "^1.1.71" - -browserslist@^4.17.3: - version "4.17.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.3.tgz#2844cd6eebe14d12384b0122d217550160d2d624" - integrity sha512-59IqHJV5VGdcJZ+GZ2hU5n4Kv3YiASzW6Xk5g9tf5a/MAzGeFwgGWU39fVzNIOVcgB3+Gp+kiQu0HEfTVU/3VQ== - dependencies: - caniuse-lite "^1.0.30001264" - electron-to-chromium "^1.3.857" - escalade "^3.1.1" - node-releases "^1.1.77" - picocolors "^0.2.1" - -browserslist@^4.17.5: - version "4.18.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.18.1.tgz#60d3920f25b6860eb917c6c7b185576f4d8b017f" - integrity sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ== - dependencies: - caniuse-lite "^1.0.30001280" - electron-to-chromium "^1.3.896" - escalade "^3.1.1" - node-releases "^2.0.1" - picocolors "^1.0.0" - bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" @@ -1452,26 +281,11 @@ bs58@^4.0.1: dependencies: base-x "^3.0.2" -builtin-modules@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484" - integrity sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw== - callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -caniuse-lite@^1.0.30001111, caniuse-lite@^1.0.30001219, caniuse-lite@^1.0.30001264: - version "1.0.30001278" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001278.tgz" - integrity sha512-mpF9KeH8u5cMoEmIic/cr7PNS+F5LWBk0t2ekGT60lFf0Wq+n9LspAj0g3P+o7DQhD3sUdlMln4YFAWhFYn9jg== - -caniuse-lite@^1.0.30001272, caniuse-lite@^1.0.30001280: - version "1.0.30001283" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001283.tgz#8573685bdae4d733ef18f78d44ba0ca5fe9e896b" - integrity sha512-9RoKo841j1GQFSJz/nCXOj0sD7tHBtlowjYlrqIUS812x9/emfBLBt6IyMz1zIaYc/eRL8Cs6HPUVi2Hzq4sIg== - chalk@^2.0.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1489,18 +303,6 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -cheerio@^1.0.0-rc.3: - version "1.0.0-rc.3" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.3.tgz#094636d425b2e9c0f4eb91a46c05630c9a1a8bf6" - integrity sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA== - dependencies: - css-select "~1.2.0" - dom-serializer "~0.1.1" - entities "~1.1.1" - htmlparser2 "^3.9.1" - lodash "^4.15.0" - parse5 "^3.0.1" - color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -1525,73 +327,30 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" - integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== - colors@^1.3.3: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -commander@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-6.0.0.tgz#2b270da94f8fb9014455312f829a1129dbf8887e" - integrity sha512-s7EA+hDtTYNhuXkTlhqew4txMZVdszBmKWSPEMxGr8ru8JXR7bLUFIAtPhcSuFdJQ0ILMxnJi8GkQL0yvDy/YA== - commander@^6.1.0: version "6.2.1" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -convert-source-map@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" - -core-js-compat@^3.16.2: - version "3.18.2" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.18.2.tgz#e40c266fbd613948dd8d2d2156345da8ac03c142" - integrity sha512-25VJYCJtGjZwLguj7d66oiHfmnVw3TMOZ0zV8DyMJp/aeQ3OjR519iOOeck08HMyVVRAqXxafc2Hl+5QstJrsQ== - dependencies: - browserslist "^4.17.3" - semver "7.0.0" - -core-js-compat@^3.6.2: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" - integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng== - dependencies: - browserslist "^4.8.5" - semver "7.0.0" - core-js@^2.5.3: version "2.6.12" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== -core-js@^3.18.1: - version "3.18.2" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.2.tgz#63a551e8a29f305cd4123754846e65896619ba5b" - integrity sha512-zNhPOUoSgoizoSQFdX1MeZO16ORRb9FFQLts8gSYbZU5FcgXhp24iMWMxnOQo5uIaIG7/6FA/IqJPwev1o9ZXQ== - core-js@^3.6.5: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" - integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== + version "3.19.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.19.3.tgz#6df8142a996337503019ff3235a7022d7cdf4559" + integrity sha512-LeLBMgEGSsG7giquSzvgBrTS7V5UL6ks3eQlUSbN8dJStlLFiRzUm5iqsRyzUB8carhfKjkJ2vzKqE6z1Vga9g== cross-spawn@^7.0.2: version "7.0.3" @@ -1613,21 +372,6 @@ css-select@^4.1.3: domutils "^2.6.0" nth-check "^2.0.0" -css-select@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= - dependencies: - boolbase "~1.0.0" - css-what "2.1" - domutils "1.5.1" - nth-check "~1.0.1" - -css-what@2.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" - integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== - css-what@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.0.1.tgz#3efa820131f4669a8ac2408f9c32e7c7de9f4cad" @@ -1638,13 +382,6 @@ cuint@^0.2.2: resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b" integrity sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs= -debug@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - debug@^4.0.1, debug@^4.1.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" @@ -1652,13 +389,6 @@ debug@^4.0.1, debug@^4.1.1: dependencies: ms "2.1.2" -debug@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - debug@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" @@ -1671,28 +401,6 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= -deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== - -define-properties@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -1707,14 +415,6 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dom-serializer@0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - dom-serializer@^1.0.1: version "1.3.2" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" @@ -1724,19 +424,6 @@ dom-serializer@^1.0.1: domhandler "^4.2.0" entities "^2.0.0" -dom-serializer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" - integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== - dependencies: - domelementtype "^1.3.0" - entities "^1.1.1" - -domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - domelementtype@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" @@ -1754,13 +441,6 @@ domexception@^1.0.1: dependencies: webidl-conversions "^4.0.2" -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - domhandler@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.0.tgz#f9768a5f034be60a89a27c2e4d0f74eba0d8b059" @@ -1773,22 +453,6 @@ dompurify@^2.3.0: resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.0.tgz#07bb39515e491588e5756b1d3e8375b5964814e2" integrity sha512-VV5C6Kr53YVHGOBKO/F86OYX6/iLTw2yVSI721gKetxpHCK/V5TaLEf9ODjRgl1KLSWRMY6cUhAbv/c+IUnwQw== -domutils@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - domutils@^2.6.0: version "2.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.7.0.tgz#8ebaf0c41ebafcf55b0b72ec31c56323712c5442" @@ -1798,41 +462,11 @@ domutils@^2.6.0: domelementtype "^2.2.0" domhandler "^4.2.0" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -electron-to-chromium@^1.3.523: - version "1.3.534" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.534.tgz#fc7af8518dd00a5b22a24aed3f116b5d097e2330" - integrity sha512-7x2S3yUrspNHQOoPk+Eo+iHViSiJiEGPI6BpmLy1eT2KRNGCkBt/NUYqjfXLd1DpDCQp7n3+LfA1RkbG+LqTZQ== - -electron-to-chromium@^1.3.723: - version "1.3.742" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.742.tgz#7223215acbbd3a5284962ebcb6df85d88b95f200" - integrity sha512-ihL14knI9FikJmH2XUIDdZFWJxvr14rPSdOhJ7PpS27xbz8qmaRwCwyg/bmFwjWKmWK9QyamiCZVCvXm5CH//Q== - -electron-to-chromium@^1.3.857: - version "1.3.866" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.866.tgz#d446338f5ad6948b27a50739760e7b0b5cc5032f" - integrity sha512-iYze6TpDXWxk+sfcpUUdTs6Pv/3kG45Pnjer2DxEeFw0N08bZeNLuz97s2lMgy8yObon48o0WHY2Bkg3xuAPOA== - -electron-to-chromium@^1.3.896: - version "1.4.7" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.7.tgz#58e0b4ec9096ee1422e4d9e83ceeb05b0cf076eb" - integrity sha512-UPy2MsQw1OdcbxR7fvwWZH/rXcv+V26+uvQVHx0fGa1kqRfydtfOw+NMGAvZJ63hyaH4aEBxbhSEtqbpliSNWA== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - enquirer@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" @@ -1840,11 +474,6 @@ enquirer@^2.3.5: dependencies: ansi-colors "^4.1.1" -entities@^1.1.1, entities@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - entities@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" @@ -1969,21 +598,6 @@ esbuild@^0.13.12, esbuild@^0.13.2: esbuild-windows-64 "0.13.15" esbuild-windows-arm64 "0.13.15" -escalade@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4" - integrity sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ== - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -2110,31 +724,11 @@ estraverse@^5.1.0, estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== -estree-walker@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" - integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== - -estree-walker@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" - integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== - -estree-walker@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.1.tgz#f8e030fb21cefa183b44b7ad516b747434e7a3e0" - integrity sha512-tF0hv+Yi2Ot1cwj9eYHtxC0jB9bmjacjQs6ZBTj82H8JwUywFuc+7E83NWfNMwHXZc11mjfFcVXPe9gEP4B8dg== - esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - extend@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -2195,19 +789,6 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -2221,26 +802,11 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== -fraction.js@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.1.tgz#ac4e520473dae67012d618aab91eda09bcb400ff" - integrity sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@~2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" - integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== - fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" @@ -2256,11 +822,6 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gensync@^1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" - integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== - glob-parent@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -2280,23 +841,6 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.6: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - globals@^13.6.0: version "13.8.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.8.0.tgz#3e20f504810ce87a8d72e55aecf8435b50f4c1b3" @@ -2333,11 +877,6 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== - has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -2350,29 +889,6 @@ he@1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -htmlparser2@^3.9.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -2413,18 +929,11 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3: +inherits@2: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -invariant@^2.2.2, invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - is-core-module@^2.2.0: version "2.5.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491" @@ -2449,38 +958,17 @@ is-glob@^4.0.0, is-glob@^4.0.1: dependencies: is-extglob "^2.1.1" -is-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" - integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-reference@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" - integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== - dependencies: - "@types/estree" "*" - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -js-cleanup@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/js-cleanup/-/js-cleanup-1.0.1.tgz#1d38080c7ee92e1d2d2b94054d0a33c48951e0df" - integrity sha512-wyHeWKqbcQV78/tiMJ6pgJrkG7p2u3b2xX9IJFvvurpJL9/++89dHfkUebhWvSMS84LG0uQ7BnG5GGyAzY21Ag== - dependencies: - magic-string "^0.25.1" - perf-regexes "^1.0.1" - skip-regex "^1.0.2" - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: +js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -2493,16 +981,6 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -2518,25 +996,6 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json5@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" - integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== - dependencies: - minimist "^1.2.5" - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levenary@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" - integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== - dependencies: - leven "^3.1.0" - levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -2550,11 +1009,6 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -2565,23 +1019,11 @@ lodash.truncate@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= -lodash@^4.15.0: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -lodash@^4.17.19, lodash@^4.7.0: +lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -2589,21 +1031,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -magic-string@^0.25.1, magic-string@^0.25.7: - version "0.25.7" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" - integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== - dependencies: - sourcemap-codec "^1.4.4" - -matched@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/matched/-/matched-5.0.0.tgz#4b10735a89f87b6f9bf457136472631e19df05d7" - integrity sha512-O0LCuxYYBNBjP2dmAg0i6PME0Mb0dvjulpMC0tTIeMRh6kXYsugOT5GOWpFkSzqjQjgOUs/eiyvpVhXdN2La4g== - dependencies: - glob "^7.1.6" - picomatch "^2.2.1" - mdn-polyfills@^5.20.0: version "5.20.0" resolved "https://registry.yarnpkg.com/mdn-polyfills/-/mdn-polyfills-5.20.0.tgz#ca8247edf20a4f60dec6804372229812b348260b" @@ -2622,11 +1049,6 @@ micromatch@^4.0.4: braces "^3.0.1" picomatch "^2.2.3" -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -2634,22 +1056,7 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -ms@2.1.2, ms@^2.1.1: +ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -2672,31 +1079,6 @@ node-html-parser@^4.0.0: css-select "^4.1.3" he "1.2.0" -node-releases@^1.1.60: - version "1.1.60" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" - integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA== - -node-releases@^1.1.71: - version "1.1.72" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe" - integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw== - -node-releases@^1.1.77: - version "1.1.77" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.77.tgz#50b0cfede855dd374e7585bf228ff34e57c1c32e" - integrity sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ== - -node-releases@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" - integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== - -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= - nth-check@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.0.tgz#1bb4f6dac70072fc313e8c9cd1417b5074c0a125" @@ -2704,35 +1086,6 @@ nth-check@^2.0.0: dependencies: boolbase "^1.0.0" -nth-check@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" - -object-keys@^1.0.11, object-keys@^1.0.12: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -2759,18 +1112,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse5@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" - integrity sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA== - dependencies: - "@types/node" "*" - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -2791,27 +1132,12 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -perf-regexes@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/perf-regexes/-/perf-regexes-1.0.1.tgz#6da1d62f5a94bf9353a0451bccacf69068b75d0b" - integrity sha512-L7MXxUDtqr4PUaLFCDCXBfGV/6KLIuSEccizDI7JxT+c9x1G1v04BQ4+4oag84SHaCdrBgQAIs/Cqn+flwFPng== - picocolors@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" - integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== - -picomatch@^2.2.2, picomatch@^2.2.3: +picomatch@^2.2.3: version "2.3.0" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== @@ -2830,11 +1156,6 @@ postcss-flexbugs-fixes@^5.0.2: resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz#2028e145313074fc9abe276cb7ca14e5401eb49d" integrity sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ== -postcss-value-parser@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" - integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== - postcss@^8.3.8: version "8.3.9" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.9.tgz#98754caa06c4ee9eb59cc48bd073bb6bd3437c31" @@ -2864,20 +1185,6 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -readable-stream@^3.1.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - realistic-structured-clone@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/realistic-structured-clone/-/realistic-structured-clone-2.0.2.tgz#2f8ec225b1f9af20efc79ac96a09043704414959" @@ -2888,64 +1195,16 @@ realistic-structured-clone@^2.0.1: typeson "^5.8.2" typeson-registry "^1.0.0-alpha.20" -regenerate-unicode-properties@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" - integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== - dependencies: - regenerate "^1.4.0" - -regenerate@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.1.tgz#cad92ad8e6b591773485fbe05a485caf4f457e6f" - integrity sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A== - -regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: - version "0.13.7" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" - integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== - -regenerator-runtime@^0.13.9: +regenerator-runtime@^0.13.7: version "0.13.9" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== -regenerator-transform@^0.14.2: - version "0.14.5" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" - integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== - dependencies: - "@babel/runtime" "^7.8.4" - regexpp@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== -regexpu-core@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" - integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.2.0" - regjsgen "^0.5.1" - regjsparser "^0.6.4" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.2.0" - -regjsgen@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" - integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== - -regjsparser@^0.6.4: - version "0.6.4" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" - integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== - dependencies: - jsesc "~0.5.0" - require-from-string@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" @@ -2956,7 +1215,7 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve@^1.14.2, resolve@^1.20.0: +resolve@^1.20.0: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -2964,13 +1223,6 @@ resolve@^1.14.2, resolve@^1.20.0: is-core-module "^2.2.0" path-parse "^1.0.6" -resolve@^1.17.0, resolve@^1.3.2: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== - dependencies: - path-parse "^1.0.6" - reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -2983,28 +1235,6 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -rollup-plugin-cleanup@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-cleanup/-/rollup-plugin-cleanup-3.1.1.tgz#d012faab5e212b1c4bfa8144ace70fc6ac7b3315" - integrity sha512-wMS9JQm4ShvlMqno1pOfqvh0yYgNLO2ZgmzDsVvKuDt4XCn+9DcMoUwRQ5t9p9b113dR5FhPFFUHnvvQ/yuEtA== - dependencies: - js-cleanup "^1.0.1" - rollup-pluginutils "^2.3.3" - -rollup-pluginutils@^2.3.3: - version "2.8.2" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" - integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== - dependencies: - estree-walker "^0.6.1" - -rollup@^2.26.4: - version "2.27.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.27.1.tgz#372744e1d36eba0fd942d997600c2fc2ca266305" - integrity sha512-GiWHQvnmMgBktSpY/1+nrGpwPsTw4b9P28og2uedfeq4JZ16rzAmnQ5Pm/E0/BEmDNia1ZbY7+qu3nBgNa19Hg== - optionalDependencies: - fsevents "~2.1.2" - rollup@^2.57.0: version "2.58.0" resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.58.0.tgz#a643983365e7bf7f5b7c62a8331b983b7c4c67fb" @@ -3024,31 +1254,6 @@ safe-buffer@^5.0.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@~5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - -semver@^5.4.1, semver@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - semver@^7.2.1, semver@^7.3.5: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" @@ -3056,45 +1261,11 @@ semver@^7.2.1, semver@^7.3.5: dependencies: lru-cache "^6.0.0" -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serve-static@^1.13.2: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -3107,11 +1278,6 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -skip-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/skip-regex/-/skip-regex-1.0.2.tgz#ac655d77e7c771ac2b9f37585fea37bff56ad65b" - integrity sha512-pEjMUbwJ5Pl/6Vn6FsamXHXItJXSRftcibixDmNCWbWhic0hzHrwkMZo0IZ7fMRH9KxcWDFSkzhccB4285PutA== - slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -3131,26 +1297,11 @@ source-map-js@^0.6.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== -source-map@^0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -sourcemap-codec@^1.4.4: - version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - string-width@^4.2.0: version "4.2.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" @@ -3160,13 +1311,6 @@ string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - strip-ansi@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -3193,11 +1337,6 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -systemjs@^6.10.3: - version "6.10.3" - resolved "https://registry.yarnpkg.com/systemjs/-/systemjs-6.10.3.tgz#7e783fccb58232f1d9eb05c7e1a661268945cade" - integrity sha512-mXwfLJdaADqWg1J5+Z0bGQEdcXSe+ePPTfzffMB29aVls5cXveRl0vneSV/19t3SfuUBsAraLP8W/g5u9cmYXA== - table@^6.0.9: version "6.7.1" resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" @@ -3220,11 +1359,6 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -3232,11 +1366,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - tr46@^2.0.2: version "2.1.0" resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" @@ -3292,34 +1421,6 @@ typeson@^6.0.0: resolved "https://registry.yarnpkg.com/typeson/-/typeson-6.1.0.tgz#5b2a53705a5f58ff4d6f82f965917cabd0d7448b" integrity sha512-6FTtyGr8ldU0pfbvW/eOZrEtEkczHRUtduBnA90Jh9kMPCiFNnXIon3vF41N0S4tV1HHQt4Hk1j4srpESziCaA== -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== - -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== - dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" - -unicode-match-property-value-ecmascript@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" - integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== - -unicode-property-aliases-ecmascript@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" - integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== - -unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -3327,11 +1428,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -util-deprecate@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - v8-compile-cache@^2.0.3: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" From ba84387722e7648ad181336eff98be5eca12ffcd Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 9 Dec 2021 18:15:22 +0100 Subject: [PATCH 242/242] remove commented out code --- vite.config.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/vite.config.js b/vite.config.js index c7c91a68..1562269e 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,5 +1,4 @@ const cssvariables = require("postcss-css-variables"); -//const autoprefixer = require("autoprefixer"); const flexbugsFixes = require("postcss-flexbugs-fixes"); const fs = require("fs"); @@ -7,7 +6,6 @@ const path = require("path"); const injectWebManifest = require("./scripts/build-plugins/manifest"); const {injectServiceWorker, createPlaceholderValues} = require("./scripts/build-plugins/service-worker"); -// const legacyBuild = require("./scripts/build-plugins/legacy-build"); const {defineConfig} = require('vite'); const version = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8")).version; @@ -38,11 +36,6 @@ export default defineConfig(({mode}) => { polyfillModulePreload: false, }, plugins: [ - // legacyBuild(scriptTagPath(path.join(__dirname, "src/platform/web/index.html"), 0), { - // "./Platform": "./LegacyPlatform" - // }, "hydrogen-legacy", [ - // './legacy-polyfill', - // ]), // important this comes before service worker // otherwise the manifest and the icons it refers to won't be cached injectWebManifest("assets/manifest.json"),