convert tabs to spaces where needed

This commit is contained in:
Bruno Windels 2019-06-26 22:31:36 +02:00
parent 56ae6670be
commit cd9f25ea80
10 changed files with 340 additions and 340 deletions

View File

@ -1,36 +1,36 @@
export default class EventEmitter {
constructor() {
this._handlersByName = {};
}
constructor() {
this._handlersByName = {};
}
emit(name, ...values) {
const handlers = this._handlersByName[name];
if (handlers) {
for(const h of handlers) {
h(...values);
}
}
}
emit(name, ...values) {
const handlers = this._handlersByName[name];
if (handlers) {
for(const h of handlers) {
h(...values);
}
}
}
on(name, callback) {
let handlers = this._handlersByName[name];
if (!handlers) {
on(name, callback) {
let handlers = this._handlersByName[name];
if (!handlers) {
this.onFirstSubscriptionAdded(name);
this._handlersByName[name] = handlers = new Set();
}
handlers.add(callback);
}
this._handlersByName[name] = handlers = new Set();
}
handlers.add(callback);
}
off(name, callback) {
const handlers = this._handlersByName[name];
if (handlers) {
handlers.delete(callback);
if (handlers.length === 0) {
delete this._handlersByName[name];
off(name, callback) {
const handlers = this._handlersByName[name];
if (handlers) {
handlers.delete(callback);
if (handlers.length === 0) {
delete this._handlersByName[name];
this.onLastSubscriptionRemoved(name);
}
}
}
}
}
}
onFirstSubscriptionAdded(name) {}
@ -38,38 +38,38 @@ export default class EventEmitter {
}
//#ifdef TESTS
export function tests() {
return {
test_on_off(assert) {
let counter = 0;
const e = new EventEmitter();
const callback = () => counter += 1;
e.on("change", callback);
e.emit("change");
e.off("change", callback);
e.emit("change");
assert.equal(counter, 1);
},
return {
test_on_off(assert) {
let counter = 0;
const e = new EventEmitter();
const callback = () => counter += 1;
e.on("change", callback);
e.emit("change");
e.off("change", callback);
e.emit("change");
assert.equal(counter, 1);
},
test_emit_value(assert) {
let value = 0;
const e = new EventEmitter();
const callback = (v) => value = v;
e.on("change", callback);
e.emit("change", 5);
e.off("change", callback);
assert.equal(value, 5);
},
test_emit_value(assert) {
let value = 0;
const e = new EventEmitter();
const callback = (v) => value = v;
e.on("change", callback);
e.emit("change", 5);
e.off("change", callback);
assert.equal(value, 5);
},
test_double_on(assert) {
let counter = 0;
const e = new EventEmitter();
const callback = () => counter += 1;
e.on("change", callback);
e.on("change", callback);
e.emit("change");
e.off("change", callback);
assert.equal(counter, 1);
}
};
test_double_on(assert) {
let counter = 0;
const e = new EventEmitter();
const callback = () => counter += 1;
e.on("change", callback);
e.on("change", callback);
e.emit("change");
e.off("change", callback);
assert.equal(counter, 1);
}
};
}
//#endif

View File

@ -12,14 +12,14 @@ const USER_ID = `@${USERNAME}:localhost`;
const PASSWORD = "testtest";
function getSessionInfo(userId) {
const sessionsJson = localStorage.getItem("brawl_sessions_v1");
if (sessionsJson) {
const sessions = JSON.parse(sessionsJson);
const session = sessions.find(session => session.userId === userId);
if (session) {
return session;
}
}
const sessionsJson = localStorage.getItem("brawl_sessions_v1");
if (sessionsJson) {
const sessions = JSON.parse(sessionsJson);
const session = sessions.find(session => session.userId === userId);
if (session) {
return session;
}
}
}
function storeSessionInfo(loginData) {
@ -39,9 +39,9 @@ function storeSessionInfo(loginData) {
}
async function login(username, password, homeserver) {
const hsApi = new HomeServerApi(homeserver);
const loginData = await hsApi.passwordLogin(username, password).response();
return storeSessionInfo(loginData);
const hsApi = new HomeServerApi(homeserver);
const loginData = await hsApi.passwordLogin(username, password).response();
return storeSessionInfo(loginData);
}
function showSession(container, session, sync) {
@ -51,11 +51,11 @@ function showSession(container, session, sync) {
}
export default async function main(container) {
try {
let sessionInfo = getSessionInfo(USER_ID);
if (!sessionInfo) {
sessionInfo = await login(USERNAME, PASSWORD, HOMESERVER);
}
try {
let sessionInfo = getSessionInfo(USER_ID);
if (!sessionInfo) {
sessionInfo = await login(USERNAME, PASSWORD, HOMESERVER);
}
const storage = await createIdbStorage(`brawl_session_${sessionInfo.id}`);
const hsApi = new HomeServerApi(HOMESERVER, sessionInfo.accessToken);
const session = new Session({storage, hsApi, sessionInfo: {
@ -65,18 +65,18 @@ export default async function main(container) {
}});
await session.load();
console.log("session loaded");
const sync = new Sync(hsApi, session, storage);
const sync = new Sync(hsApi, session, storage);
const needsInitialSync = !session.syncToken;
if (needsInitialSync) {
console.log("session needs initial sync");
} else {
showSession(container, session, sync);
}
await sync.start();
await sync.start();
if (needsInitialSync) {
showSession(container, session, sync);
}
} catch(err) {
} catch(err) {
console.error(`${err.message}:\n${err.stack}`);
}
}
}

View File

@ -1,8 +1,8 @@
export class HomeServerError extends Error {
constructor(method, url, body) {
super(`${body.error} on ${method} ${url}`);
this.errcode = body.errcode;
}
constructor(method, url, body) {
super(`${body.error} on ${method} ${url}`);
this.errcode = body.errcode;
}
}
export class RequestAbortError extends Error {

View File

@ -1,11 +1,11 @@
import {
HomeServerError,
RequestAbortError,
HomeServerError,
RequestAbortError,
NetworkError
} from "./error.js";
class RequestWrapper {
constructor(promise, controller) {
constructor(promise, controller) {
if (!controller) {
const abortPromise = new Promise((_, reject) => {
this._controller = {
@ -21,63 +21,63 @@ class RequestWrapper {
this._promise = promise;
this._controller = controller;
}
}
}
abort() {
this._controller.abort();
}
abort() {
this._controller.abort();
}
response() {
return this._promise;
}
response() {
return this._promise;
}
}
export default class HomeServerApi {
constructor(homeserver, accessToken) {
constructor(homeserver, accessToken) {
// store these both in a closure somehow so it's harder to get at in case of XSS?
// one could change the homeserver as well so the token gets sent there, so both must be protected from read/write
this._homeserver = homeserver;
this._accessToken = accessToken;
}
this._accessToken = accessToken;
}
_url(csPath) {
return `${this._homeserver}/_matrix/client/r0${csPath}`;
}
_url(csPath) {
return `${this._homeserver}/_matrix/client/r0${csPath}`;
}
_request(method, csPath, queryParams = {}, body) {
const queryString = Object.entries(queryParams)
.filter(([, value]) => value !== undefined)
.map(([name, value]) => `${encodeURIComponent(name)}=${encodeURIComponent(value)}`)
.join("&");
const url = this._url(`${csPath}?${queryString}`);
let bodyString;
const headers = new Headers();
if (this._accessToken) {
headers.append("Authorization", `Bearer ${this._accessToken}`);
}
headers.append("Accept", "application/json");
if (body) {
headers.append("Content-Type", "application/json");
bodyString = JSON.stringify(body);
}
const controller = typeof AbortController === "function" ? new AbortController() : null;
// TODO: set authenticated headers with second arguments, cache them
let promise = fetch(url, {
method,
headers,
body: bodyString,
signal: controller && controller.signal
});
promise = promise.then(async (response) => {
if (response.ok) {
return await response.json();
} else {
switch (response.status) {
default:
throw new HomeServerError(method, url, await response.json())
}
}
}, err => {
_request(method, csPath, queryParams = {}, body) {
const queryString = Object.entries(queryParams)
.filter(([, value]) => value !== undefined)
.map(([name, value]) => `${encodeURIComponent(name)}=${encodeURIComponent(value)}`)
.join("&");
const url = this._url(`${csPath}?${queryString}`);
let bodyString;
const headers = new Headers();
if (this._accessToken) {
headers.append("Authorization", `Bearer ${this._accessToken}`);
}
headers.append("Accept", "application/json");
if (body) {
headers.append("Content-Type", "application/json");
bodyString = JSON.stringify(body);
}
const controller = typeof AbortController === "function" ? new AbortController() : null;
// TODO: set authenticated headers with second arguments, cache them
let promise = fetch(url, {
method,
headers,
body: bodyString,
signal: controller && controller.signal
});
promise = promise.then(async (response) => {
if (response.ok) {
return await response.json();
} else {
switch (response.status) {
default:
throw new HomeServerError(method, url, await response.json())
}
}
}, err => {
if (err.name === "AbortError") {
throw new RequestAbortError();
} else if (err instanceof TypeError) {
@ -89,29 +89,29 @@ export default class HomeServerApi {
// but the 2 later ones are indistinguishable from javascript.
throw new NetworkError(err.message);
}
throw err;
});
return new RequestWrapper(promise, controller);
}
throw err;
});
return new RequestWrapper(promise, controller);
}
_post(csPath, queryParams, body) {
return this._request("POST", csPath, queryParams, body);
}
_post(csPath, queryParams, body) {
return this._request("POST", csPath, queryParams, body);
}
_get(csPath, queryParams, body) {
return this._request("GET", csPath, queryParams, body);
}
_get(csPath, queryParams, body) {
return this._request("GET", csPath, queryParams, body);
}
sync(since, filter, timeout) {
return this._get("/sync", {since, timeout, filter});
}
sync(since, filter, timeout) {
return this._get("/sync", {since, timeout, filter});
}
// params is from, dir and optionally to, limit, filter.
messages(roomId, params) {
return this._get(`/rooms/${roomId}/messages`, params);
}
passwordLogin(username, password) {
passwordLogin(username, password) {
return this._post("/login", undefined, {
"type": "m.login.password",
"identifier": {
@ -120,5 +120,5 @@ export default class HomeServerApi {
},
"password": password
});
}
}
}

View File

@ -1,9 +1,9 @@
import {iterateCursor, reqAsPromise} from "./utils.js";
export default class QueryTarget {
constructor(target) {
this._target = target;
}
constructor(target) {
this._target = target;
}
_openCursor(range, direction) {
if (range && direction) {
@ -21,55 +21,55 @@ export default class QueryTarget {
return reqAsPromise(this._target.get(key));
}
reduce(range, reducer, initialValue) {
return this._reduce(range, reducer, initialValue, "next");
}
reduce(range, reducer, initialValue) {
return this._reduce(range, reducer, initialValue, "next");
}
reduceReverse(range, reducer, initialValue) {
return this._reduce(range, reducer, initialValue, "prev");
}
selectLimit(range, amount) {
return this._selectLimit(range, amount, "next");
}
reduceReverse(range, reducer, initialValue) {
return this._reduce(range, reducer, initialValue, "prev");
}
selectLimit(range, amount) {
return this._selectLimit(range, amount, "next");
}
selectLimitReverse(range, amount) {
return this._selectLimit(range, amount, "prev");
}
selectLimitReverse(range, amount) {
return this._selectLimit(range, amount, "prev");
}
selectWhile(range, predicate) {
return this._selectWhile(range, predicate, "next");
}
selectWhile(range, predicate) {
return this._selectWhile(range, predicate, "next");
}
selectWhileReverse(range, predicate) {
return this._selectWhile(range, predicate, "prev");
}
selectWhileReverse(range, predicate) {
return this._selectWhile(range, predicate, "prev");
}
async selectAll(range, direction) {
const cursor = this._openCursor(range, direction);
const results = [];
await iterateCursor(cursor, (value) => {
results.push(value);
return {done: false};
});
return results;
}
async selectAll(range, direction) {
const cursor = this._openCursor(range, direction);
const results = [];
await iterateCursor(cursor, (value) => {
results.push(value);
return {done: false};
});
return results;
}
selectFirst(range) {
return this._find(range, () => true, "next");
}
selectFirst(range) {
return this._find(range, () => true, "next");
}
selectLast(range) {
return this._find(range, () => true, "prev");
}
selectLast(range) {
return this._find(range, () => true, "prev");
}
find(range, predicate) {
return this._find(range, predicate, "next");
}
find(range, predicate) {
return this._find(range, predicate, "next");
}
findReverse(range, predicate) {
return this._find(range, predicate, "prev");
}
findReverse(range, predicate) {
return this._find(range, predicate, "prev");
}
/**
* Checks if a given set of keys exist.
@ -107,43 +107,43 @@ export default class QueryTarget {
}
}
_reduce(range, reducer, initialValue, direction) {
let reducedValue = initialValue;
const cursor = this._openCursor(range, direction);
return iterateCursor(cursor, (value) => {
reducedValue = reducer(reducedValue, value);
return {done: false};
});
}
_reduce(range, reducer, initialValue, direction) {
let reducedValue = initialValue;
const cursor = this._openCursor(range, direction);
return iterateCursor(cursor, (value) => {
reducedValue = reducer(reducedValue, value);
return {done: false};
});
}
_selectLimit(range, amount, direction) {
return this._selectWhile(range, (results) => {
return results.length === amount;
}, direction);
}
_selectLimit(range, amount, direction) {
return this._selectWhile(range, (results) => {
return results.length === amount;
}, direction);
}
async _selectWhile(range, predicate, direction) {
const cursor = this._openCursor(range, direction);
const results = [];
await iterateCursor(cursor, (value) => {
results.push(value);
return {done: predicate(results)};
});
return results;
}
async _selectWhile(range, predicate, direction) {
const cursor = this._openCursor(range, direction);
const results = [];
await iterateCursor(cursor, (value) => {
results.push(value);
return {done: predicate(results)};
});
return results;
}
async _find(range, predicate, direction) {
const cursor = this._openCursor(range, direction);
let result;
const found = await iterateCursor(cursor, (value) => {
const found = predicate(value);
if (found) {
result = value;
}
return {done: found};
});
if (found) {
return result;
}
}
async _find(range, predicate, direction) {
const cursor = this._openCursor(range, direction);
let result;
const found = await iterateCursor(cursor, (value) => {
const found = predicate(value);
if (found) {
result = value;
}
return {done: found};
});
if (found) {
return result;
}
}
}

View File

@ -2,39 +2,39 @@ import Transaction from "./transaction.js";
import { STORE_NAMES, StorageError } from "../common.js";
export default class Storage {
constructor(idbDatabase) {
this._db = idbDatabase;
const nameMap = STORE_NAMES.reduce((nameMap, name) => {
nameMap[name] = name;
return nameMap;
}, {});
this.storeNames = Object.freeze(nameMap);
}
constructor(idbDatabase) {
this._db = idbDatabase;
const nameMap = STORE_NAMES.reduce((nameMap, name) => {
nameMap[name] = name;
return nameMap;
}, {});
this.storeNames = Object.freeze(nameMap);
}
_validateStoreNames(storeNames) {
const idx = storeNames.findIndex(name => !STORE_NAMES.includes(name));
if (idx !== -1) {
throw new StorageError(`Tried top, a transaction unknown store ${storeNames[idx]}`);
}
}
_validateStoreNames(storeNames) {
const idx = storeNames.findIndex(name => !STORE_NAMES.includes(name));
if (idx !== -1) {
throw new StorageError(`Tried top, a transaction unknown store ${storeNames[idx]}`);
}
}
async readTxn(storeNames) {
this._validateStoreNames(storeNames);
try {
const txn = this._db.transaction(storeNames, "readonly");
return new Transaction(txn, storeNames);
} catch(err) {
throw new StorageError("readTxn failed", err);
}
}
async readTxn(storeNames) {
this._validateStoreNames(storeNames);
try {
const txn = this._db.transaction(storeNames, "readonly");
return new Transaction(txn, storeNames);
} catch(err) {
throw new StorageError("readTxn failed", err);
}
}
async readWriteTxn(storeNames) {
this._validateStoreNames(storeNames);
try {
const txn = this._db.transaction(storeNames, "readwrite");
return new Transaction(txn, storeNames);
} catch(err) {
throw new StorageError("readWriteTxn failed", err);
}
}
async readWriteTxn(storeNames) {
this._validateStoreNames(storeNames);
try {
const txn = this._db.transaction(storeNames, "readwrite");
return new Transaction(txn, storeNames);
} catch(err) {
throw new StorageError("readWriteTxn failed", err);
}
}
}

View File

@ -57,23 +57,23 @@ class QueryTargetWrapper {
}
export default class Store extends QueryTarget {
constructor(idbStore) {
super(new QueryTargetWrapper(idbStore));
}
constructor(idbStore) {
super(new QueryTargetWrapper(idbStore));
}
get _idbStore() {
return this._target;
}
get _idbStore() {
return this._target;
}
index(indexName) {
return new QueryTarget(new QueryTargetWrapper(this._idbStore.index(indexName)));
}
index(indexName) {
return new QueryTarget(new QueryTargetWrapper(this._idbStore.index(indexName)));
}
put(value) {
return reqAsPromise(this._idbStore.put(value));
}
put(value) {
return reqAsPromise(this._idbStore.put(value));
}
add(value) {
return reqAsPromise(this._idbStore.add(value));
}
add(value) {
return reqAsPromise(this._idbStore.add(value));
}
}

View File

@ -87,9 +87,9 @@ class Range {
* @property {?Gap} gap if a gap entry, the gap
*/
export default class TimelineEventStore {
constructor(timelineStore) {
this._timelineStore = timelineStore;
}
constructor(timelineStore) {
this._timelineStore = timelineStore;
}
/** Creates a range that only includes the given key
* @param {EventKey} eventKey the key
@ -134,11 +134,11 @@ export default class TimelineEventStore {
* @param {number} amount
* @return {Promise<Entry[]>} a promise resolving to an array with 0 or more entries, in ascending order.
*/
async lastEvents(roomId, fragmentId, amount) {
async lastEvents(roomId, fragmentId, amount) {
const eventKey = EventKey.maxKey;
eventKey.fragmentId = fragmentId;
return this.eventsBefore(roomId, eventKey, amount);
}
return this.eventsBefore(roomId, eventKey, amount);
}
/** Looks up the first `amount` entries in the timeline for `roomId`.
* @param {string} roomId
@ -146,11 +146,11 @@ export default class TimelineEventStore {
* @param {number} amount
* @return {Promise<Entry[]>} a promise resolving to an array with 0 or more entries, in ascending order.
*/
async firstEvents(roomId, fragmentId, amount) {
async firstEvents(roomId, fragmentId, amount) {
const eventKey = EventKey.minKey;
eventKey.fragmentId = fragmentId;
return this.eventsAfter(roomId, eventKey, amount);
}
return this.eventsAfter(roomId, eventKey, amount);
}
/** Looks up `amount` entries after `eventKey` in the timeline for `roomId` within the same fragment.
* The entry for `eventKey` is not included.
@ -159,10 +159,10 @@ export default class TimelineEventStore {
* @param {number} amount
* @return {Promise<Entry[]>} a promise resolving to an array with 0 or more entries, in ascending order.
*/
eventsAfter(roomId, eventKey, amount) {
eventsAfter(roomId, eventKey, amount) {
const idbRange = this.lowerBoundRange(eventKey, true).asIDBKeyRange(roomId);
return this._timelineStore.selectLimit(idbRange, amount);
}
return this._timelineStore.selectLimit(idbRange, amount);
}
/** Looks up `amount` entries before `eventKey` in the timeline for `roomId` within the same fragment.
* The entry for `eventKey` is not included.

View File

@ -8,58 +8,58 @@ import RoomStateStore from "./stores/RoomStateStore.js";
import TimelineFragmentStore from "./stores/TimelineFragmentStore.js";
export default class Transaction {
constructor(txn, allowedStoreNames) {
this._txn = txn;
this._allowedStoreNames = allowedStoreNames;
this._stores = {
session: null,
roomSummary: null,
roomTimeline: null,
roomState: null,
};
}
constructor(txn, allowedStoreNames) {
this._txn = txn;
this._allowedStoreNames = allowedStoreNames;
this._stores = {
session: null,
roomSummary: null,
roomTimeline: null,
roomState: null,
};
}
_idbStore(name) {
if (!this._allowedStoreNames.includes(name)) {
// more specific error? this is a bug, so maybe not ...
throw new StorageError(`Invalid store for transaction: ${name}, only ${this._allowedStoreNames.join(", ")} are allowed.`);
}
return new Store(this._txn.objectStore(name));
}
_idbStore(name) {
if (!this._allowedStoreNames.includes(name)) {
// more specific error? this is a bug, so maybe not ...
throw new StorageError(`Invalid store for transaction: ${name}, only ${this._allowedStoreNames.join(", ")} are allowed.`);
}
return new Store(this._txn.objectStore(name));
}
_store(name, mapStore) {
if (!this._stores[name]) {
const idbStore = this._idbStore(name);
this._stores[name] = mapStore(idbStore);
}
return this._stores[name];
}
_store(name, mapStore) {
if (!this._stores[name]) {
const idbStore = this._idbStore(name);
this._stores[name] = mapStore(idbStore);
}
return this._stores[name];
}
get session() {
return this._store("session", idbStore => new SessionStore(idbStore));
}
get session() {
return this._store("session", idbStore => new SessionStore(idbStore));
}
get roomSummary() {
return this._store("roomSummary", idbStore => new RoomSummaryStore(idbStore));
}
get roomSummary() {
return this._store("roomSummary", idbStore => new RoomSummaryStore(idbStore));
}
get timelineFragments() {
return this._store("timelineFragments", idbStore => new TimelineFragmentStore(idbStore));
}
get timelineEvents() {
return this._store("timelineEvents", idbStore => new TimelineEventStore(idbStore));
}
get timelineEvents() {
return this._store("timelineEvents", idbStore => new TimelineEventStore(idbStore));
}
get roomState() {
return this._store("roomState", idbStore => new RoomStateStore(idbStore));
}
get roomState() {
return this._store("roomState", idbStore => new RoomStateStore(idbStore));
}
complete() {
return txnAsPromise(this._txn);
}
complete() {
return txnAsPromise(this._txn);
}
abort() {
this._txn.abort();
}
abort() {
this._txn.abort();
}
}

View File

@ -1,16 +1,16 @@
export default {
get minStorageKey() {
// for indexeddb, we use unsigned 32 bit integers as keys
return 0;
},
get middleStorageKey() {
// for indexeddb, we use unsigned 32 bit integers as keys
return 0x7FFFFFFF;
},
get minStorageKey() {
// for indexeddb, we use unsigned 32 bit integers as keys
return 0;
},
get middleStorageKey() {
// for indexeddb, we use unsigned 32 bit integers as keys
return 0x7FFFFFFF;
},
get maxStorageKey() {
// for indexeddb, we use unsigned 32 bit integers as keys
return 0xFFFFFFFF;
},
get maxStorageKey() {
// for indexeddb, we use unsigned 32 bit integers as keys
return 0xFFFFFFFF;
},
}