diff --git a/.eslintrc.js b/.eslintrc.js index b8b711376..e6eb64af7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,5 @@ module.exports = { + parser: "babel-eslint", parserOptions: { ecmaVersion: 6, sourceType: "module", @@ -11,12 +12,20 @@ module.exports = { }, extends: ["eslint:recommended", "google"], rules: { - // rules we've always adhered to + // rules we've always adhered to or now do "max-len": ["error", { code: 90, ignoreComments: true, }], curly: ["error", "multi-line"], + "prefer-const": ["error"], + "comma-dangle": ["error", { + arrays: "always-multiline", + objects: "always-multiline", + imports: "always-multiline", + exports: "always-multiline", + functions: "always-multiline", + }], // loosen jsdoc requirements a little "require-jsdoc": ["error", { @@ -47,8 +56,7 @@ module.exports = { // we set these to warnings, and assert that the number // of warnings doesn't exceed a given threshold "no-var": ["warn"], - "comma-dangle": ["warn"], - "brace-style": ["warn"], + "brace-style": ["warn", "1tbs", {"allowSingleLine": true}], "prefer-rest-params": ["warn"], "prefer-spread": ["warn"], "one-var": ["warn"], diff --git a/.gitignore b/.gitignore index 2f23450b5..076209806 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ out reports /dist /lib +/specbuild # version file and tarball created by 'npm pack' /git-revision.txt diff --git a/.travis.yml b/.travis.yml index 9d6a11439..0fde128e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,6 @@ language: node_js node_js: - node # Latest stable version of nodejs. +script: + - npm run lint + - npm run test diff --git a/CHANGELOG.md b/CHANGELOG.md index d8945dd91..d1816885a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +Changes in [0.7.4](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.7.4) (2017-01-16) +================================================================================================ +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.7.4-rc.1...v0.7.4) + + * Fix non-conference calling + +Changes in [0.7.4-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.7.4-rc.1) (2017-01-13) +========================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.7.3...v0.7.4-rc.1) + + * Remove babel-polyfill + [\#321](https://github.com/matrix-org/matrix-js-sdk/pull/321) + * Update build process for ES6 + [\#320](https://github.com/matrix-org/matrix-js-sdk/pull/320) + * 'babel' is not a babel package anymore + [\#319](https://github.com/matrix-org/matrix-js-sdk/pull/319) + * Add Babel for ES6 support + [\#318](https://github.com/matrix-org/matrix-js-sdk/pull/318) + * Move screen sharing check/error + [\#317](https://github.com/matrix-org/matrix-js-sdk/pull/317) + * release.sh: Bail early if there are uncommitted changes + [\#316](https://github.com/matrix-org/matrix-js-sdk/pull/316) + Changes in [0.7.3](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.7.3) (2017-01-04) ================================================================================================ [Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.7.2...v0.7.3) diff --git a/jenkins.sh b/jenkins.sh index d9c47a3f6..3034a9063 100755 --- a/jenkins.sh +++ b/jenkins.sh @@ -1,9 +1,12 @@ #!/bin/bash -l +set -x + export NVM_DIR="/home/jenkins/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" -nvm use 6 -npm install + +nvm use 6 || exit $? +npm install || exit $? RC=0 diff --git a/package.json b/package.json index 9de635281..8d6a55627 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,19 @@ { "name": "matrix-js-sdk", - "version": "0.7.3", + "version": "0.7.4", "description": "Matrix Client-Server SDK for Javascript", "main": "index.js", "scripts": { - "test": "istanbul cover --report cobertura --config .istanbul.yml -i \"lib/**/*.js\" jasmine-node -- spec --verbose --junitreport --captureExceptions", - "check": "jasmine-node spec --verbose --junitreport --captureExceptions", + "buildtest": "babel -s -d specbuild spec", + "test": "npm run buildtest && istanbul cover --report cobertura --config .istanbul.yml -i \"lib/**/*.js\" jasmine-node -- specbuild --verbose --junitreport --captureExceptions", + "check": "npm run buildtest && jasmine-node specbuild --verbose --junitreport --captureExceptions", "gendoc": "jsdoc -r lib -P package.json -R README.md -d .jsdoc", "start": "babel -s -w -d lib src", "build": "babel -s -d lib src && rimraf dist && mkdir dist && browserify --exclude olm browser-index.js -o dist/browser-matrix.js --ignore-missing && uglifyjs -c -m -o dist/browser-matrix.min.js dist/browser-matrix.js", "dist": "npm run build", "watch": "watchify --exclude olm browser-index.js -o dist/browser-matrix-dev.js -v", - "lint": "eslint --max-warnings 146 src spec", - "prepublish": "npm run lint && npm run build && git rev-parse HEAD > git-revision.txt" + "lint": "eslint --max-warnings 121 src spec", + "prepublish": "npm run build && git rev-parse HEAD > git-revision.txt" }, "repository": { "url": "https://github.com/matrix-org/matrix-js-sdk" @@ -52,6 +53,7 @@ }, "devDependencies": { "babel-cli": "^6.18.0", + "babel-eslint": "^7.1.1", "babel-preset-es2015": "^6.18.0", "eslint": "^3.13.1", "eslint-config-google": "^0.7.1", @@ -63,6 +65,6 @@ "watchify": "^3.2.1" }, "optionalDependencies": { - "olm": "https://matrix.org/packages/npm/olm/olm-2.1.0.tgz" + "olm": "https://matrix.org/packages/npm/olm/olm-2.2.1.tgz" } } diff --git a/spec/MockStorageApi.js b/spec/MockStorageApi.js index 691fccf3a..1063ad3db 100644 --- a/spec/MockStorageApi.js +++ b/spec/MockStorageApi.js @@ -40,8 +40,8 @@ MockStorageApi.prototype = { return this.keys[index]; }, _recalc: function() { - let keys = []; - for (let k in this.data) { + const keys = []; + for (const k in this.data) { if (!this.data.hasOwnProperty(k)) { continue; } diff --git a/spec/integ/matrix-client-crypto.spec.js b/spec/integ/matrix-client-crypto.spec.js index fcdf29cf3..8a9e21208 100644 --- a/spec/integ/matrix-client-crypto.spec.js +++ b/spec/integ/matrix-client-crypto.spec.js @@ -1,21 +1,21 @@ "use strict"; -let sdk = require("../.."); -let q = require("q"); -let HttpBackend = require("../mock-request"); -let utils = require("../../lib/utils"); -let test_utils = require("../test-utils"); +const sdk = require("../.."); +const q = require("q"); +const HttpBackend = require("../mock-request"); +const utils = require("../../lib/utils"); +const testUtils = require("../test-utils"); let aliHttpBackend; let bobHttpBackend; let aliClient; -let roomId = "!room:localhost"; -let aliUserId = "@ali:localhost"; -let aliDeviceId = "zxcvb"; -let aliAccessToken = "aseukfgwef"; +const roomId = "!room:localhost"; +const aliUserId = "@ali:localhost"; +const aliDeviceId = "zxcvb"; +const aliAccessToken = "aseukfgwef"; let bobClient; -let bobUserId = "@bob:localhost"; -let bobDeviceId = "bvcxz"; -let bobAccessToken = "fewgfkuesa"; +const bobUserId = "@bob:localhost"; +const bobDeviceId = "bvcxz"; +const bobAccessToken = "fewgfkuesa"; let bobOneTimeKeys; let aliDeviceKeys; let bobDeviceKeys; @@ -38,8 +38,8 @@ let bobMessages; * {one_time_keys: {}, device_keys: {}} */ function expectKeyUpload(deviceId, httpBackend) { - let uploadPath = "/keys/upload/" + deviceId; - let keys = {}; + const uploadPath = "/keys/upload/" + deviceId; + const keys = {}; httpBackend.when("POST", uploadPath).respond(200, function(path, content) { expect(content.one_time_keys).not.toBeDefined(); @@ -53,7 +53,7 @@ function expectKeyUpload(deviceId, httpBackend) { expect(content.one_time_keys).toBeDefined(); expect(content.one_time_keys).not.toEqual({}); let count = 0; - for (let key in content.one_time_keys) { + for (const key in content.one_time_keys) { if (content.one_time_keys.hasOwnProperty(key)) { count++; } @@ -105,7 +105,7 @@ function expectBobKeyUpload() { } function bobUploadsKeys() { - bobClient.uploadKeys(5).catch(test_utils.failTest); + bobClient.uploadKeys(5).catch(testUtils.failTest); return expectBobKeyUpload(); } @@ -119,11 +119,11 @@ function expectAliQueryKeys() { // can't query keys before bob has uploaded them expect(bobDeviceKeys).toBeDefined(); - let bobKeys = {}; + const bobKeys = {}; bobKeys[bobDeviceId] = bobDeviceKeys; aliHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) { expect(content.device_keys[bobUserId]).toEqual({}); - let result = {}; + const result = {}; result[bobUserId] = bobKeys; return {device_keys: result}; }); @@ -139,11 +139,11 @@ function expectBobQueryKeys() { // can't query keys before ali has uploaded them expect(aliDeviceKeys).toBeDefined(); - let aliKeys = {}; + const aliKeys = {}; aliKeys[aliDeviceId] = aliDeviceKeys; bobHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) { expect(content.device_keys[aliUserId]).toEqual({}); - let result = {}; + const result = {}; result[aliUserId] = aliKeys; return {device_keys: result}; }); @@ -160,16 +160,17 @@ function expectAliClaimKeys() { expect(bobOneTimeKeys).toBeDefined(); aliHttpBackend.when("POST", "/keys/claim").respond(200, function(path, content) { - let claimType = content.one_time_keys[bobUserId][bobDeviceId]; + const claimType = content.one_time_keys[bobUserId][bobDeviceId]; expect(claimType).toEqual("signed_curve25519"); - for (var keyId in bobOneTimeKeys) { + let keyId = null; + for (keyId in bobOneTimeKeys) { if (bobOneTimeKeys.hasOwnProperty(keyId)) { if (keyId.indexOf(claimType + ":") === 0) { break; } } } - let result = {}; + const result = {}; result[bobUserId] = {}; result[bobUserId][bobDeviceId] = {}; result[bobUserId][bobDeviceId][keyId] = bobOneTimeKeys[keyId]; @@ -184,7 +185,7 @@ function aliDownloadsKeys() { // can't query keys before bob has uploaded them expect(bobDeviceEd25519Key).toBeDefined(); - let p1 = aliClient.downloadKeys([bobUserId]).then(function() { + const p1 = aliClient.downloadKeys([bobUserId]).then(function() { expect(aliClient.listDeviceKeys(bobUserId)).toEqual([{ id: "bvcxz", key: bobDeviceEd25519Key, @@ -193,12 +194,12 @@ function aliDownloadsKeys() { display_name: null, }]); }); - let p2 = expectAliQueryKeys(); + const p2 = expectAliQueryKeys(); // check that the localStorage is updated as we expect (not sure this is // an integration test, but meh) return q.all([p1, p2]).then(function() { - let devices = aliStorage.getEndToEndDevicesForUser(bobUserId); + const devices = aliStorage.getEndToEndDevicesForUser(bobUserId); expect(devices[bobDeviceId].keys).toEqual(bobDeviceKeys.keys); expect(devices[bobDeviceId].verified). toBe(0); // DeviceVerification.UNVERIFIED @@ -278,7 +279,7 @@ function expectAliSendMessageRequest() { return expectSendMessageRequest(aliHttpBackend).then(function(content) { aliMessages.push(content); expect(utils.keys(content.ciphertext)).toEqual([bobDeviceCurve25519Key]); - let ciphertext = content.ciphertext[bobDeviceCurve25519Key]; + const ciphertext = content.ciphertext[bobDeviceCurve25519Key]; expect(ciphertext).toBeDefined(); return ciphertext; }); @@ -292,10 +293,10 @@ function expectAliSendMessageRequest() { function expectBobSendMessageRequest() { return expectSendMessageRequest(bobHttpBackend).then(function(content) { bobMessages.push(content); - let aliKeyId = "curve25519:" + aliDeviceId; - let aliDeviceCurve25519Key = aliDeviceKeys.keys[aliKeyId]; + const aliKeyId = "curve25519:" + aliDeviceId; + const aliDeviceCurve25519Key = aliDeviceKeys.keys[aliKeyId]; expect(utils.keys(content.ciphertext)).toEqual([aliDeviceCurve25519Key]); - let ciphertext = content.ciphertext[aliDeviceCurve25519Key]; + const ciphertext = content.ciphertext[aliDeviceCurve25519Key]; expect(ciphertext).toBeDefined(); return ciphertext; }); @@ -303,12 +304,12 @@ function expectBobSendMessageRequest() { function sendMessage(client) { return client.sendMessage( - roomId, {msgtype: "m.text", body: "Hello, World"} + roomId, {msgtype: "m.text", body: "Hello, World"}, ); } function expectSendMessageRequest(httpBackend) { - let path = "/send/m.room.encrypted/"; + const path = "/send/m.room.encrypted/"; let sent; httpBackend.when("PUT", path).respond(200, function(path, content) { sent = content; @@ -322,17 +323,17 @@ function expectSendMessageRequest(httpBackend) { } function aliRecvMessage() { - let message = bobMessages.shift(); + const message = bobMessages.shift(); return recvMessage(aliHttpBackend, aliClient, bobUserId, message); } function bobRecvMessage() { - let message = aliMessages.shift(); + const message = aliMessages.shift(); return recvMessage(bobHttpBackend, bobClient, aliUserId, message); } function recvMessage(httpBackend, client, sender, message) { - let syncData = { + const syncData = { next_batch: "x", rooms: { join: { @@ -343,7 +344,7 @@ function recvMessage(httpBackend, client, sender, message) { syncData.rooms.join[roomId] = { timeline: { events: [ - test_utils.mkEvent({ + testUtils.mkEvent({ type: "m.room.encrypted", room: roomId, content: message, @@ -353,8 +354,8 @@ function recvMessage(httpBackend, client, sender, message) { }, }; httpBackend.when("GET", "/sync").respond(200, syncData); - let deferred = q.defer(); - let onEvent = function(event) { + const deferred = q.defer(); + const onEvent = function(event) { console.log(client.credentials.userId + " received event", event); @@ -382,12 +383,12 @@ function recvMessage(httpBackend, client, sender, message) { function aliStartClient() { - expectAliKeyUpload().catch(test_utils.failTest); + expectAliKeyUpload().catch(testUtils.failTest); // ali will try to query her own keys on start aliHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) { expect(content.device_keys[aliUserId]).toEqual({}); - let result = {}; + const result = {}; result[aliUserId] = {}; return {device_keys: result}; }); @@ -399,12 +400,12 @@ function aliStartClient() { } function bobStartClient() { - expectBobKeyUpload().catch(test_utils.failTest); + expectBobKeyUpload().catch(testUtils.failTest); // bob will try to query his own keys on start bobHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) { expect(content.device_keys[bobUserId]).toEqual({}); - let result = {}; + const result = {}; result[bobUserId] = {}; return {device_keys: result}; }); @@ -428,7 +429,7 @@ function startClient(httpBackend, client) { httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" }); // send a sync response including our test room. - let syncData = { + const syncData = { next_batch: "x", rooms: { join: { }, @@ -437,11 +438,11 @@ function startClient(httpBackend, client) { syncData.rooms.join[roomId] = { state: { events: [ - test_utils.mkMembership({ + testUtils.mkMembership({ mship: "join", user: aliUserId, }), - test_utils.mkMembership({ + testUtils.mkMembership({ mship: "join", user: bobUserId, }), @@ -463,9 +464,9 @@ describe("MatrixClient crypto", function() { } beforeEach(function() { - test_utils.beforeEach(this); // eslint-disable-line no-invalid-this + testUtils.beforeEach(this); // eslint-disable-line no-invalid-this - aliStorage = new sdk.WebStorageSessionStore(new test_utils.MockStorageApi()); + aliStorage = new sdk.WebStorageSessionStore(new testUtils.MockStorageApi()); aliHttpBackend = new HttpBackend(); aliClient = sdk.createClient({ baseUrl: "http://alis.server", @@ -476,7 +477,7 @@ describe("MatrixClient crypto", function() { request: aliHttpBackend.requestFn, }); - bobStorage = new sdk.WebStorageSessionStore(new test_utils.MockStorageApi()); + bobStorage = new sdk.WebStorageSessionStore(new testUtils.MockStorageApi()); bobHttpBackend = new HttpBackend(); bobClient = sdk.createClient({ baseUrl: "http://bobs.server", @@ -509,30 +510,30 @@ describe("MatrixClient crypto", function() { }, }); - let p1 = aliClient.downloadKeys(['@bob:id']); - let p2 = aliHttpBackend.flush('/keys/query', 1); + const p1 = aliClient.downloadKeys(['@bob:id']); + const p2 = aliHttpBackend.flush('/keys/query', 1); q.all([p1, p2]).then(function() { - let devices = aliStorage.getEndToEndDevicesForUser('@bob:id'); + const devices = aliStorage.getEndToEndDevicesForUser('@bob:id'); expect(utils.keys(devices).length).toEqual(0); // request again: should be no more requests return aliClient.downloadKeys(['@bob:id']); }).nodeify(done); - } + }, ); it("Bob uploads without one-time keys and with one-time keys", function(done) { q() .then(bobUploadsKeys) - .catch(test_utils.failTest).done(done); + .catch(testUtils.failTest).done(done); }); it("Ali downloads Bobs keys", function(done) { q() .then(bobUploadsKeys) .then(aliDownloadsKeys) - .catch(test_utils.failTest).done(done); + .catch(testUtils.failTest).done(done); }); it("Ali gets keys with an invalid signature", function(done) { @@ -550,13 +551,13 @@ describe("MatrixClient crypto", function() { // should get an empty list expect(aliClient.listDeviceKeys(bobUserId)).toEqual([]); }) - .catch(test_utils.failTest).done(done); + .catch(testUtils.failTest).done(done); }); it("Ali gets keys with an incorrect userId", function(done) { - let eveUserId = "@eve:localhost"; + const eveUserId = "@eve:localhost"; - let bobDeviceKeys = { + const bobDeviceKeys = { algorithms: ['m.olm.v1.curve25519-aes-sha2', 'm.megolm.v1.aes-sha2'], device_id: 'bvcxz', keys: { @@ -572,26 +573,26 @@ describe("MatrixClient crypto", function() { }, }; - let bobKeys = {}; + const bobKeys = {}; bobKeys[bobDeviceId] = bobDeviceKeys; aliHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) { - let result = {}; + const result = {}; result[bobUserId] = bobKeys; return {device_keys: result}; }); q.all( aliClient.downloadKeys([bobUserId, eveUserId]), - aliHttpBackend.flush("/keys/query", 1) + aliHttpBackend.flush("/keys/query", 1), ).then(function() { // should get an empty list expect(aliClient.listDeviceKeys(bobUserId)).toEqual([]); expect(aliClient.listDeviceKeys(eveUserId)).toEqual([]); - }).catch(test_utils.failTest).done(done); + }).catch(testUtils.failTest).done(done); }); it("Ali gets keys with an incorrect deviceId", function(done) { - let bobDeviceKeys = { + const bobDeviceKeys = { algorithms: ['m.olm.v1.curve25519-aes-sha2', 'm.megolm.v1.aes-sha2'], device_id: 'bad_device', keys: { @@ -607,21 +608,21 @@ describe("MatrixClient crypto", function() { }, }; - let bobKeys = {}; + const bobKeys = {}; bobKeys[bobDeviceId] = bobDeviceKeys; aliHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) { - let result = {}; + const result = {}; result[bobUserId] = bobKeys; return {device_keys: result}; }); q.all( aliClient.downloadKeys([bobUserId]), - aliHttpBackend.flush("/keys/query", 1) + aliHttpBackend.flush("/keys/query", 1), ).then(function() { // should get an empty list expect(aliClient.listDeviceKeys(bobUserId)).toEqual([]); - }).catch(test_utils.failTest).done(done); + }).catch(testUtils.failTest).done(done); }); it("Ali enables encryption", function(done) { @@ -629,7 +630,7 @@ describe("MatrixClient crypto", function() { .then(bobUploadsKeys) .then(aliStartClient) .then(aliEnablesEncryption) - .catch(test_utils.failTest).done(done); + .catch(testUtils.failTest).done(done); }); it("Ali sends a message", function(done) { @@ -638,7 +639,7 @@ describe("MatrixClient crypto", function() { .then(aliStartClient) .then(aliEnablesEncryption) .then(aliSendsFirstMessage) - .catch(test_utils.failTest).nodeify(done); + .catch(testUtils.failTest).nodeify(done); }); it("Bob receives a message", function(done) { @@ -649,7 +650,7 @@ describe("MatrixClient crypto", function() { .then(aliSendsFirstMessage) .then(bobStartClient) .then(bobRecvMessage) - .catch(test_utils.failTest).done(done); + .catch(testUtils.failTest).done(done); }); it("Bob receives a message with a bogus sender", function(done) { @@ -660,8 +661,8 @@ describe("MatrixClient crypto", function() { .then(aliSendsFirstMessage) .then(bobStartClient) .then(function() { - let message = aliMessages.shift(); - let syncData = { + const message = aliMessages.shift(); + const syncData = { next_batch: "x", rooms: { join: { @@ -672,7 +673,7 @@ describe("MatrixClient crypto", function() { syncData.rooms.join[roomId] = { timeline: { events: [ - test_utils.mkEvent({ + testUtils.mkEvent({ type: "m.room.encrypted", room: roomId, content: message, @@ -683,8 +684,8 @@ describe("MatrixClient crypto", function() { }; bobHttpBackend.when("GET", "/sync").respond(200, syncData); - let deferred = q.defer(); - let onEvent = function(event) { + const deferred = q.defer(); + const onEvent = function(event) { console.log(bobClient.credentials.userId + " received event", event); @@ -706,7 +707,7 @@ describe("MatrixClient crypto", function() { bobHttpBackend.flush(); return deferred.promise; }) - .catch(test_utils.failTest).done(done); + .catch(testUtils.failTest).done(done); }); it("Ali blocks Bob's device", function(done) { @@ -717,8 +718,8 @@ describe("MatrixClient crypto", function() { .then(aliDownloadsKeys) .then(function() { aliClient.setDeviceBlocked(bobUserId, bobDeviceId, true); - let p1 = sendMessage(aliClient); - let p2 = expectAliQueryKeys() + const p1 = sendMessage(aliClient); + const p2 = expectAliQueryKeys() .then(expectAliClaimKeys) .then(function() { return expectSendMessageRequest(aliHttpBackend); @@ -727,7 +728,7 @@ describe("MatrixClient crypto", function() { expect(sentContent.ciphertext).toEqual({}); }); return q.all([p1, p2]); - }).catch(test_utils.failTest).nodeify(done); + }).catch(testUtils.failTest).nodeify(done); }); it("Bob receives two pre-key messages", function(done) { @@ -740,7 +741,7 @@ describe("MatrixClient crypto", function() { .then(bobRecvMessage) .then(aliSendsMessage) .then(bobRecvMessage) - .catch(test_utils.failTest).done(done); + .catch(testUtils.failTest).done(done); }); it("Bob replies to the message", function(done) { @@ -755,7 +756,7 @@ describe("MatrixClient crypto", function() { .then(bobSendsReplyMessage).then(function(ciphertext) { expect(ciphertext.type).toEqual(1); }).then(aliRecvMessage) - .catch(test_utils.failTest).done(done); + .catch(testUtils.failTest).done(done); }); @@ -764,11 +765,11 @@ describe("MatrixClient crypto", function() { .then(bobUploadsKeys) .then(aliStartClient) .then(function() { - let syncData = { + const syncData = { next_batch: '2', to_device: { events: [ - test_utils.mkEvent({ + testUtils.mkEvent({ content: { device_id: 'TEST_DEVICE', rooms: [], diff --git a/spec/integ/matrix-client-event-emitter.spec.js b/spec/integ/matrix-client-event-emitter.spec.js index 24741c29a..4f698b176 100644 --- a/spec/integ/matrix-client-event-emitter.spec.js +++ b/spec/integ/matrix-client-event-emitter.spec.js @@ -1,14 +1,14 @@ "use strict"; -let sdk = require("../.."); -let HttpBackend = require("../mock-request"); -let utils = require("../test-utils"); +const sdk = require("../.."); +const HttpBackend = require("../mock-request"); +const utils = require("../test-utils"); describe("MatrixClient events", function() { - let baseUrl = "http://localhost.or.something"; + const baseUrl = "http://localhost.or.something"; let client; let httpBackend; - let selfUserId = "@alice:localhost"; - let selfAccessToken = "aseukfgwef"; + const selfUserId = "@alice:localhost"; + const selfAccessToken = "aseukfgwef"; beforeEach(function() { utils.beforeEach(this); // eslint-disable-line no-invalid-this @@ -29,7 +29,7 @@ describe("MatrixClient events", function() { }); describe("emissions", function() { - let SYNC_DATA = { + const SYNC_DATA = { next_batch: "s_5_3", presence: { events: [ @@ -67,7 +67,7 @@ describe("MatrixClient events", function() { }, }, }; - let NEXT_SYNC_DATA = { + const NEXT_SYNC_DATA = { next_batch: "e_6_7", rooms: { join: { @@ -108,7 +108,7 @@ describe("MatrixClient events", function() { SYNC_DATA.rooms.join["!erufh:bar"].timeline.events, SYNC_DATA.rooms.join["!erufh:bar"].state.events, NEXT_SYNC_DATA.rooms.join["!erufh:bar"].timeline.events, - NEXT_SYNC_DATA.rooms.join["!erufh:bar"].ephemeral.events + NEXT_SYNC_DATA.rooms.join["!erufh:bar"].ephemeral.events, ); client.on("event", function(event) { @@ -121,7 +121,7 @@ describe("MatrixClient events", function() { } } expect(found).toBe( - true, "Unexpected 'event' emitted: " + event.getType() + true, "Unexpected 'event' emitted: " + event.getType(), ); }); @@ -129,7 +129,7 @@ describe("MatrixClient events", function() { httpBackend.flush().done(function() { expect(expectedEvents.length).toEqual( - 0, "Failed to see all events from /sync calls" + 0, "Failed to see all events from /sync calls", ); done(); }); @@ -149,7 +149,7 @@ describe("MatrixClient events", function() { expect(event.event).toEqual(SYNC_DATA.presence.events[0]); expect(user.presence).toEqual( - SYNC_DATA.presence.events[0].content.presence + SYNC_DATA.presence.events[0].content.presence, ); }); client.startClient(); @@ -182,13 +182,13 @@ describe("MatrixClient events", function() { httpBackend.flush().done(function() { expect(roomInvokeCount).toEqual( - 1, "Room fired wrong number of times." + 1, "Room fired wrong number of times.", ); expect(roomNameInvokeCount).toEqual( - 1, "Room.name fired wrong number of times." + 1, "Room.name fired wrong number of times.", ); expect(timelineFireCount).toEqual( - 3, "Room.timeline fired the wrong number of times" + 3, "Room.timeline fired the wrong number of times", ); done(); }); @@ -198,7 +198,7 @@ describe("MatrixClient events", function() { httpBackend.when("GET", "/sync").respond(200, SYNC_DATA); httpBackend.when("GET", "/sync").respond(200, NEXT_SYNC_DATA); - let roomStateEventTypes = [ + const roomStateEventTypes = [ "m.room.member", "m.room.create", ]; let eventsInvokeCount = 0; @@ -206,9 +206,9 @@ describe("MatrixClient events", function() { let newMemberInvokeCount = 0; client.on("RoomState.events", function(event, state) { eventsInvokeCount++; - let index = roomStateEventTypes.indexOf(event.getType()); + const index = roomStateEventTypes.indexOf(event.getType()); expect(index).not.toEqual( - -1, "Unexpected room state event type: " + event.getType() + -1, "Unexpected room state event type: " + event.getType(), ); if (index >= 0) { roomStateEventTypes.splice(index, 1); @@ -231,13 +231,13 @@ describe("MatrixClient events", function() { httpBackend.flush().done(function() { expect(membersInvokeCount).toEqual( - 1, "RoomState.members fired wrong number of times" + 1, "RoomState.members fired wrong number of times", ); expect(newMemberInvokeCount).toEqual( - 1, "RoomState.newMember fired wrong number of times" + 1, "RoomState.newMember fired wrong number of times", ); expect(eventsInvokeCount).toEqual( - 2, "RoomState.events fired wrong number of times" + 2, "RoomState.events fired wrong number of times", ); done(); }); @@ -270,16 +270,16 @@ describe("MatrixClient events", function() { httpBackend.flush().done(function() { expect(typingInvokeCount).toEqual( - 1, "RoomMember.typing fired wrong number of times" + 1, "RoomMember.typing fired wrong number of times", ); expect(powerLevelInvokeCount).toEqual( - 0, "RoomMember.powerLevel fired wrong number of times" + 0, "RoomMember.powerLevel fired wrong number of times", ); expect(nameInvokeCount).toEqual( - 0, "RoomMember.name fired wrong number of times" + 0, "RoomMember.name fired wrong number of times", ); expect(membershipInvokeCount).toEqual( - 1, "RoomMember.membership fired wrong number of times" + 1, "RoomMember.membership fired wrong number of times", ); done(); }); @@ -297,7 +297,7 @@ describe("MatrixClient events", function() { httpBackend.flush().done(function() { expect(sessionLoggedOutCount).toEqual( - 1, "Session.logged_out fired wrong number of times" + 1, "Session.logged_out fired wrong number of times", ); done(); }); diff --git a/spec/integ/matrix-client-event-timeline.spec.js b/spec/integ/matrix-client-event-timeline.spec.js index 27ccec94d..3291c9cfd 100644 --- a/spec/integ/matrix-client-event-timeline.spec.js +++ b/spec/integ/matrix-client-event-timeline.spec.js @@ -1,29 +1,29 @@ "use strict"; -let q = require("q"); -let sdk = require("../.."); -let HttpBackend = require("../mock-request"); -let utils = require("../test-utils"); -let EventTimeline = sdk.EventTimeline; +const q = require("q"); +const sdk = require("../.."); +const HttpBackend = require("../mock-request"); +const utils = require("../test-utils"); +const EventTimeline = sdk.EventTimeline; -let baseUrl = "http://localhost.or.something"; -let userId = "@alice:localhost"; -let userName = "Alice"; -let accessToken = "aseukfgwef"; -let roomId = "!foo:bar"; -let otherUserId = "@bob:localhost"; +const baseUrl = "http://localhost.or.something"; +const userId = "@alice:localhost"; +const userName = "Alice"; +const accessToken = "aseukfgwef"; +const roomId = "!foo:bar"; +const otherUserId = "@bob:localhost"; -let USER_MEMBERSHIP_EVENT = utils.mkMembership({ +const USER_MEMBERSHIP_EVENT = utils.mkMembership({ room: roomId, mship: "join", user: userId, name: userName, }); -let ROOM_NAME_EVENT = utils.mkEvent({ +const ROOM_NAME_EVENT = utils.mkEvent({ type: "m.room.name", room: roomId, user: otherUserId, content: { name: "Old room name", }, }); -let INITIAL_SYNC_DATA = { +const INITIAL_SYNC_DATA = { next_batch: "s_5_3", rooms: { join: { @@ -57,7 +57,7 @@ let INITIAL_SYNC_DATA = { }, }; -let EVENTS = [ +const EVENTS = [ utils.mkMessage({ room: roomId, user: userId, msg: "we", }), @@ -81,7 +81,7 @@ function startClient(httpBackend, client) { client.startClient(); // set up a promise which will resolve once the client is initialised - let deferred = q.defer(); + const deferred = q.defer(); client.on("sync", function(state) { console.log("sync", state); if (state != "SYNCING") { @@ -118,10 +118,10 @@ describe("getEventTimeline support", function() { accessToken: accessToken, }); - startClient(httpBackend, client + startClient(httpBackend, client, ).then(function() { - let room = client.getRoom(roomId); - let timelineSet = room.getTimelineSets()[0]; + const room = client.getRoom(roomId); + const timelineSet = room.getTimelineSets()[0]; expect(function() { client.getEventTimeline(timelineSet, "event"); }).toThrow(); @@ -136,10 +136,10 @@ describe("getEventTimeline support", function() { timelineSupport: true, }); - startClient(httpBackend, client + startClient(httpBackend, client, ).then(function() { - let room = client.getRoom(roomId); - let timelineSet = room.getTimelineSets()[0]; + const room = client.getRoom(roomId); + const timelineSet = room.getTimelineSets()[0]; expect(function() { client.getEventTimeline(timelineSet, "event"); }).not.toThrow(); @@ -159,7 +159,7 @@ describe("getEventTimeline support", function() { }); let room; - startClient(httpBackend, client + startClient(httpBackend, client, ).then(function() { room = client.getRoom(roomId); @@ -220,7 +220,8 @@ describe("getEventTimeline support", function() { }); describe("MatrixClient event timelines", function() { - let client, httpBackend; + let client = null; + let httpBackend = null; beforeEach(function(done) { utils.beforeEach(this); // eslint-disable-line no-invalid-this @@ -245,8 +246,8 @@ describe("MatrixClient event timelines", function() { describe("getEventTimeline", function() { it("should create a new timeline for new events", function(done) { - let room = client.getRoom(roomId); - let timelineSet = room.getTimelineSets()[0]; + const room = client.getRoom(roomId); + const timelineSet = room.getTimelineSets()[0]; httpBackend.when("GET", "/rooms/!foo%3Abar/context/event1%3Abar") .respond(200, function() { return { @@ -278,8 +279,8 @@ describe("MatrixClient event timelines", function() { }); it("should return existing timeline for known events", function(done) { - let room = client.getRoom(roomId); - let timelineSet = room.getTimelineSets()[0]; + const room = client.getRoom(roomId); + const timelineSet = room.getTimelineSets()[0]; httpBackend.when("GET", "/sync").respond(200, { next_batch: "s_5_4", rooms: { @@ -310,8 +311,8 @@ describe("MatrixClient event timelines", function() { }); it("should update timelines where they overlap a previous /sync", function(done) { - let room = client.getRoom(roomId); - let timelineSet = room.getTimelineSets()[0]; + const room = client.getRoom(roomId); + const timelineSet = room.getTimelineSets()[0]; httpBackend.when("GET", "/sync").respond(200, { next_batch: "s_5_4", rooms: { @@ -342,7 +343,7 @@ describe("MatrixClient event timelines", function() { }); client.on("sync", function() { - client.getEventTimeline(timelineSet, EVENTS[2].event_id + client.getEventTimeline(timelineSet, EVENTS[2].event_id, ).then(function(tl) { expect(tl.getEvents().length).toEqual(4); expect(tl.getEvents()[0].event).toEqual(EVENTS[1]); @@ -360,8 +361,8 @@ describe("MatrixClient event timelines", function() { it("should join timelines where they overlap a previous /context", function(done) { - let room = client.getRoom(roomId); - let timelineSet = room.getTimelineSets()[0]; + const room = client.getRoom(roomId); + const timelineSet = room.getTimelineSets()[0]; // we fetch event 0, then 2, then 3, and finally 1. 1 is returned // with context which joins them all up. @@ -417,8 +418,9 @@ describe("MatrixClient event timelines", function() { }; }); - let tl0, tl3; - client.getEventTimeline(timelineSet, EVENTS[0].event_id + let tl0; + let tl3; + client.getEventTimeline(timelineSet, EVENTS[0].event_id, ).then(function(tl) { expect(tl.getEvents().length).toEqual(1); tl0 = tl; @@ -453,8 +455,8 @@ describe("MatrixClient event timelines", function() { }); it("should fail gracefully if there is no event field", function(done) { - let room = client.getRoom(roomId); - let timelineSet = room.getTimelineSets()[0]; + const room = client.getRoom(roomId); + const timelineSet = room.getTimelineSets()[0]; // we fetch event 0, then 2, then 3, and finally 1. 1 is returned // with context which joins them all up. httpBackend.when("GET", "/rooms/!foo%3Abar/context/event1") @@ -468,7 +470,7 @@ describe("MatrixClient event timelines", function() { }; }); - client.getEventTimeline(timelineSet, "event1" + client.getEventTimeline(timelineSet, "event1", ).then(function(tl) { // could do with a fail() expect(true).toBeFalsy(); @@ -482,8 +484,8 @@ describe("MatrixClient event timelines", function() { describe("paginateEventTimeline", function() { it("should allow you to paginate backwards", function(done) { - let room = client.getRoom(roomId); - let timelineSet = room.getTimelineSets()[0]; + const room = client.getRoom(roomId); + const timelineSet = room.getTimelineSets()[0]; httpBackend.when("GET", "/rooms/!foo%3Abar/context/" + encodeURIComponent(EVENTS[0].event_id)) @@ -500,7 +502,7 @@ describe("MatrixClient event timelines", function() { httpBackend.when("GET", "/rooms/!foo%3Abar/messages") .check(function(req) { - let params = req.queryParams; + const params = req.queryParams; expect(params.dir).toEqual("b"); expect(params.from).toEqual("start_token0"); expect(params.limit).toEqual(30); @@ -512,7 +514,7 @@ describe("MatrixClient event timelines", function() { }); let tl; - client.getEventTimeline(timelineSet, EVENTS[0].event_id + client.getEventTimeline(timelineSet, EVENTS[0].event_id, ).then(function(tl0) { tl = tl0; return client.paginateEventTimeline(tl, {backwards: true}); @@ -533,8 +535,8 @@ describe("MatrixClient event timelines", function() { it("should allow you to paginate forwards", function(done) { - let room = client.getRoom(roomId); - let timelineSet = room.getTimelineSets()[0]; + const room = client.getRoom(roomId); + const timelineSet = room.getTimelineSets()[0]; httpBackend.when("GET", "/rooms/!foo%3Abar/context/" + encodeURIComponent(EVENTS[0].event_id)) @@ -551,7 +553,7 @@ describe("MatrixClient event timelines", function() { httpBackend.when("GET", "/rooms/!foo%3Abar/messages") .check(function(req) { - let params = req.queryParams; + const params = req.queryParams; expect(params.dir).toEqual("f"); expect(params.from).toEqual("end_token0"); expect(params.limit).toEqual(20); @@ -563,7 +565,7 @@ describe("MatrixClient event timelines", function() { }); let tl; - client.getEventTimeline(timelineSet, EVENTS[0].event_id + client.getEventTimeline(timelineSet, EVENTS[0].event_id, ).then(function(tl0) { tl = tl0; return client.paginateEventTimeline( @@ -585,8 +587,8 @@ describe("MatrixClient event timelines", function() { }); describe("event timeline for sent events", function() { - let TXN_ID = "txn1"; - let event = utils.mkMessage({ + const TXN_ID = "txn1"; + const event = utils.mkMessage({ room: roomId, user: userId, msg: "a body", }); event.unsigned = {transaction_id: TXN_ID}; @@ -616,8 +618,8 @@ describe("MatrixClient event timelines", function() { }); it("should work when /send returns before /sync", function(done) { - let room = client.getRoom(roomId); - let timelineSet = room.getTimelineSets()[0]; + const room = client.getRoom(roomId); + const timelineSet = room.getTimelineSets()[0]; client.sendTextMessage(roomId, "a body", TXN_ID).then(function(res) { expect(res.event_id).toEqual(event.event_id); @@ -640,8 +642,8 @@ describe("MatrixClient event timelines", function() { }); it("should work when /send returns after /sync", function(done) { - let room = client.getRoom(roomId); - let timelineSet = room.getTimelineSets()[0]; + const room = client.getRoom(roomId); + const timelineSet = room.getTimelineSets()[0]; // initiate the send, and set up checks to be done when it completes // - but note that it won't complete until after the /sync does, below. @@ -673,10 +675,10 @@ describe("MatrixClient event timelines", function() { // https://github.com/vector-im/vector-web/issues/1389 // a state event, followed by a redaction thereof - let event = utils.mkMembership({ + const event = utils.mkMembership({ room: roomId, mship: "join", user: otherUserId, }); - let redaction = utils.mkEvent({ + const redaction = utils.mkEvent({ type: "m.room.redaction", room_id: roomId, sender: otherUserId, @@ -684,7 +686,7 @@ describe("MatrixClient event timelines", function() { }); redaction.redacts = event.event_id; - let syncData = { + const syncData = { next_batch: "batch1", rooms: { join: {}, @@ -702,12 +704,12 @@ describe("MatrixClient event timelines", function() { httpBackend.when("GET", "/sync").respond(200, syncData); httpBackend.flush().then(function() { - let room = client.getRoom(roomId); - let tl = room.getLiveTimeline(); + const room = client.getRoom(roomId); + const tl = room.getLiveTimeline(); expect(tl.getEvents().length).toEqual(3); expect(tl.getEvents()[1].isRedacted()).toBe(true); - let sync2 = { + const sync2 = { next_batch: "batch2", rooms: { join: {}, @@ -728,8 +730,8 @@ describe("MatrixClient event timelines", function() { return httpBackend.flush(); }).then(function() { - let room = client.getRoom(roomId); - let tl = room.getLiveTimeline(); + const room = client.getRoom(roomId); + const tl = room.getLiveTimeline(); expect(tl.getEvents().length).toEqual(1); }).catch(utils.failTest).done(done); }); diff --git a/spec/integ/matrix-client-methods.spec.js b/spec/integ/matrix-client-methods.spec.js index 4d7a8d8a8..4acec1aa9 100644 --- a/spec/integ/matrix-client-methods.spec.js +++ b/spec/integ/matrix-client-methods.spec.js @@ -1,25 +1,28 @@ "use strict"; -let sdk = require("../.."); -let HttpBackend = require("../mock-request"); -let publicGlobals = require("../../lib/matrix"); -let Room = publicGlobals.Room; -let MatrixInMemoryStore = publicGlobals.MatrixInMemoryStore; -let Filter = publicGlobals.Filter; -let utils = require("../test-utils"); -let MockStorageApi = require("../MockStorageApi"); +const sdk = require("../.."); +const HttpBackend = require("../mock-request"); +const publicGlobals = require("../../lib/matrix"); +const Room = publicGlobals.Room; +const MatrixInMemoryStore = publicGlobals.MatrixInMemoryStore; +const Filter = publicGlobals.Filter; +const utils = require("../test-utils"); +const MockStorageApi = require("../MockStorageApi"); describe("MatrixClient", function() { - let baseUrl = "http://localhost.or.something"; - let client, httpBackend, store, sessionStore; - let userId = "@alice:localhost"; - let accessToken = "aseukfgwef"; + const baseUrl = "http://localhost.or.something"; + let client = null; + let httpBackend = null; + let store = null; + let sessionStore = null; + const userId = "@alice:localhost"; + const accessToken = "aseukfgwef"; beforeEach(function() { utils.beforeEach(this); // eslint-disable-line no-invalid-this httpBackend = new HttpBackend(); store = new MatrixInMemoryStore(); - let mockStorage = new MockStorageApi(); + const mockStorage = new MockStorageApi(); sessionStore = new sdk.WebStorageSessionStore(mockStorage); sdk.request(httpBackend.requestFn); @@ -38,10 +41,10 @@ describe("MatrixClient", function() { }); describe("uploadContent", function() { - let buf = new Buffer('hello world'); + const buf = new Buffer('hello world'); it("should upload the file", function(done) { httpBackend.when( - "POST", "/_matrix/media/v1/upload" + "POST", "/_matrix/media/v1/upload", ).check(function(req) { expect(req.data).toEqual(buf); expect(req.queryParams.filename).toEqual("hi.txt"); @@ -51,7 +54,7 @@ describe("MatrixClient", function() { expect(req.opts.timeout).toBe(undefined); }).respond(200, "content"); - let prom = client.uploadContent({ + const prom = client.uploadContent({ stream: buf, name: "hi.txt", type: "text/plain", @@ -59,7 +62,7 @@ describe("MatrixClient", function() { expect(prom).toBeDefined(); - let uploads = client.getCurrentUploads(); + const uploads = client.getCurrentUploads(); expect(uploads.length).toEqual(1); expect(uploads[0].promise).toBe(prom); expect(uploads[0].loaded).toEqual(0); @@ -68,7 +71,7 @@ describe("MatrixClient", function() { // for backwards compatibility, we return the raw JSON expect(response).toEqual("content"); - let uploads = client.getCurrentUploads(); + const uploads = client.getCurrentUploads(); expect(uploads.length).toEqual(0); }).catch(utils.failTest).done(done); @@ -77,7 +80,7 @@ describe("MatrixClient", function() { it("should parse the response if rawResponse=false", function(done) { httpBackend.when( - "POST", "/_matrix/media/v1/upload" + "POST", "/_matrix/media/v1/upload", ).check(function(req) { expect(req.opts.json).toBeFalsy(); }).respond(200, JSON.stringify({ "content_uri": "uri" })); @@ -98,7 +101,7 @@ describe("MatrixClient", function() { it("should parse errors into a MatrixError", function(done) { // opts.json is false, so request returns unparsed json. httpBackend.when( - "POST", "/_matrix/media/v1/upload" + "POST", "/_matrix/media/v1/upload", ).check(function(req) { expect(req.data).toEqual(buf); expect(req.opts.json).toBeFalsy(); @@ -123,13 +126,13 @@ describe("MatrixClient", function() { }); it("should return a promise which can be cancelled", function(done) { - let prom = client.uploadContent({ + const prom = client.uploadContent({ stream: buf, name: "hi.txt", type: "text/plain", }); - let uploads = client.getCurrentUploads(); + const uploads = client.getCurrentUploads(); expect(uploads.length).toEqual(1); expect(uploads[0].promise).toBe(prom); expect(uploads[0].loaded).toEqual(0); @@ -139,19 +142,19 @@ describe("MatrixClient", function() { }, function(error) { expect(error).toEqual("aborted"); - let uploads = client.getCurrentUploads(); + const uploads = client.getCurrentUploads(); expect(uploads.length).toEqual(0); }).catch(utils.failTest).done(done); - let r = client.cancelUpload(prom); + const r = client.cancelUpload(prom); expect(r).toBe(true); }); }); describe("joinRoom", function() { it("should no-op if you've already joined a room", function() { - let roomId = "!foo:bar"; - let room = new Room(roomId); + const roomId = "!foo:bar"; + const room = new Room(roomId); room.addLiveEvents([ utils.mkMembership({ user: userId, room: roomId, mship: "join", event: true, @@ -164,10 +167,10 @@ describe("MatrixClient", function() { }); describe("getFilter", function() { - let filterId = "f1lt3r1d"; + const filterId = "f1lt3r1d"; it("should return a filter from the store if allowCached", function(done) { - let filter = Filter.fromJson(userId, filterId, { + const filter = Filter.fromJson(userId, filterId, { event_format: "client", }); store.storeFilter(filter); @@ -180,15 +183,15 @@ describe("MatrixClient", function() { it("should do an HTTP request if !allowCached even if one exists", function(done) { - let httpFilterDefinition = { + const httpFilterDefinition = { event_format: "federation", }; httpBackend.when( - "GET", "/user/" + encodeURIComponent(userId) + "/filter/" + filterId + "GET", "/user/" + encodeURIComponent(userId) + "/filter/" + filterId, ).respond(200, httpFilterDefinition); - let storeFilter = Filter.fromJson(userId, filterId, { + const storeFilter = Filter.fromJson(userId, filterId, { event_format: "client", }); store.storeFilter(storeFilter); @@ -202,13 +205,13 @@ describe("MatrixClient", function() { it("should do an HTTP request if nothing is in the cache and then store it", function(done) { - let httpFilterDefinition = { + const httpFilterDefinition = { event_format: "federation", }; expect(store.getFilter(userId, filterId)).toBeNull(); httpBackend.when( - "GET", "/user/" + encodeURIComponent(userId) + "/filter/" + filterId + "GET", "/user/" + encodeURIComponent(userId) + "/filter/" + filterId, ).respond(200, httpFilterDefinition); client.getFilter(userId, filterId, true).done(function(gotFilter) { expect(gotFilter.getDefinition()).toEqual(httpFilterDefinition); @@ -221,17 +224,17 @@ describe("MatrixClient", function() { }); describe("createFilter", function() { - let filterId = "f1llllllerid"; + const filterId = "f1llllllerid"; it("should do an HTTP request and then store the filter", function(done) { expect(store.getFilter(userId, filterId)).toBeNull(); - let filterDefinition = { + const filterDefinition = { event_format: "client", }; httpBackend.when( - "POST", "/user/" + encodeURIComponent(userId) + "/filter" + "POST", "/user/" + encodeURIComponent(userId) + "/filter", ).check(function(req) { expect(req.data).toEqual(filterDefinition); }).respond(200, { @@ -249,7 +252,7 @@ describe("MatrixClient", function() { }); describe("searching", function() { - let response = { + const response = { search_categories: { room_events: { count: 24, @@ -294,9 +297,9 @@ describe("MatrixClient", function() { describe("downloadKeys", function() { it("should do an HTTP request and then store the keys", function(done) { - let ed25519key = "7wG2lzAqbjcyEkOP7O4gU7ItYcn+chKzh5sT/5r2l78"; + const ed25519key = "7wG2lzAqbjcyEkOP7O4gU7ItYcn+chKzh5sT/5r2l78"; // ed25519key = client.getDeviceEd25519Key(); - let borisKeys = { + const borisKeys = { dev1: { algorithms: ["1"], device_id: "dev1", @@ -312,7 +315,7 @@ describe("MatrixClient", function() { user_id: "boris", }, }; - let chazKeys = { + const chazKeys = { dev2: { algorithms: ["2"], device_id: "dev2", @@ -373,16 +376,16 @@ describe("MatrixClient", function() { }); describe("deleteDevice", function() { - let auth = {a: 1}; + const auth = {a: 1}; it("should pass through an auth dict", function(done) { httpBackend.when( - "DELETE", "/_matrix/client/unstable/devices/my_device" + "DELETE", "/_matrix/client/unstable/devices/my_device", ).check(function(req) { expect(req.data).toEqual({auth: auth}); }).respond(200); client.deleteDevice( - "my_device", auth + "my_device", auth, ).catch(utils.failTest).done(done); httpBackend.flush(); @@ -391,7 +394,7 @@ describe("MatrixClient", function() { }); function assertObjectContains(obj, expected) { - for (let k in expected) { + for (const k in expected) { if (expected.hasOwnProperty(k)) { expect(obj[k]).toEqual(expected[k]); } diff --git a/spec/integ/matrix-client-opts.spec.js b/spec/integ/matrix-client-opts.spec.js index 294dc2a43..710893e01 100644 --- a/spec/integ/matrix-client-opts.spec.js +++ b/spec/integ/matrix-client-opts.spec.js @@ -1,17 +1,18 @@ "use strict"; -let sdk = require("../.."); -let MatrixClient = sdk.MatrixClient; -let HttpBackend = require("../mock-request"); -let utils = require("../test-utils"); +const sdk = require("../.."); +const MatrixClient = sdk.MatrixClient; +const HttpBackend = require("../mock-request"); +const utils = require("../test-utils"); describe("MatrixClient opts", function() { - let baseUrl = "http://localhost.or.something"; - let client, httpBackend; - let userId = "@alice:localhost"; - let userB = "@bob:localhost"; - let accessToken = "aseukfgwef"; - let roomId = "!foo:bar"; - let syncData = { + const baseUrl = "http://localhost.or.something"; + let client = null; + let httpBackend = null; + const userId = "@alice:localhost"; + const userB = "@bob:localhost"; + const accessToken = "aseukfgwef"; + const roomId = "!foo:bar"; + const syncData = { next_batch: "s_5_3", presence: {}, rooms: { @@ -78,7 +79,7 @@ describe("MatrixClient opts", function() { }); it("should be able to send messages", function(done) { - let eventId = "$flibble:wibble"; + const eventId = "$flibble:wibble"; httpBackend.when("PUT", "/txn1").respond(200, { event_id: eventId, }); @@ -90,16 +91,16 @@ describe("MatrixClient opts", function() { }); it("should be able to sync / get new events", function(done) { - let expectedEventTypes = [ // from /initialSync + const expectedEventTypes = [ // from /initialSync "m.room.message", "m.room.name", "m.room.member", "m.room.member", "m.room.create", ]; client.on("event", function(event) { expect(expectedEventTypes.indexOf(event.getType())).not.toEqual( - -1, "Recv unexpected event type: " + event.getType() + -1, "Recv unexpected event type: " + event.getType(), ); expectedEventTypes.splice( - expectedEventTypes.indexOf(event.getType()), 1 + expectedEventTypes.indexOf(event.getType()), 1, ); }); httpBackend.when("GET", "/pushrules").respond(200, {}); @@ -112,7 +113,7 @@ describe("MatrixClient opts", function() { return httpBackend.flush("/sync", 1); }).done(function() { expect(expectedEventTypes.length).toEqual( - 0, "Expected to see event types: " + expectedEventTypes + 0, "Expected to see event types: " + expectedEventTypes, ); done(); }); diff --git a/spec/integ/matrix-client-retrying.spec.js b/spec/integ/matrix-client-retrying.spec.js index 642b944e7..4df7d422c 100644 --- a/spec/integ/matrix-client-retrying.spec.js +++ b/spec/integ/matrix-client-retrying.spec.js @@ -1,16 +1,17 @@ "use strict"; -let sdk = require("../.."); -let HttpBackend = require("../mock-request"); -let utils = require("../test-utils"); -let EventStatus = sdk.EventStatus; +const sdk = require("../.."); +const HttpBackend = require("../mock-request"); +const utils = require("../test-utils"); +const EventStatus = sdk.EventStatus; describe("MatrixClient retrying", function() { - let baseUrl = "http://localhost.or.something"; - let client, httpBackend; + const baseUrl = "http://localhost.or.something"; + let client = null; + let httpBackend = null; let scheduler; - let userId = "@alice:localhost"; - let accessToken = "aseukfgwef"; - let roomId = "!room:here"; + const userId = "@alice:localhost"; + const accessToken = "aseukfgwef"; + const roomId = "!room:here"; let room; beforeEach(function() { @@ -50,7 +51,6 @@ describe("MatrixClient retrying", function() { it("should mark events as EventStatus.CANCELLED when cancelled", function(done) { // send a couple of events; the second will be queued - let ev1, ev2; client.sendMessage(roomId, "m1").then(function(ev) { expect(ev).toEqual(ev1); }); @@ -59,10 +59,10 @@ describe("MatrixClient retrying", function() { }); // both events should be in the timeline at this point - let tl = room.getLiveTimeline().getEvents(); + const tl = room.getLiveTimeline().getEvents(); expect(tl.length).toEqual(2); - ev1 = tl[0]; - ev2 = tl[1]; + const ev1 = tl[0]; + const ev2 = tl[1]; expect(ev1.status).toEqual(EventStatus.SENDING); expect(ev2.status).toEqual(EventStatus.SENDING); diff --git a/spec/integ/matrix-client-room-timeline.spec.js b/spec/integ/matrix-client-room-timeline.spec.js index b1dc8bbf2..a3eff279a 100644 --- a/spec/integ/matrix-client-room-timeline.spec.js +++ b/spec/integ/matrix-client-room-timeline.spec.js @@ -1,28 +1,29 @@ "use strict"; -let sdk = require("../.."); -let EventStatus = sdk.EventStatus; -let HttpBackend = require("../mock-request"); -let utils = require("../test-utils"); +const sdk = require("../.."); +const EventStatus = sdk.EventStatus; +const HttpBackend = require("../mock-request"); +const utils = require("../test-utils"); describe("MatrixClient room timelines", function() { - let baseUrl = "http://localhost.or.something"; - let client, httpBackend; - let userId = "@alice:localhost"; - let userName = "Alice"; - let accessToken = "aseukfgwef"; - let roomId = "!foo:bar"; - let otherUserId = "@bob:localhost"; - let USER_MEMBERSHIP_EVENT = utils.mkMembership({ + const baseUrl = "http://localhost.or.something"; + let client = null; + let httpBackend = null; + const userId = "@alice:localhost"; + const userName = "Alice"; + const accessToken = "aseukfgwef"; + const roomId = "!foo:bar"; + const otherUserId = "@bob:localhost"; + const USER_MEMBERSHIP_EVENT = utils.mkMembership({ room: roomId, mship: "join", user: userId, name: userName, }); - let ROOM_NAME_EVENT = utils.mkEvent({ + const ROOM_NAME_EVENT = utils.mkEvent({ type: "m.room.name", room: roomId, user: otherUserId, content: { name: "Old room name", }, }); let NEXT_SYNC_DATA; - let SYNC_DATA = { + const SYNC_DATA = { next_batch: "s_5_3", rooms: { join: { @@ -81,7 +82,7 @@ describe("MatrixClient room timelines", function() { if (e.__prev_event === undefined) { throw new Error( "setNextSyncData needs the prev state set to '__prev_event' " + - "for " + e.type + "for " + e.type, ); } if (e.__prev_event !== null) { @@ -134,7 +135,7 @@ describe("MatrixClient room timelines", function() { if (state !== "PREPARED") { return; } - let room = client.getRoom(roomId); + const room = client.getRoom(roomId); expect(room.timeline.length).toEqual(1); client.sendTextMessage(roomId, "I am a fish", "txn1"); @@ -143,7 +144,7 @@ describe("MatrixClient room timelines", function() { // check status expect(room.timeline[1].status).toEqual(EventStatus.SENDING); // check member - let member = room.timeline[1].sender; + const member = room.timeline[1].sender; expect(member.userId).toEqual(userId); expect(member.name).toEqual(userName); @@ -156,12 +157,12 @@ describe("MatrixClient room timelines", function() { it("should be updated correctly when the send request finishes " + "BEFORE the event comes down the event stream", function(done) { - let eventId = "$foo:bar"; + const eventId = "$foo:bar"; httpBackend.when("PUT", "/txn1").respond(200, { event_id: eventId, }); - let ev = utils.mkMessage({ + const ev = utils.mkMessage({ body: "I am a fish", user: userId, room: roomId, }); ev.event_id = eventId; @@ -172,7 +173,7 @@ describe("MatrixClient room timelines", function() { if (state !== "PREPARED") { return; } - let room = client.getRoom(roomId); + const room = client.getRoom(roomId); client.sendTextMessage(roomId, "I am a fish", "txn1").done( function() { expect(room.timeline[1].getId()).toEqual(eventId); @@ -188,12 +189,12 @@ describe("MatrixClient room timelines", function() { it("should be updated correctly when the send request finishes " + "AFTER the event comes down the event stream", function(done) { - let eventId = "$foo:bar"; + const eventId = "$foo:bar"; httpBackend.when("PUT", "/txn1").respond(200, { event_id: eventId, }); - let ev = utils.mkMessage({ + const ev = utils.mkMessage({ body: "I am a fish", user: userId, room: roomId, }); ev.event_id = eventId; @@ -204,8 +205,8 @@ describe("MatrixClient room timelines", function() { if (state !== "PREPARED") { return; } - let room = client.getRoom(roomId); - let promise = client.sendTextMessage(roomId, "I am a fish", "txn1"); + const room = client.getRoom(roomId); + const promise = client.sendTextMessage(roomId, "I am a fish", "txn1"); httpBackend.flush("/sync", 1).done(function() { expect(room.timeline.length).toEqual(2); httpBackend.flush("/txn1", 1); @@ -222,7 +223,7 @@ describe("MatrixClient room timelines", function() { describe("paginated events", function() { let sbEvents; - let sbEndTok = "pagin_end"; + const sbEndTok = "pagin_end"; beforeEach(function() { sbEvents = []; @@ -241,7 +242,7 @@ describe("MatrixClient room timelines", function() { if (state !== "PREPARED") { return; } - let room = client.getRoom(roomId); + const room = client.getRoom(roomId); expect(room.timeline.length).toEqual(1); client.scrollback(room).done(function() { @@ -267,14 +268,14 @@ describe("MatrixClient room timelines", function() { // hello // make an m.room.member event for alice's join - let joinMshipEvent = utils.mkMembership({ + const joinMshipEvent = utils.mkMembership({ mship: "join", user: userId, room: roomId, name: "Old Alice", url: null, }); // make an m.room.member event with prev_content for alice's nick // change - let oldMshipEvent = utils.mkMembership({ + const oldMshipEvent = utils.mkMembership({ mship: "join", user: userId, room: roomId, name: userName, url: "mxc://some/url", }); @@ -301,17 +302,17 @@ describe("MatrixClient room timelines", function() { if (state !== "PREPARED") { return; } - let room = client.getRoom(roomId); + const room = client.getRoom(roomId); // sync response expect(room.timeline.length).toEqual(1); client.scrollback(room).done(function() { expect(room.timeline.length).toEqual(5); - let joinMsg = room.timeline[0]; + const joinMsg = room.timeline[0]; expect(joinMsg.sender.name).toEqual("Old Alice"); - let oldMsg = room.timeline[1]; + const oldMsg = room.timeline[1]; expect(oldMsg.sender.name).toEqual("Old Alice"); - let newMsg = room.timeline[3]; + const newMsg = room.timeline[3]; expect(newMsg.sender.name).toEqual(userName); done(); }); @@ -337,7 +338,7 @@ describe("MatrixClient room timelines", function() { if (state !== "PREPARED") { return; } - let room = client.getRoom(roomId); + const room = client.getRoom(roomId); expect(room.timeline.length).toEqual(1); client.scrollback(room).done(function() { @@ -365,7 +366,7 @@ describe("MatrixClient room timelines", function() { if (state !== "PREPARED") { return; } - let room = client.getRoom(roomId); + const room = client.getRoom(roomId); expect(room.oldState.paginationToken).toBeDefined(); client.scrollback(room, 1).done(function() { @@ -383,7 +384,7 @@ describe("MatrixClient room timelines", function() { describe("new events", function() { it("should be added to the right place in the timeline", function(done) { - let eventData = [ + const eventData = [ utils.mkMessage({user: userId, room: roomId}), utils.mkMessage({user: userId, room: roomId}), ]; @@ -393,7 +394,7 @@ describe("MatrixClient room timelines", function() { if (state !== "PREPARED") { return; } - let room = client.getRoom(roomId); + const room = client.getRoom(roomId); let index = 0; client.on("Room.timeline", function(event, rm, toStart) { @@ -408,10 +409,10 @@ describe("MatrixClient room timelines", function() { expect(index).toEqual(2); expect(room.timeline.length).toEqual(3); expect(room.timeline[2].event).toEqual( - eventData[1] + eventData[1], ); expect(room.timeline[1].event).toEqual( - eventData[0] + eventData[0], ); }).catch(utils.failTest).done(done); }); @@ -419,7 +420,7 @@ describe("MatrixClient room timelines", function() { }); it("should set the right event.sender values", function(done) { - let eventData = [ + const eventData = [ utils.mkMessage({user: userId, room: roomId}), utils.mkMembership({ user: userId, room: roomId, mship: "join", name: "New Name", @@ -433,10 +434,10 @@ describe("MatrixClient room timelines", function() { if (state !== "PREPARED") { return; } - let room = client.getRoom(roomId); + const room = client.getRoom(roomId); httpBackend.flush("/sync", 1).then(function() { - let preNameEvent = room.timeline[room.timeline.length - 3]; - let postNameEvent = room.timeline[room.timeline.length - 1]; + const preNameEvent = room.timeline[room.timeline.length - 3]; + const postNameEvent = room.timeline[room.timeline.length - 1]; expect(preNameEvent.sender.name).toEqual(userName); expect(postNameEvent.sender.name).toEqual("New Name"); }).catch(utils.failTest).done(done); @@ -445,7 +446,7 @@ describe("MatrixClient room timelines", function() { }); it("should set the right room.name", function(done) { - let secondRoomNameEvent = utils.mkEvent({ + const secondRoomNameEvent = utils.mkEvent({ user: userId, room: roomId, type: "m.room.name", content: { name: "Room 2", }, @@ -457,7 +458,7 @@ describe("MatrixClient room timelines", function() { if (state !== "PREPARED") { return; } - let room = client.getRoom(roomId); + const room = client.getRoom(roomId); let nameEmitCount = 0; client.on("Room.name", function(rm) { nameEmitCount += 1; @@ -467,7 +468,7 @@ describe("MatrixClient room timelines", function() { expect(nameEmitCount).toEqual(1); expect(room.name).toEqual("Room 2"); // do another round - let thirdRoomNameEvent = utils.mkEvent({ + const thirdRoomNameEvent = utils.mkEvent({ user: userId, room: roomId, type: "m.room.name", content: { name: "Room 3", }, @@ -486,9 +487,9 @@ describe("MatrixClient room timelines", function() { }); it("should set the right room members", function(done) { - let userC = "@cee:bar"; - let userD = "@dee:bar"; - let eventData = [ + const userC = "@cee:bar"; + const userD = "@dee:bar"; + const eventData = [ utils.mkMembership({ user: userC, room: roomId, mship: "join", name: "C", }), @@ -504,16 +505,16 @@ describe("MatrixClient room timelines", function() { if (state !== "PREPARED") { return; } - let room = client.getRoom(roomId); + const room = client.getRoom(roomId); httpBackend.flush("/sync", 1).then(function() { expect(room.currentState.getMembers().length).toEqual(4); expect(room.currentState.getMember(userC).name).toEqual("C"); expect(room.currentState.getMember(userC).membership).toEqual( - "join" + "join", ); expect(room.currentState.getMember(userD).name).toEqual(userD); expect(room.currentState.getMember(userD).membership).toEqual( - "invite" + "invite", ); }).catch(utils.failTest).done(done); }); @@ -523,7 +524,7 @@ describe("MatrixClient room timelines", function() { describe("gappy sync", function() { it("should copy the last known state to the new timeline", function(done) { - let eventData = [ + const eventData = [ utils.mkMessage({user: userId, room: roomId}), ]; setNextSyncData(eventData); @@ -533,7 +534,7 @@ describe("MatrixClient room timelines", function() { if (state !== "PREPARED") { return; } - let room = client.getRoom(roomId); + const room = client.getRoom(roomId); httpBackend.flush("/messages", 1); httpBackend.flush("/sync", 1).done(function() { @@ -542,11 +543,11 @@ describe("MatrixClient room timelines", function() { expect(room.currentState.getMembers().length).toEqual(2); expect(room.currentState.getMember(userId).name).toEqual(userName); expect(room.currentState.getMember(userId).membership).toEqual( - "join" + "join", ); expect(room.currentState.getMember(otherUserId).name).toEqual("Bob"); expect(room.currentState.getMember(otherUserId).membership).toEqual( - "join" + "join", ); done(); }); @@ -555,7 +556,7 @@ describe("MatrixClient room timelines", function() { }); it("should emit a 'Room.timelineReset' event", function(done) { - let eventData = [ + const eventData = [ utils.mkMessage({user: userId, room: roomId}), ]; setNextSyncData(eventData); @@ -565,7 +566,7 @@ describe("MatrixClient room timelines", function() { if (state !== "PREPARED") { return; } - let room = client.getRoom(roomId); + const room = client.getRoom(roomId); let emitCount = 0; client.on("Room.timelineReset", function(emitRoom) { diff --git a/spec/integ/matrix-client-syncing.spec.js b/spec/integ/matrix-client-syncing.spec.js index df2d0f42b..641c59b99 100644 --- a/spec/integ/matrix-client-syncing.spec.js +++ b/spec/integ/matrix-client-syncing.spec.js @@ -1,21 +1,22 @@ "use strict"; -let sdk = require("../.."); -let HttpBackend = require("../mock-request"); -let utils = require("../test-utils"); -let MatrixEvent = sdk.MatrixEvent; -let EventTimeline = sdk.EventTimeline; +const sdk = require("../.."); +const HttpBackend = require("../mock-request"); +const utils = require("../test-utils"); +const MatrixEvent = sdk.MatrixEvent; +const EventTimeline = sdk.EventTimeline; describe("MatrixClient syncing", function() { - let baseUrl = "http://localhost.or.something"; - let client, httpBackend; - let selfUserId = "@alice:localhost"; - let selfAccessToken = "aseukfgwef"; - let otherUserId = "@bob:localhost"; - let userA = "@alice:bar"; - let userB = "@bob:bar"; - let userC = "@claire:bar"; - let roomOne = "!foo:localhost"; - let roomTwo = "!bar:localhost"; + const baseUrl = "http://localhost.or.something"; + let client = null; + let httpBackend = null; + const selfUserId = "@alice:localhost"; + const selfAccessToken = "aseukfgwef"; + const otherUserId = "@bob:localhost"; + const userA = "@alice:bar"; + const userB = "@bob:bar"; + const userC = "@claire:bar"; + const roomOne = "!foo:localhost"; + const roomTwo = "!bar:localhost"; beforeEach(function() { utils.beforeEach(this); // eslint-disable-line no-invalid-this @@ -36,7 +37,7 @@ describe("MatrixClient syncing", function() { }); describe("startClient", function() { - let syncData = { + const syncData = { next_batch: "batch_token", rooms: {}, presence: {}, @@ -68,7 +69,7 @@ describe("MatrixClient syncing", function() { }); describe("resolving invites to profile info", function() { - let syncData = { + const syncData = { next_batch: "s_5_3", presence: { events: [], @@ -113,7 +114,7 @@ describe("MatrixClient syncing", function() { syncData.rooms.join[roomOne].state.events.push( utils.mkMembership({ room: roomOne, mship: "invite", user: userC, - }) + }), ); httpBackend.when("GET", "/sync").respond(200, syncData); @@ -121,7 +122,7 @@ describe("MatrixClient syncing", function() { 200, { avatar_url: "mxc://flibble/wibble", displayname: "The Boss", - } + }, ); client.startClient({ @@ -129,10 +130,10 @@ describe("MatrixClient syncing", function() { }); httpBackend.flush().done(function() { - let member = client.getRoom(roomOne).getMember(userC); + const member = client.getRoom(roomOne).getMember(userC); expect(member.name).toEqual("The Boss"); expect( - member.getAvatarUrl("home.server.url", null, null, null, false) + member.getAvatarUrl("home.server.url", null, null, null, false), ).toBeDefined(); done(); }); @@ -147,7 +148,7 @@ describe("MatrixClient syncing", function() { syncData.rooms.join[roomOne].state.events.push( utils.mkMembership({ room: roomOne, mship: "invite", user: userC, - }) + }), ); httpBackend.when("GET", "/sync").respond(200, syncData); @@ -157,7 +158,7 @@ describe("MatrixClient syncing", function() { }); httpBackend.flush().done(function() { - let member = client.getRoom(roomOne).getMember(userC); + const member = client.getRoom(roomOne).getMember(userC); expect(member.name).toEqual("The Ghost"); done(); }); @@ -172,7 +173,7 @@ describe("MatrixClient syncing", function() { syncData.rooms.join[roomOne].state.events.push( utils.mkMembership({ room: roomOne, mship: "invite", user: userC, - }) + }), ); httpBackend.when("GET", "/sync").respond(200, syncData); @@ -198,7 +199,7 @@ describe("MatrixClient syncing", function() { syncData.rooms.join[roomOne].state.events.push( utils.mkMembership({ room: roomOne, mship: "invite", user: userC, - }) + }), ); httpBackend.when("GET", "/sync").respond(200, syncData); @@ -206,10 +207,10 @@ describe("MatrixClient syncing", function() { client.startClient(); httpBackend.flush().done(function() { - let member = client.getRoom(roomOne).getMember(userC); + const member = client.getRoom(roomOne).getMember(userC); expect(member.name).toEqual(userC); expect( - member.getAvatarUrl("home.server.url", null, null, null, false) + member.getAvatarUrl("home.server.url", null, null, null, false), ).toBeNull(); done(); }); @@ -217,7 +218,7 @@ describe("MatrixClient syncing", function() { }); describe("users", function() { - let syncData = { + const syncData = { next_batch: "nb", presence: { events: [ @@ -246,10 +247,10 @@ describe("MatrixClient syncing", function() { }); describe("room state", function() { - let msgText = "some text here"; - let otherDisplayName = "Bob Smith"; + const msgText = "some text here"; + const otherDisplayName = "Bob Smith"; - let syncData = { + const syncData = { rooms: { join: { @@ -314,7 +315,7 @@ describe("MatrixClient syncing", function() { }, }; - let nextSyncData = { + const nextSyncData = { rooms: { join: { @@ -358,10 +359,10 @@ describe("MatrixClient syncing", function() { client.startClient(); httpBackend.flush().done(function() { - let room = client.getRoom(roomOne); + const room = client.getRoom(roomOne); // should have clobbered the name to the one from /events expect(room.name).toEqual( - nextSyncData.rooms.join[roomOne].state.events[0].content.name + nextSyncData.rooms.join[roomOne].state.events[0].content.name, ); done(); }); @@ -374,7 +375,7 @@ describe("MatrixClient syncing", function() { client.startClient(); httpBackend.flush().done(function() { - let room = client.getRoom(roomTwo); + const room = client.getRoom(roomTwo); // should have added the message from /events expect(room.timeline.length).toEqual(2); expect(room.timeline[1].getContent().body).toEqual(msgText); @@ -388,7 +389,7 @@ describe("MatrixClient syncing", function() { client.startClient(); httpBackend.flush().done(function() { - let room = client.getRoom(roomTwo); + const room = client.getRoom(roomTwo); // should use the display name of the other person. expect(room.name).toEqual(otherDisplayName); done(); @@ -402,7 +403,7 @@ describe("MatrixClient syncing", function() { client.startClient(); httpBackend.flush().done(function() { - let room = client.getRoom(roomTwo); + const room = client.getRoom(roomTwo); let member = room.getMember(otherUserId); expect(member).toBeDefined(); expect(member.typing).toEqual(true); @@ -424,7 +425,7 @@ describe("MatrixClient syncing", function() { describe("timeline", function() { beforeEach(function() { - let syncData = { + const syncData = { next_batch: "batch_token", rooms: { join: {}, @@ -448,7 +449,7 @@ describe("MatrixClient syncing", function() { }); it("should set the back-pagination token on new rooms", function(done) { - let syncData = { + const syncData = { next_batch: "batch_token", rooms: { join: {}, @@ -468,8 +469,8 @@ describe("MatrixClient syncing", function() { httpBackend.when("GET", "/sync").respond(200, syncData); httpBackend.flush().then(function() { - let room = client.getRoom(roomTwo); - let tok = room.getLiveTimeline() + const room = client.getRoom(roomTwo); + const tok = room.getLiveTimeline() .getPaginationToken(EventTimeline.BACKWARDS); expect(tok).toEqual("roomtwotok"); done(); @@ -477,7 +478,7 @@ describe("MatrixClient syncing", function() { }); it("should set the back-pagination token on gappy syncs", function(done) { - let syncData = { + const syncData = { next_batch: "batch_token", rooms: { join: {}, @@ -501,15 +502,15 @@ describe("MatrixClient syncing", function() { client.on("Room.timelineReset", function(room) { resetCallCount++; - let tl = room.getLiveTimeline(); + const tl = room.getLiveTimeline(); expect(tl.getEvents().length).toEqual(0); - let tok = tl.getPaginationToken(EventTimeline.BACKWARDS); + const tok = tl.getPaginationToken(EventTimeline.BACKWARDS); expect(tok).toEqual("newerTok"); }); httpBackend.flush().then(function() { - let room = client.getRoom(roomOne); - let tl = room.getLiveTimeline(); + const room = client.getRoom(roomOne); + const tl = room.getLiveTimeline(); expect(tl.getEvents().length).toEqual(1); expect(resetCallCount).toEqual(1); done(); @@ -518,7 +519,7 @@ describe("MatrixClient syncing", function() { }); describe("receipts", function() { - let syncData = { + const syncData = { rooms: { join: { @@ -567,8 +568,8 @@ describe("MatrixClient syncing", function() { }); it("should sync receipts from /sync.", function(done) { - let ackEvent = syncData.rooms.join[roomOne].timeline.events[0]; - let receipt = {}; + const ackEvent = syncData.rooms.join[roomOne].timeline.events[0]; + const receipt = {}; receipt[ackEvent.event_id] = { "m.read": {}, }; @@ -585,7 +586,7 @@ describe("MatrixClient syncing", function() { client.startClient(); httpBackend.flush().done(function() { - let room = client.getRoom(roomOne); + const room = client.getRoom(roomOne); expect(room.getReceiptsForEvent(new MatrixEvent(ackEvent))).toEqual([{ type: "m.read", userId: userC, @@ -646,7 +647,7 @@ describe("MatrixClient syncing", function() { }); it("should set the back-pagination token on left rooms", function(done) { - let syncData = { + const syncData = { next_batch: "batch_token", rooms: { leave: {}, @@ -671,8 +672,8 @@ describe("MatrixClient syncing", function() { httpBackend.when("GET", "/sync").respond(200, syncData); client.syncLeftRooms().then(function() { - let room = client.getRoom(roomTwo); - let tok = room.getLiveTimeline().getPaginationToken( + const room = client.getRoom(roomTwo); + const tok = room.getLiveTimeline().getPaginationToken( EventTimeline.BACKWARDS); expect(tok).toEqual("pagTok"); diff --git a/spec/integ/megolm.spec.js b/spec/integ/megolm.spec.js index c4531765c..662599cde 100644 --- a/spec/integ/megolm.spec.js +++ b/spec/integ/megolm.spec.js @@ -17,19 +17,20 @@ limitations under the License. "use strict"; +let Olm = null; try { - var Olm = require('olm'); + Olm = require('olm'); } catch (e) {} -let anotherjson = require('another-json'); -let q = require('q'); +const anotherjson = require('another-json'); +const q = require('q'); -let sdk = require('../..'); -let utils = require('../../lib/utils'); -let test_utils = require('../test-utils'); -let MockHttpBackend = require('../mock-request'); +const sdk = require('../..'); +const utils = require('../../lib/utils'); +const testUtils = require('../test-utils'); +const MockHttpBackend = require('../mock-request'); -let ROOM_ID = "!room:id"; +const ROOM_ID = "!room:id"; /** * Wrapper for a MockStorageApi, MockHttpBackend and MatrixClient @@ -43,7 +44,7 @@ function TestClient(userId, deviceId, accessToken) { this.userId = userId; this.deviceId = deviceId; - this.storage = new sdk.WebStorageSessionStore(new test_utils.MockStorageApi()); + this.storage = new sdk.WebStorageSessionStore(new testUtils.MockStorageApi()); this.httpBackend = new MockHttpBackend(); this.client = sdk.createClient({ baseUrl: "http://test.server", @@ -66,7 +67,7 @@ function TestClient(userId, deviceId, accessToken) { * @return {Promise} */ TestClient.prototype.start = function(existingDevices) { - let self = this; + const self = this; this.httpBackend.when("GET", "/pushrules").respond(200, {}); this.httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" }); @@ -114,8 +115,8 @@ TestClient.prototype.stop = function() { * @return {string} base64 device key */ TestClient.prototype.getDeviceKey = function() { - let key_id = 'curve25519:' + this.deviceId; - return this.deviceKeys.keys[key_id]; + const keyId = 'curve25519:' + this.deviceId; + return this.deviceKeys.keys[keyId]; }; @@ -125,8 +126,8 @@ TestClient.prototype.getDeviceKey = function() { * @return {string} base64 device key */ TestClient.prototype.getSigningKey = function() { - let key_id = 'ed25519:' + this.deviceId; - return this.deviceKeys.keys[key_id]; + const keyId = 'ed25519:' + this.deviceId; + return this.deviceKeys.keys[keyId]; }; /** @@ -137,12 +138,12 @@ TestClient.prototype.getSigningKey = function() { * @return {Olm.Session} */ function createOlmSession(olmAccount, recipientTestClient) { - let otk_id = utils.keys(recipientTestClient.oneTimeKeys)[0]; - let otk = recipientTestClient.oneTimeKeys[otk_id]; + const otkId = utils.keys(recipientTestClient.oneTimeKeys)[0]; + const otk = recipientTestClient.oneTimeKeys[otkId]; - let session = new Olm.Session(); + const session = new Olm.Session(); session.create_outbound( - olmAccount, recipientTestClient.getDeviceKey(), otk.key + olmAccount, recipientTestClient.getDeviceKey(), otk.key, ); return session; } @@ -165,7 +166,7 @@ function encryptOlmEvent(opts) { expect(opts.p2pSession).toBeDefined(); expect(opts.recipient).toBeDefined(); - let plaintext = { + const plaintext = { content: opts.plaincontent || {}, recipient: opts.recipient.userId, recipient_keys: { @@ -175,7 +176,7 @@ function encryptOlmEvent(opts) { type: opts.plaintype || 'm.test', }; - let event = { + const event = { content: { algorithm: 'm.olm.v1.curve25519-aes-sha2', ciphertext: {}, @@ -204,7 +205,7 @@ function encryptMegolmEvent(opts) { expect(opts.senderKey).toBeDefined(); expect(opts.groupSession).toBeDefined(); - let plaintext = opts.plaintext || {}; + const plaintext = opts.plaintext || {}; if (!plaintext.content) { plaintext.content = { body: '42', @@ -267,10 +268,10 @@ function encryptGroupSessionKey(opts) { * @return {object} event */ function getSyncResponse(roomMembers) { - let roomResponse = { + const roomResponse = { state: { events: [ - test_utils.mkEvent({ + testUtils.mkEvent({ type: 'm.room.encryption', skey: '', content: { @@ -283,14 +284,14 @@ function getSyncResponse(roomMembers) { for (let i = 0; i < roomMembers.length; i++) { roomResponse.state.events.push( - test_utils.mkMembership({ + testUtils.mkMembership({ mship: 'join', sender: roomMembers[i], - }) + }), ); } - let syncResponse = { + const syncResponse = { next_batch: 1, rooms: { join: {}, @@ -318,8 +319,8 @@ describe("megolm", function() { * @returns {Object} The fake query response */ function getTestKeysQueryResponse(userId) { - let testE2eKeys = JSON.parse(testOlmAccount.identity_keys()); - let testDeviceKeys = { + const testE2eKeys = JSON.parse(testOlmAccount.identity_keys()); + const testDeviceKeys = { algorithms: ['m.olm.v1.curve25519-aes-sha2', 'm.megolm.v1.aes-sha2'], device_id: 'DEVICE_ID', keys: { @@ -328,14 +329,14 @@ describe("megolm", function() { }, user_id: userId, }; - let j = anotherjson.stringify(testDeviceKeys); - let sig = testOlmAccount.sign(j); + const j = anotherjson.stringify(testDeviceKeys); + const sig = testOlmAccount.sign(j); testDeviceKeys.signatures = {}; testDeviceKeys.signatures[userId] = { 'ed25519:DEVICE_ID': sig, }; - let queryResponse = { + const queryResponse = { device_keys: {}, }; @@ -355,22 +356,22 @@ describe("megolm", function() { */ function getTestKeysClaimResponse(userId) { testOlmAccount.generate_one_time_keys(1); - let testOneTimeKeys = JSON.parse(testOlmAccount.one_time_keys()); + const testOneTimeKeys = JSON.parse(testOlmAccount.one_time_keys()); testOlmAccount.mark_keys_as_published(); - let keyId = utils.keys(testOneTimeKeys.curve25519)[0]; - let oneTimeKey = testOneTimeKeys.curve25519[keyId]; - let keyResult = { + const keyId = utils.keys(testOneTimeKeys.curve25519)[0]; + const oneTimeKey = testOneTimeKeys.curve25519[keyId]; + const keyResult = { 'key': oneTimeKey, }; - let j = anotherjson.stringify(keyResult); - let sig = testOlmAccount.sign(j); + const j = anotherjson.stringify(keyResult); + const sig = testOlmAccount.sign(j); keyResult.signatures = {}; keyResult.signatures[userId] = { 'ed25519:DEVICE_ID': sig, }; - let claimResponse = {one_time_keys: {}}; + const claimResponse = {one_time_keys: {}}; claimResponse.one_time_keys[userId] = { 'DEVICE_ID': {}, }; @@ -380,15 +381,15 @@ describe("megolm", function() { } beforeEach(function() { - test_utils.beforeEach(this); // eslint-disable-line no-invalid-this + testUtils.beforeEach(this); // eslint-disable-line no-invalid-this aliceTestClient = new TestClient( - "@alice:localhost", "xzcvb", "akjgkrgjs" + "@alice:localhost", "xzcvb", "akjgkrgjs", ); testOlmAccount = new Olm.Account(); testOlmAccount.create(); - let testE2eKeys = JSON.parse(testOlmAccount.identity_keys()); + const testE2eKeys = JSON.parse(testOlmAccount.identity_keys()); testSenderKey = testE2eKeys.curve25519; }); @@ -398,13 +399,13 @@ describe("megolm", function() { it("Alice receives a megolm message", function(done) { return aliceTestClient.start().then(function() { - let p2pSession = createOlmSession(testOlmAccount, aliceTestClient); + const p2pSession = createOlmSession(testOlmAccount, aliceTestClient); - let groupSession = new Olm.OutboundGroupSession(); + const groupSession = new Olm.OutboundGroupSession(); groupSession.create(); // make the room_key event - let roomKeyEncrypted = encryptGroupSessionKey({ + const roomKeyEncrypted = encryptGroupSessionKey({ senderKey: testSenderKey, recipient: aliceTestClient, p2pSession: p2pSession, @@ -413,14 +414,14 @@ describe("megolm", function() { }); // encrypt a message with the group session - let messageEncrypted = encryptMegolmEvent({ + const messageEncrypted = encryptMegolmEvent({ senderKey: testSenderKey, groupSession: groupSession, room_id: ROOM_ID, }); // Alice gets both the events in a single sync - let syncResponse = { + const syncResponse = { next_batch: 1, to_device: { events: [roomKeyEncrypted], @@ -438,21 +439,21 @@ describe("megolm", function() { aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse); return aliceTestClient.httpBackend.flush("/sync", 1); }).then(function() { - let room = aliceTestClient.client.getRoom(ROOM_ID); - let event = room.getLiveTimeline().getEvents()[0]; + const room = aliceTestClient.client.getRoom(ROOM_ID); + const event = room.getLiveTimeline().getEvents()[0]; expect(event.getContent().body).toEqual('42'); }).nodeify(done); }); it("Alice gets a second room_key message", function(done) { return aliceTestClient.start().then(function() { - let p2pSession = createOlmSession(testOlmAccount, aliceTestClient); + const p2pSession = createOlmSession(testOlmAccount, aliceTestClient); - let groupSession = new Olm.OutboundGroupSession(); + const groupSession = new Olm.OutboundGroupSession(); groupSession.create(); // make the room_key event - let roomKeyEncrypted1 = encryptGroupSessionKey({ + const roomKeyEncrypted1 = encryptGroupSessionKey({ senderKey: testSenderKey, recipient: aliceTestClient, p2pSession: p2pSession, @@ -461,7 +462,7 @@ describe("megolm", function() { }); // encrypt a message with the group session - let messageEncrypted = encryptMegolmEvent({ + const messageEncrypted = encryptMegolmEvent({ senderKey: testSenderKey, groupSession: groupSession, room_id: ROOM_ID, @@ -469,7 +470,7 @@ describe("megolm", function() { // make a second room_key event now that we have advanced the group // session. - let roomKeyEncrypted2 = encryptGroupSessionKey({ + const roomKeyEncrypted2 = encryptGroupSessionKey({ senderKey: testSenderKey, recipient: aliceTestClient, p2pSession: p2pSession, @@ -488,7 +489,7 @@ describe("megolm", function() { // on the second sync, send the advanced room key, along with the // message. This simulates the situation where Alice has been sent a // later copy of the room key and is reloading the client. - let syncResponse2 = { + const syncResponse2 = { next_batch: 2, to_device: { events: [roomKeyEncrypted2], @@ -506,8 +507,8 @@ describe("megolm", function() { return aliceTestClient.httpBackend.flush("/sync", 2); }).then(function() { - let room = aliceTestClient.client.getRoom(ROOM_ID); - let event = room.getLiveTimeline().getEvents()[0]; + const room = aliceTestClient.client.getRoom(ROOM_ID); + const event = room.getLiveTimeline().getEvents()[0]; expect(event.getContent().body).toEqual('42'); }).nodeify(done); }); @@ -516,12 +517,12 @@ describe("megolm", function() { let p2pSession; return aliceTestClient.start().then(function() { - let syncResponse = getSyncResponse(['@bob:xyz']); + const syncResponse = getSyncResponse(['@bob:xyz']); // establish an olm session with alice p2pSession = createOlmSession(testOlmAccount, aliceTestClient); - let olmEvent = encryptOlmEvent({ + const olmEvent = encryptOlmEvent({ senderKey: testSenderKey, recipient: aliceTestClient, p2pSession: p2pSession, @@ -534,15 +535,15 @@ describe("megolm", function() { }).then(function() { let inboundGroupSession; aliceTestClient.httpBackend.when('POST', '/keys/query').respond( - 200, getTestKeysQueryResponse('@bob:xyz') + 200, getTestKeysQueryResponse('@bob:xyz'), ); aliceTestClient.httpBackend.when( - 'PUT', '/sendToDevice/m.room.encrypted/' + 'PUT', '/sendToDevice/m.room.encrypted/', ).respond(200, function(path, content) { - let m = content.messages['@bob:xyz'].DEVICE_ID; - let ct = m.ciphertext[testSenderKey]; - let decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body)); + const m = content.messages['@bob:xyz'].DEVICE_ID; + const ct = m.ciphertext[testSenderKey]; + const decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body)); expect(decrypted.type).toEqual('m.room_key'); inboundGroupSession = new Olm.InboundGroupSession(); @@ -551,14 +552,14 @@ describe("megolm", function() { }); aliceTestClient.httpBackend.when( - 'PUT', '/send/' + 'PUT', '/send/', ).respond(200, function(path, content) { - let ct = content.ciphertext; - let r = inboundGroupSession.decrypt(ct); + const ct = content.ciphertext; + const r = inboundGroupSession.decrypt(ct); console.log('Decrypted received megolm message', r); expect(r.message_index).toEqual(0); - let decrypted = JSON.parse(r.plaintext); + const decrypted = JSON.parse(r.plaintext); expect(decrypted.type).toEqual('m.room.message'); expect(decrypted.content.body).toEqual('test'); @@ -576,7 +577,7 @@ describe("megolm", function() { it("Alice shouldn't do a second /query for non-e2e-capable devices", function(done) { return aliceTestClient.start().then(function() { - let syncResponse = getSyncResponse(['@bob:xyz']); + const syncResponse = getSyncResponse(['@bob:xyz']); aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse); return aliceTestClient.httpBackend.flush('/sync', 1); @@ -597,7 +598,7 @@ describe("megolm", function() { console.log("Telling alice to send a megolm message"); aliceTestClient.httpBackend.when( - 'PUT', '/send/' + 'PUT', '/send/', ).respond(200, { event_id: '$event_id', }); @@ -612,12 +613,12 @@ describe("megolm", function() { it("We shouldn't attempt to send to blocked devices", function(done) { return aliceTestClient.start().then(function() { - let syncResponse = getSyncResponse(['@bob:xyz']); + const syncResponse = getSyncResponse(['@bob:xyz']); // establish an olm session with alice - let p2pSession = createOlmSession(testOlmAccount, aliceTestClient); + const p2pSession = createOlmSession(testOlmAccount, aliceTestClient); - let olmEvent = encryptOlmEvent({ + const olmEvent = encryptOlmEvent({ senderKey: testSenderKey, recipient: aliceTestClient, p2pSession: p2pSession, @@ -631,7 +632,7 @@ describe("megolm", function() { console.log('Forcing alice to download our device keys'); aliceTestClient.httpBackend.when('POST', '/keys/query').respond( - 200, getTestKeysQueryResponse('@bob:xyz') + 200, getTestKeysQueryResponse('@bob:xyz'), ); return q.all([ @@ -644,7 +645,7 @@ describe("megolm", function() { console.log('Telling alice to send a megolm message'); aliceTestClient.httpBackend.when( - 'PUT', '/send/' + 'PUT', '/send/', ).respond(200, { event_id: '$event_id', }); @@ -661,12 +662,12 @@ describe("megolm", function() { let megolmSessionId; return aliceTestClient.start().then(function() { - let syncResponse = getSyncResponse(['@bob:xyz']); + const syncResponse = getSyncResponse(['@bob:xyz']); // establish an olm session with alice p2pSession = createOlmSession(testOlmAccount, aliceTestClient); - let olmEvent = encryptOlmEvent({ + const olmEvent = encryptOlmEvent({ senderKey: testSenderKey, recipient: aliceTestClient, p2pSession: p2pSession, @@ -680,17 +681,17 @@ describe("megolm", function() { console.log('Telling alice to send a megolm message'); aliceTestClient.httpBackend.when('POST', '/keys/query').respond( - 200, getTestKeysQueryResponse('@bob:xyz') + 200, getTestKeysQueryResponse('@bob:xyz'), ); aliceTestClient.httpBackend.when( - 'PUT', '/sendToDevice/m.room.encrypted/' + 'PUT', '/sendToDevice/m.room.encrypted/', ).respond(200, function(path, content) { console.log('sendToDevice: ', content); - let m = content.messages['@bob:xyz'].DEVICE_ID; - let ct = m.ciphertext[testSenderKey]; + const m = content.messages['@bob:xyz'].DEVICE_ID; + const ct = m.ciphertext[testSenderKey]; expect(ct.type).toEqual(1); // normal message - let decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body)); + const decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body)); console.log('decrypted sendToDevice:', decrypted); expect(decrypted.type).toEqual('m.room_key'); megolmSessionId = decrypted.content.session_id; @@ -698,7 +699,7 @@ describe("megolm", function() { }); aliceTestClient.httpBackend.when( - 'PUT', '/send/' + 'PUT', '/send/', ).respond(200, function(path, content) { console.log('/send:', content); expect(content.session_id).toEqual(megolmSessionId); @@ -717,7 +718,7 @@ describe("megolm", function() { console.log('Telling alice to send another megolm message'); aliceTestClient.httpBackend.when( - 'PUT', '/send/' + 'PUT', '/send/', ).respond(200, function(path, content) { console.log('/send:', content); expect(content.session_id).not.toEqual(megolmSessionId); @@ -743,10 +744,10 @@ describe("megolm", function() { let decrypted; return aliceTestClient.start( - getTestKeysQueryResponse(aliceTestClient.userId) + getTestKeysQueryResponse(aliceTestClient.userId), ).then(function() { // an encrypted room with just alice - let syncResponse = { + const syncResponse = { next_batch: 1, rooms: { join: {}, @@ -755,14 +756,14 @@ describe("megolm", function() { syncResponse.rooms.join[ROOM_ID] = { state: { events: [ - test_utils.mkEvent({ + testUtils.mkEvent({ type: 'm.room.encryption', skey: '', content: { algorithm: 'm.megolm.v1.aes-sha2', }, }), - test_utils.mkMembership({ + testUtils.mkMembership({ mship: 'join', sender: aliceTestClient.userId, }), @@ -781,16 +782,16 @@ describe("megolm", function() { }); aliceTestClient.httpBackend.when( - 'PUT', '/sendToDevice/m.room.encrypted/' + 'PUT', '/sendToDevice/m.room.encrypted/', ).respond(200, function(path, content) { console.log("sendToDevice: ", content); - let m = content.messages[aliceTestClient.userId].DEVICE_ID; - let ct = m.ciphertext[testSenderKey]; + const m = content.messages[aliceTestClient.userId].DEVICE_ID; + const ct = m.ciphertext[testSenderKey]; expect(ct.type).toEqual(0); // pre-key message p2pSession = new Olm.Session(); p2pSession.create_inbound(testOlmAccount, ct.body); - let decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body)); + const decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body)); expect(decrypted.type).toEqual('m.room_key'); inboundGroupSession = new Olm.InboundGroupSession(); @@ -799,10 +800,10 @@ describe("megolm", function() { }); aliceTestClient.httpBackend.when( - 'PUT', '/send/' + 'PUT', '/send/', ).respond(200, function(path, content) { - let ct = content.ciphertext; - let r = inboundGroupSession.decrypt(ct); + const ct = content.ciphertext; + const r = inboundGroupSession.decrypt(ct); console.log('Decrypted received megolm message', r); decrypted = JSON.parse(r.plaintext); @@ -831,11 +832,11 @@ describe("megolm", function() { let sendPromise; aliceTestClient.httpBackend.when( - 'PUT', '/sendToDevice/m.room.encrypted/' + 'PUT', '/sendToDevice/m.room.encrypted/', ).respond(200, function(path, content) { - let m = content.messages['@bob:xyz'].DEVICE_ID; - let ct = m.ciphertext[testSenderKey]; - let decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body)); + const m = content.messages['@bob:xyz'].DEVICE_ID; + const ct = m.ciphertext[testSenderKey]; + const decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body)); expect(decrypted.type).toEqual('m.room_key'); inboundGroupSession = new Olm.InboundGroupSession(); @@ -844,14 +845,14 @@ describe("megolm", function() { }); aliceTestClient.httpBackend.when( - 'PUT', '/send/' + 'PUT', '/send/', ).respond(200, function(path, content) { - let ct = content.ciphertext; - let r = inboundGroupSession.decrypt(ct); + const ct = content.ciphertext; + const r = inboundGroupSession.decrypt(ct); console.log('Decrypted received megolm message', r); expect(r.message_index).toEqual(0); - let decrypted = JSON.parse(r.plaintext); + const decrypted = JSON.parse(r.plaintext); expect(decrypted.type).toEqual('m.room.message'); expect(decrypted.content.body).toEqual('test'); @@ -861,12 +862,12 @@ describe("megolm", function() { }); return aliceTestClient.start().then(function() { - let syncResponse = getSyncResponse(['@bob:xyz']); + const syncResponse = getSyncResponse(['@bob:xyz']); // establish an olm session with alice p2pSession = createOlmSession(testOlmAccount, aliceTestClient); - let olmEvent = encryptOlmEvent({ + const olmEvent = encryptOlmEvent({ senderKey: testSenderKey, recipient: aliceTestClient, p2pSession: p2pSession, @@ -886,7 +887,7 @@ describe("megolm", function() { sendPromise = aliceTestClient.client.sendTextMessage(ROOM_ID, 'test'); }).then(function() { aliceTestClient.httpBackend.when('POST', '/keys/query').respond( - 200, getTestKeysQueryResponse('@bob:xyz') + 200, getTestKeysQueryResponse('@bob:xyz'), ); return aliceTestClient.httpBackend.flush(); @@ -894,4 +895,89 @@ describe("megolm", function() { return q.all([downloadPromise, sendPromise]); }).nodeify(done); }); + + + it("Alice exports megolm keys and imports them to a new device", function(done) { + let messageEncrypted; + + return aliceTestClient.start().then(() => { + const p2pSession = createOlmSession( + testOlmAccount, aliceTestClient, + ); + + const groupSession = new Olm.OutboundGroupSession(); + groupSession.create(); + + // make the room_key event + const roomKeyEncrypted = encryptGroupSessionKey({ + senderKey: testSenderKey, + recipient: aliceTestClient, + p2pSession: p2pSession, + groupSession: groupSession, + room_id: ROOM_ID, + }); + + // encrypt a message with the group session + messageEncrypted = encryptMegolmEvent({ + senderKey: testSenderKey, + groupSession: groupSession, + room_id: ROOM_ID, + }); + + // Alice gets both the events in a single sync + const syncResponse = { + next_batch: 1, + to_device: { + events: [roomKeyEncrypted], + }, + rooms: { + join: {}, + }, + }; + syncResponse.rooms.join[ROOM_ID] = { + timeline: { + events: [messageEncrypted], + }, + }; + + aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse); + return aliceTestClient.httpBackend.flush("/sync", 1); + }).then(function() { + const room = aliceTestClient.client.getRoom(ROOM_ID); + const event = room.getLiveTimeline().getEvents()[0]; + expect(event.getContent().body).toEqual('42'); + + return aliceTestClient.client.exportRoomKeys(); + }).then(function(exported) { + // start a new client + aliceTestClient.stop(); + + aliceTestClient = new TestClient( + "@alice:localhost", "device2", "access_token2", + ); + + aliceTestClient.client.importRoomKeys(exported); + + return aliceTestClient.start(); + }).then(function() { + const syncResponse = { + next_batch: 1, + rooms: { + join: {}, + }, + }; + syncResponse.rooms.join[ROOM_ID] = { + timeline: { + events: [messageEncrypted], + }, + }; + + aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse); + return aliceTestClient.httpBackend.flush("/sync", 1); + }).then(function() { + const room = aliceTestClient.client.getRoom(ROOM_ID); + const event = room.getLiveTimeline().getEvents()[0]; + expect(event.getContent().body).toEqual('42'); + }).nodeify(done); + }); }); diff --git a/spec/mock-request.js b/spec/mock-request.js index 99df7e91c..8b64131a8 100644 --- a/spec/mock-request.js +++ b/spec/mock-request.js @@ -1,5 +1,5 @@ "use strict"; -let q = require("q"); +const q = require("q"); /** * Construct a mock HTTP backend, heavily inspired by Angular.js. @@ -8,15 +8,15 @@ let q = require("q"); function HttpBackend() { this.requests = []; this.expectedRequests = []; - let self = this; + const self = this; // the request function dependency that the SDK needs. this.requestFn = function(opts, callback) { - let req = new Request(opts, callback); + const req = new Request(opts, callback); console.log("HTTP backend received request: %s", req); self.requests.push(req); - let abort = function() { - let idx = self.requests.indexOf(req); + const abort = function() { + const idx = self.requests.indexOf(req); if (idx >= 0) { console.log("Aborting HTTP request: %s %s", opts.method, opts.uri); @@ -38,18 +38,18 @@ HttpBackend.prototype = { * @return {Promise} resolved when there is nothing left to flush. */ flush: function(path, numToFlush) { - let defer = q.defer(); - let self = this; + const defer = q.defer(); + const self = this; let flushed = 0; let triedWaiting = false; console.log( - "HTTP backend flushing... (path=%s numToFlush=%s)", path, numToFlush + "HTTP backend flushing... (path=%s numToFlush=%s)", path, numToFlush, ); - let tryFlush = function() { + const tryFlush = function() { // if there's more real requests and more expected requests, flush 'em. console.log( " trying to flush queue => reqs=%s expected=%s [%s]", - self.requests.length, self.expectedRequests.length, path + self.requests.length, self.expectedRequests.length, path, ); if (self._takeFromQueue(path)) { // try again on the next tick. @@ -84,8 +84,11 @@ HttpBackend.prototype = { */ _takeFromQueue: function(path) { let req = null; - let i, j; - let matchingReq, expectedReq, testResponse = null; + let i; + let j; + let matchingReq = null; + let expectedReq = null; + let testResponse = null; for (i = 0; i < this.requests.length; i++) { req = this.requests[i]; for (j = 0; j < this.expectedRequests.length; j++) { @@ -119,7 +122,7 @@ HttpBackend.prototype = { body = body(req.path, req.data); } req.callback( - testResponse.err, testResponse.response, body + testResponse.err, testResponse.response, body, ); matchingReq = null; } @@ -134,10 +137,10 @@ HttpBackend.prototype = { * Makes sure that the SDK hasn't sent any more requests to the backend. */ verifyNoOutstandingRequests: function() { - let firstOutstandingReq = this.requests[0] || {}; + const firstOutstandingReq = this.requests[0] || {}; expect(this.requests.length).toEqual(0, "Expected no more HTTP requests but received request to " + - firstOutstandingReq.path + firstOutstandingReq.path, ); }, @@ -145,9 +148,9 @@ HttpBackend.prototype = { * Makes sure that the test doesn't have any unresolved requests. */ verifyNoOutstandingExpectation: function() { - let firstOutstandingExpectation = this.expectedRequests[0] || {}; + const firstOutstandingExpectation = this.expectedRequests[0] || {}; expect(this.expectedRequests.length).toEqual(0, - "Expected to see HTTP request for " + firstOutstandingExpectation.path + "Expected to see HTTP request for " + firstOutstandingExpectation.path, ); }, @@ -159,7 +162,7 @@ HttpBackend.prototype = { * @return {Request} An expected request. */ when: function(method, path, data) { - let pendingReq = new ExpectedRequest(method, path, data); + const pendingReq = new ExpectedRequest(method, path, data); this.expectedRequests.push(pendingReq); return pendingReq; }, diff --git a/spec/test-utils.js b/spec/test-utils.js index b5d53df83..718c672ed 100644 --- a/spec/test-utils.js +++ b/spec/test-utils.js @@ -1,6 +1,6 @@ "use strict"; -let sdk = require(".."); -let MatrixEvent = sdk.MatrixEvent; +const sdk = require(".."); +const MatrixEvent = sdk.MatrixEvent; /** * Perform common actions before each test case, e.g. printing the test case @@ -8,7 +8,7 @@ let MatrixEvent = sdk.MatrixEvent; * @param {TestCase} testCase The test case that is about to be run. */ module.exports.beforeEach = function(testCase) { - let desc = testCase.suite.description + " : " + testCase.description; + const desc = testCase.suite.description + " : " + testCase.description; console.log(desc); console.log(new Array(1 + desc.length).join("=")); }; @@ -22,13 +22,13 @@ module.exports.beforeEach = function(testCase) { module.exports.mock = function(constr, name) { // By Tim Buschtöns // http://eclipsesource.com/blogs/2014/03/27/mocks-in-jasmine-tests/ - let HelperConstr = new Function(); // jshint ignore:line + const HelperConstr = new Function(); // jshint ignore:line HelperConstr.prototype = constr.prototype; - let result = new HelperConstr(); + const result = new HelperConstr(); result.jasmineToString = function() { return "mock" + (name ? " of " + name : ""); }; - for (let key in constr.prototype) { // eslint-disable-line guard-for-in + for (const key in constr.prototype) { // eslint-disable-line guard-for-in try { if (constr.prototype[key] instanceof Function) { result[key] = jasmine.createSpy((name || "mock") + '.' + key); @@ -57,7 +57,7 @@ module.exports.mkEvent = function(opts) { if (!opts.type || !opts.content) { throw new Error("Missing .type or .content =>" + JSON.stringify(opts)); } - let event = { + const event = { type: opts.type, room_id: opts.room, sender: opts.sender || opts.user, // opts.user for backwards-compat @@ -83,7 +83,7 @@ module.exports.mkPresence = function(opts) { if (!opts.user) { throw new Error("Missing user"); } - let event = { + const event = { event_id: "$" + Math.random() + "-" + Math.random(), type: "m.presence", sender: opts.sender || opts.user, // opts.user for backwards-compat @@ -193,6 +193,12 @@ module.exports.MockStorageApi = function() { this.data = {}; }; module.exports.MockStorageApi.prototype = { + get length() { + return Object.keys(this.data).length; + }, + key: function(i) { + return Object.keys(this.data)[i]; + }, setItem: function(k, v) { this.data[k] = v; }, diff --git a/spec/unit/content-repo.spec.js b/spec/unit/content-repo.spec.js index de8e6fb3c..6da3015b3 100644 --- a/spec/unit/content-repo.spec.js +++ b/spec/unit/content-repo.spec.js @@ -1,9 +1,9 @@ "use strict"; -let ContentRepo = require("../../lib/content-repo"); -let testUtils = require("../test-utils"); +const ContentRepo = require("../../lib/content-repo"); +const testUtils = require("../test-utils"); describe("ContentRepo", function() { - let baseUrl = "https://my.home.server"; + const baseUrl = "https://my.home.server"; beforeEach(function() { testUtils.beforeEach(this); // eslint-disable-line no-invalid-this @@ -11,24 +11,24 @@ describe("ContentRepo", function() { describe("getHttpUriForMxc", function() { it("should do nothing to HTTP URLs when allowing direct links", function() { - let httpUrl = "http://example.com/image.jpeg"; + const httpUrl = "http://example.com/image.jpeg"; expect( ContentRepo.getHttpUriForMxc( - baseUrl, httpUrl, undefined, undefined, undefined, true - ) + baseUrl, httpUrl, undefined, undefined, undefined, true, + ), ).toEqual(httpUrl); }); it("should return the empty string HTTP URLs by default", function() { - let httpUrl = "http://example.com/image.jpeg"; + const httpUrl = "http://example.com/image.jpeg"; expect(ContentRepo.getHttpUriForMxc(baseUrl, httpUrl)).toEqual(""); }); it("should return a download URL if no width/height/resize are specified", function() { - let mxcUri = "mxc://server.name/resourceid"; + const mxcUri = "mxc://server.name/resourceid"; expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri)).toEqual( - baseUrl + "/_matrix/media/v1/download/server.name/resourceid" + baseUrl + "/_matrix/media/v1/download/server.name/resourceid", ); }); @@ -38,27 +38,27 @@ describe("ContentRepo", function() { it("should return a thumbnail URL if a width/height/resize is specified", function() { - let mxcUri = "mxc://server.name/resourceid"; + const mxcUri = "mxc://server.name/resourceid"; expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri, 32, 64, "crop")).toEqual( baseUrl + "/_matrix/media/v1/thumbnail/server.name/resourceid" + - "?width=32&height=64&method=crop" + "?width=32&height=64&method=crop", ); }); it("should put fragments from mxc:// URIs after any query parameters", function() { - let mxcUri = "mxc://server.name/resourceid#automade"; + const mxcUri = "mxc://server.name/resourceid#automade"; expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri, 32)).toEqual( baseUrl + "/_matrix/media/v1/thumbnail/server.name/resourceid" + - "?width=32#automade" + "?width=32#automade", ); }); it("should put fragments from mxc:// URIs at the end of the HTTP URI", function() { - let mxcUri = "mxc://server.name/resourceid#automade"; + const mxcUri = "mxc://server.name/resourceid#automade"; expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri)).toEqual( - baseUrl + "/_matrix/media/v1/download/server.name/resourceid#automade" + baseUrl + "/_matrix/media/v1/download/server.name/resourceid#automade", ); }); }); @@ -71,21 +71,21 @@ describe("ContentRepo", function() { it("should set w/h by default to 96", function() { expect(ContentRepo.getIdenticonUri(baseUrl, "foobar")).toEqual( baseUrl + "/_matrix/media/v1/identicon/foobar" + - "?width=96&height=96" + "?width=96&height=96", ); }); it("should be able to set custom w/h", function() { expect(ContentRepo.getIdenticonUri(baseUrl, "foobar", 32, 64)).toEqual( baseUrl + "/_matrix/media/v1/identicon/foobar" + - "?width=32&height=64" + "?width=32&height=64", ); }); it("should URL encode the identicon string", function() { expect(ContentRepo.getIdenticonUri(baseUrl, "foo#bar", 32, 64)).toEqual( baseUrl + "/_matrix/media/v1/identicon/foo%23bar" + - "?width=32&height=64" + "?width=32&height=64", ); }); }); diff --git a/spec/unit/crypto.spec.js b/spec/unit/crypto.spec.js index bde8c6c8b..eb0747d3d 100644 --- a/spec/unit/crypto.spec.js +++ b/spec/unit/crypto.spec.js @@ -1,7 +1,7 @@ "use strict"; -let Crypto = require("../../lib/crypto"); -let sdk = require("../.."); +const Crypto = require("../../lib/crypto"); +const sdk = require("../.."); describe("Crypto", function() { if (!sdk.CRYPTO_ENABLED) { diff --git a/spec/unit/event-timeline.spec.js b/spec/unit/event-timeline.spec.js index 9876b8c76..bf2230508 100644 --- a/spec/unit/event-timeline.spec.js +++ b/spec/unit/event-timeline.spec.js @@ -1,7 +1,7 @@ "use strict"; -let sdk = require("../.."); -let EventTimeline = sdk.EventTimeline; -let utils = require("../test-utils"); +const sdk = require("../.."); +const EventTimeline = sdk.EventTimeline; +const utils = require("../test-utils"); function mockRoomStates(timeline) { timeline._startState = utils.mock(sdk.RoomState, "startState"); @@ -9,16 +9,16 @@ function mockRoomStates(timeline) { } describe("EventTimeline", function() { - let roomId = "!foo:bar"; - let userA = "@alice:bar"; - let userB = "@bertha:bar"; + const roomId = "!foo:bar"; + const userA = "@alice:bar"; + const userB = "@bertha:bar"; let timeline; beforeEach(function() { utils.beforeEach(this); // eslint-disable-line no-invalid-this // XXX: this is a horrid hack; should use sinon or something instead to mock - let timelineSet = { room: { roomId: roomId }}; + const timelineSet = { room: { roomId: roomId }}; timelineSet.room.getUnfilteredTimelineSet = function() { return timelineSet; }; @@ -28,7 +28,7 @@ describe("EventTimeline", function() { describe("construction", function() { it("getRoomId should get room id", function() { - let v = timeline.getRoomId(); + const v = timeline.getRoomId(); expect(v).toEqual(roomId); }); }); @@ -39,7 +39,7 @@ describe("EventTimeline", function() { }); it("should copy state events to start and end state", function() { - let events = [ + const events = [ utils.mkMembership({ room: roomId, mship: "invite", user: userB, skey: userA, event: true, @@ -52,21 +52,21 @@ describe("EventTimeline", function() { ]; timeline.initialiseState(events); expect(timeline._startState.setStateEvents).toHaveBeenCalledWith( - events + events, ); expect(timeline._endState.setStateEvents).toHaveBeenCalledWith( - events + events, ); }); it("should raise an exception if called after events are added", function() { - let event = + const event = utils.mkMessage({ room: roomId, user: userA, msg: "Adam stole the plushies", event: true, }); - let state = [ + const state = [ utils.mkMembership({ room: roomId, mship: "invite", user: userB, skey: userA, event: true, @@ -105,8 +105,8 @@ describe("EventTimeline", function() { }); it("setNeighbouringTimeline should set neighbour", function() { - let prev = {a: "a"}; - let next = {b: "b"}; + const prev = {a: "a"}; + const next = {b: "b"}; timeline.setNeighbouringTimeline(prev, EventTimeline.BACKWARDS); timeline.setNeighbouringTimeline(next, EventTimeline.FORWARDS); expect(timeline.getNeighbouringTimeline(EventTimeline.BACKWARDS)).toBe(prev); @@ -114,8 +114,8 @@ describe("EventTimeline", function() { }); it("setNeighbouringTimeline should throw if called twice", function() { - let prev = {a: "a"}; - let next = {b: "b"}; + const prev = {a: "a"}; + const next = {b: "b"}; expect(function() { timeline.setNeighbouringTimeline(prev, EventTimeline.BACKWARDS); }).not.toThrow(); @@ -141,7 +141,7 @@ describe("EventTimeline", function() { mockRoomStates(timeline); }); - let events = [ + const events = [ utils.mkMessage({ room: roomId, user: userA, msg: "hungry hungry hungry", event: true, @@ -154,7 +154,7 @@ describe("EventTimeline", function() { it("should be able to add events to the end", function() { timeline.addEvent(events[0], false); - let initialIndex = timeline.getBaseIndex(); + const initialIndex = timeline.getBaseIndex(); timeline.addEvent(events[1], false); expect(timeline.getBaseIndex()).toEqual(initialIndex); expect(timeline.getEvents().length).toEqual(2); @@ -164,7 +164,7 @@ describe("EventTimeline", function() { it("should be able to add events to the start", function() { timeline.addEvent(events[0], true); - let initialIndex = timeline.getBaseIndex(); + const initialIndex = timeline.getBaseIndex(); timeline.addEvent(events[1], true); expect(timeline.getBaseIndex()).toEqual(initialIndex + 1); expect(timeline.getEvents().length).toEqual(2); @@ -173,12 +173,12 @@ describe("EventTimeline", function() { }); it("should set event.sender for new and old events", function() { - let sentinel = { + const sentinel = { userId: userA, membership: "join", name: "Alice", }; - let oldSentinel = { + const oldSentinel = { userId: userA, membership: "join", name: "Old Alice", @@ -198,11 +198,11 @@ describe("EventTimeline", function() { return null; }); - let newEv = utils.mkEvent({ + const newEv = utils.mkEvent({ type: "m.room.name", room: roomId, user: userA, event: true, content: { name: "New Room Name" }, }); - let oldEv = utils.mkEvent({ + const oldEv = utils.mkEvent({ type: "m.room.name", room: roomId, user: userA, event: true, content: { name: "Old Room Name" }, }); @@ -215,12 +215,12 @@ describe("EventTimeline", function() { it("should set event.target for new and old m.room.member events", function() { - let sentinel = { + const sentinel = { userId: userA, membership: "join", name: "Alice", }; - let oldSentinel = { + const oldSentinel = { userId: userA, membership: "join", name: "Old Alice", @@ -240,10 +240,10 @@ describe("EventTimeline", function() { return null; }); - let newEv = utils.mkMembership({ + const newEv = utils.mkMembership({ room: roomId, mship: "invite", user: userB, skey: userA, event: true, }); - let oldEv = utils.mkMembership({ + const oldEv = utils.mkMembership({ room: roomId, mship: "ban", user: userB, skey: userA, event: true, }); timeline.addEvent(newEv, false); @@ -254,7 +254,7 @@ describe("EventTimeline", function() { it("should call setStateEvents on the right RoomState with the right " + "forwardLooking value for new events", function() { - let events = [ + const events = [ utils.mkMembership({ room: roomId, mship: "invite", user: userB, skey: userA, event: true, }), @@ -284,7 +284,7 @@ describe("EventTimeline", function() { it("should call setStateEvents on the right RoomState with the right " + "forwardLooking value for old events", function() { - let events = [ + const events = [ utils.mkMembership({ room: roomId, mship: "invite", user: userB, skey: userA, event: true, }), @@ -313,7 +313,7 @@ describe("EventTimeline", function() { }); describe("removeEvent", function() { - let events = [ + const events = [ utils.mkMessage({ room: roomId, user: userA, msg: "hungry hungry hungry", event: true, @@ -365,7 +365,7 @@ describe("EventTimeline", function() { function() { timeline.addEvent(events[0], true); timeline.removeEvent(events[0].getId()); - let initialIndex = timeline.getBaseIndex(); + const initialIndex = timeline.getBaseIndex(); timeline.addEvent(events[1], false); timeline.addEvent(events[2], false); expect(timeline.getBaseIndex()).toEqual(initialIndex); diff --git a/spec/unit/filter.spec.js b/spec/unit/filter.spec.js index 527db651f..9a28c2b03 100644 --- a/spec/unit/filter.spec.js +++ b/spec/unit/filter.spec.js @@ -1,11 +1,11 @@ "use strict"; -let sdk = require("../.."); -let Filter = sdk.Filter; -let utils = require("../test-utils"); +const sdk = require("../.."); +const Filter = sdk.Filter; +const utils = require("../test-utils"); describe("Filter", function() { - let filterId = "f1lt3ring15g00d4ursoul"; - let userId = "@sir_arthur_david:humming.tiger"; + const filterId = "f1lt3ring15g00d4ursoul"; + const userId = "@sir_arthur_david:humming.tiger"; let filter; beforeEach(function() { @@ -15,10 +15,10 @@ describe("Filter", function() { describe("fromJson", function() { it("create a new Filter from the provided values", function() { - let definition = { + const definition = { event_fields: ["type", "content"], }; - let f = Filter.fromJson(userId, filterId, definition); + const f = Filter.fromJson(userId, filterId, definition); expect(f.getDefinition()).toEqual(definition); expect(f.userId).toEqual(userId); expect(f.filterId).toEqual(filterId); @@ -40,7 +40,7 @@ describe("Filter", function() { describe("setDefinition/getDefinition", function() { it("should set and get the filter body", function() { - let definition = { + const definition = { event_format: "client", }; filter.setDefinition(definition); diff --git a/spec/unit/interactive-auth.spec.js b/spec/unit/interactive-auth.spec.js index b03dd0629..5c783db3d 100644 --- a/spec/unit/interactive-auth.spec.js +++ b/spec/unit/interactive-auth.spec.js @@ -15,12 +15,12 @@ limitations under the License. */ "use strict"; -let q = require("q"); -let sdk = require("../.."); -let utils = require("../test-utils"); +const q = require("q"); +const sdk = require("../.."); +const utils = require("../test-utils"); -let InteractiveAuth = sdk.InteractiveAuth; -let MatrixError = sdk.MatrixError; +const InteractiveAuth = sdk.InteractiveAuth; +const MatrixError = sdk.MatrixError; describe("InteractiveAuth", function() { beforeEach(function() { @@ -28,10 +28,10 @@ describe("InteractiveAuth", function() { }); it("should start an auth stage and complete it", function(done) { - let doRequest = jasmine.createSpy('doRequest'); - let startAuthStage = jasmine.createSpy('startAuthStage'); + const doRequest = jasmine.createSpy('doRequest'); + const startAuthStage = jasmine.createSpy('startAuthStage'); - let ia = new InteractiveAuth({ + const ia = new InteractiveAuth({ doRequest: doRequest, startAuthStage: startAuthStage, authData: { @@ -60,7 +60,7 @@ describe("InteractiveAuth", function() { }); // .. which should trigger a call here - let requestRes = {"a": "b"}; + const requestRes = {"a": "b"}; doRequest.andCallFake(function(authData) { expect(authData).toEqual({ session: "sessionId", @@ -78,10 +78,10 @@ describe("InteractiveAuth", function() { }); it("should make a request if no authdata is provided", function(done) { - let doRequest = jasmine.createSpy('doRequest'); - let startAuthStage = jasmine.createSpy('startAuthStage'); + const doRequest = jasmine.createSpy('doRequest'); + const startAuthStage = jasmine.createSpy('startAuthStage'); - let ia = new InteractiveAuth({ + const ia = new InteractiveAuth({ doRequest: doRequest, startAuthStage: startAuthStage, }); @@ -93,7 +93,7 @@ describe("InteractiveAuth", function() { doRequest.andCallFake(function(authData) { console.log("request1", authData); expect(authData).toBe(null); - let err = new MatrixError({ + const err = new MatrixError({ session: "sessionId", flows: [ { stages: ["logintype"] }, @@ -107,7 +107,7 @@ describe("InteractiveAuth", function() { }); // .. which should be followed by a call to startAuthStage - let requestRes = {"a": "b"}; + const requestRes = {"a": "b"}; startAuthStage.andCallFake(function(stage) { expect(stage).toEqual("logintype"); expect(ia.getSessionId()).toEqual("sessionId"); diff --git a/spec/unit/matrix-client.spec.js b/spec/unit/matrix-client.spec.js index 11897cd7c..bf3ecf86d 100644 --- a/spec/unit/matrix-client.spec.js +++ b/spec/unit/matrix-client.spec.js @@ -1,40 +1,40 @@ "use strict"; -let q = require("q"); -let sdk = require("../.."); -let MatrixClient = sdk.MatrixClient; -let utils = require("../test-utils"); +const q = require("q"); +const sdk = require("../.."); +const MatrixClient = sdk.MatrixClient; +const utils = require("../test-utils"); describe("MatrixClient", function() { - let userId = "@alice:bar"; - let identityServerUrl = "https://identity.server"; - let identityServerDomain = "identity.server"; + const userId = "@alice:bar"; + const identityServerUrl = "https://identity.server"; + const identityServerDomain = "identity.server"; let client; let store; let scheduler; - let KEEP_ALIVE_PATH = "/_matrix/client/versions"; + const KEEP_ALIVE_PATH = "/_matrix/client/versions"; - let PUSH_RULES_RESPONSE = { + const PUSH_RULES_RESPONSE = { method: "GET", path: "/pushrules/", data: {}, }; - let FILTER_PATH = "/user/" + encodeURIComponent(userId) + "/filter"; + const FILTER_PATH = "/user/" + encodeURIComponent(userId) + "/filter"; - let FILTER_RESPONSE = { + const FILTER_RESPONSE = { method: "POST", path: FILTER_PATH, data: { filter_id: "f1lt3r" }, }; - let SYNC_DATA = { + const SYNC_DATA = { next_batch: "s_5_3", presence: { events: [] }, rooms: {}, }; - let SYNC_RESPONSE = { + const SYNC_RESPONSE = { method: "GET", path: "/sync", data: SYNC_DATA, @@ -59,8 +59,8 @@ describe("MatrixClient", function() { if (path === KEEP_ALIVE_PATH && acceptKeepalives) { return q(); } - let next = httpLookups.shift(); - let logLine = ( + const next = httpLookups.shift(); + const logLine = ( "MatrixClient[UT] RECV " + method + " " + path + " " + "EXPECT " + (next ? next.method : next) + " " + (next ? next.path : next) ); @@ -75,7 +75,7 @@ describe("MatrixClient", function() { expect(false).toBe( true, ">1 pending request. You should probably handle them. " + "PENDING: " + JSON.stringify(pendingLookup) + " JUST GOT: " + - method + " " + path + method + " " + path, ); } pendingLookup = { @@ -88,7 +88,7 @@ describe("MatrixClient", function() { if (next.path === path && next.method === method) { console.log( "MatrixClient[UT] Matched. Returning " + - (next.error ? "BAD" : "GOOD") + " response" + (next.error ? "BAD" : "GOOD") + " response", ); if (next.expectBody) { expect(next.expectBody).toEqual(data); @@ -176,9 +176,9 @@ describe("MatrixClient", function() { httpLookups = []; httpLookups.push(PUSH_RULES_RESPONSE); httpLookups.push(SYNC_RESPONSE); - let filterId = "ehfewf"; + const filterId = "ehfewf"; store.getFilterIdByName.andReturn(filterId); - let filter = new sdk.Filter(0, filterId); + const filter = new sdk.Filter(0, filterId); filter.setDefinition({"room": {"timeline": {"limit": 8}}}); store.getFilter.andReturn(filter); client.startClient(); @@ -220,7 +220,7 @@ describe("MatrixClient", function() { // and they all need to be stored! return "FILTER_SYNC_" + userId + (suffix ? "_" + suffix : ""); } - let invalidFilterId = 'invalidF1lt3r'; + const invalidFilterId = 'invalidF1lt3r'; httpLookups = []; httpLookups.push({ method: "GET", @@ -236,9 +236,9 @@ describe("MatrixClient", function() { httpLookups.push(FILTER_RESPONSE); store.getFilterIdByName.andReturn(invalidFilterId); - let filterName = getFilterName(client.credentials.userId); + const filterName = getFilterName(client.credentials.userId); client.store.setFilterIdByName(filterName, invalidFilterId); - let filter = new sdk.Filter(client.credentials.userId); + const filter = new sdk.Filter(client.credentials.userId); client.getOrCreateFilter(filterName, filter).then(function(filterId) { expect(filterId).toEqual(FILTER_RESPONSE.data.filter_id); @@ -290,7 +290,7 @@ describe("MatrixClient", function() { if (state === "ERROR" && httpLookups.length > 0) { expect(httpLookups.length).toEqual(1); expect(client.retryImmediately()).toBe( - true, "retryImmediately returned false" + true, "retryImmediately returned false", ); jasmine.Clock.tick(1); } else if (state === "RECONNECTING" && httpLookups.length > 0) { @@ -332,9 +332,9 @@ describe("MatrixClient", function() { describe("emitted sync events", function() { function syncChecker(expectedStates, done) { return function syncListener(state, old) { - let expected = expectedStates.shift(); + const expected = expectedStates.shift(); console.log( - "'sync' curr=%s old=%s EXPECT=%s", state, old, expected + "'sync' curr=%s old=%s EXPECT=%s", state, old, expected, ); if (!expected) { done(); @@ -352,14 +352,14 @@ describe("MatrixClient", function() { } it("should transition null -> PREPARED after the first /sync", function(done) { - let expectedStates = []; + const expectedStates = []; expectedStates.push(["PREPARED", null]); client.on("sync", syncChecker(expectedStates, done)); client.startClient(); }); it("should transition null -> ERROR after a failed /filter", function(done) { - let expectedStates = []; + const expectedStates = []; httpLookups = []; httpLookups.push(PUSH_RULES_RESPONSE); httpLookups.push({ @@ -372,7 +372,7 @@ describe("MatrixClient", function() { it("should transition ERROR -> PREPARED after /sync if prev failed", function(done) { - let expectedStates = []; + const expectedStates = []; acceptKeepalives = false; httpLookups = []; httpLookups.push(PUSH_RULES_RESPONSE); @@ -399,7 +399,7 @@ describe("MatrixClient", function() { }); it("should transition PREPARED -> SYNCING after /sync", function(done) { - let expectedStates = []; + const expectedStates = []; expectedStates.push(["PREPARED", null]); expectedStates.push(["SYNCING", "PREPARED"]); client.on("sync", syncChecker(expectedStates, done)); @@ -408,7 +408,7 @@ describe("MatrixClient", function() { it("should transition SYNCING -> ERROR after a failed /sync", function(done) { acceptKeepalives = false; - let expectedStates = []; + const expectedStates = []; httpLookups.push({ method: "GET", path: "/sync", error: { errcode: "NONONONONO" }, }); @@ -427,7 +427,7 @@ describe("MatrixClient", function() { xit("should transition ERROR -> SYNCING after /sync if prev failed", function(done) { - let expectedStates = []; + const expectedStates = []; httpLookups.push({ method: "GET", path: "/sync", error: { errcode: "NONONONONO" }, }); @@ -442,7 +442,7 @@ describe("MatrixClient", function() { it("should transition SYNCING -> SYNCING on subsequent /sync successes", function(done) { - let expectedStates = []; + const expectedStates = []; httpLookups.push(SYNC_RESPONSE); httpLookups.push(SYNC_RESPONSE); @@ -455,7 +455,7 @@ describe("MatrixClient", function() { it("should transition ERROR -> ERROR if keepalive keeps failing", function(done) { acceptKeepalives = false; - let expectedStates = []; + const expectedStates = []; httpLookups.push({ method: "GET", path: "/sync", error: { errcode: "NONONONONO" }, }); @@ -479,7 +479,7 @@ describe("MatrixClient", function() { }); describe("inviteByEmail", function() { - let roomId = "!foo:bar"; + const roomId = "!foo:bar"; it("should send an invite HTTP POST", function() { httpLookups = [{ diff --git a/spec/unit/pushprocessor.spec.js b/spec/unit/pushprocessor.spec.js index f22fd5539..9c09771b5 100644 --- a/spec/unit/pushprocessor.spec.js +++ b/spec/unit/pushprocessor.spec.js @@ -1,18 +1,18 @@ "use strict"; -let PushProcessor = require("../../lib/pushprocessor"); -let utils = require("../test-utils"); +const PushProcessor = require("../../lib/pushprocessor"); +const utils = require("../test-utils"); describe('NotificationService', function() { - let testUserId = "@ali:matrix.org"; - let testDisplayName = "Alice M"; - let testRoomId = "!fl1bb13:localhost"; + const testUserId = "@ali:matrix.org"; + const testDisplayName = "Alice M"; + const testRoomId = "!fl1bb13:localhost"; let testEvent; let pushProcessor; // These would be better if individual rules were configured in the tests themselves. - let matrixClient = { + const matrixClient = { getRoom: function() { return { currentState: { @@ -213,25 +213,25 @@ describe('NotificationService', function() { it('should bing on a user ID.', function() { testEvent.event.content.body = "Hello @ali:matrix.org, how are you?"; - let actions = pushProcessor.actionsForEvent(testEvent); + const actions = pushProcessor.actionsForEvent(testEvent); expect(actions.tweaks.highlight).toEqual(true); }); it('should bing on a partial user ID with an @.', function() { testEvent.event.content.body = "Hello @ali, how are you?"; - let actions = pushProcessor.actionsForEvent(testEvent); + const actions = pushProcessor.actionsForEvent(testEvent); expect(actions.tweaks.highlight).toEqual(true); }); it('should bing on a partial user ID without @.', function() { testEvent.event.content.body = "Hello ali, how are you?"; - let actions = pushProcessor.actionsForEvent(testEvent); + const actions = pushProcessor.actionsForEvent(testEvent); expect(actions.tweaks.highlight).toEqual(true); }); it('should bing on a case-insensitive user ID.', function() { testEvent.event.content.body = "Hello @AlI:matrix.org, how are you?"; - let actions = pushProcessor.actionsForEvent(testEvent); + const actions = pushProcessor.actionsForEvent(testEvent); expect(actions.tweaks.highlight).toEqual(true); }); @@ -239,13 +239,13 @@ describe('NotificationService', function() { it('should bing on a display name.', function() { testEvent.event.content.body = "Hello Alice M, how are you?"; - let actions = pushProcessor.actionsForEvent(testEvent); + const actions = pushProcessor.actionsForEvent(testEvent); expect(actions.tweaks.highlight).toEqual(true); }); it('should bing on a case-insensitive display name.', function() { testEvent.event.content.body = "Hello ALICE M, how are you?"; - let actions = pushProcessor.actionsForEvent(testEvent); + const actions = pushProcessor.actionsForEvent(testEvent); expect(actions.tweaks.highlight).toEqual(true); }); @@ -253,19 +253,19 @@ describe('NotificationService', function() { it('should bing on a bing word.', function() { testEvent.event.content.body = "I really like coffee"; - let actions = pushProcessor.actionsForEvent(testEvent); + const actions = pushProcessor.actionsForEvent(testEvent); expect(actions.tweaks.highlight).toEqual(true); }); it('should bing on case-insensitive bing words.', function() { testEvent.event.content.body = "Coffee is great"; - let actions = pushProcessor.actionsForEvent(testEvent); + const actions = pushProcessor.actionsForEvent(testEvent); expect(actions.tweaks.highlight).toEqual(true); }); it('should bing on wildcard (.*) bing words.', function() { testEvent.event.content.body = "It was foomahbar I think."; - let actions = pushProcessor.actionsForEvent(testEvent); + const actions = pushProcessor.actionsForEvent(testEvent); expect(actions.tweaks.highlight).toEqual(true); }); @@ -280,7 +280,7 @@ describe('NotificationService', function() { it('should bing on character range ([a-z]) bing words.', function() { testEvent.event.content.body = "I ate 6 pies"; - let actions = pushProcessor.actionsForEvent(testEvent); + const actions = pushProcessor.actionsForEvent(testEvent); expect(actions.tweaks.highlight).toEqual(true); }); @@ -297,7 +297,7 @@ describe('NotificationService', function() { it('should gracefully handle bad input.', function() { testEvent.event.content.body = { "foo": "bar" }; - let actions = pushProcessor.actionsForEvent(testEvent); + const actions = pushProcessor.actionsForEvent(testEvent); expect(actions.tweaks.highlight).toEqual(false); }); }); diff --git a/spec/unit/realtime-callbacks.spec.js b/spec/unit/realtime-callbacks.spec.js index 29e551bd6..92ed513db 100644 --- a/spec/unit/realtime-callbacks.spec.js +++ b/spec/unit/realtime-callbacks.spec.js @@ -1,10 +1,10 @@ "use strict"; -let callbacks = require("../../lib/realtime-callbacks"); -let test_utils = require("../test-utils.js"); +const callbacks = require("../../lib/realtime-callbacks"); +const testUtils = require("../test-utils.js"); describe("realtime-callbacks", function() { - let clock = jasmine.Clock; + const clock = jasmine.Clock; let fakeDate; function tick(millis) { @@ -14,7 +14,7 @@ describe("realtime-callbacks", function() { } beforeEach(function() { - test_utils.beforeEach(this); // eslint-disable-line no-invalid-this + testUtils.beforeEach(this); // eslint-disable-line no-invalid-this clock.useMock(); fakeDate = Date.now(); callbacks.setNow(function() { @@ -28,7 +28,7 @@ describe("realtime-callbacks", function() { describe("setTimeout", function() { it("should call the callback after the timeout", function() { - let callback = jasmine.createSpy(); + const callback = jasmine.createSpy(); callbacks.setTimeout(callback, 100); expect(callback).not.toHaveBeenCalled(); @@ -38,7 +38,7 @@ describe("realtime-callbacks", function() { it("should default to a zero timeout", function() { - let callback = jasmine.createSpy(); + const callback = jasmine.createSpy(); callbacks.setTimeout(callback); expect(callback).not.toHaveBeenCalled(); @@ -47,14 +47,14 @@ describe("realtime-callbacks", function() { }); it("should pass any parameters to the callback", function() { - let callback = jasmine.createSpy(); + const callback = jasmine.createSpy(); callbacks.setTimeout(callback, 0, "a", "b", "c"); tick(0); expect(callback).toHaveBeenCalledWith("a", "b", "c"); }); it("should set 'this' to the global object", function() { - let callback = jasmine.createSpy(); + const callback = jasmine.createSpy(); callback.andCallFake(function() { expect(this).toBe(global); // eslint-disable-line no-invalid-this expect(this.console).toBeDefined(); // eslint-disable-line no-invalid-this @@ -65,7 +65,7 @@ describe("realtime-callbacks", function() { }); it("should handle timeouts of several seconds", function() { - let callback = jasmine.createSpy(); + const callback = jasmine.createSpy(); callbacks.setTimeout(callback, 2000); expect(callback).not.toHaveBeenCalled(); @@ -76,9 +76,9 @@ describe("realtime-callbacks", function() { }); it("should call multiple callbacks in the right order", function() { - let callback1 = jasmine.createSpy("callback1"); - let callback2 = jasmine.createSpy("callback2"); - let callback3 = jasmine.createSpy("callback3"); + const callback1 = jasmine.createSpy("callback1"); + const callback2 = jasmine.createSpy("callback2"); + const callback3 = jasmine.createSpy("callback3"); callbacks.setTimeout(callback2, 200); callbacks.setTimeout(callback1, 100); callbacks.setTimeout(callback3, 300); @@ -101,8 +101,8 @@ describe("realtime-callbacks", function() { }); it("should treat -ve timeouts the same as a zero timeout", function() { - let callback1 = jasmine.createSpy("callback1"); - let callback2 = jasmine.createSpy("callback2"); + const callback1 = jasmine.createSpy("callback1"); + const callback2 = jasmine.createSpy("callback2"); // check that cb1 is called before cb2 callback1.andCallFake(function() { @@ -120,8 +120,8 @@ describe("realtime-callbacks", function() { }); it("should not get confused by chained calls", function() { - let callback2 = jasmine.createSpy("callback2"); - let callback1 = jasmine.createSpy("callback1"); + const callback2 = jasmine.createSpy("callback2"); + const callback1 = jasmine.createSpy("callback1"); callback1.andCallFake(function() { callbacks.setTimeout(callback2, 0); expect(callback2).not.toHaveBeenCalled(); @@ -136,11 +136,11 @@ describe("realtime-callbacks", function() { }); it("should be immune to exceptions", function() { - let callback1 = jasmine.createSpy("callback1"); + const callback1 = jasmine.createSpy("callback1"); callback1.andCallFake(function() { throw new Error("prepare to die"); }); - let callback2 = jasmine.createSpy("callback2"); + const callback2 = jasmine.createSpy("callback2"); callbacks.setTimeout(callback1, 0); callbacks.setTimeout(callback2, 0); @@ -154,19 +154,19 @@ describe("realtime-callbacks", function() { describe("cancelTimeout", function() { it("should cancel a pending timeout", function() { - let callback = jasmine.createSpy(); - let k = callbacks.setTimeout(callback); + const callback = jasmine.createSpy(); + const k = callbacks.setTimeout(callback); callbacks.clearTimeout(k); tick(0); expect(callback).not.toHaveBeenCalled(); }); it("should not affect sooner timeouts", function() { - let callback1 = jasmine.createSpy("callback1"); - let callback2 = jasmine.createSpy("callback2"); + const callback1 = jasmine.createSpy("callback1"); + const callback2 = jasmine.createSpy("callback2"); callbacks.setTimeout(callback1, 100); - let k = callbacks.setTimeout(callback2, 200); + const k = callbacks.setTimeout(callback2, 200); callbacks.clearTimeout(k); tick(100); diff --git a/spec/unit/room-member.spec.js b/spec/unit/room-member.spec.js index 6cd3ab109..04622c6ab 100644 --- a/spec/unit/room-member.spec.js +++ b/spec/unit/room-member.spec.js @@ -1,13 +1,13 @@ "use strict"; -let sdk = require("../.."); -let RoomMember = sdk.RoomMember; -let utils = require("../test-utils"); +const sdk = require("../.."); +const RoomMember = sdk.RoomMember; +const utils = require("../test-utils"); describe("RoomMember", function() { - let roomId = "!foo:bar"; - let userA = "@alice:bar"; - let userB = "@bertha:bar"; - let userC = "@clarissa:bar"; + const roomId = "!foo:bar"; + const userA = "@alice:bar"; + const userB = "@bertha:bar"; + const userC = "@clarissa:bar"; let member; beforeEach(function() { @@ -16,7 +16,7 @@ describe("RoomMember", function() { }); describe("getAvatarUrl", function() { - let hsUrl = "https://my.home.server"; + const hsUrl = "https://my.home.server"; it("should return the URL from m.room.member preferentially", function() { member.events.member = utils.mkEvent({ @@ -30,7 +30,7 @@ describe("RoomMember", function() { avatar_url: "mxc://flibble/wibble", }, }); - let url = member.getAvatarUrl(hsUrl); + const url = member.getAvatarUrl(hsUrl); // we don't care about how the mxc->http conversion is done, other // than it contains the mxc body. expect(url.indexOf("flibble/wibble")).not.toEqual(-1); @@ -38,20 +38,20 @@ describe("RoomMember", function() { it("should return an identicon HTTP URL if allowDefault was set and there " + "was no m.room.member event", function() { - let url = member.getAvatarUrl(hsUrl, 64, 64, "crop", true); + const url = member.getAvatarUrl(hsUrl, 64, 64, "crop", true); expect(url.indexOf("http")).toEqual(0); // don't care about form }); it("should return nothing if there is no m.room.member and allowDefault=false", function() { - let url = member.getAvatarUrl(hsUrl, 64, 64, "crop", false); + const url = member.getAvatarUrl(hsUrl, 64, 64, "crop", false); expect(url).toEqual(null); }); }); describe("setPowerLevelEvent", function() { it("should set 'powerLevel' and 'powerLevelNorm'.", function() { - let event = utils.mkEvent({ + const event = utils.mkEvent({ type: "m.room.power_levels", room: roomId, user: userA, @@ -68,7 +68,7 @@ describe("RoomMember", function() { expect(member.powerLevel).toEqual(20); expect(member.powerLevelNorm).toEqual(10); - let memberB = new RoomMember(roomId, userB); + const memberB = new RoomMember(roomId, userB); memberB.setPowerLevelEvent(event); expect(memberB.powerLevel).toEqual(200); expect(memberB.powerLevelNorm).toEqual(100); @@ -76,7 +76,7 @@ describe("RoomMember", function() { it("should emit 'RoomMember.powerLevel' if the power level changes.", function() { - let event = utils.mkEvent({ + const event = utils.mkEvent({ type: "m.room.power_levels", room: roomId, user: userA, @@ -105,7 +105,7 @@ describe("RoomMember", function() { it("should honour power levels of zero.", function() { - let event = utils.mkEvent({ + const event = utils.mkEvent({ type: "m.room.power_levels", room: roomId, user: userA, @@ -138,12 +138,12 @@ describe("RoomMember", function() { describe("setTypingEvent", function() { it("should set 'typing'", function() { member.typing = false; - let memberB = new RoomMember(roomId, userB); + const memberB = new RoomMember(roomId, userB); memberB.typing = true; - let memberC = new RoomMember(roomId, userC); + const memberC = new RoomMember(roomId, userC); memberC.typing = true; - let event = utils.mkEvent({ + const event = utils.mkEvent({ type: "m.typing", user: userA, room: roomId, @@ -165,7 +165,7 @@ describe("RoomMember", function() { it("should emit 'RoomMember.typing' if the typing state changes", function() { - let event = utils.mkEvent({ + const event = utils.mkEvent({ type: "m.typing", room: roomId, content: { @@ -190,7 +190,7 @@ describe("RoomMember", function() { }); describe("setMembershipEvent", function() { - let joinEvent = utils.mkMembership({ + const joinEvent = utils.mkMembership({ event: true, mship: "join", user: userA, @@ -198,7 +198,7 @@ describe("RoomMember", function() { name: "Alice", }); - let inviteEvent = utils.mkMembership({ + const inviteEvent = utils.mkMembership({ event: true, mship: "invite", user: userB, @@ -218,7 +218,7 @@ describe("RoomMember", function() { it("should set 'name' based on user_id, displayname and room state", function() { - let roomState = { + const roomState = { getStateEvents: function(type) { if (type !== "m.room.member") { return []; diff --git a/spec/unit/room-state.spec.js b/spec/unit/room-state.spec.js index 20903785a..8409da86b 100644 --- a/spec/unit/room-state.spec.js +++ b/spec/unit/room-state.spec.js @@ -1,13 +1,13 @@ "use strict"; -let sdk = require("../.."); -let RoomState = sdk.RoomState; -let RoomMember = sdk.RoomMember; -let utils = require("../test-utils"); +const sdk = require("../.."); +const RoomState = sdk.RoomState; +const RoomMember = sdk.RoomMember; +const utils = require("../test-utils"); describe("RoomState", function() { - let roomId = "!foo:bar"; - let userA = "@alice:bar"; - let userB = "@bob:bar"; + const roomId = "!foo:bar"; + const userA = "@alice:bar"; + const userB = "@bob:bar"; let state; beforeEach(function() { @@ -40,7 +40,7 @@ describe("RoomState", function() { }); it("should return a member for each m.room.member event", function() { - let members = state.getMembers(); + const members = state.getMembers(); expect(members.length).toEqual(2); // ordering unimportant expect([userA, userB].indexOf(members[0].userId)).not.toEqual(-1); @@ -58,7 +58,7 @@ describe("RoomState", function() { }); it("should return a member which changes as state changes", function() { - let member = state.getMember(userB); + const member = state.getMember(userB); expect(member.membership).toEqual("join"); expect(member.name).toEqual(userB); @@ -81,14 +81,14 @@ describe("RoomState", function() { it("should return a member which doesn't change when the state is updated", function() { - let preLeaveUser = state.getSentinelMember(userA); + const preLeaveUser = state.getSentinelMember(userA); state.setStateEvents([ utils.mkMembership({ room: roomId, user: userA, mship: "leave", event: true, name: "AliceIsGone", }), ]); - let postLeaveUser = state.getSentinelMember(userA); + const postLeaveUser = state.getSentinelMember(userA); expect(preLeaveUser.membership).toEqual("join"); expect(preLeaveUser.name).toEqual(userA); @@ -111,7 +111,7 @@ describe("RoomState", function() { it("should return a list of matching events if no state_key was specified", function() { - let events = state.getStateEvents("m.room.member"); + const events = state.getStateEvents("m.room.member"); expect(events.length).toEqual(2); // ordering unimportant expect([userA, userB].indexOf(events[0].getStateKey())).not.toEqual(-1); @@ -120,7 +120,7 @@ describe("RoomState", function() { it("should return a single MatrixEvent if a state_key was specified", function() { - let event = state.getStateEvents("m.room.member", userA); + const event = state.getStateEvents("m.room.member", userA); expect(event.getContent()).toEqual({ membership: "join", }); @@ -129,7 +129,7 @@ describe("RoomState", function() { describe("setStateEvents", function() { it("should emit 'RoomState.members' for each m.room.member event", function() { - let memberEvents = [ + const memberEvents = [ utils.mkMembership({ user: "@cleo:bar", mship: "invite", room: roomId, event: true, }), @@ -149,7 +149,7 @@ describe("RoomState", function() { }); it("should emit 'RoomState.newMember' for each new member added", function() { - let memberEvents = [ + const memberEvents = [ utils.mkMembership({ user: "@cleo:bar", mship: "invite", room: roomId, event: true, }), @@ -168,7 +168,7 @@ describe("RoomState", function() { }); it("should emit 'RoomState.events' for each state event", function() { - let events = [ + const events = [ utils.mkMembership({ user: "@cleo:bar", mship: "invite", room: roomId, event: true, }), @@ -198,7 +198,7 @@ describe("RoomState", function() { state.members[userA] = utils.mock(RoomMember); state.members[userB] = utils.mock(RoomMember); - let powerLevelEvent = utils.mkEvent({ + const powerLevelEvent = utils.mkEvent({ type: "m.room.power_levels", room: roomId, user: userA, event: true, content: { users_default: 10, @@ -210,20 +210,20 @@ describe("RoomState", function() { state.setStateEvents([powerLevelEvent]); expect(state.members[userA].setPowerLevelEvent).toHaveBeenCalledWith( - powerLevelEvent + powerLevelEvent, ); expect(state.members[userB].setPowerLevelEvent).toHaveBeenCalledWith( - powerLevelEvent + powerLevelEvent, ); }); it("should call setPowerLevelEvent on a new RoomMember if power levels exist", function() { - let userC = "@cleo:bar"; - let memberEvent = utils.mkMembership({ + const userC = "@cleo:bar"; + const memberEvent = utils.mkMembership({ mship: "join", user: userC, room: roomId, event: true, }); - let powerLevelEvent = utils.mkEvent({ + const powerLevelEvent = utils.mkEvent({ type: "m.room.power_levels", room: roomId, user: userA, event: true, content: { users_default: 10, @@ -247,21 +247,21 @@ describe("RoomState", function() { state.members[userA] = utils.mock(RoomMember); state.members[userB] = utils.mock(RoomMember); - let memberEvent = utils.mkMembership({ + const memberEvent = utils.mkMembership({ user: userB, mship: "leave", room: roomId, event: true, }); state.setStateEvents([memberEvent]); expect(state.members[userA].setMembershipEvent).not.toHaveBeenCalled(); expect(state.members[userB].setMembershipEvent).toHaveBeenCalledWith( - memberEvent, state + memberEvent, state, ); }); }); describe("setTypingEvent", function() { it("should call setTypingEvent on each RoomMember", function() { - let typingEvent = utils.mkEvent({ + const typingEvent = utils.mkEvent({ type: "m.typing", room: roomId, event: true, content: { user_ids: [userA], }, @@ -272,10 +272,10 @@ describe("RoomState", function() { state.setTypingEvent(typingEvent); expect(state.members[userA].setTypingEvent).toHaveBeenCalledWith( - typingEvent + typingEvent, ); expect(state.members[userB].setTypingEvent).toHaveBeenCalledWith( - typingEvent + typingEvent, ); }); }); @@ -284,7 +284,7 @@ describe("RoomState", function() { it("should say non-joined members may not send state", function() { expect(state.maySendStateEvent( - 'm.room.name', "@nobody:nowhere" + 'm.room.name', "@nobody:nowhere", )).toEqual(false); }); @@ -296,7 +296,7 @@ describe("RoomState", function() { it("should say members with power >=50 may send state with power level event " + "but no state default", function() { - let powerLevelEvent = { + const powerLevelEvent = { type: "m.room.power_levels", room: roomId, user: userA, event: true, content: { users_default: 10, @@ -316,7 +316,7 @@ describe("RoomState", function() { it("should obey state_default", function() { - let powerLevelEvent = { + const powerLevelEvent = { type: "m.room.power_levels", room: roomId, user: userA, event: true, content: { users_default: 10, @@ -337,7 +337,7 @@ describe("RoomState", function() { it("should honour explicit event power levels in the power_levels event", function() { - let powerLevelEvent = { + const powerLevelEvent = { type: "m.room.power_levels", room: roomId, user: userA, event: true, content: { events: { @@ -367,7 +367,7 @@ describe("RoomState", function() { it("should say non-joined members may not send events", function() { expect(state.maySendEvent( - 'm.room.message', "@nobody:nowhere" + 'm.room.message', "@nobody:nowhere", )).toEqual(false); expect(state.maySendMessage("@nobody:nowhere")).toEqual(false); }); @@ -380,7 +380,7 @@ describe("RoomState", function() { it("should obey events_default", function() { - let powerLevelEvent = { + const powerLevelEvent = { type: "m.room.power_levels", room: roomId, user: userA, event: true, content: { users_default: 10, @@ -404,7 +404,7 @@ describe("RoomState", function() { it("should honour explicit event power levels in the power_levels event", function() { - let powerLevelEvent = { + const powerLevelEvent = { type: "m.room.power_levels", room: roomId, user: userA, event: true, content: { events: { diff --git a/spec/unit/room.spec.js b/spec/unit/room.spec.js index 599dbbc2a..b6820ecdd 100644 --- a/spec/unit/room.spec.js +++ b/spec/unit/room.spec.js @@ -1,18 +1,18 @@ "use strict"; -let sdk = require("../.."); -let Room = sdk.Room; -let RoomState = sdk.RoomState; -let MatrixEvent = sdk.MatrixEvent; -let EventStatus = sdk.EventStatus; -let EventTimeline = sdk.EventTimeline; -let utils = require("../test-utils"); +const sdk = require("../.."); +const Room = sdk.Room; +const RoomState = sdk.RoomState; +const MatrixEvent = sdk.MatrixEvent; +const EventStatus = sdk.EventStatus; +const EventTimeline = sdk.EventTimeline; +const utils = require("../test-utils"); describe("Room", function() { - let roomId = "!foo:bar"; - let userA = "@alice:bar"; - let userB = "@bertha:bar"; - let userC = "@clarissa:bar"; - let userD = "@dorothy:bar"; + const roomId = "!foo:bar"; + const userA = "@alice:bar"; + const userB = "@bertha:bar"; + const userC = "@clarissa:bar"; + const userD = "@dorothy:bar"; let room; beforeEach(function() { @@ -26,7 +26,7 @@ describe("Room", function() { }); describe("getAvatarUrl", function() { - let hsUrl = "https://my.home.server"; + const hsUrl = "https://my.home.server"; it("should return the URL from m.room.avatar preferentially", function() { room.currentState.getStateEvents.andCallFake(function(type, key) { @@ -43,7 +43,7 @@ describe("Room", function() { }); } }); - let url = room.getAvatarUrl(hsUrl); + const url = room.getAvatarUrl(hsUrl); // we don't care about how the mxc->http conversion is done, other // than it contains the mxc body. expect(url.indexOf("flibble/wibble")).not.toEqual(-1); @@ -51,13 +51,13 @@ describe("Room", function() { it("should return an identicon HTTP URL if allowDefault was set and there " + "was no m.room.avatar event", function() { - let url = room.getAvatarUrl(hsUrl, 64, 64, "crop", true); + const url = room.getAvatarUrl(hsUrl, 64, 64, "crop", true); expect(url.indexOf("http")).toEqual(0); // don't care about form }); it("should return nothing if there is no m.room.avatar and allowDefault=false", function() { - let url = room.getAvatarUrl(hsUrl, 64, 64, "crop", false); + const url = room.getAvatarUrl(hsUrl, 64, 64, "crop", false); expect(url).toEqual(null); }); }); @@ -83,7 +83,7 @@ describe("Room", function() { }); describe("addLiveEvents", function() { - let events = [ + const events = [ utils.mkMessage({ room: roomId, user: userA, msg: "changing room name", event: true, }), @@ -95,7 +95,7 @@ describe("Room", function() { it("should call RoomState.setTypingEvent on m.typing events", function() { room.currentState = utils.mock(RoomState); - let typing = utils.mkEvent({ + const typing = utils.mkEvent({ room: roomId, type: "m.typing", event: true, content: { user_ids: [userA], }, @@ -112,7 +112,7 @@ describe("Room", function() { it("should replace a timeline event if dupe strategy is 'replace'", function() { // make a duplicate - let dupe = utils.mkMessage({ + const dupe = utils.mkMessage({ room: roomId, user: userA, msg: "dupe", event: true, }); dupe.event.event_id = events[0].getId(); @@ -124,7 +124,7 @@ describe("Room", function() { it("should ignore a given dupe event if dupe strategy is 'ignore'", function() { // make a duplicate - let dupe = utils.mkMessage({ + const dupe = utils.mkMessage({ room: roomId, user: userA, msg: "dupe", event: true, }); dupe.event.event_id = events[0].getId(); @@ -150,7 +150,7 @@ describe("Room", function() { it("should call setStateEvents on the right RoomState with the right " + "forwardLooking value for new events", function() { - let events = [ + const events = [ utils.mkMembership({ room: roomId, mship: "invite", user: userB, skey: userA, event: true, }), @@ -163,10 +163,10 @@ describe("Room", function() { ]; room.addLiveEvents(events); expect(room.currentState.setStateEvents).toHaveBeenCalledWith( - [events[0]] + [events[0]], ); expect(room.currentState.setStateEvents).toHaveBeenCalledWith( - [events[1]] + [events[1]], ); expect(events[0].forwardLooking).toBe(true); expect(events[1].forwardLooking).toBe(true); @@ -174,7 +174,7 @@ describe("Room", function() { }); it("should synthesize read receipts for the senders of events", function() { - let sentinel = { + const sentinel = { userId: userA, membership: "join", name: "Alice", @@ -190,17 +190,17 @@ describe("Room", function() { }); it("should emit Room.localEchoUpdated when a local echo is updated", function() { - let localEvent = utils.mkMessage({ + const localEvent = utils.mkMessage({ room: roomId, user: userA, event: true, }); localEvent.status = EventStatus.SENDING; - let localEventId = localEvent.getId(); + const localEventId = localEvent.getId(); - let remoteEvent = utils.mkMessage({ + const remoteEvent = utils.mkMessage({ room: roomId, user: userA, event: true, }); remoteEvent.event.unsigned = {transaction_id: "TXN_ID"}; - let remoteEventId = remoteEvent.getId(); + const remoteEventId = remoteEvent.getId(); let callCount = 0; room.on("Room.localEchoUpdated", @@ -222,7 +222,7 @@ describe("Room", function() { break; } callCount += 1; - } + }, ); // first add the local echo @@ -238,7 +238,7 @@ describe("Room", function() { }); describe("addEventsToTimeline", function() { - let events = [ + const events = [ utils.mkMessage({ room: roomId, user: userA, msg: "changing room name", event: true, }), @@ -278,12 +278,12 @@ describe("Room", function() { describe("event metadata handling", function() { it("should set event.sender for new and old events", function() { - let sentinel = { + const sentinel = { userId: userA, membership: "join", name: "Alice", }; - let oldSentinel = { + const oldSentinel = { userId: userA, membership: "join", name: "Old Alice", @@ -301,11 +301,11 @@ describe("Room", function() { return null; }); - let newEv = utils.mkEvent({ + const newEv = utils.mkEvent({ type: "m.room.name", room: roomId, user: userA, event: true, content: { name: "New Room Name" }, }); - let oldEv = utils.mkEvent({ + const oldEv = utils.mkEvent({ type: "m.room.name", room: roomId, user: userA, event: true, content: { name: "Old Room Name" }, }); @@ -317,12 +317,12 @@ describe("Room", function() { it("should set event.target for new and old m.room.member events", function() { - let sentinel = { + const sentinel = { userId: userA, membership: "join", name: "Alice", }; - let oldSentinel = { + const oldSentinel = { userId: userA, membership: "join", name: "Old Alice", @@ -340,10 +340,10 @@ describe("Room", function() { return null; }); - let newEv = utils.mkMembership({ + const newEv = utils.mkMembership({ room: roomId, mship: "invite", user: userB, skey: userA, event: true, }); - let oldEv = utils.mkMembership({ + const oldEv = utils.mkMembership({ room: roomId, mship: "ban", user: userB, skey: userA, event: true, }); room.addLiveEvents([newEv]); @@ -354,7 +354,7 @@ describe("Room", function() { it("should call setStateEvents on the right RoomState with the right " + "forwardLooking value for old events", function() { - let events = [ + const events = [ utils.mkMembership({ room: roomId, mship: "invite", user: userB, skey: userA, event: true, }), @@ -368,10 +368,10 @@ describe("Room", function() { room.addEventsToTimeline(events, true, room.getLiveTimeline()); expect(room.oldState.setStateEvents).toHaveBeenCalledWith( - [events[0]] + [events[0]], ); expect(room.oldState.setStateEvents).toHaveBeenCalledWith( - [events[1]] + [events[1]], ); expect(events[0].forwardLooking).toBe(false); expect(events[1].forwardLooking).toBe(false); @@ -379,8 +379,8 @@ describe("Room", function() { }); }); - let resetTimelineTests = function(timelineSupport) { - let events = [ + const resetTimelineTests = function(timelineSupport) { + const events = [ utils.mkMessage({ room: roomId, user: userA, msg: "A message", event: true, }), @@ -404,8 +404,8 @@ describe("Room", function() { room.resetLiveTimeline(); room.addLiveEvents([events[2]]); - let oldState = room.getLiveTimeline().getState(EventTimeline.BACKWARDS); - let newState = room.getLiveTimeline().getState(EventTimeline.FORWARDS); + const oldState = room.getLiveTimeline().getState(EventTimeline.BACKWARDS); + const newState = room.getLiveTimeline().getState(EventTimeline.FORWARDS); expect(room.getLiveTimeline().getEvents().length).toEqual(1); expect(oldState.getStateEvents("m.room.name", "")).toEqual(events[1]); expect(newState.getStateEvents("m.room.name", "")).toEqual(events[2]); @@ -417,7 +417,7 @@ describe("Room", function() { room.resetLiveTimeline(); room.addLiveEvents([events[2]]); - let newLiveTimeline = room.getLiveTimeline(); + const newLiveTimeline = room.getLiveTimeline(); expect(room.timeline).toEqual(newLiveTimeline.getEvents()); expect(room.oldState).toEqual( newLiveTimeline.getState(EventTimeline.BACKWARDS)); @@ -434,7 +434,7 @@ describe("Room", function() { // make sure that the pagination token has been set before the // event is emitted. - let tok = emitRoom.getLiveTimeline() + const tok = emitRoom.getLiveTimeline() .getPaginationToken(EventTimeline.BACKWARDS); expect(tok).toEqual("pagToken"); @@ -447,10 +447,10 @@ describe("Room", function() { " old timelines", function() { room.addLiveEvents([events[0]]); expect(room.timeline.length).toEqual(1); - let firstLiveTimeline = room.getLiveTimeline(); + const firstLiveTimeline = room.getLiveTimeline(); room.resetLiveTimeline(); - let tl = room.getTimelineForEvent(events[0].getId()); + const tl = room.getTimelineForEvent(events[0].getId()); expect(tl).toBe(timelineSupport ? firstLiveTimeline : null); }); }; @@ -465,7 +465,7 @@ describe("Room", function() { room = new Room(roomId, {timelineSupport: true}); }); - let events = [ + const events = [ utils.mkMessage({ room: roomId, user: userA, msg: "1111", event: true, }), @@ -492,7 +492,7 @@ describe("Room", function() { }); it("should handle events in adjacent timelines", function() { - let oldTimeline = room.addTimeline(); + const oldTimeline = room.addTimeline(); oldTimeline.setNeighbouringTimeline(room.getLiveTimeline(), 'f'); room.getLiveTimeline().setNeighbouringTimeline(oldTimeline, 'b'); @@ -508,7 +508,7 @@ describe("Room", function() { }); it("should return null for events in non-adjacent timelines", function() { - let oldTimeline = room.addTimeline(); + const oldTimeline = room.addTimeline(); room.addEventsToTimeline([events[0]], false, oldTimeline); room.addLiveEvents([events[1]]); @@ -545,7 +545,7 @@ describe("Room", function() { { userId: "@cleo:bar", membership: "leave" }, ]; }); - let res = room.getJoinedMembers(); + const res = room.getJoinedMembers(); expect(res.length).toEqual(1); expect(res[0].userId).toEqual("@alice:bar"); }); @@ -556,7 +556,7 @@ describe("Room", function() { { userId: "@bob:bar", membership: "invite" }, ]; }); - let res = room.getJoinedMembers(); + const res = room.getJoinedMembers(); expect(res.length).toEqual(0); }); }); @@ -607,14 +607,14 @@ describe("Room", function() { // event.type + "$" event.state_key : MatrixEvent }; - let setJoinRule = function(rule) { + const setJoinRule = function(rule) { stateLookup["m.room.join_rules$"] = utils.mkEvent({ type: "m.room.join_rules", room: roomId, user: userA, content: { join_rule: rule, }, event: true, }); }; - let setAliases = function(aliases, stateKey) { + const setAliases = function(aliases, stateKey) { if (!stateKey) { stateKey = "flibble"; } @@ -624,14 +624,14 @@ describe("Room", function() { }, event: true, }); }; - let setRoomName = function(name) { + const setRoomName = function(name) { stateLookup["m.room.name$"] = utils.mkEvent({ type: "m.room.name", room: roomId, user: userA, content: { name: name, }, event: true, }); }; - let addMember = function(userId, state, opts) { + const addMember = function(userId, state, opts) { if (!state) { state = "join"; } @@ -648,9 +648,9 @@ describe("Room", function() { stateLookup = {}; room.currentState.getStateEvents.andCallFake(function(type, key) { if (key === undefined) { - let prefix = type + "$"; - let list = []; - for (let stateBlob in stateLookup) { + const prefix = type + "$"; + const list = []; + for (const stateBlob in stateLookup) { if (!stateLookup.hasOwnProperty(stateBlob)) { continue; } @@ -664,8 +664,8 @@ describe("Room", function() { } }); room.currentState.getMembers.andCallFake(function() { - let memberEvents = room.currentState.getStateEvents("m.room.member"); - let members = []; + const memberEvents = room.currentState.getStateEvents("m.room.member"); + const members = []; for (let i = 0; i < memberEvents.length; i++) { members.push({ name: memberEvents[i].event.content && @@ -679,8 +679,8 @@ describe("Room", function() { return members; }); room.currentState.getMember.andCallFake(function(userId) { - let memberEvent = room.currentState.getStateEvents( - "m.room.member", userId + const memberEvent = room.currentState.getStateEvents( + "m.room.member", userId, ); return { name: memberEvent.event.content && @@ -696,7 +696,7 @@ describe("Room", function() { describe("Room.recalculate => Stripped State Events", function() { it("should set stripped state events as actual state events if the " + "room is an invite room", function() { - let roomName = "flibble"; + const roomName = "flibble"; addMember(userA, "invite"); stateLookup["m.room.member$" + userA].event.invite_room_state = [ @@ -712,7 +712,7 @@ describe("Room", function() { room.recalculate(userA); expect(room.currentState.setStateEvents).toHaveBeenCalled(); // first call, first arg (which is an array), first element in array - let fakeEvent = room.currentState.setStateEvents.calls[0].args[0][0]; + const fakeEvent = room.currentState.setStateEvents.calls[0].args[0][0]; expect(fakeEvent.getContent()).toEqual({ name: roomName, }); @@ -745,9 +745,9 @@ describe("Room", function() { addMember(userC); addMember(userD); room.recalculate(userA); - let name = room.name; + const name = room.name; // we expect at least 1 member to be mentioned - let others = [userB, userC, userD]; + const others = [userB, userC, userD]; let found = false; for (let i = 0; i < others.length; i++) { if (name.indexOf(others[i]) !== -1) { @@ -766,7 +766,7 @@ describe("Room", function() { addMember(userB); addMember(userC); room.recalculate(userA); - let name = room.name; + const name = room.name; expect(name.indexOf(userB)).not.toEqual(-1, name); expect(name.indexOf(userC)).not.toEqual(-1, name); }); @@ -779,7 +779,7 @@ describe("Room", function() { addMember(userB); addMember(userC); room.recalculate(userA); - let name = room.name; + const name = room.name; expect(name.indexOf(userB)).not.toEqual(-1, name); expect(name.indexOf(userC)).not.toEqual(-1, name); }); @@ -791,7 +791,7 @@ describe("Room", function() { addMember(userA); addMember(userB); room.recalculate(userA); - let name = room.name; + const name = room.name; expect(name.indexOf(userB)).not.toEqual(-1, name); }); @@ -802,7 +802,7 @@ describe("Room", function() { addMember(userA); addMember(userB); room.recalculate(userA); - let name = room.name; + const name = room.name; expect(name.indexOf(userB)).not.toEqual(-1, name); }); @@ -812,47 +812,47 @@ describe("Room", function() { addMember(userA, "invite", {user: userB}); addMember(userB); room.recalculate(userA); - let name = room.name; + const name = room.name; expect(name.indexOf(userB)).not.toEqual(-1, name); }); it("should show the room alias if one exists for private " + "(invite join_rules) rooms if a room name doesn't exist.", function() { - let alias = "#room_alias:here"; + const alias = "#room_alias:here"; setJoinRule("invite"); setAliases([alias, "#another:one"]); room.recalculate(userA); - let name = room.name; + const name = room.name; expect(name).toEqual(alias); }); it("should show the room alias if one exists for public " + "(public join_rules) rooms if a room name doesn't exist.", function() { - let alias = "#room_alias:here"; + const alias = "#room_alias:here"; setJoinRule("public"); setAliases([alias, "#another:one"]); room.recalculate(userA); - let name = room.name; + const name = room.name; expect(name).toEqual(alias); }); it("should show the room name if one exists for private " + "(invite join_rules) rooms.", function() { - let roomName = "A mighty name indeed"; + const roomName = "A mighty name indeed"; setJoinRule("invite"); setRoomName(roomName); room.recalculate(userA); - let name = room.name; + const name = room.name; expect(name).toEqual(roomName); }); it("should show the room name if one exists for public " + "(public join_rules) rooms.", function() { - let roomName = "A mighty name indeed"; + const roomName = "A mighty name indeed"; setJoinRule("public"); setRoomName(roomName); room.recalculate(userA); - let name = room.name; + const name = room.name; expect(name).toEqual(roomName); }); @@ -861,7 +861,7 @@ describe("Room", function() { setJoinRule("invite"); addMember(userA); room.recalculate(userA); - let name = room.name; + const name = room.name; expect(name).toEqual("Empty room"); }); @@ -870,7 +870,7 @@ describe("Room", function() { setJoinRule("public"); addMember(userA); room.recalculate(userA); - let name = room.name; + const name = room.name; expect(name).toEqual("Empty room"); }); @@ -878,7 +878,7 @@ describe("Room", function() { "alias or members in the room.", function() { room.recalculate(userA); - let name = room.name; + const name = room.name; expect(name).toEqual("Empty room"); }); @@ -889,7 +889,7 @@ describe("Room", function() { addMember(userA, 'join', {name: "Alice"}); addMember(userB, "invite", {user: userA}); room.recalculate(userB); - let name = room.name; + const name = room.name; expect(name).toEqual("Invite from Alice"); }); @@ -899,20 +899,20 @@ describe("Room", function() { addMember(userA); addMember(userB, "invite", {user: userA}); room.recalculate(userB); - let name = room.name; + const name = room.name; expect(name).toEqual("Invite from " + userA); }); }); }); describe("receipts", function() { - let eventToAck = utils.mkMessage({ + const eventToAck = utils.mkMessage({ room: roomId, user: userA, msg: "PLEASE ACKNOWLEDGE MY EXISTENCE", event: true, }); function mkReceipt(roomId, records) { - let content = {}; + const content = {}; records.forEach(function(r) { if (!content[r.eventId]) { content[r.eventId] = {}; @@ -944,7 +944,7 @@ describe("Room", function() { describe("addReceipt", function() { it("should store the receipt so it can be obtained via getReceiptsForEvent", function() { - let ts = 13787898424; + const ts = 13787898424; room.addReceipt(mkReceipt(roomId, [ mkRecord(eventToAck.getId(), "m.read", userB, ts), ])); @@ -959,12 +959,12 @@ describe("Room", function() { it("should emit an event when a receipt is added", function() { - let listener = jasmine.createSpy('spy'); + const listener = jasmine.createSpy('spy'); room.on("Room.receipt", listener); - let ts = 13787898424; + const ts = 13787898424; - let receiptEvent = mkReceipt(roomId, [ + const receiptEvent = mkReceipt(roomId, [ mkRecord(eventToAck.getId(), "m.read", userB, ts), ]); @@ -973,15 +973,15 @@ describe("Room", function() { }); it("should clobber receipts based on type and user ID", function() { - let nextEventToAck = utils.mkMessage({ + const nextEventToAck = utils.mkMessage({ room: roomId, user: userA, msg: "I AM HERE YOU KNOW", event: true, }); - let ts = 13787898424; + const ts = 13787898424; room.addReceipt(mkReceipt(roomId, [ mkRecord(eventToAck.getId(), "m.read", userB, ts), ])); - let ts2 = 13787899999; + const ts2 = 13787899999; room.addReceipt(mkReceipt(roomId, [ mkRecord(nextEventToAck.getId(), "m.read", userB, ts2), ])); @@ -996,27 +996,27 @@ describe("Room", function() { }); it("should persist multiple receipts for a single event ID", function() { - let ts = 13787898424; + const ts = 13787898424; room.addReceipt(mkReceipt(roomId, [ mkRecord(eventToAck.getId(), "m.read", userB, ts), mkRecord(eventToAck.getId(), "m.read", userC, ts), mkRecord(eventToAck.getId(), "m.read", userD, ts), ])); expect(room.getUsersReadUpTo(eventToAck)).toEqual( - [userB, userC, userD] + [userB, userC, userD], ); }); it("should persist multiple receipts for a single receipt type", function() { - let eventTwo = utils.mkMessage({ + const eventTwo = utils.mkMessage({ room: roomId, user: userA, msg: "2222", event: true, }); - let eventThree = utils.mkMessage({ + const eventThree = utils.mkMessage({ room: roomId, user: userA, msg: "3333", event: true, }); - let ts = 13787898424; + const ts = 13787898424; room.addReceipt(mkReceipt(roomId, [ mkRecord(eventToAck.getId(), "m.read", userB, ts), mkRecord(eventTwo.getId(), "m.read", userC, ts), @@ -1059,7 +1059,7 @@ describe("Room", function() { }); it("should prioritise the most recent event", function() { - let events = [ + const events = [ utils.mkMessage({ room: roomId, user: userA, msg: "1111", event: true, @@ -1075,7 +1075,7 @@ describe("Room", function() { ]; room.addLiveEvents(events); - let ts = 13787898424; + const ts = 13787898424; // check it initialises correctly room.addReceipt(mkReceipt(roomId, [ @@ -1099,7 +1099,7 @@ describe("Room", function() { describe("getUsersReadUpTo", function() { it("should return user IDs read up to the given event", function() { - let ts = 13787898424; + const ts = 13787898424; room.addReceipt(mkReceipt(roomId, [ mkRecord(eventToAck.getId(), "m.read", userB, ts), ])); @@ -1110,7 +1110,7 @@ describe("Room", function() { describe("tags", function() { function mkTags(roomId, tags) { - let content = { "tags": tags }; + const content = { "tags": tags }; return new MatrixEvent({ content: content, room_id: roomId, @@ -1122,7 +1122,7 @@ describe("Room", function() { it("should set tags on rooms from event stream so " + "they can be obtained by the tags property", function() { - let tags = { "m.foo": { "order": 0.5 } }; + const tags = { "m.foo": { "order": 0.5 } }; room.addTags(mkTags(roomId, tags)); expect(room.tags).toEqual(tags); }); @@ -1130,11 +1130,11 @@ describe("Room", function() { it("should emit Room.tags event when new tags are " + "received on the event stream", function() { - let listener = jasmine.createSpy('spy'); + const listener = jasmine.createSpy('spy'); room.on("Room.tags", listener); - let tags = { "m.foo": { "order": 0.5 } }; - let event = mkTags(roomId, tags); + const tags = { "m.foo": { "order": 0.5 } }; + const event = mkTags(roomId, tags); room.addTags(event); expect(listener).toHaveBeenCalledWith(event, room); }); @@ -1147,27 +1147,27 @@ describe("Room", function() { describe("addPendingEvent", function() { it("should add pending events to the pendingEventList if " + "pendingEventOrdering == 'detached'", function() { - let room = new Room(roomId, { + const room = new Room(roomId, { pendingEventOrdering: "detached", }); - let eventA = utils.mkMessage({ + const eventA = utils.mkMessage({ room: roomId, user: userA, msg: "remote 1", event: true, }); - let eventB = utils.mkMessage({ + const eventB = utils.mkMessage({ room: roomId, user: userA, msg: "local 1", event: true, }); eventB.status = EventStatus.SENDING; - let eventC = utils.mkMessage({ + const eventC = utils.mkMessage({ room: roomId, user: userA, msg: "remote 2", event: true, }); room.addLiveEvents([eventA]); room.addPendingEvent(eventB, "TXN1"); room.addLiveEvents([eventC]); expect(room.timeline).toEqual( - [eventA, eventC] + [eventA, eventC], ); expect(room.getPendingEvents()).toEqual( - [eventB] + [eventB], ); }); @@ -1176,39 +1176,39 @@ describe("Room", function() { room = new Room(roomId, { pendingEventOrdering: "chronological", }); - let eventA = utils.mkMessage({ + const eventA = utils.mkMessage({ room: roomId, user: userA, msg: "remote 1", event: true, }); - let eventB = utils.mkMessage({ + const eventB = utils.mkMessage({ room: roomId, user: userA, msg: "local 1", event: true, }); eventB.status = EventStatus.SENDING; - let eventC = utils.mkMessage({ + const eventC = utils.mkMessage({ room: roomId, user: userA, msg: "remote 2", event: true, }); room.addLiveEvents([eventA]); room.addPendingEvent(eventB, "TXN1"); room.addLiveEvents([eventC]); expect(room.timeline).toEqual( - [eventA, eventB, eventC] + [eventA, eventB, eventC], ); }); }); describe("updatePendingEvent", function() { it("should remove cancelled events from the pending list", function() { - let room = new Room(roomId, { + const room = new Room(roomId, { pendingEventOrdering: "detached", }); - let eventA = utils.mkMessage({ + const eventA = utils.mkMessage({ room: roomId, user: userA, event: true, }); eventA.status = EventStatus.SENDING; - let eventId = eventA.getId(); + const eventId = eventA.getId(); room.addPendingEvent(eventA, "TXN1"); expect(room.getPendingEvents()).toEqual( - [eventA] + [eventA], ); // the event has to have been failed or queued before it can be @@ -1233,16 +1233,16 @@ describe("Room", function() { it("should remove cancelled events from the timeline", function() { - let room = new Room(roomId); - let eventA = utils.mkMessage({ + const room = new Room(roomId); + const eventA = utils.mkMessage({ room: roomId, user: userA, event: true, }); eventA.status = EventStatus.SENDING; - let eventId = eventA.getId(); + const eventId = eventA.getId(); room.addPendingEvent(eventA, "TXN1"); expect(room.getLiveTimeline().getEvents()).toEqual( - [eventA] + [eventA], ); // the event has to have been failed or queued before it can be diff --git a/spec/unit/scheduler.spec.js b/spec/unit/scheduler.spec.js index cf50c36df..fd3b9ab2e 100644 --- a/spec/unit/scheduler.spec.js +++ b/spec/unit/scheduler.spec.js @@ -1,21 +1,22 @@ // This file had a function whose name is all caps, which displeases eslint /* eslint new-cap: "off" */ -let q = require("q"); -let sdk = require("../.."); -let MatrixScheduler = sdk.MatrixScheduler; -let MatrixError = sdk.MatrixError; -let utils = require("../test-utils"); +const q = require("q"); +const sdk = require("../.."); +const MatrixScheduler = sdk.MatrixScheduler; +const MatrixError = sdk.MatrixError; +const utils = require("../test-utils"); describe("MatrixScheduler", function() { let scheduler; - let retryFn, queueFn; + let retryFn; + let queueFn; let defer; - let roomId = "!foo:bar"; - let eventA = utils.mkMessage({ + const roomId = "!foo:bar"; + const eventA = utils.mkMessage({ user: "@alice:bar", room: roomId, event: true, }); - let eventB = utils.mkMessage({ + const eventB = utils.mkMessage({ user: "@alice:bar", room: roomId, event: true, }); @@ -45,8 +46,8 @@ describe("MatrixScheduler", function() { queueFn = function() { return "one_big_queue"; }; - let deferA = q.defer(); - let deferB = q.defer(); + const deferA = q.defer(); + const deferB = q.defer(); let resolvedA = false; scheduler.setProcessFunction(function(event) { if (resolvedA) { @@ -69,8 +70,8 @@ describe("MatrixScheduler", function() { it("should invoke the retryFn on failure and wait the amount of time specified", function(done) { - let waitTimeMs = 1500; - let retryDefer = q.defer(); + const waitTimeMs = 1500; + const retryDefer = q.defer(); retryFn = function() { retryDefer.resolve(); return waitTimeMs; @@ -115,8 +116,8 @@ describe("MatrixScheduler", function() { return "yep"; }; - let deferA = q.defer(); - let deferB = q.defer(); + const deferA = q.defer(); + const deferB = q.defer(); let procCount = 0; scheduler.setProcessFunction(function(ev) { procCount += 1; @@ -130,7 +131,7 @@ describe("MatrixScheduler", function() { expect(procCount).toBeLessThan(3); }); - let globalA = scheduler.queueEvent(eventA); + const globalA = scheduler.queueEvent(eventA); scheduler.queueEvent(eventB); expect(procCount).toEqual(1); @@ -148,10 +149,10 @@ describe("MatrixScheduler", function() { // Expect to have processFn invoked for A&B. // Resolve A. // Expect to have processFn invoked for D. - let eventC = utils.mkMessage({user: "@a:bar", room: roomId, event: true}); - let eventD = utils.mkMessage({user: "@b:bar", room: roomId, event: true}); + const eventC = utils.mkMessage({user: "@a:bar", room: roomId, event: true}); + const eventD = utils.mkMessage({user: "@b:bar", room: roomId, event: true}); - let buckets = {}; + const buckets = {}; buckets[eventA.getId()] = "queue_A"; buckets[eventD.getId()] = "queue_A"; buckets[eventB.getId()] = "queue_B"; @@ -164,12 +165,12 @@ describe("MatrixScheduler", function() { return buckets[event.getId()]; }; - let expectOrder = [ + const expectOrder = [ eventA.getId(), eventB.getId(), eventD.getId(), ]; - let deferA = q.defer(); + const deferA = q.defer(); scheduler.setProcessFunction(function(event) { - let id = expectOrder.shift(); + const id = expectOrder.shift(); expect(id).toEqual(event.getId()); if (expectOrder.length === 0) { done(); @@ -200,7 +201,7 @@ describe("MatrixScheduler", function() { queueFn = function() { return "yep"; }; - let prom = scheduler.queueEvent(eventA); + const prom = scheduler.queueEvent(eventA); expect(prom).toBeDefined(); expect(prom.then).toBeDefined(); }); @@ -228,15 +229,15 @@ describe("MatrixScheduler", function() { }; scheduler.queueEvent(eventA); scheduler.queueEvent(eventB); - let queue = scheduler.getQueueForEvent(eventA); + const queue = scheduler.getQueueForEvent(eventA); expect(queue.length).toEqual(2); expect(queue).toEqual([eventA, eventB]); // modify the queue - let eventC = utils.mkMessage( - {user: "@a:bar", room: roomId, event: true} + const eventC = utils.mkMessage( + {user: "@a:bar", room: roomId, event: true}, ); queue.push(eventC); - let queueAgain = scheduler.getQueueForEvent(eventA); + const queueAgain = scheduler.getQueueForEvent(eventA); expect(queueAgain.length).toEqual(2); }); @@ -247,9 +248,9 @@ describe("MatrixScheduler", function() { }; scheduler.queueEvent(eventA); scheduler.queueEvent(eventB); - let queue = scheduler.getQueueForEvent(eventA); + const queue = scheduler.getQueueForEvent(eventA); queue[1].event.content.body = "foo"; - let queueAgain = scheduler.getQueueForEvent(eventA); + const queueAgain = scheduler.getQueueForEvent(eventA); expect(queueAgain[1].event.content.body).toEqual("foo"); }); }); @@ -312,40 +313,40 @@ describe("MatrixScheduler", function() { expect(MatrixScheduler.QUEUE_MESSAGES( utils.mkMembership({ user: "@alice:bar", room: roomId, mship: "join", event: true, - }) + }), )).toEqual(null); }); }); describe("RETRY_BACKOFF_RATELIMIT", function() { it("should wait at least the time given on M_LIMIT_EXCEEDED", function() { - let res = MatrixScheduler.RETRY_BACKOFF_RATELIMIT( + const res = MatrixScheduler.RETRY_BACKOFF_RATELIMIT( eventA, 1, new MatrixError({ errcode: "M_LIMIT_EXCEEDED", retry_after_ms: 5000, - }) + }), ); expect(res >= 500).toBe(true, "Didn't wait long enough."); }); it("should give up after 5 attempts", function() { - let res = MatrixScheduler.RETRY_BACKOFF_RATELIMIT( - eventA, 5, {} + const res = MatrixScheduler.RETRY_BACKOFF_RATELIMIT( + eventA, 5, {}, ); expect(res).toBe(-1, "Didn't give up."); }); it("should do exponential backoff", function() { expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT( - eventA, 1, {} + eventA, 1, {}, )).toEqual(2000); expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT( - eventA, 2, {} + eventA, 2, {}, )).toEqual(4000); expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT( - eventA, 3, {} + eventA, 3, {}, )).toEqual(8000); expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT( - eventA, 4, {} + eventA, 4, {}, )).toEqual(16000); }); }); diff --git a/spec/unit/timeline-window.spec.js b/spec/unit/timeline-window.spec.js index 2906d7807..68cab72b0 100644 --- a/spec/unit/timeline-window.spec.js +++ b/spec/unit/timeline-window.spec.js @@ -1,14 +1,14 @@ "use strict"; -let q = require("q"); -let sdk = require("../.."); -let EventTimeline = sdk.EventTimeline; -let TimelineWindow = sdk.TimelineWindow; -let TimelineIndex = require("../../lib/timeline-window").TimelineIndex; +const q = require("q"); +const sdk = require("../.."); +const EventTimeline = sdk.EventTimeline; +const TimelineWindow = sdk.TimelineWindow; +const TimelineIndex = require("../../lib/timeline-window").TimelineIndex; -let utils = require("../test-utils"); +const utils = require("../test-utils"); -let ROOM_ID = "roomId"; -let USER_ID = "userId"; +const ROOM_ID = "roomId"; +const USER_ID = "userId"; /* * create a timeline with a bunch (default 3) events. @@ -23,12 +23,12 @@ function createTimeline(numEvents, baseIndex) { } // XXX: this is a horrid hack - let timelineSet = { room: { roomId: ROOM_ID }}; + const timelineSet = { room: { roomId: ROOM_ID }}; timelineSet.room.getUnfilteredTimelineSet = function() { return timelineSet; }; - let timeline = new EventTimeline(timelineSet); + const timeline = new EventTimeline(timelineSet); // add the events after the baseIndex first addEventsToTimeline(timeline, numEvents - baseIndex, false); @@ -46,7 +46,7 @@ function addEventsToTimeline(timeline, numEvents, atStart) { utils.mkMessage({ room: ROOM_ID, user: USER_ID, event: true, - }), atStart + }), atStart, ); } } @@ -56,8 +56,8 @@ function addEventsToTimeline(timeline, numEvents, atStart) { * create a pair of linked timelines */ function createLinkedTimelines() { - let tl1 = createTimeline(); - let tl2 = createTimeline(); + const tl1 = createTimeline(); + const tl2 = createTimeline(); tl1.setNeighbouringTimeline(tl2, EventTimeline.FORWARDS); tl2.setNeighbouringTimeline(tl1, EventTimeline.BACKWARDS); return [tl1, tl2]; @@ -71,41 +71,42 @@ describe("TimelineIndex", function() { describe("minIndex", function() { it("should return the min index relative to BaseIndex", function() { - let timelineIndex = new TimelineIndex(createTimeline(), 0); + const timelineIndex = new TimelineIndex(createTimeline(), 0); expect(timelineIndex.minIndex()).toEqual(-1); }); }); describe("maxIndex", function() { it("should return the max index relative to BaseIndex", function() { - let timelineIndex = new TimelineIndex(createTimeline(), 0); + const timelineIndex = new TimelineIndex(createTimeline(), 0); expect(timelineIndex.maxIndex()).toEqual(2); }); }); describe("advance", function() { it("should advance up to the end of the timeline", function() { - let timelineIndex = new TimelineIndex(createTimeline(), 0); - let result = timelineIndex.advance(3); + const timelineIndex = new TimelineIndex(createTimeline(), 0); + const result = timelineIndex.advance(3); expect(result).toEqual(2); expect(timelineIndex.index).toEqual(2); }); it("should retreat back to the start of the timeline", function() { - let timelineIndex = new TimelineIndex(createTimeline(), 0); - let result = timelineIndex.advance(-2); + const timelineIndex = new TimelineIndex(createTimeline(), 0); + const result = timelineIndex.advance(-2); expect(result).toEqual(-1); expect(timelineIndex.index).toEqual(-1); }); it("should advance into the next timeline", function() { - let timelines = createLinkedTimelines(); - let tl1 = timelines[0], tl2 = timelines[1]; + const timelines = createLinkedTimelines(); + const tl1 = timelines[0]; + const tl2 = timelines[1]; // initialise the index pointing at the end of the first timeline - let timelineIndex = new TimelineIndex(tl1, 2); + const timelineIndex = new TimelineIndex(tl1, 2); - let result = timelineIndex.advance(1); + const result = timelineIndex.advance(1); expect(result).toEqual(1); expect(timelineIndex.timeline).toBe(tl2); @@ -116,14 +117,15 @@ describe("TimelineIndex", function() { }); it("should retreat into the previous timeline", function() { - let timelines = createLinkedTimelines(); - let tl1 = timelines[0], tl2 = timelines[1]; + const timelines = createLinkedTimelines(); + const tl1 = timelines[0]; + const tl2 = timelines[1]; // initialise the index pointing at the start of the second // timeline - let timelineIndex = new TimelineIndex(tl2, -1); + const timelineIndex = new TimelineIndex(tl2, -1); - let result = timelineIndex.advance(-1); + const result = timelineIndex.advance(-1); expect(result).toEqual(-1); expect(timelineIndex.timeline).toBe(tl1); expect(timelineIndex.index).toEqual(1); @@ -132,8 +134,8 @@ describe("TimelineIndex", function() { describe("retreat", function() { it("should retreat up to the start of the timeline", function() { - let timelineIndex = new TimelineIndex(createTimeline(), 0); - let result = timelineIndex.retreat(2); + const timelineIndex = new TimelineIndex(createTimeline(), 0); + const result = timelineIndex.retreat(2); expect(result).toEqual(1); expect(timelineIndex.index).toEqual(-1); }); @@ -146,7 +148,8 @@ describe("TimelineWindow", function() { * create a dummy eventTimelineSet and client, and a TimelineWindow * attached to them. */ - let timelineSet, client; + let timelineSet; + let client; function createWindow(timeline, opts) { timelineSet = {}; client = {}; @@ -164,50 +167,50 @@ describe("TimelineWindow", function() { describe("load", function() { it("should initialise from the live timeline", function(done) { - let liveTimeline = createTimeline(); - let room = {}; + const liveTimeline = createTimeline(); + const room = {}; room.getLiveTimeline = function() { return liveTimeline; }; - let timelineWindow = new TimelineWindow(undefined, room); + const timelineWindow = new TimelineWindow(undefined, room); timelineWindow.load(undefined, 2).then(function() { - let expectedEvents = liveTimeline.getEvents().slice(1); + const expectedEvents = liveTimeline.getEvents().slice(1); expect(timelineWindow.getEvents()).toEqual(expectedEvents); }).catch(utils.failTest).done(done); }); it("should initialise from a specific event", function(done) { - let timeline = createTimeline(); - let eventId = timeline.getEvents()[1].getId(); + const timeline = createTimeline(); + const eventId = timeline.getEvents()[1].getId(); - let timelineSet = {}; - let client = {}; + const timelineSet = {}; + const client = {}; client.getEventTimeline = function(timelineSet0, eventId0) { expect(timelineSet0).toBe(timelineSet); expect(eventId0).toEqual(eventId); return q(timeline); }; - let timelineWindow = new TimelineWindow(client, timelineSet); + const timelineWindow = new TimelineWindow(client, timelineSet); timelineWindow.load(eventId, 3).then(function() { - let expectedEvents = timeline.getEvents(); + const expectedEvents = timeline.getEvents(); expect(timelineWindow.getEvents()).toEqual(expectedEvents); }).catch(utils.failTest).done(done); }); it("canPaginate should return false until load has returned", function(done) { - let timeline = createTimeline(); + const timeline = createTimeline(); timeline.setPaginationToken("toktok1", EventTimeline.BACKWARDS); timeline.setPaginationToken("toktok2", EventTimeline.FORWARDS); - let eventId = timeline.getEvents()[1].getId(); + const eventId = timeline.getEvents()[1].getId(); - let timelineSet = {}; - let client = {}; + const timelineSet = {}; + const client = {}; - let timelineWindow = new TimelineWindow(client, timelineSet); + const timelineWindow = new TimelineWindow(client, timelineSet); client.getEventTimeline = function(timelineSet0, eventId0) { expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) @@ -218,7 +221,7 @@ describe("TimelineWindow", function() { }; timelineWindow.load(eventId, 3).then(function() { - let expectedEvents = timeline.getEvents(); + const expectedEvents = timeline.getEvents(); expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) .toBe(true); @@ -231,12 +234,12 @@ describe("TimelineWindow", function() { describe("pagination", function() { it("should be able to advance across the initial timeline", function(done) { - let timeline = createTimeline(); - let eventId = timeline.getEvents()[1].getId(); - let timelineWindow = createWindow(timeline); + const timeline = createTimeline(); + const eventId = timeline.getEvents()[1].getId(); + const timelineWindow = createWindow(timeline); timelineWindow.load(eventId, 1).then(function() { - let expectedEvents = [timeline.getEvents()[1]]; + const expectedEvents = [timeline.getEvents()[1]]; expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) @@ -247,7 +250,7 @@ describe("TimelineWindow", function() { return timelineWindow.paginate(EventTimeline.FORWARDS, 2); }).then(function(success) { expect(success).toBe(true); - let expectedEvents = timeline.getEvents().slice(1); + const expectedEvents = timeline.getEvents().slice(1); expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) @@ -262,7 +265,7 @@ describe("TimelineWindow", function() { return timelineWindow.paginate(EventTimeline.BACKWARDS, 2); }).then(function(success) { expect(success).toBe(true); - let expectedEvents = timeline.getEvents(); + const expectedEvents = timeline.getEvents(); expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) @@ -276,12 +279,12 @@ describe("TimelineWindow", function() { }); it("should advance into next timeline", function(done) { - let tls = createLinkedTimelines(); - let eventId = tls[0].getEvents()[1].getId(); - let timelineWindow = createWindow(tls[0], {windowLimit: 5}); + const tls = createLinkedTimelines(); + const eventId = tls[0].getEvents()[1].getId(); + const timelineWindow = createWindow(tls[0], {windowLimit: 5}); timelineWindow.load(eventId, 3).then(function() { - let expectedEvents = tls[0].getEvents(); + const expectedEvents = tls[0].getEvents(); expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) @@ -292,7 +295,7 @@ describe("TimelineWindow", function() { return timelineWindow.paginate(EventTimeline.FORWARDS, 2); }).then(function(success) { expect(success).toBe(true); - let expectedEvents = tls[0].getEvents() + const expectedEvents = tls[0].getEvents() .concat(tls[1].getEvents().slice(0, 2)); expect(timelineWindow.getEvents()).toEqual(expectedEvents); @@ -306,7 +309,7 @@ describe("TimelineWindow", function() { expect(success).toBe(true); // the windowLimit should have made us drop an event from // tls[0] - let expectedEvents = tls[0].getEvents().slice(1) + const expectedEvents = tls[0].getEvents().slice(1) .concat(tls[1].getEvents()); expect(timelineWindow.getEvents()).toEqual(expectedEvents); @@ -321,12 +324,12 @@ describe("TimelineWindow", function() { }); it("should retreat into previous timeline", function(done) { - let tls = createLinkedTimelines(); - let eventId = tls[1].getEvents()[1].getId(); - let timelineWindow = createWindow(tls[1], {windowLimit: 5}); + const tls = createLinkedTimelines(); + const eventId = tls[1].getEvents()[1].getId(); + const timelineWindow = createWindow(tls[1], {windowLimit: 5}); timelineWindow.load(eventId, 3).then(function() { - let expectedEvents = tls[1].getEvents(); + const expectedEvents = tls[1].getEvents(); expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) @@ -337,7 +340,7 @@ describe("TimelineWindow", function() { return timelineWindow.paginate(EventTimeline.BACKWARDS, 2); }).then(function(success) { expect(success).toBe(true); - let expectedEvents = tls[0].getEvents().slice(1, 3) + const expectedEvents = tls[0].getEvents().slice(1, 3) .concat(tls[1].getEvents()); expect(timelineWindow.getEvents()).toEqual(expectedEvents); @@ -351,7 +354,7 @@ describe("TimelineWindow", function() { expect(success).toBe(true); // the windowLimit should have made us drop an event from // tls[1] - let expectedEvents = tls[0].getEvents() + const expectedEvents = tls[0].getEvents() .concat(tls[1].getEvents().slice(0, 2)); expect(timelineWindow.getEvents()).toEqual(expectedEvents); @@ -366,11 +369,11 @@ describe("TimelineWindow", function() { }); it("should make forward pagination requests", function(done) { - let timeline = createTimeline(); + const timeline = createTimeline(); timeline.setPaginationToken("toktok", EventTimeline.FORWARDS); - let timelineWindow = createWindow(timeline, {windowLimit: 5}); - let eventId = timeline.getEvents()[1].getId(); + const timelineWindow = createWindow(timeline, {windowLimit: 5}); + const eventId = timeline.getEvents()[1].getId(); client.paginateEventTimeline = function(timeline0, opts) { expect(timeline0).toBe(timeline); @@ -382,7 +385,7 @@ describe("TimelineWindow", function() { }; timelineWindow.load(eventId, 3).then(function() { - let expectedEvents = timeline.getEvents(); + const expectedEvents = timeline.getEvents(); expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) @@ -392,18 +395,18 @@ describe("TimelineWindow", function() { return timelineWindow.paginate(EventTimeline.FORWARDS, 2); }).then(function(success) { expect(success).toBe(true); - let expectedEvents = timeline.getEvents().slice(0, 5); + const expectedEvents = timeline.getEvents().slice(0, 5); expect(timelineWindow.getEvents()).toEqual(expectedEvents); }).catch(utils.failTest).done(done); }); it("should make backward pagination requests", function(done) { - let timeline = createTimeline(); + const timeline = createTimeline(); timeline.setPaginationToken("toktok", EventTimeline.BACKWARDS); - let timelineWindow = createWindow(timeline, {windowLimit: 5}); - let eventId = timeline.getEvents()[1].getId(); + const timelineWindow = createWindow(timeline, {windowLimit: 5}); + const eventId = timeline.getEvents()[1].getId(); client.paginateEventTimeline = function(timeline0, opts) { expect(timeline0).toBe(timeline); @@ -415,7 +418,7 @@ describe("TimelineWindow", function() { }; timelineWindow.load(eventId, 3).then(function() { - let expectedEvents = timeline.getEvents(); + const expectedEvents = timeline.getEvents(); expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) @@ -425,18 +428,18 @@ describe("TimelineWindow", function() { return timelineWindow.paginate(EventTimeline.BACKWARDS, 2); }).then(function(success) { expect(success).toBe(true); - let expectedEvents = timeline.getEvents().slice(1, 6); + const expectedEvents = timeline.getEvents().slice(1, 6); expect(timelineWindow.getEvents()).toEqual(expectedEvents); }).catch(utils.failTest).done(done); }); it("should limit the number of unsuccessful pagination requests", function(done) { - let timeline = createTimeline(); + const timeline = createTimeline(); timeline.setPaginationToken("toktok", EventTimeline.FORWARDS); - let timelineWindow = createWindow(timeline, {windowLimit: 5}); - let eventId = timeline.getEvents()[1].getId(); + const timelineWindow = createWindow(timeline, {windowLimit: 5}); + const eventId = timeline.getEvents()[1].getId(); let paginateCount = 0; client.paginateEventTimeline = function(timeline0, opts) { @@ -448,7 +451,7 @@ describe("TimelineWindow", function() { }; timelineWindow.load(eventId, 3).then(function() { - let expectedEvents = timeline.getEvents(); + const expectedEvents = timeline.getEvents(); expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) @@ -459,7 +462,7 @@ describe("TimelineWindow", function() { }).then(function(success) { expect(success).toBe(false); expect(paginateCount).toEqual(3); - let expectedEvents = timeline.getEvents().slice(0, 3); + const expectedEvents = timeline.getEvents().slice(0, 3); expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) diff --git a/spec/unit/user.spec.js b/spec/unit/user.spec.js index 1ed0a0206..51a8f68d1 100644 --- a/spec/unit/user.spec.js +++ b/spec/unit/user.spec.js @@ -1,10 +1,10 @@ "use strict"; -let sdk = require("../.."); -let User = sdk.User; -let utils = require("../test-utils"); +const sdk = require("../.."); +const User = sdk.User; +const utils = require("../test-utils"); describe("User", function() { - let userId = "@alice:bar"; + const userId = "@alice:bar"; let user; beforeEach(function() { @@ -13,7 +13,7 @@ describe("User", function() { }); describe("setPresenceEvent", function() { - let event = utils.mkEvent({ + const event = utils.mkEvent({ type: "m.presence", content: { presence: "online", user_id: userId, diff --git a/spec/unit/utils.spec.js b/spec/unit/utils.spec.js index 626820907..1836ad218 100644 --- a/spec/unit/utils.spec.js +++ b/spec/unit/utils.spec.js @@ -1,6 +1,6 @@ "use strict"; -let utils = require("../../lib/utils"); -let testUtils = require("../test-utils"); +const utils = require("../../lib/utils"); +const testUtils = require("../test-utils"); describe("utils", function() { beforeEach(function() { @@ -9,32 +9,32 @@ describe("utils", function() { describe("encodeParams", function() { it("should url encode and concat with &s", function() { - let params = { + const params = { foo: "bar", baz: "beer@", }; expect(utils.encodeParams(params)).toEqual( - "foo=bar&baz=beer%40" + "foo=bar&baz=beer%40", ); }); }); describe("encodeUri", function() { it("should replace based on object keys and url encode", function() { - let path = "foo/bar/%something/%here"; - let vals = { + const path = "foo/bar/%something/%here"; + const vals = { "%something": "baz", "%here": "beer@", }; expect(utils.encodeUri(path, vals)).toEqual( - "foo/bar/baz/beer%40" + "foo/bar/baz/beer%40", ); }); }); describe("forEach", function() { it("should be invoked for each element", function() { - let arr = []; + const arr = []; utils.forEach([55, 66, 77], function(element) { arr.push(element); }); @@ -44,50 +44,50 @@ describe("utils", function() { describe("findElement", function() { it("should find only 1 element if there is a match", function() { - let matchFn = function() { + const matchFn = function() { return true; }; - let arr = [55, 66, 77]; + const arr = [55, 66, 77]; expect(utils.findElement(arr, matchFn)).toEqual(55); }); it("should be able to find in reverse order", function() { - let matchFn = function() { + const matchFn = function() { return true; }; - let arr = [55, 66, 77]; + const arr = [55, 66, 77]; expect(utils.findElement(arr, matchFn, true)).toEqual(77); }); it("should find nothing if the function never returns true", function() { - let matchFn = function() { + const matchFn = function() { return false; }; - let arr = [55, 66, 77]; + const arr = [55, 66, 77]; expect(utils.findElement(arr, matchFn)).toBeFalsy(); }); }); describe("removeElement", function() { it("should remove only 1 element if there is a match", function() { - let matchFn = function() { + const matchFn = function() { return true; }; - let arr = [55, 66, 77]; + const arr = [55, 66, 77]; utils.removeElement(arr, matchFn); expect(arr).toEqual([66, 77]); }); it("should be able to remove in reverse order", function() { - let matchFn = function() { + const matchFn = function() { return true; }; - let arr = [55, 66, 77]; + const arr = [55, 66, 77]; utils.removeElement(arr, matchFn, true); expect(arr).toEqual([55, 66]); }); it("should remove nothing if the function never returns true", function() { - let matchFn = function() { + const matchFn = function() { return false; }; - let arr = [55, 66, 77]; + const arr = [55, 66, 77]; utils.removeElement(arr, matchFn); expect(arr).toEqual(arr); }); @@ -104,7 +104,7 @@ describe("utils", function() { expect(utils.isFunction(555)).toBe(false); expect(utils.isFunction(function() {})).toBe(true); - let s = { foo: function() {} }; + const s = { foo: function() {} }; expect(utils.isFunction(s.foo)).toBe(true); }); }); @@ -154,7 +154,7 @@ describe("utils", function() { }); describe("deepCompare", function() { - let assert = { + const assert = { isTrue: function(x) { expect(x).toBe(true); }, @@ -174,7 +174,7 @@ describe("utils", function() { it("should handle regexps", function() { assert.isTrue(utils.deepCompare(/abc/, /abc/)); assert.isFalse(utils.deepCompare(/abc/, /123/)); - let r = /abc/; + const r = /abc/; assert.isTrue(utils.deepCompare(r, r)); }); @@ -216,10 +216,10 @@ describe("utils", function() { // no two different function is equal really, they capture their // context variables so even if they have same toString(), they // won't have same functionality - let func = function(x) { + const func = function(x) { return true; }; - let func2 = function(x) { + const func2 = function(x) { return true; }; assert.isTrue(utils.deepCompare(func, func)); @@ -231,44 +231,44 @@ describe("utils", function() { describe("extend", function() { - let SOURCE = { "prop2": 1, "string2": "x", "newprop": "new" }; + const SOURCE = { "prop2": 1, "string2": "x", "newprop": "new" }; it("should extend", function() { - let target = { + const target = { "prop1": 5, "prop2": 7, "string1": "baz", "string2": "foo", }; - let merged = { + const merged = { "prop1": 5, "prop2": 1, "string1": "baz", "string2": "x", "newprop": "new", }; - let source_orig = JSON.stringify(SOURCE); + const sourceOrig = JSON.stringify(SOURCE); utils.extend(target, SOURCE); expect(JSON.stringify(target)).toEqual(JSON.stringify(merged)); // check the originial wasn't modified - expect(JSON.stringify(SOURCE)).toEqual(source_orig); + expect(JSON.stringify(SOURCE)).toEqual(sourceOrig); }); it("should ignore null", function() { - let target = { + const target = { "prop1": 5, "prop2": 7, "string1": "baz", "string2": "foo", }; - let merged = { + const merged = { "prop1": 5, "prop2": 1, "string1": "baz", "string2": "x", "newprop": "new", }; - let source_orig = JSON.stringify(SOURCE); + const sourceOrig = JSON.stringify(SOURCE); utils.extend(target, null, SOURCE); expect(JSON.stringify(target)).toEqual(JSON.stringify(merged)); // check the originial wasn't modified - expect(JSON.stringify(SOURCE)).toEqual(source_orig); + expect(JSON.stringify(SOURCE)).toEqual(sourceOrig); }); it("should handle properties created with defineProperties", function() { - let source = Object.defineProperties({}, { + const source = Object.defineProperties({}, { "enumerableProp": { get: function() { return true; @@ -282,7 +282,7 @@ describe("utils", function() { }, }); - let target = {}; + const target = {}; utils.extend(target, source); expect(target.enumerableProp).toBe(true); expect(target.nonenumerableProp).toBe(undefined); diff --git a/src/base-apis.js b/src/base-apis.js index 76c64a545..d928c406e 100644 --- a/src/base-apis.js +++ b/src/base-apis.js @@ -22,8 +22,8 @@ limitations under the License. * @module base-apis */ -let httpApi = require("./http-api"); -let utils = require("./utils"); +const httpApi = require("./http-api"); +const utils = require("./utils"); /** * Low-level wrappers for the Matrix APIs @@ -60,7 +60,7 @@ function MatrixBaseApis(opts) { this.baseUrl = opts.baseUrl; this.idBaseUrl = opts.idBaseUrl; - let httpOpts = { + const httpOpts = { baseUrl: opts.baseUrl, idBaseUrl: opts.idBaseUrl, accessToken: opts.accessToken, @@ -133,7 +133,7 @@ MatrixBaseApis.prototype.makeTxnId = function() { MatrixBaseApis.prototype.register = function( username, password, sessionId, auth, bindEmail, guestAccessToken, - callback + callback, ) { if (auth === undefined) { auth = {}; @@ -142,7 +142,7 @@ MatrixBaseApis.prototype.register = function( auth.session = sessionId; } - let params = { + const params = { auth: auth, }; if (username !== undefined && username !== null) { @@ -183,13 +183,13 @@ MatrixBaseApis.prototype.registerGuest = function(opts, callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.registerRequest = function(data, kind, callback) { - let params = {}; + const params = {}; if (kind) { params.kind = kind; } return this._http.request( - callback, "POST", "/register", params, data + callback, "POST", "/register", params, data, ); }; @@ -210,7 +210,7 @@ MatrixBaseApis.prototype.loginFlows = function(callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.login = function(loginType, data, callback) { - let login_data = { + const login_data = { type: loginType, }; @@ -218,7 +218,7 @@ MatrixBaseApis.prototype.login = function(loginType, data, callback) { utils.extend(login_data, data); return this._http.authedRequest( - callback, "POST", "/login", undefined, login_data + callback, "POST", "/login", undefined, login_data, ); }; @@ -283,7 +283,7 @@ MatrixBaseApis.prototype.loginWithToken = function(token, callback) { */ MatrixBaseApis.prototype.logout = function(callback) { return this._http.authedRequest( - callback, "POST", '/logout' + callback, "POST", '/logout', ); }; @@ -305,7 +305,7 @@ MatrixBaseApis.prototype.deactivateAccount = function(auth, callback) { }; } return this._http.authedRequestWithPrefix( - callback, "POST", '/account/deactivate', undefined, body, httpApi.PREFIX_UNSTABLE + callback, "POST", '/account/deactivate', undefined, body, httpApi.PREFIX_UNSTABLE, ); }; @@ -318,7 +318,7 @@ MatrixBaseApis.prototype.deactivateAccount = function(auth, callback) { * @return {string} HS URL to hit to for the fallback interface */ MatrixBaseApis.prototype.getFallbackAuthUrl = function(loginType, authSessionId) { - let path = utils.encodeUri("/auth/$loginType/fallback/web", { + const path = utils.encodeUri("/auth/$loginType/fallback/web", { $loginType: loginType, }); @@ -347,7 +347,7 @@ MatrixBaseApis.prototype.getFallbackAuthUrl = function(loginType, authSessionId) MatrixBaseApis.prototype.createRoom = function(options, callback) { // valid options include: room_alias_name, visibility, invite return this._http.authedRequest( - callback, "POST", "/createRoom", undefined, options + callback, "POST", "/createRoom", undefined, options, ); }; @@ -358,7 +358,7 @@ MatrixBaseApis.prototype.createRoom = function(options, callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.roomState = function(roomId, callback) { - let path = utils.encodeUri("/rooms/$roomId/state", {$roomId: roomId}); + const path = utils.encodeUri("/rooms/$roomId/state", {$roomId: roomId}); return this._http.authedRequest(callback, "GET", path); }; @@ -372,7 +372,7 @@ MatrixBaseApis.prototype.roomState = function(roomId, callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.getStateEvent = function(roomId, eventType, stateKey, callback) { - let pathParams = { + const pathParams = { $roomId: roomId, $eventType: eventType, $stateKey: stateKey, @@ -382,7 +382,7 @@ MatrixBaseApis.prototype.getStateEvent = function(roomId, eventType, stateKey, c path = utils.encodeUri(path + "/$stateKey", pathParams); } return this._http.authedRequest( - callback, "GET", path + callback, "GET", path, ); }; @@ -397,7 +397,7 @@ MatrixBaseApis.prototype.getStateEvent = function(roomId, eventType, stateKey, c */ MatrixBaseApis.prototype.sendStateEvent = function(roomId, eventType, content, stateKey, callback) { - let pathParams = { + const pathParams = { $roomId: roomId, $eventType: eventType, $stateKey: stateKey, @@ -407,7 +407,7 @@ MatrixBaseApis.prototype.sendStateEvent = function(roomId, eventType, content, s path = utils.encodeUri(path + "/$stateKey", pathParams); } return this._http.authedRequest( - callback, "PUT", path, undefined, content + callback, "PUT", path, undefined, content, ); }; @@ -419,7 +419,7 @@ MatrixBaseApis.prototype.sendStateEvent = function(roomId, eventType, content, s * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.redactEvent = function(roomId, eventId, callback) { - let path = utils.encodeUri("/rooms/$roomId/redact/$eventId", { + const path = utils.encodeUri("/rooms/$roomId/redact/$eventId", { $roomId: roomId, $eventId: eventId, }); @@ -437,14 +437,14 @@ MatrixBaseApis.prototype.roomInitialSync = function(roomId, limit, callback) { if (utils.isFunction(limit)) { callback = limit; limit = undefined; } - let path = utils.encodeUri("/rooms/$roomId/initialSync", - {$roomId: roomId} + const path = utils.encodeUri("/rooms/$roomId/initialSync", + {$roomId: roomId}, ); if (!limit) { limit = 30; } return this._http.authedRequest( - callback, "GET", path, { limit: limit } + callback, "GET", path, { limit: limit }, ); }; @@ -474,7 +474,7 @@ MatrixBaseApis.prototype.publicRooms = function(options, callback) { options = {}; } - let query_params = {}; + const query_params = {}; if (options.server) { query_params.server = options.server; delete options.server; @@ -484,7 +484,7 @@ MatrixBaseApis.prototype.publicRooms = function(options, callback) { return this._http.authedRequest(callback, "GET", "/publicRooms"); } else { return this._http.authedRequest( - callback, "POST", "/publicRooms", query_params, options + callback, "POST", "/publicRooms", query_params, options, ); } }; @@ -498,14 +498,14 @@ MatrixBaseApis.prototype.publicRooms = function(options, callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.createAlias = function(alias, roomId, callback) { - let path = utils.encodeUri("/directory/room/$alias", { + const path = utils.encodeUri("/directory/room/$alias", { $alias: alias, }); - let data = { + const data = { room_id: roomId, }; return this._http.authedRequest( - callback, "PUT", path, undefined, data + callback, "PUT", path, undefined, data, ); }; @@ -518,11 +518,11 @@ MatrixBaseApis.prototype.createAlias = function(alias, roomId, callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.deleteAlias = function(alias, callback) { - let path = utils.encodeUri("/directory/room/$alias", { + const path = utils.encodeUri("/directory/room/$alias", { $alias: alias, }); return this._http.authedRequest( - callback, "DELETE", path, undefined, undefined + callback, "DELETE", path, undefined, undefined, ); }; @@ -535,11 +535,11 @@ MatrixBaseApis.prototype.deleteAlias = function(alias, callback) { */ MatrixBaseApis.prototype.getRoomIdForAlias = function(alias, callback) { // TODO: deprecate this or resolveRoomAlias - let path = utils.encodeUri("/directory/room/$alias", { + const path = utils.encodeUri("/directory/room/$alias", { $alias: alias, }); return this._http.authedRequest( - callback, "GET", path + callback, "GET", path, ); }; @@ -551,7 +551,7 @@ MatrixBaseApis.prototype.getRoomIdForAlias = function(alias, callback) { */ MatrixBaseApis.prototype.resolveRoomAlias = function(roomAlias, callback) { // TODO: deprecate this or getRoomIdForAlias - let path = utils.encodeUri("/directory/room/$alias", {$alias: roomAlias}); + const path = utils.encodeUri("/directory/room/$alias", {$alias: roomAlias}); return this._http.request(callback, "GET", path); }; @@ -564,7 +564,7 @@ MatrixBaseApis.prototype.resolveRoomAlias = function(roomAlias, callback) { */ MatrixBaseApis.prototype.getRoomDirectoryVisibility = function(roomId, callback) { - let path = utils.encodeUri("/directory/list/room/$roomId", { + const path = utils.encodeUri("/directory/list/room/$roomId", { $roomId: roomId, }); return this._http.authedRequest(callback, "GET", path); @@ -582,11 +582,11 @@ MatrixBaseApis.prototype.getRoomDirectoryVisibility = */ MatrixBaseApis.prototype.setRoomDirectoryVisibility = function(roomId, visibility, callback) { - let path = utils.encodeUri("/directory/list/room/$roomId", { + const path = utils.encodeUri("/directory/list/room/$roomId", { $roomId: roomId, }); return this._http.authedRequest( - callback, "PUT", path, undefined, { "visibility": visibility } + callback, "PUT", path, undefined, { "visibility": visibility }, ); }; @@ -605,12 +605,12 @@ MatrixBaseApis.prototype.setRoomDirectoryVisibility = */ MatrixBaseApis.prototype.setRoomDirectoryVisibilityAppService = function(networkId, roomId, visibility, callback) { - let path = utils.encodeUri("/directory/list/appservice/$networkId/$roomId", { + const path = utils.encodeUri("/directory/list/appservice/$networkId/$roomId", { $networkId: networkId, $roomId: roomId, }); return this._http.authedRequest( - callback, "PUT", path, undefined, { "visibility": visibility } + callback, "PUT", path, undefined, { "visibility": visibility }, ); }; @@ -692,7 +692,7 @@ MatrixBaseApis.prototype.getProfileInfo = function(userId, info, callback) { callback = info; info = undefined; } - let path = info ? + const path = info ? utils.encodeUri("/profile/$userId/$info", { $userId: userId, $info: info }) : utils.encodeUri("/profile/$userId", @@ -710,9 +710,9 @@ MatrixBaseApis.prototype.getProfileInfo = function(userId, info, callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.getThreePids = function(callback) { - let path = "/account/3pid"; + const path = "/account/3pid"; return this._http.authedRequest( - callback, "GET", path, undefined, undefined + callback, "GET", path, undefined, undefined, ); }; @@ -724,13 +724,13 @@ MatrixBaseApis.prototype.getThreePids = function(callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.addThreePid = function(creds, bind, callback) { - let path = "/account/3pid"; - let data = { + const path = "/account/3pid"; + const data = { 'threePidCreds': creds, 'bind': bind, }; return this._http.authedRequest( - callback, "POST", path, null, data + callback, "POST", path, null, data, ); }; @@ -743,13 +743,13 @@ MatrixBaseApis.prototype.addThreePid = function(creds, bind, callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.deleteThreePid = function(medium, address) { - let path = "/account/3pid/delete"; - let data = { + const path = "/account/3pid/delete"; + const data = { 'medium': medium, 'address': address, }; return this._http.authedRequestWithPrefix( - undefined, "POST", path, null, data, httpApi.PREFIX_UNSTABLE + undefined, "POST", path, null, data, httpApi.PREFIX_UNSTABLE, ); }; @@ -762,14 +762,14 @@ MatrixBaseApis.prototype.deleteThreePid = function(medium, address) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.setPassword = function(authDict, newPassword, callback) { - let path = "/account/password"; - let data = { + const path = "/account/password"; + const data = { 'auth': authDict, 'new_password': newPassword, }; return this._http.authedRequest( - callback, "POST", path, null, data + callback, "POST", path, null, data, ); }; @@ -783,10 +783,10 @@ MatrixBaseApis.prototype.setPassword = function(authDict, newPassword, callback) * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.getDevices = function() { - let path = "/devices"; + const path = "/devices"; return this._http.authedRequestWithPrefix( undefined, "GET", path, undefined, undefined, - httpApi.PREFIX_UNSTABLE + httpApi.PREFIX_UNSTABLE, ); }; @@ -799,14 +799,14 @@ MatrixBaseApis.prototype.getDevices = function() { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.setDeviceDetails = function(device_id, body) { - let path = utils.encodeUri("/devices/$device_id", { + const path = utils.encodeUri("/devices/$device_id", { $device_id: device_id, }); return this._http.authedRequestWithPrefix( undefined, "PUT", path, undefined, body, - httpApi.PREFIX_UNSTABLE + httpApi.PREFIX_UNSTABLE, ); }; @@ -819,11 +819,11 @@ MatrixBaseApis.prototype.setDeviceDetails = function(device_id, body) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.deleteDevice = function(device_id, auth) { - let path = utils.encodeUri("/devices/$device_id", { + const path = utils.encodeUri("/devices/$device_id", { $device_id: device_id, }); - let body = {}; + const body = {}; if (auth) { body.auth = auth; @@ -831,7 +831,7 @@ MatrixBaseApis.prototype.deleteDevice = function(device_id, auth) { return this._http.authedRequestWithPrefix( undefined, "DELETE", path, undefined, body, - httpApi.PREFIX_UNSTABLE + httpApi.PREFIX_UNSTABLE, ); }; @@ -847,9 +847,9 @@ MatrixBaseApis.prototype.deleteDevice = function(device_id, auth) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.getPushers = function(callback) { - let path = "/pushers"; + const path = "/pushers"; return this._http.authedRequest( - callback, "GET", path, undefined, undefined + callback, "GET", path, undefined, undefined, ); }; @@ -862,9 +862,9 @@ MatrixBaseApis.prototype.getPushers = function(callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.setPusher = function(pusher, callback) { - let path = "/pushers/set"; + const path = "/pushers/set"; return this._http.authedRequest( - callback, "POST", path, null, pusher + callback, "POST", path, null, pusher, ); }; @@ -888,12 +888,12 @@ MatrixBaseApis.prototype.getPushRules = function(callback) { */ MatrixBaseApis.prototype.addPushRule = function(scope, kind, ruleId, body, callback) { // NB. Scope not uri encoded because devices need the '/' - let path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId", { + const path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId", { $kind: kind, $ruleId: ruleId, }); return this._http.authedRequest( - callback, "PUT", path, undefined, body + callback, "PUT", path, undefined, body, ); }; @@ -907,7 +907,7 @@ MatrixBaseApis.prototype.addPushRule = function(scope, kind, ruleId, body, callb */ MatrixBaseApis.prototype.deletePushRule = function(scope, kind, ruleId, callback) { // NB. Scope not uri encoded because devices need the '/' - let path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId", { + const path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId", { $kind: kind, $ruleId: ruleId, }); @@ -926,12 +926,12 @@ MatrixBaseApis.prototype.deletePushRule = function(scope, kind, ruleId, callback */ MatrixBaseApis.prototype.setPushRuleEnabled = function(scope, kind, ruleId, enabled, callback) { - let path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId/enabled", { + const path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId/enabled", { $kind: kind, $ruleId: ruleId, }); return this._http.authedRequest( - callback, "PUT", path, undefined, {"enabled": enabled} + callback, "PUT", path, undefined, {"enabled": enabled}, ); }; @@ -947,12 +947,12 @@ MatrixBaseApis.prototype.setPushRuleEnabled = function(scope, kind, */ MatrixBaseApis.prototype.setPushRuleActions = function(scope, kind, ruleId, actions, callback) { - let path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId/actions", { + const path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId/actions", { $kind: kind, $ruleId: ruleId, }); return this._http.authedRequest( - callback, "PUT", path, undefined, {"actions": actions} + callback, "PUT", path, undefined, {"actions": actions}, ); }; @@ -970,12 +970,12 @@ MatrixBaseApis.prototype.setPushRuleActions = function(scope, kind, * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.search = function(opts, callback) { - let queryparams = {}; + const queryparams = {}; if (opts.next_batch) { queryparams.next_batch = opts.next_batch; } return this._http.authedRequest( - callback, "POST", "/search", queryparams, opts.body + callback, "POST", "/search", queryparams, opts.body, ); }; @@ -999,7 +999,7 @@ MatrixBaseApis.prototype.search = function(opts, callback) { */ MatrixBaseApis.prototype.uploadKeysRequest = function(content, opts, callback) { opts = opts || {}; - let deviceId = opts.device_id; + const deviceId = opts.device_id; let path; if (deviceId) { path = utils.encodeUri("/keys/upload/$deviceId", { @@ -1009,7 +1009,7 @@ MatrixBaseApis.prototype.uploadKeysRequest = function(content, opts, callback) { path = "/keys/upload"; } return this._http.authedRequestWithPrefix( - callback, "POST", path, undefined, content, httpApi.PREFIX_UNSTABLE + callback, "POST", path, undefined, content, httpApi.PREFIX_UNSTABLE, ); }; @@ -1024,15 +1024,15 @@ MatrixBaseApis.prototype.uploadKeysRequest = function(content, opts, callback) { * an error response ({@link module:http-api.MatrixError}). */ MatrixBaseApis.prototype.downloadKeysForUsers = function(userIds, callback) { - let downloadQuery = {}; + const downloadQuery = {}; for (let i = 0; i < userIds.length; ++i) { downloadQuery[userIds[i]] = {}; } - let content = {device_keys: downloadQuery}; + const content = {device_keys: downloadQuery}; return this._http.authedRequestWithPrefix( callback, "POST", "/keys/query", undefined, content, - httpApi.PREFIX_UNSTABLE + httpApi.PREFIX_UNSTABLE, ); }; @@ -1047,23 +1047,23 @@ MatrixBaseApis.prototype.downloadKeysForUsers = function(userIds, callback) { * an error response ({@link module:http-api.MatrixError}). */ MatrixBaseApis.prototype.claimOneTimeKeys = function(devices, key_algorithm) { - let queries = {}; + const queries = {}; if (key_algorithm === undefined) { key_algorithm = "signed_curve25519"; } for (let i = 0; i < devices.length; ++i) { - let userId = devices[i][0]; - let deviceId = devices[i][1]; - let query = queries[userId] || {}; + const userId = devices[i][0]; + const deviceId = devices[i][1]; + const query = queries[userId] || {}; queries[userId] = query; query[deviceId] = key_algorithm; } - let content = {one_time_keys: queries}; + const content = {one_time_keys: queries}; return this._http.authedRequestWithPrefix( undefined, "POST", "/keys/claim", undefined, content, - httpApi.PREFIX_UNSTABLE + httpApi.PREFIX_UNSTABLE, ); }; @@ -1093,7 +1093,7 @@ MatrixBaseApis.prototype.claimOneTimeKeys = function(devices, key_algorithm) { */ MatrixBaseApis.prototype.requestEmailToken = function(email, clientSecret, sendAttempt, nextLink, callback) { - let params = { + const params = { client_secret: clientSecret, email: email, send_attempt: sendAttempt, @@ -1101,7 +1101,7 @@ MatrixBaseApis.prototype.requestEmailToken = function(email, clientSecret, }; return this._http.idServerRequest( callback, "POST", "/validate/email/requestToken", - params, httpApi.PREFIX_IDENTITY_V1 + params, httpApi.PREFIX_IDENTITY_V1, ); }; @@ -1117,13 +1117,13 @@ MatrixBaseApis.prototype.requestEmailToken = function(email, clientSecret, * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.lookupThreePid = function(medium, address, callback) { - let params = { + const params = { medium: medium, address: address, }; return this._http.idServerRequest( callback, "GET", "/lookup", - params, httpApi.PREFIX_IDENTITY_V1 + params, httpApi.PREFIX_IDENTITY_V1, ); }; @@ -1142,20 +1142,20 @@ MatrixBaseApis.prototype.lookupThreePid = function(medium, address, callback) { * @return {module:client.Promise} Resolves to the result object */ MatrixBaseApis.prototype.sendToDevice = function( - eventType, contentMap, txnId + eventType, contentMap, txnId, ) { - let path = utils.encodeUri("/sendToDevice/$eventType/$txnId", { + const path = utils.encodeUri("/sendToDevice/$eventType/$txnId", { $eventType: eventType, $txnId: txnId ? txnId : this.makeTxnId(), }); - let body = { + const body = { messages: contentMap, }; return this._http.authedRequestWithPrefix( undefined, "PUT", path, undefined, body, - httpApi.PREFIX_UNSTABLE + httpApi.PREFIX_UNSTABLE, ); }; @@ -1170,7 +1170,7 @@ MatrixBaseApis.prototype.sendToDevice = function( MatrixBaseApis.prototype.getThirdpartyProtocols = function() { return this._http.authedRequestWithPrefix( undefined, "GET", "/thirdparty/protocols", undefined, undefined, - httpApi.PREFIX_UNSTABLE + httpApi.PREFIX_UNSTABLE, ); }; @@ -1183,13 +1183,13 @@ MatrixBaseApis.prototype.getThirdpartyProtocols = function() { * @return {module:client.Promise} Resolves to the result object */ MatrixBaseApis.prototype.getThirdpartyLocation = function(protocol, params) { - let path = utils.encodeUri("/thirdparty/location/$protocol", { + const path = utils.encodeUri("/thirdparty/location/$protocol", { $protocol: protocol, }); return this._http.authedRequestWithPrefix( undefined, "GET", path, params, undefined, - httpApi.PREFIX_UNSTABLE + httpApi.PREFIX_UNSTABLE, ); }; diff --git a/src/client.js b/src/client.js index de8cfb19e..319835d9e 100644 --- a/src/client.js +++ b/src/client.js @@ -15,31 +15,31 @@ limitations under the License. */ "use strict"; -let PushProcessor = require('./pushprocessor'); +const PushProcessor = require('./pushprocessor'); /** * This is an internal module. See {@link MatrixClient} for the public class. * @module client */ -let EventEmitter = require("events").EventEmitter; -let q = require("q"); -let url = require('url'); +const EventEmitter = require("events").EventEmitter; +const q = require("q"); +const url = require('url'); -let httpApi = require("./http-api"); -let MatrixEvent = require("./models/event").MatrixEvent; -let EventStatus = require("./models/event").EventStatus; -let EventTimeline = require("./models/event-timeline"); -let SearchResult = require("./models/search-result"); -let StubStore = require("./store/stub"); -let webRtcCall = require("./webrtc/call"); -let utils = require("./utils"); -let contentRepo = require("./content-repo"); -let Filter = require("./filter"); -let SyncApi = require("./sync"); -let MatrixBaseApis = require("./base-apis"); -let MatrixError = httpApi.MatrixError; +const httpApi = require("./http-api"); +const MatrixEvent = require("./models/event").MatrixEvent; +const EventStatus = require("./models/event").EventStatus; +const EventTimeline = require("./models/event-timeline"); +const SearchResult = require("./models/search-result"); +const StubStore = require("./store/stub"); +const webRtcCall = require("./webrtc/call"); +const utils = require("./utils"); +const contentRepo = require("./content-repo"); +const Filter = require("./filter"); +const SyncApi = require("./sync"); +const MatrixBaseApis = require("./base-apis"); +const MatrixError = httpApi.MatrixError; -let SCROLLBACK_DELAY_MS = 3000; +const SCROLLBACK_DELAY_MS = 3000; let CRYPTO_ENABLED = false; try { @@ -111,16 +111,16 @@ function MatrixClient(opts) { this.deviceId = opts.deviceId || null; - let userId = (opts.userId || null); + const userId = (opts.userId || null); this.credentials = { userId: userId, }; this.scheduler = opts.scheduler; if (this.scheduler) { - let self = this; + const self = this; this.scheduler.setProcessFunction(function(eventToSend) { - let room = self.getRoom(eventToSend.getRoomId()); + const room = self.getRoom(eventToSend.getRoomId()); if (eventToSend.status !== EventStatus.SENDING) { _updatePendingEventStatus(room, eventToSend, EventStatus.SENDING); @@ -136,7 +136,7 @@ function MatrixClient(opts) { // try constructing a MatrixCall to see if we are running in an environment // which has WebRTC. If we are, listen for and handle m.call.* events. - let call = webRtcCall.createNewMatrixCall(this); + const call = webRtcCall.createNewMatrixCall(this); this._supportsVoip = false; if (call) { setupCallEventHandler(this); @@ -157,7 +157,7 @@ function MatrixClient(opts) { this._crypto = new Crypto( this, this, opts.sessionStore, - userId, this.deviceId + userId, this.deviceId, ); this.olmVersion = Crypto.getOlmVersion(); @@ -427,7 +427,7 @@ MatrixClient.prototype.getEventSenderDeviceInfo = function(event) { * {@link module:client~MatrixClient#setDeviceVerified|setDeviceVerified}. */ MatrixClient.prototype.isEventSenderVerified = function(event) { - let device = this.getEventSenderDeviceInfo(event); + const device = this.getEventSenderDeviceInfo(event); if (!device) { return false; } @@ -461,6 +461,33 @@ MatrixClient.prototype.isRoomEncrypted = function(roomId) { return this._crypto.isRoomEncrypted(roomId); }; +/** + * Get a list containing all of the room keys + * + * This should be encrypted before returning it to the user. + * + * @return {module:client.Promise} a promise which resolves to a list of + * session export objects + */ +MatrixClient.prototype.exportRoomKeys = function() { + if (!this._crypto) { + return q.reject(new Error("End-to-end encryption disabled")); + } + return this._crypto.exportRoomKeys(); +}; + +/** + * Import a list of room keys previously exported by exportRoomKeys + * + * @param {Object[]} keys a list of session export objects + */ +MatrixClient.prototype.importRoomKeys = function(keys) { + if (!this._crypto) { + throw new Error("End-to-end encryption disabled"); + } + this._crypto.importRoomKeys(keys); +}; + /** * Decrypt a received event according to the algorithm specified in the event. * @@ -547,12 +574,12 @@ MatrixClient.prototype.getUsers = function() { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.setAccountData = function(eventType, contents, callback) { - let path = utils.encodeUri("/user/$userId/account_data/$type", { + const path = utils.encodeUri("/user/$userId/account_data/$type", { $userId: this.credentials.userId, $type: eventType, }); return this._http.authedRequest( - callback, "PUT", path, undefined, contents + callback, "PUT", path, undefined, contents, ); }; @@ -592,7 +619,7 @@ MatrixClient.prototype.joinRoom = function(roomIdOrAlias, opts, callback) { opts.syncRoom = true; } - let room = this.getRoom(roomIdOrAlias); + const room = this.getRoom(roomIdOrAlias); if (room && room.hasMembershipState(this.credentials.userId, "join")) { return q(room); } @@ -602,25 +629,25 @@ MatrixClient.prototype.joinRoom = function(roomIdOrAlias, opts, callback) { if (opts.inviteSignUrl) { sign_promise = this._http.requestOtherUrl( undefined, 'POST', - opts.inviteSignUrl, { mxid: this.credentials.userId } + opts.inviteSignUrl, { mxid: this.credentials.userId }, ); } - let defer = q.defer(); + const defer = q.defer(); - let self = this; + const self = this; sign_promise.then(function(signed_invite_object) { - let data = {}; + const data = {}; if (signed_invite_object) { data.third_party_signed = signed_invite_object; } - let path = utils.encodeUri("/join/$roomid", { $roomid: roomIdOrAlias}); + const path = utils.encodeUri("/join/$roomid", { $roomid: roomIdOrAlias}); return self._http.authedRequest(undefined, "POST", path, undefined, data); }).then(function(res) { - let roomId = res.room_id; - let syncApi = new SyncApi(self, self._clientOpts); - let room = syncApi.createRoom(roomId); + const roomId = res.room_id; + const syncApi = new SyncApi(self, self._clientOpts); + const room = syncApi.createRoom(roomId); if (opts.syncRoom) { // v2 will do this for us // return syncApi.syncRoom(room); @@ -665,7 +692,7 @@ MatrixClient.prototype.cancelPendingEvent = function(event) { // then tell the room about the change of state, which will remove it // from the room's list of pending events. - let room = this.getRoom(event.getRoomId()); + const room = this.getRoom(event.getRoomId()); _updatePendingEventStatus(room, event, EventStatus.CANCELLED); }; @@ -700,12 +727,12 @@ MatrixClient.prototype.setRoomTopic = function(roomId, topic, callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.getRoomTags = function(roomId, callback) { - let path = utils.encodeUri("/user/$userId/rooms/$roomId/tags/", { + const path = utils.encodeUri("/user/$userId/rooms/$roomId/tags/", { $userId: this.credentials.userId, $roomId: roomId, }); return this._http.authedRequest( - callback, "GET", path, undefined + callback, "GET", path, undefined, ); }; @@ -718,13 +745,13 @@ MatrixClient.prototype.getRoomTags = function(roomId, callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.setRoomTag = function(roomId, tagName, metadata, callback) { - let path = utils.encodeUri("/user/$userId/rooms/$roomId/tags/$tag", { + const path = utils.encodeUri("/user/$userId/rooms/$roomId/tags/$tag", { $userId: this.credentials.userId, $roomId: roomId, $tag: tagName, }); return this._http.authedRequest( - callback, "PUT", path, undefined, metadata + callback, "PUT", path, undefined, metadata, ); }; @@ -736,13 +763,13 @@ MatrixClient.prototype.setRoomTag = function(roomId, tagName, metadata, callback * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.deleteRoomTag = function(roomId, tagName, callback) { - let path = utils.encodeUri("/user/$userId/rooms/$roomId/tags/$tag", { + const path = utils.encodeUri("/user/$userId/rooms/$roomId/tags/$tag", { $userId: this.credentials.userId, $roomId: roomId, $tag: tagName, }); return this._http.authedRequest( - callback, "DELETE", path, undefined, undefined + callback, "DELETE", path, undefined, undefined, ); }; @@ -756,13 +783,13 @@ MatrixClient.prototype.deleteRoomTag = function(roomId, tagName, callback) { */ MatrixClient.prototype.setRoomAccountData = function(roomId, eventType, content, callback) { - let path = utils.encodeUri("/user/$userId/rooms/$roomId/account_data/$type", { + const path = utils.encodeUri("/user/$userId/rooms/$roomId/account_data/$type", { $userId: this.credentials.userId, $roomId: roomId, $type: eventType, }); return this._http.authedRequest( - callback, "PUT", path, undefined, content + callback, "PUT", path, undefined, content, ); }; @@ -787,11 +814,11 @@ MatrixClient.prototype.setPowerLevel = function(roomId, userId, powerLevel, content = utils.deepCopy(event.getContent()); } content.users[userId] = powerLevel; - let path = utils.encodeUri("/rooms/$roomId/state/m.room.power_levels", { + const path = utils.encodeUri("/rooms/$roomId/state/m.room.power_levels", { $roomId: roomId, }); return this._http.authedRequest( - callback, "PUT", path, undefined, content + callback, "PUT", path, undefined, content, ); }; @@ -817,8 +844,8 @@ MatrixClient.prototype.sendEvent = function(roomId, eventType, content, txnId, // we always construct a MatrixEvent when sending because the store and // scheduler use them. We'll extract the params back out if it turns out // the client has no scheduler or store. - let room = this.getRoom(roomId); - let localEvent = new MatrixEvent({ + const room = this.getRoom(roomId); + const localEvent = new MatrixEvent({ event_id: "~" + roomId + ":" + txnId, user_id: this.credentials.userId, room_id: roomId, @@ -912,9 +939,9 @@ function _updatePendingEventStatus(room, event, newStatus) { } function _sendEventHttpRequest(client, event) { - let txnId = event._txnId ? event._txnId : client.makeTxnId(); + const txnId = event._txnId ? event._txnId : client.makeTxnId(); - let pathParams = { + const pathParams = { $roomId: event.getRoomId(), $eventType: event.getWireType(), $stateKey: event.getStateKey(), @@ -931,12 +958,12 @@ function _sendEventHttpRequest(client, event) { path = utils.encodeUri(pathTemplate, pathParams); } else { path = utils.encodeUri( - "/rooms/$roomId/send/$eventType/$txnId", pathParams + "/rooms/$roomId/send/$eventType/$txnId", pathParams, ); } return client._http.authedRequest( - undefined, "PUT", path, undefined, event.getWireContent() + undefined, "PUT", path, undefined, event.getWireContent(), ); } @@ -953,7 +980,7 @@ MatrixClient.prototype.sendMessage = function(roomId, content, txnId, callback) callback = txnId; txnId = undefined; } return this.sendEvent( - roomId, "m.room.message", content, txnId, callback + roomId, "m.room.message", content, txnId, callback, ); }; @@ -966,7 +993,7 @@ MatrixClient.prototype.sendMessage = function(roomId, content, txnId, callback) * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.sendTextMessage = function(roomId, body, txnId, callback) { - let content = { + const content = { msgtype: "m.text", body: body, }; @@ -982,7 +1009,7 @@ MatrixClient.prototype.sendTextMessage = function(roomId, body, txnId, callback) * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.sendNotice = function(roomId, body, txnId, callback) { - let content = { + const content = { msgtype: "m.notice", body: body, }; @@ -998,7 +1025,7 @@ MatrixClient.prototype.sendNotice = function(roomId, body, txnId, callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.sendEmoteMessage = function(roomId, body, txnId, callback) { - let content = { + const content = { msgtype: "m.emote", body: body, }; @@ -1021,7 +1048,7 @@ MatrixClient.prototype.sendImageMessage = function(roomId, url, info, text, call if (!text) { text = "Image"; } - let content = { + const content = { msgtype: "m.image", url: url, info: info, @@ -1039,7 +1066,7 @@ MatrixClient.prototype.sendImageMessage = function(roomId, url, info, text, call * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.sendHtmlMessage = function(roomId, body, htmlBody, callback) { - let content = { + const content = { msgtype: "m.text", format: "org.matrix.custom.html", body: body, @@ -1057,7 +1084,7 @@ MatrixClient.prototype.sendHtmlMessage = function(roomId, body, htmlBody, callba * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.sendHtmlNotice = function(roomId, body, htmlBody, callback) { - let content = { + const content = { msgtype: "m.notice", format: "org.matrix.custom.html", body: body, @@ -1075,7 +1102,7 @@ MatrixClient.prototype.sendHtmlNotice = function(roomId, body, htmlBody, callbac * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.sendHtmlEmote = function(roomId, body, htmlBody, callback) { - let content = { + const content = { msgtype: "m.emote", format: "org.matrix.custom.html", body: body, @@ -1097,16 +1124,16 @@ MatrixClient.prototype.sendReceipt = function(event, receiptType, callback) { return q({}); // guests cannot send receipts so don't bother. } - let path = utils.encodeUri("/rooms/$roomId/receipt/$receiptType/$eventId", { + const path = utils.encodeUri("/rooms/$roomId/receipt/$receiptType/$eventId", { $roomId: event.getRoomId(), $receiptType: receiptType, $eventId: event.getId(), }); - let promise = this._http.authedRequest( - callback, "POST", path, undefined, {} + const promise = this._http.authedRequest( + callback, "POST", path, undefined, {}, ); - let room = this.getRoom(event.getRoomId()); + const room = this.getRoom(event.getRoomId()); if (room) { room._addLocalEchoReceipt(this.credentials.userId, event, receiptType); } @@ -1141,18 +1168,18 @@ MatrixClient.prototype.sendReadReceipt = function(event, callback) { * May return synthesized attributes if the URL lacked OG meta. */ MatrixClient.prototype.getUrlPreview = function(url, ts, callback) { - let key = ts + "_" + url; - let og = this.urlPreviewCache[key]; + const key = ts + "_" + url; + const og = this.urlPreviewCache[key]; if (og) { return q(og); } - let self = this; + const self = this; return this._http.authedRequestWithPrefix( callback, "GET", "/preview_url", { url: url, ts: ts, - }, undefined, httpApi.PREFIX_MEDIA_R0 + }, undefined, httpApi.PREFIX_MEDIA_R0, ).then(function(response) { // TODO: expire cache occasionally self.urlPreviewCache[key] = response; @@ -1173,18 +1200,18 @@ MatrixClient.prototype.sendTyping = function(roomId, isTyping, timeoutMs, callba return q({}); // guests cannot send typing notifications so don't bother. } - let path = utils.encodeUri("/rooms/$roomId/typing/$userId", { + const path = utils.encodeUri("/rooms/$roomId/typing/$userId", { $roomId: roomId, $userId: this.credentials.userId, }); - let data = { + const data = { typing: isTyping, }; if (isTyping) { data.timeout = timeoutMs ? timeoutMs : 20000; } return this._http.authedRequest( - callback, "PUT", path, undefined, data + callback, "PUT", path, undefined, data, ); }; @@ -1210,7 +1237,7 @@ MatrixClient.prototype.invite = function(roomId, userId, callback) { */ MatrixClient.prototype.inviteByEmail = function(roomId, email, callback) { return this.inviteByThreePid( - roomId, "email", email, callback + roomId, "email", email, callback, ); }; @@ -1224,9 +1251,9 @@ MatrixClient.prototype.inviteByEmail = function(roomId, email, callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.inviteByThreePid = function(roomId, medium, address, callback) { - let path = utils.encodeUri( + const path = utils.encodeUri( "/rooms/$roomId/invite", - { $roomId: roomId } + { $roomId: roomId }, ); let identityServerUrl = this.getIdentityServerUrl(); @@ -1285,12 +1312,12 @@ MatrixClient.prototype.forget = function(roomId, deleteRoom, callback) { if (deleteRoom === undefined) { deleteRoom = true; } - let promise = _membershipChange(this, roomId, undefined, "forget", undefined, + const promise = _membershipChange(this, roomId, undefined, "forget", undefined, callback); if (!deleteRoom) { return promise; } - let self = this; + const self = this; return promise.then(function(response) { self.store.removeRoom(roomId); self.emit("deleteRoom", roomId); @@ -1308,7 +1335,7 @@ MatrixClient.prototype.forget = function(roomId, deleteRoom, callback) { MatrixClient.prototype.unban = function(roomId, userId, callback) { // unbanning = set their state to leave return _setMembershipState( - this, roomId, userId, "leave", undefined, callback + this, roomId, userId, "leave", undefined, callback, ); }; @@ -1322,7 +1349,7 @@ MatrixClient.prototype.unban = function(roomId, userId, callback) { */ MatrixClient.prototype.kick = function(roomId, userId, reason, callback) { return _setMembershipState( - this, roomId, userId, "leave", reason, callback + this, roomId, userId, "leave", reason, callback, ); }; @@ -1343,9 +1370,9 @@ function _setMembershipState(client, roomId, userId, membershipValue, reason, callback = reason; reason = undefined; } - let path = utils.encodeUri( + const path = utils.encodeUri( "/rooms/$roomId/state/m.room.member/$userId", - { $roomId: roomId, $userId: userId} + { $roomId: roomId, $userId: userId}, ); return client._http.authedRequest(callback, "PUT", path, undefined, { @@ -1370,7 +1397,7 @@ function _membershipChange(client, roomId, userId, membership, reason, callback) callback = reason; reason = undefined; } - let path = utils.encodeUri("/rooms/$room_id/$membership", { + const path = utils.encodeUri("/rooms/$room_id/$membership", { $room_id: roomId, $membership: membership, }); @@ -1378,7 +1405,7 @@ function _membershipChange(client, roomId, userId, membership, reason, callback) callback, "POST", path, undefined, { user_id: userId, // may be undefined e.g. on leave reason: reason, - } + }, ); } @@ -1390,7 +1417,7 @@ function _membershipChange(client, roomId, userId, membership, reason, callback) */ MatrixClient.prototype.getPushActionsForEvent = function(event) { if (!event.getPushActions()) { - let pushProcessor = new PushProcessor(this); + const pushProcessor = new PushProcessor(this); event.setPushActions(pushProcessor.actionsForEvent(event)); } return event.getPushActions(); @@ -1407,12 +1434,12 @@ MatrixClient.prototype.getPushActionsForEvent = function(event) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.setProfileInfo = function(info, data, callback) { - let path = utils.encodeUri("/profile/$userId/$info", { + const path = utils.encodeUri("/profile/$userId/$info", { $userId: this.credentials.userId, $info: info, }); return this._http.authedRequest( - callback, "PUT", path, undefined, data + callback, "PUT", path, undefined, data, ); }; @@ -1424,7 +1451,7 @@ MatrixClient.prototype.setProfileInfo = function(info, data, callback) { */ MatrixClient.prototype.setDisplayName = function(name, callback) { return this.setProfileInfo( - "displayname", { displayname: name }, callback + "displayname", { displayname: name }, callback, ); }; @@ -1436,7 +1463,7 @@ MatrixClient.prototype.setDisplayName = function(name, callback) { */ MatrixClient.prototype.setAvatarUrl = function(url, callback) { return this.setProfileInfo( - "avatar_url", { avatar_url: url }, callback + "avatar_url", { avatar_url: url }, callback, ); }; @@ -1456,7 +1483,7 @@ MatrixClient.prototype.setAvatarUrl = function(url, callback) { MatrixClient.prototype.mxcUrlToHttp = function(mxcUrl, width, height, resizeMethod, allowDirectLinks) { return contentRepo.getHttpUriForMxc( - this.baseUrl, mxcUrl, width, height, resizeMethod, allowDirectLinks + this.baseUrl, mxcUrl, width, height, resizeMethod, allowDirectLinks, ); }; @@ -1470,7 +1497,7 @@ MatrixClient.prototype.mxcUrlToHttp = * @throws If 'presence' isn't a valid presence enum value. */ MatrixClient.prototype.setPresence = function(opts, callback) { - let path = utils.encodeUri("/presence/$userId/status", { + const path = utils.encodeUri("/presence/$userId/status", { $userId: this.credentials.userId, }); @@ -1478,17 +1505,17 @@ MatrixClient.prototype.setPresence = function(opts, callback) { opts = { presence: opts }; } - let validStates = ["offline", "online", "unavailable"]; + const validStates = ["offline", "online", "unavailable"]; if (validStates.indexOf(opts.presence) == -1) { throw new Error("Bad presence value: " + opts.presence); } return this._http.authedRequest( - callback, "PUT", path, undefined, opts + callback, "PUT", path, undefined, opts, ); }; function _presenceList(callback, client, opts, method) { - let path = utils.encodeUri("/presence/list/$userId", { + const path = utils.encodeUri("/presence/list/$userId", { $userId: client.credentials.userId, }); return client._http.authedRequest(callback, method, path, undefined, opts); @@ -1512,7 +1539,7 @@ MatrixClient.prototype.getPresenceList = function(callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.inviteToPresenceList = function(callback, userIds) { - let opts = {"invite": userIds}; + const opts = {"invite": userIds}; return _presenceList(callback, this, opts, "POST"); }; @@ -1524,7 +1551,7 @@ MatrixClient.prototype.inviteToPresenceList = function(callback, userIds) { * @return {module:http-api.MatrixError} Rejects: with an error response. **/ MatrixClient.prototype.dropFromPresenceList = function(callback, userIds) { - let opts = {"drop": userIds}; + const opts = {"drop": userIds}; return _presenceList(callback, this, opts, "POST"); }; @@ -1556,7 +1583,7 @@ MatrixClient.prototype.scrollback = function(room, limit, callback) { if (info.promise) { return info.promise; } else if (info.errorTs) { - let timeWaitedMs = Date.now() - info.errorTs; + const timeWaitedMs = Date.now() - info.errorTs; timeToWaitMs = Math.max(SCROLLBACK_DELAY_MS - timeWaitedMs, 0); } @@ -1564,7 +1591,7 @@ MatrixClient.prototype.scrollback = function(room, limit, callback) { return q(room); // already at the start. } // attempt to grab more events from the store first - let numAdded = this.store.scrollback(room, limit).length; + const numAdded = this.store.scrollback(room, limit).length; if (numAdded === limit) { // store contained everything we needed. return q(room); @@ -1572,26 +1599,26 @@ MatrixClient.prototype.scrollback = function(room, limit, callback) { // reduce the required number of events appropriately limit = limit - numAdded; - let path = utils.encodeUri( - "/rooms/$roomId/messages", {$roomId: room.roomId} + const path = utils.encodeUri( + "/rooms/$roomId/messages", {$roomId: room.roomId}, ); - let params = { + const params = { from: room.oldState.paginationToken, limit: limit, dir: 'b', }; - let defer = q.defer(); + const defer = q.defer(); info = { promise: defer.promise, errorTs: null, }; - let self = this; + const self = this; // wait for a time before doing this request // (which may be 0 in order not to special case the code paths) q.delay(timeToWaitMs).then(function() { return self._http.authedRequest(callback, "GET", path, params); }).done(function(res) { - let matrixEvents = utils.map(res.chunk, _PojoToMatrixEventMapper(self)); + const matrixEvents = utils.map(res.chunk, _PojoToMatrixEventMapper(self)); room.addEventsToTimeline(matrixEvents, true, room.getLiveTimeline()); room.oldState.paginationToken = res.end; if (res.chunk.length === 0) { @@ -1626,40 +1653,40 @@ MatrixClient.prototype.paginateEventContext = function(eventContext, opts) { // TODO: we should implement a backoff (as per scrollback()) to deal more // nicely with HTTP errors. opts = opts || {}; - let backwards = opts.backwards || false; + const backwards = opts.backwards || false; - let token = eventContext.getPaginateToken(backwards); + const token = eventContext.getPaginateToken(backwards); if (!token) { // no more results. return q.reject(new Error("No paginate token")); } - let dir = backwards ? 'b' : 'f'; - let pendingRequest = eventContext._paginateRequests[dir]; + const dir = backwards ? 'b' : 'f'; + const pendingRequest = eventContext._paginateRequests[dir]; if (pendingRequest) { // already a request in progress - return the existing promise return pendingRequest; } - let path = utils.encodeUri( - "/rooms/$roomId/messages", {$roomId: eventContext.getEvent().getRoomId()} + const path = utils.encodeUri( + "/rooms/$roomId/messages", {$roomId: eventContext.getEvent().getRoomId()}, ); - let params = { + const params = { from: token, limit: ('limit' in opts) ? opts.limit : 30, dir: dir, }; - let self = this; - let promise = - self._http.authedRequest(undefined, "GET", path, params + const self = this; + const promise = + self._http.authedRequest(undefined, "GET", path, params, ).then(function(res) { let token = res.end; if (res.chunk.length === 0) { token = null; } else { - let matrixEvents = utils.map(res.chunk, self.getEventMapper()); + const matrixEvents = utils.map(res.chunk, self.getEventMapper()); if (backwards) { // eventContext expects the events in timeline order, but // back-pagination returns them in reverse order. @@ -1703,18 +1730,18 @@ MatrixClient.prototype.getEventTimeline = function(timelineSet, eventId) { return q(timelineSet.getTimelineForEvent(eventId)); } - let path = utils.encodeUri( + const path = utils.encodeUri( "/rooms/$roomId/context/$eventId", { $roomId: timelineSet.room.roomId, $eventId: eventId, - } + }, ); // TODO: we should implement a backoff (as per scrollback()) to deal more // nicely with HTTP errors. - let self = this; - let promise = - self._http.authedRequest(undefined, "GET", path + const self = this; + const promise = + self._http.authedRequest(undefined, "GET", path, ).then(function(res) { if (!res.event) { throw new Error("'event' not in '/context' result - homeserver too old?"); @@ -1730,10 +1757,10 @@ MatrixClient.prototype.getEventTimeline = function(timelineSet, eventId) { // have known state. // events_after is already backwards; events_before is forwards. res.events_after.reverse(); - let events = res.events_after + const events = res.events_after .concat([res.event]) .concat(res.events_before); - let matrixEvents = utils.map(events, self.getEventMapper()); + const matrixEvents = utils.map(events, self.getEventMapper()); let timeline = timelineSet.getTimelineForEvent(matrixEvents[0].getId()); if (!timeline) { @@ -1749,7 +1776,7 @@ MatrixClient.prototype.getEventTimeline = function(timelineSet, eventId) { // room's index again. On the other hand, there's no guarantee the // event ended up anywhere, if it was later redacted, so we just // return the timeline we first thought of. - let tl = timelineSet.getTimelineForEvent(eventId) || timeline; + const tl = timelineSet.getTimelineForEvent(eventId) || timeline; return tl; }); return promise; @@ -1770,12 +1797,12 @@ MatrixClient.prototype.getEventTimeline = function(timelineSet, eventId) { * events and we reached either end of the timeline; else true. */ MatrixClient.prototype.paginateEventTimeline = function(eventTimeline, opts) { - let isNotifTimeline = (eventTimeline.getTimelineSet() === this._notifTimelineSet); + const isNotifTimeline = (eventTimeline.getTimelineSet() === this._notifTimelineSet); // TODO: we should implement a backoff (as per scrollback()) to deal more // nicely with HTTP errors. opts = opts || {}; - let backwards = opts.backwards || false; + const backwards = opts.backwards || false; if (isNotifTimeline) { if (!backwards) { @@ -1783,15 +1810,15 @@ MatrixClient.prototype.paginateEventTimeline = function(eventTimeline, opts) { } } - let dir = backwards ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS; + const dir = backwards ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS; - let token = eventTimeline.getPaginationToken(dir); + const token = eventTimeline.getPaginationToken(dir); if (!token) { // no token - no results. return q(false); } - let pendingRequest = eventTimeline._paginationRequests[dir]; + const pendingRequest = eventTimeline._paginationRequests[dir]; if (pendingRequest) { // already a request in progress - return the existing promise @@ -1799,7 +1826,7 @@ MatrixClient.prototype.paginateEventTimeline = function(eventTimeline, opts) { } let path, params, promise; - let self = this; + const self = this; if (isNotifTimeline) { path = "/notifications"; @@ -1814,16 +1841,16 @@ MatrixClient.prototype.paginateEventTimeline = function(eventTimeline, opts) { promise = this._http.authedRequestWithPrefix(undefined, "GET", path, params, - undefined, httpApi.PREFIX_UNSTABLE + undefined, httpApi.PREFIX_UNSTABLE, ).then(function(res) { - let token = res.next_token; - let matrixEvents = []; + const token = res.next_token; + const matrixEvents = []; for (let i = 0; i < res.notifications.length; i++) { - let notification = res.notifications[i]; - let event = self.getEventMapper()(notification.event); + const notification = res.notifications[i]; + const event = self.getEventMapper()(notification.event); event.setPushActions( - PushProcessor.actionListToActionsObject(notification.actions) + PushProcessor.actionListToActionsObject(notification.actions), ); event.event.room_id = notification.room_id; // XXX: gutwrenching matrixEvents[i] = event; @@ -1844,13 +1871,13 @@ MatrixClient.prototype.paginateEventTimeline = function(eventTimeline, opts) { }); eventTimeline._paginationRequests[dir] = promise; } else { - let room = this.getRoom(eventTimeline.getRoomId()); + const room = this.getRoom(eventTimeline.getRoomId()); if (!room) { throw new Error("Unknown room " + eventTimeline.getRoomId()); } path = utils.encodeUri( - "/rooms/$roomId/messages", {$roomId: eventTimeline.getRoomId()} + "/rooms/$roomId/messages", {$roomId: eventTimeline.getRoomId()}, ); params = { from: token, @@ -1858,7 +1885,7 @@ MatrixClient.prototype.paginateEventTimeline = function(eventTimeline, opts) { dir: dir, }; - let filter = eventTimeline.getFilter(); + const filter = eventTimeline.getFilter(); if (filter) { // XXX: it's horrific that /messages' filter parameter doesn't match // /sync's one - see https://matrix.org/jira/browse/SPEC-451 @@ -1866,10 +1893,10 @@ MatrixClient.prototype.paginateEventTimeline = function(eventTimeline, opts) { } promise = - this._http.authedRequest(undefined, "GET", path, params + this._http.authedRequest(undefined, "GET", path, params, ).then(function(res) { - let token = res.end; - let matrixEvents = utils.map(res.chunk, self.getEventMapper()); + const token = res.end; + const matrixEvents = utils.map(res.chunk, self.getEventMapper()); eventTimeline.getTimelineSet() .addEventsToTimeline(matrixEvents, backwards, eventTimeline, token); @@ -1961,7 +1988,7 @@ MatrixClient.prototype.stopPeeking = function() { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.setGuestAccess = function(roomId, opts) { - let writePromise = this.sendStateEvent(roomId, "m.room.guest_access", { + const writePromise = this.sendStateEvent(roomId, "m.room.guest_access", { guest_access: opts.allowJoin ? "can_join" : "forbidden", }); @@ -2002,7 +2029,7 @@ MatrixClient.prototype.requestRegisterEmailToken = function(email, clientSecret, sendAttempt, nextLink, callback) { return this._requestTokenFromEndpoint( "/register/email/requestToken", - email, clientSecret, sendAttempt, nextLink, callback + email, clientSecret, sendAttempt, nextLink, callback, ); }; @@ -2030,7 +2057,7 @@ MatrixClient.prototype.requestAdd3pidEmailToken = function(email, clientSecret, sendAttempt, nextLink, callback) { return this._requestTokenFromEndpoint( "/account/3pid/email/requestToken", - email, clientSecret, sendAttempt, nextLink, callback + email, clientSecret, sendAttempt, nextLink, callback, ); }; @@ -2057,7 +2084,7 @@ MatrixClient.prototype.requestPasswordEmailToken = function(email, clientSecret, sendAttempt, nextLink, callback) { return this._requestTokenFromEndpoint( "/account/password/email/requestToken", - email, clientSecret, sendAttempt, nextLink, callback + email, clientSecret, sendAttempt, nextLink, callback, ); }; @@ -2076,12 +2103,12 @@ MatrixClient.prototype.requestPasswordEmailToken = function(email, clientSecret, MatrixClient.prototype._requestTokenFromEndpoint = function(endpoint, email, clientSecret, sendAttempt, nextLink, callback) { - let id_server_url = url.parse(this.idBaseUrl); + const id_server_url = url.parse(this.idBaseUrl); if (id_server_url.host === null) { throw new Error("Invalid ID server URL: " + this.idBaseUrl); } - let params = { + const params = { client_secret: clientSecret, email: email, send_attempt: sendAttempt, @@ -2090,7 +2117,7 @@ MatrixClient.prototype._requestTokenFromEndpoint = function(endpoint, }; return this._http.request( callback, "POST", endpoint, undefined, - params + params, ); }; @@ -2109,14 +2136,14 @@ MatrixClient.prototype.getRoomPushRule = function(scope, roomId) { // and its id is the room id. if (this.pushRules) { for (let i = 0; i < this.pushRules[scope].room.length; i++) { - let rule = this.pushRules[scope].room[i]; + const rule = this.pushRules[scope].room[i]; if (rule.rule_id === roomId) { return rule; } } } else { throw new Error( - "SyncApi.sync() must be done before accessing to push rules." + "SyncApi.sync() must be done before accessing to push rules.", ); } }; @@ -2131,11 +2158,11 @@ MatrixClient.prototype.getRoomPushRule = function(scope, roomId) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.setRoomMutePushRule = function(scope, roomId, mute) { - let self = this; + const self = this; let deferred, hasDontNotifyRule; // Get the existing room-kind push rule if any - let roomPushRule = this.getRoomPushRule(scope, roomId); + const roomPushRule = this.getRoomPushRule(scope, roomId); if (roomPushRule) { if (0 <= roomPushRule.actions.indexOf("dont_notify")) { hasDontNotifyRule = true; @@ -2175,7 +2202,7 @@ MatrixClient.prototype.setRoomMutePushRule = function(scope, roomId, mute) { if (deferred) { // Update this.pushRules when the operation completes - let ruleRefreshDeferred = q.defer(); + const ruleRefreshDeferred = q.defer(); deferred.done(function() { self.getPushRules().done(function(result) { self.pushRules = result; @@ -2246,7 +2273,7 @@ MatrixClient.prototype.searchMessageText = function(opts, callback) { MatrixClient.prototype.searchRoomEvents = function(opts) { // TODO: support groups - let body = { + const body = { search_categories: { room_events: { search_term: opts.term, @@ -2261,14 +2288,14 @@ MatrixClient.prototype.searchRoomEvents = function(opts) { }, }; - let searchResults = { + const searchResults = { _query: body, results: [], highlights: [], }; return this.search({body: body}).then( - this._processRoomEventsSearch.bind(this, searchResults) + this._processRoomEventsSearch.bind(this, searchResults), ); }; @@ -2292,13 +2319,13 @@ MatrixClient.prototype.backPaginateRoomEventsSearch = function(searchResults) { return searchResults.pendingRequest; } - let searchOpts = { + const searchOpts = { body: searchResults._query, next_batch: searchResults.next_batch, }; - let promise = this.search(searchOpts).then( - this._processRoomEventsSearch.bind(this, searchResults) + const promise = this.search(searchOpts).then( + this._processRoomEventsSearch.bind(this, searchResults), ).finally(function() { searchResults.pendingRequest = null; }); @@ -2317,14 +2344,14 @@ MatrixClient.prototype.backPaginateRoomEventsSearch = function(searchResults) { * @private */ MatrixClient.prototype._processRoomEventsSearch = function(searchResults, response) { - let room_events = response.search_categories.room_events; + const room_events = response.search_categories.room_events; searchResults.count = room_events.count; searchResults.next_batch = room_events.next_batch; // combine the highlight list with our existing list; build an object // to avoid O(N^2) fail - let highlights = {}; + const highlights = {}; room_events.highlights.forEach(function(hl) { highlights[hl] = 1; }); @@ -2337,7 +2364,7 @@ MatrixClient.prototype._processRoomEventsSearch = function(searchResults, respon // append the new results to our existing results for (let i = 0; i < room_events.results.length; i++) { - let sr = SearchResult.fromJson(room_events.results[i], this.getEventMapper()); + const sr = SearchResult.fromJson(room_events.results[i], this.getEventMapper()); searchResults.results.push(sr); } return searchResults; @@ -2358,8 +2385,8 @@ MatrixClient.prototype.syncLeftRooms = function() { if (this._syncLeftRoomsPromise) { return this._syncLeftRoomsPromise; // return the ongoing request } - let self = this; - let syncApi = new SyncApi(this, this._clientOpts); + const self = this; + const syncApi = new SyncApi(this, this._clientOpts); this._syncLeftRoomsPromise = syncApi.syncLeftRooms(); // cleanup locks @@ -2383,16 +2410,16 @@ MatrixClient.prototype.syncLeftRooms = function() { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.createFilter = function(content) { - let self = this; - let path = utils.encodeUri("/user/$userId/filter", { + const self = this; + const path = utils.encodeUri("/user/$userId/filter", { $userId: this.credentials.userId, }); return this._http.authedRequest( - undefined, "POST", path, undefined, content + undefined, "POST", path, undefined, content, ).then(function(response) { // persist the filter - let filter = Filter.fromJson( - self.credentials.userId, response.filter_id, content + const filter = Filter.fromJson( + self.credentials.userId, response.filter_id, content, ); self.store.storeFilter(filter); return filter; @@ -2410,24 +2437,24 @@ MatrixClient.prototype.createFilter = function(content) { */ MatrixClient.prototype.getFilter = function(userId, filterId, allowCached) { if (allowCached) { - let filter = this.store.getFilter(userId, filterId); + const filter = this.store.getFilter(userId, filterId); if (filter) { return q(filter); } } - let self = this; - let path = utils.encodeUri("/user/$userId/filter/$filterId", { + const self = this; + const path = utils.encodeUri("/user/$userId/filter/$filterId", { $userId: userId, $filterId: filterId, }); return this._http.authedRequest( - undefined, "GET", path, undefined, undefined + undefined, "GET", path, undefined, undefined, ).then(function(response) { // persist the filter - let filter = Filter.fromJson( - userId, filterId, response + const filter = Filter.fromJson( + userId, filterId, response, ); self.store.storeFilter(filter); return filter; @@ -2440,17 +2467,17 @@ MatrixClient.prototype.getFilter = function(userId, filterId, allowCached) { * @return {Promise} Filter ID */ MatrixClient.prototype.getOrCreateFilter = function(filterName, filter) { - let filterId = this.store.getFilterIdByName(filterName); + const filterId = this.store.getFilterIdByName(filterName); let promise = q(); - let self = this; + const self = this; if (filterId) { // check that the existing filter matches our expectations promise = self.getFilter(self.credentials.userId, - filterId, true + filterId, true, ).then(function(existingFilter) { - let oldDef = existingFilter.getDefinition(); - let newDef = filter.getDefinition(); + const oldDef = existingFilter.getDefinition(); + const newDef = filter.getDefinition(); if (utils.deepCompare(oldDef, newDef)) { // super, just use that. @@ -2489,7 +2516,7 @@ MatrixClient.prototype.getOrCreateFilter = function(filterName, filter) { } // create a new filter - return self.createFilter(filter.getDefinition() + return self.createFilter(filter.getDefinition(), ).then(function(createdFilter) { // debuglog("Created new filter ID %s: %s", createdFilter.filterId, // JSON.stringify(createdFilter.getDefinition())); @@ -2508,12 +2535,12 @@ MatrixClient.prototype.getOrCreateFilter = function(filterName, filter) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixClient.prototype.getOpenIdToken = function() { - let path = utils.encodeUri("/user/$userId/openid/request_token", { + const path = utils.encodeUri("/user/$userId/openid/request_token", { $userId: this.credentials.userId, }); return this._http.authedRequest( - undefined, "POST", path, undefined, {} + undefined, "POST", path, undefined, {}, ); }; @@ -2597,8 +2624,8 @@ MatrixClient.prototype.startClient = function(opts) { if (this._crypto) { this._crypto.uploadKeys(5).done(); - let tenMinutes = 1000 * 60 * 10; - let self = this; + const tenMinutes = 1000 * 60 * 10; + const self = this; this._uploadIntervalID = global.setInterval(function() { self._crypto.uploadKeys(5).done(); }, tenMinutes); @@ -2634,7 +2661,7 @@ MatrixClient.prototype.stopClient = function() { }; function setupCallEventHandler(client) { - let candidatesByCall = { + const candidatesByCall = { // callId: [Candidate] }; @@ -2647,11 +2674,11 @@ function setupCallEventHandler(client) { client.on("sync", function(state) { if (state === "PREPARED") { isClientPrepared = true; - let ignoreCallIds = {}; // Set + const ignoreCallIds = {}; // Set // inspect the buffer and mark all calls which have been answered // or hung up before passing them to the call event handler. for (let i = callEventBuffer.length - 1; i >= 0; i--) { - let ev = callEventBuffer[i]; + const ev = callEventBuffer[i]; if (ev.getType() === "m.call.answer" || ev.getType() === "m.call.hangup") { ignoreCallIds[ev.getContent().call_id] = "yep"; @@ -2682,7 +2709,7 @@ function setupCallEventHandler(client) { if (event.getType().indexOf("m.call.") !== 0) { return; // not a call event } - let content = event.getContent(); + const content = event.getContent(); let call = content.call_id ? client.callList[content.call_id] : undefined; let i; //console.log("RECV %s content=%s", event.getType(), JSON.stringify(content)); @@ -2703,7 +2730,7 @@ function setupCallEventHandler(client) { console.log( "WARN: Already have a MatrixCall with id %s but got an " + "invite. Clobbering.", - content.call_id + content.call_id, ); } @@ -2711,7 +2738,7 @@ function setupCallEventHandler(client) { if (!call) { console.log( "Incoming call ID " + content.call_id + " but this client " + - "doesn't support WebRTC" + "doesn't support WebRTC", ); // don't hang up the call: there could be other clients // connected that do support WebRTC and declining the @@ -2727,16 +2754,16 @@ function setupCallEventHandler(client) { if (candidatesByCall[call.callId]) { for (i = 0; i < candidatesByCall[call.callId].length; i++) { call._gotRemoteIceCandidate( - candidatesByCall[call.callId][i] + candidatesByCall[call.callId][i], ); } } // Were we trying to call that user (room)? let existingCall; - let existingCalls = utils.values(client.callList); + const existingCalls = utils.values(client.callList); for (i = 0; i < existingCalls.length; ++i) { - let thisCall = existingCalls[i]; + const thisCall = existingCalls[i]; if (call.room_id === thisCall.room_id && thisCall.direction === 'outbound' && (["wait_local_media", "create_offer", "invite_sent"].indexOf( @@ -2756,14 +2783,14 @@ function setupCallEventHandler(client) { existingCall.callId > call.callId) { console.log( "Glare detected: answering incoming call " + call.callId + - " and canceling outgoing call " + existingCall.callId + " and canceling outgoing call " + existingCall.callId, ); existingCall._replacedBy(call); call.answer(); } else { console.log( "Glare detected: rejecting incoming call " + call.callId + - " and keeping outgoing call " + existingCall.callId + " and keeping outgoing call " + existingCall.callId, ); call.hangup(); } @@ -2835,7 +2862,7 @@ function checkTurnServers(client) { res.ttl + " secs"); // map the response to a format that can be fed to // RTCPeerConnection - let servers = { + const servers = { urls: res.uris, username: res.username, credential: res.password, @@ -2871,7 +2898,7 @@ function _resolve(callback, defer, res) { function _PojoToMatrixEventMapper(client) { function mapper(plainOldJsObject) { - let event = new MatrixEvent(plainOldJsObject); + const event = new MatrixEvent(plainOldJsObject); if (event.isEncrypted()) { _decryptEvent(client, event); } @@ -2897,7 +2924,7 @@ MatrixClient.prototype.getEventMapper = function() { */ MatrixClient.prototype.generateClientSecret = function() { let ret = ""; - let chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; for (let i = 0; i < 32; i++) { ret += chars.charAt(Math.floor(Math.random() * chars.length)); diff --git a/src/content-repo.js b/src/content-repo.js index 124e4ca27..2a1765151 100644 --- a/src/content-repo.js +++ b/src/content-repo.js @@ -16,7 +16,7 @@ limitations under the License. /** * @module content-repo */ -let utils = require("./utils"); +const utils = require("./utils"); /** Content Repo utility functions */ module.exports = { @@ -48,7 +48,7 @@ module.exports = { } let serverAndMediaId = mxc.slice(6); // strips mxc:// let prefix = "/_matrix/media/v1/download/"; - let params = {}; + const params = {}; if (width) { params.width = width; @@ -65,8 +65,8 @@ module.exports = { prefix = "/_matrix/media/v1/thumbnail/"; } - let fragmentOffset = serverAndMediaId.indexOf("#"), - fragment = ""; + const fragmentOffset = serverAndMediaId.indexOf("#"); + let fragment = ""; if (fragmentOffset >= 0) { fragment = serverAndMediaId.substr(fragmentOffset); serverAndMediaId = serverAndMediaId.substr(0, fragmentOffset); @@ -94,12 +94,12 @@ module.exports = { if (!height) { height = 96; } - let params = { + const params = { width: width, height: height, }; - let path = utils.encodeUri("/_matrix/media/v1/identicon/$ident", { + const path = utils.encodeUri("/_matrix/media/v1/identicon/$ident", { $ident: identiconString, }); return baseUrl + path + diff --git a/src/crypto/OlmDevice.js b/src/crypto/OlmDevice.js index e01b56d20..979ebbcfa 100644 --- a/src/crypto/OlmDevice.js +++ b/src/crypto/OlmDevice.js @@ -20,13 +20,13 @@ limitations under the License. * * @module crypto/OlmDevice */ -let Olm = require("olm"); -let utils = require("../utils"); +const Olm = require("olm"); +const utils = require("../utils"); // The maximum size of an event is 65K, and we base64 the content, so this is a // reasonable approximation to the biggest plaintext we can encrypt. -let MAX_PLAINTEXT_LENGTH = 65536 * 3 / 4; +const MAX_PLAINTEXT_LENGTH = 65536 * 3 / 4; function checkPayloadLength(payloadString) { if (payloadString === undefined) { @@ -47,6 +47,18 @@ function checkPayloadLength(payloadString) { } +/** + * The type of object we use for importing and exporting megolm session data. + * + * @typedef {Object} module:crypto/OlmDevice.MegolmSessionData + * @property {String} sender_key Sender's Curve25519 device key + * @property {Object} sender_claimed_keys Other keys the sender claims. + * @property {String} room_id Room this session is used in + * @property {String} session_id Unique id for the session + * @property {String} session_key Base64'ed key data + */ + + /** * Manages the olm cryptography functions. Each OlmDevice has a single * OlmAccount and a number of OlmSessions. @@ -67,7 +79,7 @@ function OlmDevice(sessionStore) { this._pickleKey = "DEFAULT_KEY"; let e2eKeys; - let account = new Olm.Account(); + const account = new Olm.Account(); try { _initialise_account(this._sessionStore, this._pickleKey, account); e2eKeys = JSON.parse(account.identity_keys()); @@ -96,14 +108,14 @@ function OlmDevice(sessionStore) { } function _initialise_account(sessionStore, pickleKey, account) { - let e2eAccount = sessionStore.getEndToEndAccount(); + const e2eAccount = sessionStore.getEndToEndAccount(); if (e2eAccount !== null) { account.unpickle(pickleKey, e2eAccount); return; } account.create(); - let pickled = account.pickle(pickleKey); + const pickled = account.pickle(pickleKey); sessionStore.storeEndToEndAccount(pickled); } @@ -123,9 +135,9 @@ OlmDevice.getOlmVersion = function() { * @private */ OlmDevice.prototype._getAccount = function(func) { - let account = new Olm.Account(); + const account = new Olm.Account(); try { - let pickledAccount = this._sessionStore.getEndToEndAccount(); + const pickledAccount = this._sessionStore.getEndToEndAccount(); account.unpickle(this._pickleKey, pickledAccount); return func(account); } finally { @@ -141,7 +153,7 @@ OlmDevice.prototype._getAccount = function(func) { * @private */ OlmDevice.prototype._saveAccount = function(account) { - let pickledAccount = account.pickle(this._pickleKey); + const pickledAccount = account.pickle(this._pickleKey); this._sessionStore.storeEndToEndAccount(pickledAccount); }; @@ -156,10 +168,10 @@ OlmDevice.prototype._saveAccount = function(account) { * @private */ OlmDevice.prototype._getSession = function(deviceKey, sessionId, func) { - let sessions = this._sessionStore.getEndToEndSessions(deviceKey); - let pickledSession = sessions[sessionId]; + const sessions = this._sessionStore.getEndToEndSessions(deviceKey); + const pickledSession = sessions[sessionId]; - let session = new Olm.Session(); + const session = new Olm.Session(); try { session.unpickle(this._pickleKey, pickledSession); return func(session); @@ -177,9 +189,9 @@ OlmDevice.prototype._getSession = function(deviceKey, sessionId, func) { * @private */ OlmDevice.prototype._saveSession = function(deviceKey, session) { - let pickledSession = session.pickle(this._pickleKey); + const pickledSession = session.pickle(this._pickleKey); this._sessionStore.storeEndToEndSession( - deviceKey, session.session_id(), pickledSession + deviceKey, session.session_id(), pickledSession, ); }; @@ -192,7 +204,7 @@ OlmDevice.prototype._saveSession = function(deviceKey, session) { * @private */ OlmDevice.prototype._getUtility = function(func) { - let utility = new Olm.Utility(); + const utility = new Olm.Utility(); try { return func(utility); } finally { @@ -242,7 +254,7 @@ OlmDevice.prototype.maxNumberOfOneTimeKeys = function() { * Marks all of the one-time keys as published. */ OlmDevice.prototype.markKeysAsPublished = function() { - let self = this; + const self = this; this._getAccount(function(account) { account.mark_keys_as_published(); self._saveAccount(account); @@ -255,7 +267,7 @@ OlmDevice.prototype.markKeysAsPublished = function() { * @param {number} numKeys number of keys to generate */ OlmDevice.prototype.generateOneTimeKeys = function(numKeys) { - let self = this; + const self = this; this._getAccount(function(account) { account.generate_one_time_keys(numKeys); self._saveAccount(account); @@ -272,11 +284,11 @@ OlmDevice.prototype.generateOneTimeKeys = function(numKeys) { * @return {string} sessionId for the outbound session. */ OlmDevice.prototype.createOutboundSession = function( - theirIdentityKey, theirOneTimeKey + theirIdentityKey, theirOneTimeKey, ) { - let self = this; + const self = this; return this._getAccount(function(account) { - let session = new Olm.Session(); + const session = new Olm.Session(); try { session.create_outbound(account, theirIdentityKey, theirOneTimeKey); self._saveSession(theirIdentityKey, session); @@ -302,21 +314,21 @@ OlmDevice.prototype.createOutboundSession = function( * didn't use a valid one-time key). */ OlmDevice.prototype.createInboundSession = function( - theirDeviceIdentityKey, message_type, ciphertext + theirDeviceIdentityKey, message_type, ciphertext, ) { if (message_type !== 0) { throw new Error("Need message_type == 0 to create inbound session"); } - let self = this; + const self = this; return this._getAccount(function(account) { - let session = new Olm.Session(); + const session = new Olm.Session(); try { session.create_inbound_from(account, theirDeviceIdentityKey, ciphertext); account.remove_one_time_keys(session); self._saveAccount(account); - let payloadString = session.decrypt(message_type, ciphertext); + const payloadString = session.decrypt(message_type, ciphertext); self._saveSession(theirDeviceIdentityKey, session); @@ -339,8 +351,8 @@ OlmDevice.prototype.createInboundSession = function( * @return {string[]} a list of known session ids for the device */ OlmDevice.prototype.getSessionIdsForDevice = function(theirDeviceIdentityKey) { - let sessions = this._sessionStore.getEndToEndSessions( - theirDeviceIdentityKey + const sessions = this._sessionStore.getEndToEndSessions( + theirDeviceIdentityKey, ); return utils.keys(sessions); }; @@ -353,7 +365,7 @@ OlmDevice.prototype.getSessionIdsForDevice = function(theirDeviceIdentityKey) { * @return {string?} session id, or null if no established session */ OlmDevice.prototype.getSessionIdForDevice = function(theirDeviceIdentityKey) { - let sessionIds = this.getSessionIdsForDevice(theirDeviceIdentityKey); + const sessionIds = this.getSessionIdsForDevice(theirDeviceIdentityKey); if (sessionIds.length === 0) { return null; } @@ -374,10 +386,10 @@ OlmDevice.prototype.getSessionIdForDevice = function(theirDeviceIdentityKey) { * @return {Array.<{sessionId: string, hasReceivedMessage: Boolean}>} */ OlmDevice.prototype.getSessionInfoForDevice = function(deviceIdentityKey) { - let sessionIds = this.getSessionIdsForDevice(deviceIdentityKey); + const sessionIds = this.getSessionIdsForDevice(deviceIdentityKey); sessionIds.sort(); - let info = []; + const info = []; function getSessionInfo(session) { return { @@ -386,8 +398,8 @@ OlmDevice.prototype.getSessionInfoForDevice = function(deviceIdentityKey) { } for (let i = 0; i < sessionIds.length; i++) { - let sessionId = sessionIds[i]; - let res = this._getSession(deviceIdentityKey, sessionId, getSessionInfo); + const sessionId = sessionIds[i]; + const res = this._getSession(deviceIdentityKey, sessionId, getSessionInfo); res.sessionId = sessionId; info.push(res); } @@ -405,14 +417,14 @@ OlmDevice.prototype.getSessionInfoForDevice = function(deviceIdentityKey) { * @return {string} ciphertext */ OlmDevice.prototype.encryptMessage = function( - theirDeviceIdentityKey, sessionId, payloadString + theirDeviceIdentityKey, sessionId, payloadString, ) { - let self = this; + const self = this; checkPayloadLength(payloadString); return this._getSession(theirDeviceIdentityKey, sessionId, function(session) { - let res = session.encrypt(payloadString); + const res = session.encrypt(payloadString); self._saveSession(theirDeviceIdentityKey, session); return res; }); @@ -430,12 +442,12 @@ OlmDevice.prototype.encryptMessage = function( * @return {string} decrypted payload. */ OlmDevice.prototype.decryptMessage = function( - theirDeviceIdentityKey, sessionId, message_type, ciphertext + theirDeviceIdentityKey, sessionId, message_type, ciphertext, ) { - let self = this; + const self = this; return this._getSession(theirDeviceIdentityKey, sessionId, function(session) { - let payloadString = session.decrypt(message_type, ciphertext); + const payloadString = session.decrypt(message_type, ciphertext); self._saveSession(theirDeviceIdentityKey, session); return payloadString; @@ -455,7 +467,7 @@ OlmDevice.prototype.decryptMessage = function( * the given session. */ OlmDevice.prototype.matchesSession = function( - theirDeviceIdentityKey, sessionId, message_type, ciphertext + theirDeviceIdentityKey, sessionId, message_type, ciphertext, ) { if (message_type !== 0) { return false; @@ -477,7 +489,7 @@ OlmDevice.prototype.matchesSession = function( * @private */ OlmDevice.prototype._saveOutboundGroupSession = function(session) { - let pickledSession = session.pickle(this._pickleKey); + const pickledSession = session.pickle(this._pickleKey); this._outboundGroupSessionStore[session.session_id()] = pickledSession; }; @@ -492,12 +504,12 @@ OlmDevice.prototype._saveOutboundGroupSession = function(session) { * @private */ OlmDevice.prototype._getOutboundGroupSession = function(sessionId, func) { - let pickled = this._outboundGroupSessionStore[sessionId]; + const pickled = this._outboundGroupSessionStore[sessionId]; if (pickled === null) { throw new Error("Unknown outbound group session " + sessionId); } - let session = new Olm.OutboundGroupSession(); + const session = new Olm.OutboundGroupSession(); try { session.unpickle(this._pickleKey, pickled); return func(session); @@ -513,7 +525,7 @@ OlmDevice.prototype._getOutboundGroupSession = function(sessionId, func) { * @return {string} sessionId for the outbound session. */ OlmDevice.prototype.createOutboundGroupSession = function() { - let session = new Olm.OutboundGroupSession(); + const session = new Olm.OutboundGroupSession(); try { session.create(); this._saveOutboundGroupSession(session); @@ -533,12 +545,12 @@ OlmDevice.prototype.createOutboundGroupSession = function() { * @return {string} ciphertext */ OlmDevice.prototype.encryptGroupMessage = function(sessionId, payloadString) { - let self = this; + const self = this; checkPayloadLength(payloadString); return this._getOutboundGroupSession(sessionId, function(session) { - let res = session.encrypt(payloadString); + const res = session.encrypt(payloadString); self._saveOutboundGroupSession(session); return res; }); @@ -576,16 +588,16 @@ OlmDevice.prototype.getOutboundGroupSessionKey = function(sessionId) { * @private */ OlmDevice.prototype._saveInboundGroupSession = function( - roomId, senderCurve25519Key, sessionId, session, keysClaimed + roomId, senderCurve25519Key, sessionId, session, keysClaimed, ) { - let r = { + const r = { room_id: roomId, session: session.pickle(this._pickleKey), keysClaimed: keysClaimed, }; this._sessionStore.storeEndToEndInboundGroupSession( - senderCurve25519Key, sessionId, JSON.stringify(r) + senderCurve25519Key, sessionId, JSON.stringify(r), ); }; @@ -606,10 +618,10 @@ OlmDevice.prototype._saveInboundGroupSession = function( * @template {T} */ OlmDevice.prototype._getInboundGroupSession = function( - roomId, senderKey, sessionId, func + roomId, senderKey, sessionId, func, ) { let r = this._sessionStore.getEndToEndInboundGroupSession( - senderKey, sessionId + senderKey, sessionId, ); if (r === null) { @@ -623,11 +635,11 @@ OlmDevice.prototype._getInboundGroupSession = function( if (roomId !== r.room_id) { throw new Error( "Mismatched room_id for inbound group session (expected " + r.room_id + - ", was " + roomId + ")" + ", was " + roomId + ")", ); } - let session = new Olm.InboundGroupSession(); + const session = new Olm.InboundGroupSession(); try { session.unpickle(this._pickleKey, r.session); return func(session, r.keysClaimed || {}); @@ -646,9 +658,9 @@ OlmDevice.prototype._getInboundGroupSession = function( * @param {Object} keysClaimed Other keys the sender claims. */ OlmDevice.prototype.addInboundGroupSession = function( - roomId, senderKey, sessionId, sessionKey, keysClaimed + roomId, senderKey, sessionId, sessionKey, keysClaimed, ) { - let self = this; + const self = this; /* if we already have this session, consider updating it */ function updateSession(session) { @@ -658,8 +670,8 @@ OlmDevice.prototype.addInboundGroupSession = function( return true; } - let r = this._getInboundGroupSession( - roomId, senderKey, sessionId, updateSession + const r = this._getInboundGroupSession( + roomId, senderKey, sessionId, updateSession, ); if (r !== null) { @@ -667,16 +679,58 @@ OlmDevice.prototype.addInboundGroupSession = function( } // new session. - let session = new Olm.InboundGroupSession(); + const session = new Olm.InboundGroupSession(); try { session.create(sessionKey); if (sessionId != session.session_id()) { throw new Error( - "Mismatched group session ID from senderKey: " + senderKey + "Mismatched group session ID from senderKey: " + senderKey, ); } self._saveInboundGroupSession( - roomId, senderKey, sessionId, session, keysClaimed + roomId, senderKey, sessionId, session, keysClaimed, + ); + } finally { + session.free(); + } +}; + + +/** + * Add a previously-exported inbound group session to the session store + * + * @param {module:crypto/OlmDevice.MegolmSessionData} data session data + */ +OlmDevice.prototype.importInboundGroupSession = function(data) { + /* if we already have this session, consider updating it */ + function updateSession(session) { + console.log("Update for megolm session " + data.sender_key + "|" + + data.session_id); + // for now we just ignore updates. TODO: implement something here + + return true; + } + + const r = this._getInboundGroupSession( + data.room_id, data.sender_key, data.session_id, updateSession, + ); + + if (r !== null) { + return; + } + + // new session. + const session = new Olm.InboundGroupSession(); + try { + session.import_session(data.session_key); + if (data.session_id != session.session_id()) { + throw new Error( + "Mismatched group session ID from senderKey: " + data.sender_key, + ); + } + this._saveInboundGroupSession( + data.room_id, data.sender_key, data.session_id, session, + data.sender_claimed_keys, ); } finally { session.free(); @@ -697,12 +751,12 @@ OlmDevice.prototype.addInboundGroupSession = function( * Object}} result */ OlmDevice.prototype.decryptGroupMessage = function( - roomId, senderKey, sessionId, body + roomId, senderKey, sessionId, body, ) { - let self = this; + const self = this; function decrypt(session, keysClaimed) { - let res = session.decrypt(body); + const res = session.decrypt(body); let plaintext = res.plaintext; if (plaintext === undefined) { @@ -710,11 +764,11 @@ OlmDevice.prototype.decryptGroupMessage = function( plaintext = res; } else { // Check if we have seen this message index before to detect replay attacks. - let messageIndexKey = senderKey + "|" + sessionId + "|" + res.message_index; + const messageIndexKey = senderKey + "|" + sessionId + "|" + res.message_index; if (messageIndexKey in self._inboundGroupSessionMessageIndexes) { throw new Error( "Duplicate message index, possible replay attack: " + - messageIndexKey + messageIndexKey, ); } self._inboundGroupSessionMessageIndexes[messageIndexKey] = true; @@ -722,10 +776,10 @@ OlmDevice.prototype.decryptGroupMessage = function( // the sender must have had the senderKey to persuade us to save the // session. - let keysProved = {curve25519: senderKey}; + const keysProved = {curve25519: senderKey}; self._saveInboundGroupSession( - roomId, senderKey, sessionId, session, keysClaimed + roomId, senderKey, sessionId, session, keysClaimed, ); return { result: plaintext, @@ -735,10 +789,45 @@ OlmDevice.prototype.decryptGroupMessage = function( } return this._getInboundGroupSession( - roomId, senderKey, sessionId, decrypt + roomId, senderKey, sessionId, decrypt, ); }; +/** + * Export an inbound group session + * + * @param {string} senderKey base64-encoded curve25519 key of the sender + * @param {string} sessionId session identifier + * @return {module:crypto/OlmDevice.MegolmSessionData} exported session data + */ +OlmDevice.prototype.exportInboundGroupSession = function(senderKey, sessionId) { + const s = this._sessionStore.getEndToEndInboundGroupSession( + senderKey, sessionId, + ); + + if (s === null) { + throw new Error("Unknown inbound group session [" + senderKey + "," + + sessionId + "]"); + } + const r = JSON.parse(s); + + const session = new Olm.InboundGroupSession(); + try { + session.unpickle(this._pickleKey, r.session); + + const messageIndex = session.first_known_index(); + + return { + "sender_key": senderKey, + "sender_claimed_keys": r.keysClaimed, + "room_id": r.room_id, + "session_id": sessionId, + "session_key": session.export_session(messageIndex), + }; + } finally { + session.free(); + } +}; // Utilities // ========= @@ -755,7 +844,7 @@ OlmDevice.prototype.decryptGroupMessage = function( * was invalid then the message will be "OLM.BAD_MESSAGE_MAC". */ OlmDevice.prototype.verifySignature = function( - key, message, signature + key, message, signature, ) { this._getUtility(function(util) { util.ed25519_verify(key, message, signature); diff --git a/src/crypto/algorithms/base.js b/src/crypto/algorithms/base.js index df24b2aa2..96502ef6c 100644 --- a/src/crypto/algorithms/base.js +++ b/src/crypto/algorithms/base.js @@ -20,7 +20,7 @@ limitations under the License. * * @module crypto/algorithms/base */ -let utils = require("../../utils"); +const utils = require("../../utils"); /** * map of registered encryption algorithm classes. A map from string to {@link @@ -53,7 +53,7 @@ module.exports.DECRYPTION_CLASSES = {}; * @param {string} params.roomId The ID of the room we will be sending to * @param {object} params.config The body of the m.room.encryption event */ -let EncryptionAlgorithm = function(params) { +const EncryptionAlgorithm = function(params) { this._userId = params.userId; this._deviceId = params.deviceId; this._crypto = params.crypto; @@ -85,7 +85,7 @@ module.exports.EncryptionAlgorithm = EncryptionAlgorithm; * @param {string=} oldMembership previous membership */ EncryptionAlgorithm.prototype.onRoomMembership = function( - event, member, oldMembership + event, member, oldMembership, ) {}; /** @@ -101,7 +101,7 @@ EncryptionAlgorithm.prototype.onRoomMembership = function( * @param {string=} params.roomId The ID of the room we will be receiving * from. Null for to-device events. */ -let DecryptionAlgorithm = function(params) { +const DecryptionAlgorithm = function(params) { this._userId = params.userId; this._crypto = params.crypto; this._olmDevice = params.olmDevice; @@ -136,6 +136,15 @@ DecryptionAlgorithm.prototype.onRoomKeyEvent = function(params) { // ignore by default }; +/** + * Import a room key + * + * @param {module:crypto/OlmDevice.MegolmSessionData} session + */ +DecryptionAlgorithm.prototype.importRoomKey = function(session) { + // ignore by default +}; + /** * Exception thrown when decryption fails * diff --git a/src/crypto/algorithms/index.js b/src/crypto/algorithms/index.js index 532b2f205..ce64b3b11 100644 --- a/src/crypto/algorithms/index.js +++ b/src/crypto/algorithms/index.js @@ -19,7 +19,7 @@ limitations under the License. * @module crypto/algorithms */ -let base = require("./base"); +const base = require("./base"); require("./olm"); require("./megolm"); diff --git a/src/crypto/algorithms/megolm.js b/src/crypto/algorithms/megolm.js index 7962bdeb1..ccae2703a 100644 --- a/src/crypto/algorithms/megolm.js +++ b/src/crypto/algorithms/megolm.js @@ -21,11 +21,11 @@ limitations under the License. * @module crypto/algorithms/megolm */ -let q = require("q"); +const q = require("q"); -let utils = require("../../utils"); -let olmlib = require("../olmlib"); -let base = require("./base"); +const utils = require("../../utils"); +const olmlib = require("../olmlib"); +const base = require("./base"); /** * @private @@ -57,16 +57,16 @@ function OutboundSessionInfo(sessionId) { * @return {Boolean} */ OutboundSessionInfo.prototype.needsRotation = function( - rotationPeriodMsgs, rotationPeriodMs + rotationPeriodMsgs, rotationPeriodMs, ) { - let sessionLifetime = new Date().getTime() - this.creationTime; + const sessionLifetime = new Date().getTime() - this.creationTime; if (this.useCount >= rotationPeriodMsgs || sessionLifetime >= rotationPeriodMs ) { console.log( "Rotating megolm session after " + this.useCount + - " messages, " + sessionLifetime + "ms" + " messages, " + sessionLifetime + "ms", ); return true; } @@ -86,9 +86,9 @@ OutboundSessionInfo.prototype.needsRotation = function( * in devicesInRoom. */ OutboundSessionInfo.prototype.sharedWithTooManyDevices = function( - devicesInRoom + devicesInRoom, ) { - for (let userId in this.sharedWithDevices) { + for (const userId in this.sharedWithDevices) { if (!this.sharedWithDevices.hasOwnProperty(userId)) { continue; } @@ -98,7 +98,7 @@ OutboundSessionInfo.prototype.sharedWithTooManyDevices = function( return true; } - for (let deviceId in this.sharedWithDevices[userId]) { + for (const deviceId in this.sharedWithDevices[userId]) { if (!this.sharedWithDevices[userId].hasOwnProperty(deviceId)) { continue; } @@ -106,7 +106,7 @@ OutboundSessionInfo.prototype.sharedWithTooManyDevices = function( if (!devicesInRoom[userId].hasOwnProperty(deviceId)) { console.log( "Starting new session because we shared with " + - userId + ":" + deviceId + userId + ":" + deviceId, ); return true; } @@ -157,7 +157,7 @@ utils.inherits(MegolmEncryption, base.EncryptionAlgorithm); * OutboundSessionInfo when setup is complete. */ MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) { - let self = this; + const self = this; let session; @@ -187,23 +187,23 @@ MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) { } // now check if we need to share with any devices - let shareMap = {}; + const shareMap = {}; - for (let userId in devicesInRoom) { + for (const userId in devicesInRoom) { if (!devicesInRoom.hasOwnProperty(userId)) { continue; } - let userDevices = devicesInRoom[userId]; + const userDevices = devicesInRoom[userId]; - for (let deviceId in userDevices) { + for (const deviceId in userDevices) { if (!userDevices.hasOwnProperty(deviceId)) { continue; } - let deviceInfo = userDevices[deviceId]; + const deviceInfo = userDevices[deviceId]; - let key = deviceInfo.getIdentityKey(); + const key = deviceInfo.getIdentityKey(); if (key == self._olmDevice.deviceCurve25519Key) { // don't bother sending to ourself continue; @@ -220,7 +220,7 @@ MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) { } return self._shareKeyWithDevices( - session, shareMap + session, shareMap, ); } @@ -230,7 +230,7 @@ MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) { } // first wait for the previous share to complete - let prom = this._setupPromise.then(prepareSession); + const prom = this._setupPromise.then(prepareSession); // _setupPromise resolves to `session` whether or not the share succeeds this._setupPromise = prom.then(returnSession, returnSession); @@ -245,12 +245,12 @@ MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) { * @return {module:crypto/algorithms/megolm.OutboundSessionInfo} session */ MegolmEncryption.prototype._prepareNewSession = function() { - let session_id = this._olmDevice.createOutboundGroupSession(); - let key = this._olmDevice.getOutboundGroupSessionKey(session_id); + const session_id = this._olmDevice.createOutboundGroupSession(); + const key = this._olmDevice.getOutboundGroupSessionKey(session_id); this._olmDevice.addInboundGroupSession( this._roomId, this._olmDevice.deviceCurve25519Key, session_id, - key.key, {ed25519: this._olmDevice.deviceEd25519Key} + key.key, {ed25519: this._olmDevice.deviceEd25519Key}, ); return new OutboundSessionInfo(session_id); @@ -268,10 +268,10 @@ MegolmEncryption.prototype._prepareNewSession = function() { * message has been sent. */ MegolmEncryption.prototype._shareKeyWithDevices = function(session, devicesByUser) { - let self = this; + const self = this; - let key = this._olmDevice.getOutboundGroupSessionKey(session.sessionId); - let payload = { + const key = this._olmDevice.getOutboundGroupSessionKey(session.sessionId); + const payload = { type: "m.room_key", content: { algorithm: olmlib.MEGOLM_ALGORITHM, @@ -282,26 +282,26 @@ MegolmEncryption.prototype._shareKeyWithDevices = function(session, devicesByUse }, }; - let contentMap = {}; + const contentMap = {}; return olmlib.ensureOlmSessionsForDevices( - this._olmDevice, this._baseApis, devicesByUser + this._olmDevice, this._baseApis, devicesByUser, ).then(function(devicemap) { let haveTargets = false; - for (let userId in devicesByUser) { + for (const userId in devicesByUser) { if (!devicesByUser.hasOwnProperty(userId)) { continue; } - let devicesToShareWith = devicesByUser[userId]; - let sessionResults = devicemap[userId]; + const devicesToShareWith = devicesByUser[userId]; + const sessionResults = devicemap[userId]; for (let i = 0; i < devicesToShareWith.length; i++) { - let deviceInfo = devicesToShareWith[i]; - let deviceId = deviceInfo.deviceId; + const deviceInfo = devicesToShareWith[i]; + const deviceId = deviceInfo.deviceId; - let sessionResult = sessionResults[deviceId]; + const sessionResult = sessionResults[deviceId]; if (!sessionResult.sessionId) { // no session with this device, probably because there // were no one-time keys. @@ -318,10 +318,10 @@ MegolmEncryption.prototype._shareKeyWithDevices = function(session, devicesByUse } console.log( - "sharing keys with device " + userId + ":" + deviceId + "sharing keys with device " + userId + ":" + deviceId, ); - let encryptedContent = { + const encryptedContent = { algorithm: olmlib.OLM_ALGORITHM, sender_key: self._olmDevice.deviceCurve25519Key, ciphertext: {}, @@ -334,7 +334,7 @@ MegolmEncryption.prototype._shareKeyWithDevices = function(session, devicesByUse self._olmDevice, userId, deviceInfo, - payload + payload, ); if (!contentMap[userId]) { @@ -359,16 +359,16 @@ MegolmEncryption.prototype._shareKeyWithDevices = function(session, devicesByUse // attempted to share with) rather than the contentMap (those we did // share with), because we don't want to try to claim a one-time-key // for dead devices on every message. - for (let userId in devicesByUser) { + for (const userId in devicesByUser) { if (!devicesByUser.hasOwnProperty(userId)) { continue; } if (!session.sharedWithDevices[userId]) { session.sharedWithDevices[userId] = {}; } - let devicesToShareWith = devicesByUser[userId]; + const devicesToShareWith = devicesByUser[userId]; for (let i = 0; i < devicesToShareWith.length; i++) { - let deviceInfo = devicesToShareWith[i]; + const deviceInfo = devicesToShareWith[i]; session.sharedWithDevices[userId][deviceInfo.deviceId] = key.chain_index; } @@ -386,21 +386,21 @@ MegolmEncryption.prototype._shareKeyWithDevices = function(session, devicesByUse * @return {module:client.Promise} Promise which resolves to the new event body */ MegolmEncryption.prototype.encryptMessage = function(room, eventType, content) { - let self = this; + const self = this; return this._getDevicesInRoom(room).then(function(devicesInRoom) { return self._ensureOutboundSession(devicesInRoom); }).then(function(session) { - let payloadJson = { + const payloadJson = { room_id: self._roomId, type: eventType, content: content, }; - let ciphertext = self._olmDevice.encryptGroupMessage( - session.sessionId, JSON.stringify(payloadJson) + const ciphertext = self._olmDevice.encryptGroupMessage( + session.sessionId, JSON.stringify(payloadJson), ); - let encryptedContent = { + const encryptedContent = { algorithm: olmlib.MEGOLM_ALGORITHM, sender_key: self._olmDevice.deviceCurve25519Key, ciphertext: ciphertext, @@ -425,7 +425,7 @@ MegolmEncryption.prototype.encryptMessage = function(room, eventType, content) { */ MegolmEncryption.prototype._getDevicesInRoom = function(room) { // XXX what about rooms where invitees can see the content? - let roomMembers = utils.map(room.getJoinedMembers(), function(u) { + const roomMembers = utils.map(room.getJoinedMembers(), function(u) { return u.userId; }); @@ -435,13 +435,13 @@ MegolmEncryption.prototype._getDevicesInRoom = function(room) { // an m.new_device. return this._crypto.downloadKeys(roomMembers, false).then(function(devices) { // remove any blocked devices - for (let userId in devices) { + for (const userId in devices) { if (!devices.hasOwnProperty(userId)) { continue; } - let userDevices = devices[userId]; - for (let deviceId in userDevices) { + const userDevices = devices[userId]; + for (const deviceId in userDevices) { if (!userDevices.hasOwnProperty(deviceId)) { continue; } @@ -482,7 +482,7 @@ utils.inherits(MegolmDecryption, base.DecryptionAlgorithm); * problem decrypting the event */ MegolmDecryption.prototype.decryptEvent = function(event) { - let content = event.getWireContent(); + const content = event.getWireContent(); if (!content.sender_key || !content.session_id || !content.ciphertext @@ -493,7 +493,7 @@ MegolmDecryption.prototype.decryptEvent = function(event) { let res; try { res = this._olmDevice.decryptGroupMessage( - event.getRoomId(), content.sender_key, content.session_id, content.ciphertext + event.getRoomId(), content.sender_key, content.session_id, content.ciphertext, ); } catch (e) { if (e.message === 'OLM.UNKNOWN_MESSAGE_INDEX') { @@ -506,18 +506,18 @@ MegolmDecryption.prototype.decryptEvent = function(event) { // We've got a message for a session we don't have. this._addEventToPendingList(event); throw new base.DecryptionError( - "The sender's device has not sent us the keys for this message." + "The sender's device has not sent us the keys for this message.", ); } - let payload = JSON.parse(res.result); + const payload = JSON.parse(res.result); // belt-and-braces check that the room id matches that indicated by the HS // (this is somewhat redundant, since the megolm session is scoped to the // room, so neither the sender nor a MITM can lie about the room_id). if (payload.room_id !== event.getRoomId()) { throw new base.DecryptionError( - "Message intended for room " + payload.room_id + "Message intended for room " + payload.room_id, ); } @@ -534,8 +534,8 @@ MegolmDecryption.prototype.decryptEvent = function(event) { * @param {module:models/event.MatrixEvent} event */ MegolmDecryption.prototype._addEventToPendingList = function(event) { - let content = event.getWireContent(); - let k = content.sender_key + "|" + content.session_id; + const content = event.getWireContent(); + const k = content.sender_key + "|" + content.session_id; if (!this._pendingEvents[k]) { this._pendingEvents[k] = []; } @@ -549,7 +549,7 @@ MegolmDecryption.prototype._addEventToPendingList = function(event) { */ MegolmDecryption.prototype.onRoomKeyEvent = function(event) { console.log("Adding key from ", event); - let content = event.getContent(); + const content = event.getContent(); if (!content.room_id || !content.session_id || @@ -561,26 +561,52 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) { this._olmDevice.addInboundGroupSession( content.room_id, event.getSenderKey(), content.session_id, - content.session_key, event.getKeysClaimed() + content.session_key, event.getKeysClaimed(), ); - let k = event.getSenderKey() + "|" + content.session_id; - let pending = this._pendingEvents[k]; - if (pending) { - // have another go at decrypting events sent with this session. - delete this._pendingEvents[k]; + // have another go at decrypting events sent with this session. + this._retryDecryption(event.getSenderKey, content.session_id); +}; - for (let i = 0; i < pending.length; i++) { - try { - this.decryptEvent(pending[i]); - console.log("successful re-decryption of", pending[i]); - } catch (e) { - console.log("Still can't decrypt", pending[i], e.stack || e); - } + +/** + * @inheritdoc + * + * @param {module:crypto/OlmDevice.MegolmSessionData} session + */ +MegolmDecryption.prototype.importRoomKey = function(session) { + this._olmDevice.importInboundGroupSession(session); + + // have another go at decrypting events sent with this session. + this._retryDecryption(session.sender_key, session.session_id); +}; + +/** + * Have another go at decrypting events after we receive a key + * + * @private + * @param {String} senderKey + * @param {String} sessionId + */ +MegolmDecryption.prototype._retryDecryption = function(senderKey, sessionId) { + const k = senderKey + "|" + sessionId; + const pending = this._pendingEvents[k]; + if (!pending) { + return; + } + + delete this._pendingEvents[k]; + + for (let i = 0; i < pending.length; i++) { + try { + this.decryptEvent(pending[i]); + console.log("successful re-decryption of", pending[i]); + } catch (e) { + console.log("Still can't decrypt", pending[i], e.stack || e); } } }; base.registerAlgorithm( - olmlib.MEGOLM_ALGORITHM, MegolmEncryption, MegolmDecryption + olmlib.MEGOLM_ALGORITHM, MegolmEncryption, MegolmDecryption, ); diff --git a/src/crypto/algorithms/olm.js b/src/crypto/algorithms/olm.js index 7efa05c64..b98dccde5 100644 --- a/src/crypto/algorithms/olm.js +++ b/src/crypto/algorithms/olm.js @@ -20,15 +20,15 @@ limitations under the License. * * @module crypto/algorithms/olm */ -let q = require('q'); +const q = require('q'); -let utils = require("../../utils"); -let olmlib = require("../olmlib"); -let DeviceInfo = require("../deviceinfo"); -let DeviceVerification = DeviceInfo.DeviceVerification; +const utils = require("../../utils"); +const olmlib = require("../olmlib"); +const DeviceInfo = require("../deviceinfo"); +const DeviceVerification = DeviceInfo.DeviceVerification; -let base = require("./base"); +const base = require("./base"); /** * Olm encryption implementation @@ -63,7 +63,7 @@ OlmEncryption.prototype._ensureSession = function(roomMembers) { return q(); } - let self = this; + const self = this; this._prepPromise = self._crypto.downloadKeys(roomMembers, true).then(function(res) { return self._crypto.ensureOlmSessionsForUsers(roomMembers); }).then(function() { @@ -89,31 +89,31 @@ OlmEncryption.prototype.encryptMessage = function(room, eventType, content) { // TODO: there is a race condition here! What if a new user turns up // just as you are sending a secret message? - let users = utils.map(room.getJoinedMembers(), function(u) { + const users = utils.map(room.getJoinedMembers(), function(u) { return u.userId; }); - let self = this; + const self = this; return this._ensureSession(users).then(function() { - let payloadFields = { + const payloadFields = { room_id: room.roomId, type: eventType, content: content, }; - let encryptedContent = { + const encryptedContent = { algorithm: olmlib.OLM_ALGORITHM, sender_key: self._olmDevice.deviceCurve25519Key, ciphertext: {}, }; for (let i = 0; i < users.length; ++i) { - let userId = users[i]; - let devices = self._crypto.getStoredDevicesForUser(userId); + const userId = users[i]; + const devices = self._crypto.getStoredDevicesForUser(userId); for (let j = 0; j < devices.length; ++j) { - let deviceInfo = devices[j]; - let key = deviceInfo.getIdentityKey(); + const deviceInfo = devices[j]; + const key = deviceInfo.getIdentityKey(); if (key == self._olmDevice.deviceCurve25519Key) { // don't bother sending to ourself continue; @@ -126,7 +126,7 @@ OlmEncryption.prototype.encryptMessage = function(room, eventType, content) { olmlib.encryptMessageForDevice( encryptedContent.ciphertext, self._userId, self._deviceId, self._olmDevice, - userId, deviceInfo, payloadFields + userId, deviceInfo, payloadFields, ); } } @@ -157,9 +157,9 @@ utils.inherits(OlmDecryption, base.DecryptionAlgorithm); * problem decrypting the event */ OlmDecryption.prototype.decryptEvent = function(event) { - let content = event.getWireContent(); - let deviceKey = content.sender_key; - let ciphertext = content.ciphertext; + const content = event.getWireContent(); + const deviceKey = content.sender_key; + const ciphertext = content.ciphertext; if (!ciphertext) { throw new base.DecryptionError("Missing ciphertext"); @@ -168,7 +168,7 @@ OlmDecryption.prototype.decryptEvent = function(event) { if (!(this._olmDevice.deviceCurve25519Key in ciphertext)) { throw new base.DecryptionError("Not included in recipients"); } - let message = ciphertext[this._olmDevice.deviceCurve25519Key]; + const message = ciphertext[this._olmDevice.deviceCurve25519Key]; let payloadString; try { @@ -177,22 +177,22 @@ OlmDecryption.prototype.decryptEvent = function(event) { console.warn( "Failed to decrypt Olm event (id=" + event.getId() + ") from " + deviceKey + - ": " + e.message + ": " + e.message, ); throw new base.DecryptionError("Bad Encrypted Message"); } - let payload = JSON.parse(payloadString); + const payload = JSON.parse(payloadString); // check that we were the intended recipient, to avoid unknown-key attack // https://github.com/vector-im/vector-web/issues/2483 if (payload.recipient != this._userId) { console.warn( "Event " + event.getId() + ": Intended recipient " + - payload.recipient + " does not match our id " + this._userId + payload.recipient + " does not match our id " + this._userId, ); throw new base.DecryptionError( - "Message was intented for " + payload.recipient + "Message was intented for " + payload.recipient, ); } @@ -200,7 +200,7 @@ OlmDecryption.prototype.decryptEvent = function(event) { this._olmDevice.deviceEd25519Key) { console.warn( "Event " + event.getId() + ": Intended recipient ed25519 key " + - payload.recipient_keys.ed25519 + " did not match ours" + payload.recipient_keys.ed25519 + " did not match ours", ); throw new base.DecryptionError("Message not intended for this device"); } @@ -212,10 +212,10 @@ OlmDecryption.prototype.decryptEvent = function(event) { if (payload.sender != event.getSender()) { console.warn( "Event " + event.getId() + ": original sender " + payload.sender + - " does not match reported sender " + event.getSender() + " does not match reported sender " + event.getSender(), ); throw new base.DecryptionError( - "Message forwarded from " + payload.sender + "Message forwarded from " + payload.sender, ); } @@ -223,10 +223,10 @@ OlmDecryption.prototype.decryptEvent = function(event) { if (payload.room_id !== event.getRoomId()) { console.warn( "Event " + event.getId() + ": original room " + payload.room_id + - " does not match reported room " + event.room_id + " does not match reported room " + event.room_id, ); throw new base.DecryptionError( - "Message intended for room " + payload.room_id + "Message intended for room " + payload.room_id, ); } @@ -243,24 +243,24 @@ OlmDecryption.prototype.decryptEvent = function(event) { * @return {string} payload, if decrypted successfully. */ OlmDecryption.prototype._decryptMessage = function(theirDeviceIdentityKey, message) { - let sessionIds = this._olmDevice.getSessionIdsForDevice(theirDeviceIdentityKey); + const sessionIds = this._olmDevice.getSessionIdsForDevice(theirDeviceIdentityKey); // try each session in turn. - let decryptionErrors = {}; + const decryptionErrors = {}; for (let i = 0; i < sessionIds.length; i++) { - let sessionId = sessionIds[i]; + const sessionId = sessionIds[i]; try { - let payload = this._olmDevice.decryptMessage( - theirDeviceIdentityKey, sessionId, message.type, message.body + const payload = this._olmDevice.decryptMessage( + theirDeviceIdentityKey, sessionId, message.type, message.body, ); console.log( "Decrypted Olm message from " + theirDeviceIdentityKey + - " with session " + sessionId + " with session " + sessionId, ); return payload; } catch (e) { - let foundSession = this._olmDevice.matchesSession( - theirDeviceIdentityKey, sessionId, message.type, message.body + const foundSession = this._olmDevice.matchesSession( + theirDeviceIdentityKey, sessionId, message.type, message.body, ); if (foundSession) { @@ -268,7 +268,7 @@ OlmDecryption.prototype._decryptMessage = function(theirDeviceIdentityKey, messa // session, so it should have worked. throw new Error( "Error decrypting prekey message with existing session id " + - sessionId + ": " + e.message + sessionId + ": " + e.message, ); } @@ -288,7 +288,7 @@ OlmDecryption.prototype._decryptMessage = function(theirDeviceIdentityKey, messa throw new Error( "Error decrypting non-prekey message with existing sessions: " + - JSON.stringify(decryptionErrors) + JSON.stringify(decryptionErrors), ); } @@ -298,19 +298,19 @@ OlmDecryption.prototype._decryptMessage = function(theirDeviceIdentityKey, messa let res; try { res = this._olmDevice.createInboundSession( - theirDeviceIdentityKey, message.type, message.body + theirDeviceIdentityKey, message.type, message.body, ); } catch (e) { decryptionErrors["(new)"] = e.message; throw new Error( "Error decrypting prekey message: " + - JSON.stringify(decryptionErrors) + JSON.stringify(decryptionErrors), ); } console.log( "created new inbound Olm session ID " + - res.session_id + " with " + theirDeviceIdentityKey + res.session_id + " with " + theirDeviceIdentityKey, ); return res.payload; }; diff --git a/src/crypto/deviceinfo.js b/src/crypto/deviceinfo.js index d14ff27c0..d3dd682ca 100644 --- a/src/crypto/deviceinfo.js +++ b/src/crypto/deviceinfo.js @@ -62,8 +62,8 @@ function DeviceInfo(deviceId) { * @return {module:crypto~DeviceInfo} new DeviceInfo */ DeviceInfo.fromStorage = function(obj, deviceId) { - let res = new DeviceInfo(deviceId); - for (let prop in obj) { + const res = new DeviceInfo(deviceId); + for (const prop in obj) { if (obj.hasOwnProperty(prop)) { res[prop] = obj[prop]; } @@ -139,7 +139,7 @@ DeviceInfo.DeviceVerification = { BLOCKED: -1, }; -let DeviceVerification = DeviceInfo.DeviceVerification; +const DeviceVerification = DeviceInfo.DeviceVerification; /** */ module.exports = DeviceInfo; diff --git a/src/crypto/index.js b/src/crypto/index.js index 6e54d936a..b1866156d 100644 --- a/src/crypto/index.js +++ b/src/crypto/index.js @@ -20,15 +20,15 @@ limitations under the License. * @module crypto */ -let anotherjson = require('another-json'); -let q = require("q"); +const anotherjson = require('another-json'); +const q = require("q"); -let utils = require("../utils"); -let OlmDevice = require("./OlmDevice"); -let olmlib = require("./olmlib"); -let algorithms = require("./algorithms"); -let DeviceInfo = require("./deviceinfo"); -let DeviceVerification = DeviceInfo.DeviceVerification; +const utils = require("../utils"); +const OlmDevice = require("./OlmDevice"); +const olmlib = require("./olmlib"); +const algorithms = require("./algorithms"); +const DeviceInfo = require("./deviceinfo"); +const DeviceVerification = DeviceInfo.DeviceVerification; /** * Cryptography bits @@ -69,7 +69,7 @@ function Crypto(baseApis, eventEmitter, sessionStore, userId, deviceId) { this._roomDecryptors = {}; this._supportedAlgorithms = utils.keys( - algorithms.DECRYPTION_CLASSES + algorithms.DECRYPTION_CLASSES, ); // build our device keys: these will later be uploaded @@ -80,7 +80,7 @@ function Crypto(baseApis, eventEmitter, sessionStore, userId, deviceId) { this._olmDevice.deviceCurve25519Key; let myDevices = this._sessionStore.getEndToEndDevicesForUser( - this._userId + this._userId, ); if (!myDevices) { @@ -92,7 +92,7 @@ function Crypto(baseApis, eventEmitter, sessionStore, userId, deviceId) { if (!myDevices[this._deviceId]) { // add our own deviceinfo to the sessionstore - let deviceInfo = { + const deviceInfo = { keys: this._deviceKeys, algorithms: this._supportedAlgorithms, verified: DeviceVerification.VERIFIED, @@ -100,7 +100,7 @@ function Crypto(baseApis, eventEmitter, sessionStore, userId, deviceId) { myDevices[this._deviceId] = deviceInfo; this._sessionStore.storeEndToEndDevicesForUser( - this._userId, myDevices + this._userId, myDevices, ); } @@ -113,7 +113,7 @@ function _registerEventHandlers(crypto, eventEmitter) { if (syncState == "PREPARED") { // XXX ugh. we're assuming the eventEmitter is a MatrixClient. // how can we avoid doing so? - let rooms = eventEmitter.getRooms(); + const rooms = eventEmitter.getRooms(); crypto._onInitialSyncCompleted(rooms); } } catch (e) { @@ -176,7 +176,7 @@ Crypto.prototype.getDeviceEd25519Key = function() { * @return {object} A promise that will resolve when the keys are uploaded. */ Crypto.prototype.uploadKeys = function(maxKeys) { - let self = this; + const self = this; return _uploadDeviceKeys(this).then(function(res) { // We need to keep a pool of one time public keys on the server so that // other devices can start conversations with us. But we can only store @@ -191,16 +191,16 @@ Crypto.prototype.uploadKeys = function(maxKeys) { // these factors. // We first find how many keys the server has for us. - let keyCount = res.one_time_key_counts.signed_curve25519 || 0; + const keyCount = res.one_time_key_counts.signed_curve25519 || 0; // We then check how many keys we can store in the Account object. - let maxOneTimeKeys = self._olmDevice.maxNumberOfOneTimeKeys(); + const maxOneTimeKeys = self._olmDevice.maxNumberOfOneTimeKeys(); // Try to keep at most half that number on the server. This leaves the // rest of the slots free to hold keys that have been claimed from the // server but we haven't recevied a message for. // If we run out of slots when generating new keys then olm will // discard the oldest private keys first. This will eventually clean // out stale private keys that won't receive a message. - let keyLimit = Math.floor(maxOneTimeKeys / 2); + const keyLimit = Math.floor(maxOneTimeKeys / 2); // We work out how many new keys we need to create to top up the server // If there are too many keys on the server then we don't need to // create any more keys. @@ -225,10 +225,10 @@ Crypto.prototype.uploadKeys = function(maxKeys) { // returns a promise which resolves to the response function _uploadDeviceKeys(crypto) { - let userId = crypto._userId; - let deviceId = crypto._deviceId; + const userId = crypto._userId; + const deviceId = crypto._deviceId; - let deviceKeys = { + const deviceKeys = { algorithms: crypto._supportedAlgorithms, device_id: deviceId, keys: crypto._deviceKeys, @@ -247,12 +247,12 @@ function _uploadDeviceKeys(crypto) { // returns a promise which resolves to the response function _uploadOneTimeKeys(crypto) { - let oneTimeKeys = crypto._olmDevice.getOneTimeKeys(); - let oneTimeJson = {}; + const oneTimeKeys = crypto._olmDevice.getOneTimeKeys(); + const oneTimeJson = {}; - for (let keyId in oneTimeKeys.curve25519) { + for (const keyId in oneTimeKeys.curve25519) { if (oneTimeKeys.curve25519.hasOwnProperty(keyId)) { - let k = { + const k = { key: oneTimeKeys.curve25519[keyId], }; crypto._signObject(k); @@ -282,10 +282,10 @@ function _uploadOneTimeKeys(crypto) { * module:crypto/deviceinfo|DeviceInfo}. */ Crypto.prototype.downloadKeys = function(userIds, forceDownload) { - let self = this; + const self = this; // promises we need to wait for while the download happens - let promises = []; + const promises = []; // list of userids we need to download keys for let downloadUsers = []; @@ -300,9 +300,9 @@ Crypto.prototype.downloadKeys = function(userIds, forceDownload) { downloadUsers = userIds; } else { for (let i = 0; i < userIds.length; ++i) { - let u = userIds[i]; + const u = userIds[i]; - let inprogress = this._keyDownloadsInProgressByUser[u]; + const inprogress = this._keyDownloadsInProgressByUser[u]; if (inprogress) { // wait for the download to complete promises.push(q.any(inprogress).catch(perUserCatch(u))); @@ -313,7 +313,7 @@ Crypto.prototype.downloadKeys = function(userIds, forceDownload) { } if (downloadUsers.length > 0) { - let r = this._doKeyDownloadForUsers(downloadUsers); + const r = this._doKeyDownloadForUsers(downloadUsers); downloadUsers.map(function(u) { promises.push(r[u].catch(perUserCatch(u))); }); @@ -333,11 +333,11 @@ Crypto.prototype.downloadKeys = function(userIds, forceDownload) { * @return {Object} userId->deviceId->{@link module:crypto/deviceinfo|DeviceInfo}. */ Crypto.prototype._getDevicesFromStore = function(userIds) { - let stored = {}; - let self = this; + const stored = {}; + const self = this; userIds.map(function(u) { stored[u] = {}; - let devices = self.getStoredDevicesForUser(u) || []; + const devices = self.getStoredDevicesForUser(u) || []; devices.map(function(dev) { stored[u][dev.deviceId] = dev; }); @@ -351,17 +351,17 @@ Crypto.prototype._getDevicesFromStore = function(userIds) { * @return {Object} a map from userId to a promise for a result for that user */ Crypto.prototype._doKeyDownloadForUsers = function(downloadUsers) { - let self = this; + const self = this; console.log('Starting key download for ' + downloadUsers); - let deferMap = {}; - let promiseMap = {}; + const deferMap = {}; + const promiseMap = {}; downloadUsers.map(function(u) { - let deferred = q.defer(); - let promise = deferred.promise.finally(function() { - let inProgress = self._keyDownloadsInProgressByUser[u]; + const deferred = q.defer(); + const promise = deferred.promise.finally(function() { + const inProgress = self._keyDownloadsInProgressByUser[u]; utils.removeElement(inProgress, function(e) { return e === promise; }); @@ -381,42 +381,42 @@ Crypto.prototype._doKeyDownloadForUsers = function(downloadUsers) { }); this._baseApis.downloadKeysForUsers( - downloadUsers + downloadUsers, ).done(function(res) { - let dk = res.device_keys || {}; + const dk = res.device_keys || {}; for (let i = 0; i < downloadUsers.length; ++i) { - let userId = downloadUsers[i]; + const userId = downloadUsers[i]; var deviceId; console.log('got keys for ' + userId + ':', dk[userId]); if (!dk[userId]) { // no result for this user - let err = 'Unknown'; + const err = 'Unknown'; // TODO: do something with res.failures deferMap[userId].reject(err); continue; } // map from deviceid -> deviceinfo for this user - let userStore = {}; - let devs = self._sessionStore.getEndToEndDevicesForUser(userId); + const userStore = {}; + const devs = self._sessionStore.getEndToEndDevicesForUser(userId); if (devs) { for (deviceId in devs) { if (devs.hasOwnProperty(deviceId)) { - let d = DeviceInfo.fromStorage(devs[deviceId], deviceId); + const d = DeviceInfo.fromStorage(devs[deviceId], deviceId); userStore[deviceId] = d; } } } _updateStoredDeviceKeysForUser( - self._olmDevice, userId, userStore, dk[userId] + self._olmDevice, userId, userStore, dk[userId], ); // update the session store - let storage = {}; + const storage = {}; for (deviceId in userStore) { if (!userStore.hasOwnProperty(deviceId)) { continue; @@ -425,7 +425,7 @@ Crypto.prototype._doKeyDownloadForUsers = function(downloadUsers) { storage[deviceId] = userStore[deviceId].toStorage(); } self._sessionStore.storeEndToEndDevicesForUser( - userId, storage + userId, storage, ); deferMap[userId].resolve(); @@ -462,7 +462,7 @@ function _updateStoredDeviceKeysForUser(_olmDevice, userId, userStore, continue; } - let deviceResult = userResult[deviceId]; + const deviceResult = userResult[deviceId]; // check that the user_id and device_id in the response object are // correct @@ -496,18 +496,18 @@ function _storeDeviceKeys(_olmDevice, userStore, deviceResult) { return false; } - let deviceId = deviceResult.device_id; - let userId = deviceResult.user_id; + const deviceId = deviceResult.device_id; + const userId = deviceResult.user_id; - let signKeyId = "ed25519:" + deviceId; - let signKey = deviceResult.keys[signKeyId]; + const signKeyId = "ed25519:" + deviceId; + const signKey = deviceResult.keys[signKeyId]; if (!signKey) { console.log("Device " + userId + ":" + deviceId + " has no ed25519 key"); return false; } - let unsigned = deviceResult.unsigned || {}; + const unsigned = deviceResult.unsigned || {}; try { olmlib.verifySignature(_olmDevice, deviceResult, userId, deviceId, signKey); @@ -552,12 +552,12 @@ function _storeDeviceKeys(_olmDevice, userStore, deviceResult) { * managed to get a list of devices for this user yet. */ Crypto.prototype.getStoredDevicesForUser = function(userId) { - let devs = this._sessionStore.getEndToEndDevicesForUser(userId); + const devs = this._sessionStore.getEndToEndDevicesForUser(userId); if (!devs) { return null; } - let res = []; - for (let deviceId in devs) { + const res = []; + for (const deviceId in devs) { if (devs.hasOwnProperty(deviceId)) { res.push(DeviceInfo.fromStorage(devs[deviceId], deviceId)); } @@ -575,7 +575,7 @@ Crypto.prototype.getStoredDevicesForUser = function(userId) { * if we don't know about this device */ Crypto.prototype.getStoredDevice = function(userId, deviceId) { - let devs = this._sessionStore.getEndToEndDevicesForUser(userId); + const devs = this._sessionStore.getEndToEndDevicesForUser(userId); if (!devs || !devs[deviceId]) { return undefined; } @@ -593,13 +593,13 @@ Crypto.prototype.getStoredDevice = function(userId, deviceId) { * "key", and "display_name" parameters. */ Crypto.prototype.listDeviceKeys = function(userId) { - let devices = this.getStoredDevicesForUser(userId) || []; + const devices = this.getStoredDevicesForUser(userId) || []; - let result = []; + const result = []; for (let i = 0; i < devices.length; ++i) { - let device = devices[i]; - let ed25519Key = device.getFingerprint(); + const device = devices[i]; + const ed25519Key = device.getFingerprint(); if (ed25519Key) { result.push({ id: device.deviceId, @@ -643,25 +643,25 @@ Crypto.prototype.getDeviceByIdentityKey = function(userId, algorithm, sender_key return null; } - let devices = this._sessionStore.getEndToEndDevicesForUser(userId); + const devices = this._sessionStore.getEndToEndDevicesForUser(userId); if (!devices) { return null; } - for (let deviceId in devices) { + for (const deviceId in devices) { if (!devices.hasOwnProperty(deviceId)) { continue; } - let device = devices[deviceId]; - for (let keyId in device.keys) { + const device = devices[deviceId]; + for (const keyId in device.keys) { if (!device.keys.hasOwnProperty(keyId)) { continue; } if (keyId.indexOf("curve25519:") !== 0) { continue; } - let deviceKey = device.keys[keyId]; + const deviceKey = device.keys[keyId]; if (deviceKey == sender_key) { return DeviceInfo.fromStorage(device, deviceId); } @@ -686,12 +686,12 @@ Crypto.prototype.getDeviceByIdentityKey = function(userId, algorithm, sender_key * leave unchanged. */ Crypto.prototype.setDeviceVerification = function(userId, deviceId, verified, blocked) { - let devices = this._sessionStore.getEndToEndDevicesForUser(userId); + const devices = this._sessionStore.getEndToEndDevicesForUser(userId); if (!devices || !devices[deviceId]) { throw new Error("Unknown device " + userId + ":" + deviceId); } - let dev = devices[deviceId]; + const dev = devices[deviceId]; let verificationStatus = dev.verified; if (verified) { @@ -729,12 +729,12 @@ Crypto.prototype.setDeviceVerification = function(userId, deviceId, verified, bl * @return {Object.} */ Crypto.prototype.getOlmSessionsForUser = function(userId) { - let devices = this.getStoredDevicesForUser(userId) || []; - let result = {}; + const devices = this.getStoredDevicesForUser(userId) || []; + const result = {}; for (let j = 0; j < devices.length; ++j) { - let device = devices[j]; - let deviceKey = device.getIdentityKey(); - let sessions = this._olmDevice.getSessionInfoForDevice(deviceKey); + const device = devices[j]; + const deviceKey = device.getIdentityKey(); + const sessions = this._olmDevice.getSessionInfoForDevice(deviceKey); result[device.deviceId] = { deviceIdKey: deviceKey, @@ -753,8 +753,8 @@ Crypto.prototype.getOlmSessionsForUser = function(userId) { * @return {module:crypto/deviceinfo?} */ Crypto.prototype.getEventSenderDeviceInfo = function(event) { - let sender_key = event.getSenderKey(); - let algorithm = event.getWireContent().algorithm; + const sender_key = event.getSenderKey(); + const algorithm = event.getWireContent().algorithm; if (!sender_key || !algorithm) { return null; @@ -764,8 +764,8 @@ Crypto.prototype.getEventSenderDeviceInfo = function(event) { // was sent from. In the case of Megolm, it's actually the Curve25519 // identity key of the device which set up the Megolm session. - let device = this.getDeviceByIdentityKey( - event.getSender(), algorithm, sender_key + const device = this.getDeviceByIdentityKey( + event.getSender(), algorithm, sender_key, ); if (device === null) { @@ -781,7 +781,7 @@ Crypto.prototype.getEventSenderDeviceInfo = function(event) { // // (see https://github.com/vector-im/vector-web/issues/2215) - let claimedKey = event.getKeysClaimed().ed25519; + const claimedKey = event.getKeysClaimed().ed25519; if (!claimedKey) { console.warn("Event " + event.getId() + " claims no ed25519 key: " + "cannot verify sending device"); @@ -808,7 +808,7 @@ Crypto.prototype.getEventSenderDeviceInfo = function(event) { Crypto.prototype.setRoomEncryption = function(roomId, config) { // if we already have encryption in this room, we should ignore this event // (for now at least. maybe we should alert the user somehow?) - let existingConfig = this._sessionStore.getEndToEndRoom(roomId); + const existingConfig = this._sessionStore.getEndToEndRoom(roomId); if (existingConfig) { if (JSON.stringify(existingConfig) != JSON.stringify(config)) { console.error("Ignoring m.room.encryption event which requests " + @@ -817,7 +817,7 @@ Crypto.prototype.setRoomEncryption = function(roomId, config) { } } - let AlgClass = algorithms.ENCRYPTION_CLASSES[config.algorithm]; + const AlgClass = algorithms.ENCRYPTION_CLASSES[config.algorithm]; if (!AlgClass) { throw new Error("Unable to encrypt with " + config.algorithm); } @@ -828,7 +828,7 @@ Crypto.prototype.setRoomEncryption = function(roomId, config) { }; this._sessionStore.storeEndToEndRoom(roomId, config); - let alg = new AlgClass({ + const alg = new AlgClass({ userId: this._userId, deviceId: this._deviceId, crypto: this, @@ -859,17 +859,17 @@ Crypto.prototype.setRoomEncryption = function(roomId, config) { * {@link module:crypto~OlmSessionResult} */ Crypto.prototype.ensureOlmSessionsForUsers = function(users) { - let devicesByUser = {}; + const devicesByUser = {}; for (let i = 0; i < users.length; ++i) { - let userId = users[i]; + const userId = users[i]; devicesByUser[userId] = []; - let devices = this.getStoredDevicesForUser(userId) || []; + const devices = this.getStoredDevicesForUser(userId) || []; for (let j = 0; j < devices.length; ++j) { - let deviceInfo = devices[j]; + const deviceInfo = devices[j]; - let key = deviceInfo.getIdentityKey(); + const key = deviceInfo.getIdentityKey(); if (key == this._olmDevice.deviceCurve25519Key) { // don't bother setting up session to ourself continue; @@ -884,7 +884,7 @@ Crypto.prototype.ensureOlmSessionsForUsers = function(users) { } return olmlib.ensureOlmSessionsForDevices( - this._olmDevice, this._baseApis, devicesByUser + this._olmDevice, this._baseApis, devicesByUser, ); }; @@ -897,6 +897,45 @@ Crypto.prototype.isRoomEncrypted = function(roomId) { return Boolean(this._roomEncryptors[roomId]); }; + +/** + * Get a list containing all of the room keys + * + * @return {module:client.Promise} a promise which resolves to a list of + * session export objects + */ +Crypto.prototype.exportRoomKeys = function() { + return q( + this._sessionStore.getAllEndToEndInboundGroupSessionKeys().map( + (s) => { + const sess = this._olmDevice.exportInboundGroupSession( + s.senderKey, s.sessionId, + ); + + sess.algorithm = olmlib.MEGOLM_ALGORITHM; + return sess; + }, + ), + ); +}; + +/** + * Import a list of room keys previously exported by exportRoomKeys + * + * @param {Object[]} keys a list of session export objects + */ +Crypto.prototype.importRoomKeys = function(keys) { + keys.map((session) => { + if (!session.room_id || !session.algorithm) { + console.warn("ignoring session entry with missing fields", session); + return; + } + + const alg = this._getRoomDecryptor(session.room_id, session.algorithm); + alg.importRoomKey(session); + }); +}; + /** * Encrypt an event according to the configuration of the room, if necessary. * @@ -920,9 +959,9 @@ Crypto.prototype.encryptEventIfNeeded = function(event, room) { throw new Error("Cannot send encrypted messages in unknown rooms"); } - let roomId = event.getRoomId(); + const roomId = event.getRoomId(); - let alg = this._roomEncryptors[roomId]; + const alg = this._roomEncryptors[roomId]; if (!alg) { // not encrypting messages in this room @@ -931,7 +970,7 @@ Crypto.prototype.encryptEventIfNeeded = function(event, room) { throw new Error( "Room was previously configured to use encryption, but is " + "no longer. Perhaps the homeserver is hiding the " + - "configuration event." + "configuration event.", ); } return null; @@ -940,13 +979,13 @@ Crypto.prototype.encryptEventIfNeeded = function(event, room) { // We can claim and prove ownership of all our device keys in the local // echo of the event since we know that all the local echos come from // this device. - let myKeys = { + const myKeys = { curve25519: this._olmDevice.deviceCurve25519Key, ed25519: this._olmDevice.deviceEd25519Key, }; return alg.encryptMessage( - room, event.getType(), event.getContent() + room, event.getType(), event.getContent(), ).then(function(encryptedContent) { event.makeEncrypted("m.room.encrypted", encryptedContent, myKeys); }); @@ -960,8 +999,8 @@ Crypto.prototype.encryptEventIfNeeded = function(event, room) { * @raises {algorithms.DecryptionError} if there is a problem decrypting the event */ Crypto.prototype.decryptEvent = function(event) { - let content = event.getWireContent(); - let alg = this._getRoomDecryptor(event.getRoomId(), content.algorithm); + const content = event.getWireContent(); + const alg = this._getRoomDecryptor(event.getRoomId(), content.algorithm); alg.decryptEvent(event); }; @@ -972,8 +1011,8 @@ Crypto.prototype.decryptEvent = function(event) { * @param {module:models/event.MatrixEvent} event encryption event */ Crypto.prototype._onCryptoEvent = function(event) { - let roomId = event.getRoomId(); - let content = event.getContent(); + const roomId = event.getRoomId(); + const content = event.getContent(); try { this.setRoomEncryption(roomId, content); @@ -1004,27 +1043,27 @@ Crypto.prototype._onInitialSyncCompleted = function(rooms) { // we need to tell all the devices in all the rooms we are members of that // we have arrived. // build a list of rooms for each user. - let roomsByUser = {}; + const roomsByUser = {}; for (let i = 0; i < rooms.length; i++) { - let room = rooms[i]; + const room = rooms[i]; // check for rooms with encryption enabled - let alg = this._roomEncryptors[room.roomId]; + const alg = this._roomEncryptors[room.roomId]; if (!alg) { continue; } // ignore any rooms which we have left - let me = room.getMember(this._userId); + const me = room.getMember(this._userId); if (!me || ( me.membership !== "join" && me.membership !== "invite" )) { continue; } - let members = room.getJoinedMembers(); + const members = room.getJoinedMembers(); for (let j = 0; j < members.length; j++) { - let m = members[j]; + const m = members[j]; if (!roomsByUser[m.userId]) { roomsByUser[m.userId] = []; } @@ -1033,8 +1072,8 @@ Crypto.prototype._onInitialSyncCompleted = function(rooms) { } // build a per-device message for each user - let content = {}; - for (let userId in roomsByUser) { + const content = {}; + for (const userId in roomsByUser) { if (!roomsByUser.hasOwnProperty(userId)) { continue; } @@ -1046,10 +1085,10 @@ Crypto.prototype._onInitialSyncCompleted = function(rooms) { }; } - let self = this; + const self = this; this._baseApis.sendToDevice( "m.new_device", // OH HAI! - content + content, ).done(function() { self._sessionStore.setDeviceAnnounced(); }); @@ -1062,14 +1101,14 @@ Crypto.prototype._onInitialSyncCompleted = function(rooms) { * @param {module:models/event.MatrixEvent} event key event */ Crypto.prototype._onRoomKeyEvent = function(event) { - let content = event.getContent(); + const content = event.getContent(); if (!content.room_id || !content.algorithm) { console.error("key event is missing fields"); return; } - let alg = this._getRoomDecryptor(content.room_id, content.algorithm); + const alg = this._getRoomDecryptor(content.room_id, content.algorithm); alg.onRoomKeyEvent(event); }; @@ -1090,9 +1129,9 @@ Crypto.prototype._onRoomMembership = function(event, member, oldMembership) { // Further, it is automatically registered and called when new members // arrive in the room. - let roomId = member.roomId; + const roomId = member.roomId; - let alg = this._roomEncryptors[roomId]; + const alg = this._roomEncryptors[roomId]; if (!alg) { // not encrypting in this room return; @@ -1109,10 +1148,10 @@ Crypto.prototype._onRoomMembership = function(event, member, oldMembership) { * @param {module:models/event.MatrixEvent} event announcement event */ Crypto.prototype._onNewDeviceEvent = function(event) { - let content = event.getContent(); - let userId = event.getSender(); - let deviceId = content.device_id; - let rooms = content.rooms; + const content = event.getContent(); + const userId = event.getSender(); + const deviceId = content.device_id; + const rooms = content.rooms; if (!rooms || !deviceId) { console.warn("new_device event missing keys"); @@ -1140,15 +1179,15 @@ Crypto.prototype._onNewDeviceEvent = function(event) { * Start device queries for any users who sent us an m.new_device recently */ Crypto.prototype._flushNewDeviceRequests = function() { - let self = this; + const self = this; - let users = utils.keys(this._pendingUsersWithNewDevices); + const users = utils.keys(this._pendingUsersWithNewDevices); if (users.length === 0) { return; } - let r = this._doKeyDownloadForUsers(users); + const r = this._doKeyDownloadForUsers(users); // we've kicked off requests to these users: remove their // pending flag for now. @@ -1157,7 +1196,7 @@ Crypto.prototype._flushNewDeviceRequests = function() { users.map(function(u) { r[u] = r[u].catch(function(e) { console.error( - 'Error updating device keys for user ' + u + ':', e + 'Error updating device keys for user ' + u + ':', e, ); // reinstate the pending flags on any users which failed; this will @@ -1206,10 +1245,10 @@ Crypto.prototype._getRoomDecryptor = function(roomId, algorithm) { } } - let AlgClass = algorithms.DECRYPTION_CLASSES[algorithm]; + const AlgClass = algorithms.DECRYPTION_CLASSES[algorithm]; if (!AlgClass) { throw new algorithms.DecryptionError( - 'Unknown encryption algorithm "' + algorithm + '".' + 'Unknown encryption algorithm "' + algorithm + '".', ); } alg = new AlgClass({ @@ -1232,7 +1271,7 @@ Crypto.prototype._getRoomDecryptor = function(roomId, algorithm) { * @param {Object} obj Object to which we will add a 'signatures' property */ Crypto.prototype._signObject = function(obj) { - let sigs = {}; + const sigs = {}; sigs[this._userId] = {}; sigs[this._userId]["ed25519:" + this._deviceId] = this._olmDevice.sign(anotherjson.stringify(obj)); diff --git a/src/crypto/olmlib.js b/src/crypto/olmlib.js index 0a731e82a..7b487b7b4 100644 --- a/src/crypto/olmlib.js +++ b/src/crypto/olmlib.js @@ -20,10 +20,10 @@ limitations under the License. * Utilities common to olm encryption algorithms */ -let q = require('q'); -let anotherjson = require('another-json'); +const q = require('q'); +const anotherjson = require('another-json'); -let utils = require("../utils"); +const utils = require("../utils"); /** * matrix algorithm tag for olm @@ -52,10 +52,10 @@ module.exports.MEGOLM_ALGORITHM = "m.megolm.v1.aes-sha2"; module.exports.encryptMessageForDevice = function( resultsObject, ourUserId, ourDeviceId, olmDevice, recipientUserId, recipientDevice, - payloadFields + payloadFields, ) { - let deviceKey = recipientDevice.getIdentityKey(); - let sessionId = olmDevice.getSessionIdForDevice(deviceKey); + const deviceKey = recipientDevice.getIdentityKey(); + const sessionId = olmDevice.getSessionIdForDevice(deviceKey); if (sessionId === null) { // If we don't have a session for a device then // we can't encrypt a message for it. @@ -64,10 +64,10 @@ module.exports.encryptMessageForDevice = function( console.log( "Using sessionid " + sessionId + " for device " + - recipientUserId + ":" + recipientDevice.deviceId + recipientUserId + ":" + recipientDevice.deviceId, ); - let payload = { + const payload = { sender: ourUserId, sender_device: ourDeviceId, @@ -100,7 +100,7 @@ module.exports.encryptMessageForDevice = function( utils.extend(payload, payloadFields); resultsObject[deviceKey] = olmDevice.encryptMessage( - deviceKey, sessionId, JSON.stringify(payload) + deviceKey, sessionId, JSON.stringify(payload), ); }; @@ -119,24 +119,24 @@ module.exports.encryptMessageForDevice = function( * {@link module:crypto~OlmSessionResult} */ module.exports.ensureOlmSessionsForDevices = function( - olmDevice, baseApis, devicesByUser + olmDevice, baseApis, devicesByUser, ) { - let devicesWithoutSession = [ + const devicesWithoutSession = [ // [userId, deviceId], ... ]; - let result = {}; + const result = {}; - for (let userId in devicesByUser) { + for (const userId in devicesByUser) { if (!devicesByUser.hasOwnProperty(userId)) { continue; } result[userId] = {}; - let devices = devicesByUser[userId]; + const devices = devicesByUser[userId]; for (let j = 0; j < devices.length; j++) { - let deviceInfo = devices[j]; - let deviceId = deviceInfo.deviceId; - let key = deviceInfo.getIdentityKey(); - let sessionId = olmDevice.getSessionIdForDevice(key); + const deviceInfo = devices[j]; + const deviceId = deviceInfo.deviceId; + const key = deviceInfo.getIdentityKey(); + const sessionId = olmDevice.getSessionIdForDevice(key); if (sessionId === null) { devicesWithoutSession.push([userId, deviceId]); } @@ -157,28 +157,28 @@ module.exports.ensureOlmSessionsForDevices = function( // // That should eventually resolve itself, but it's poor form. - let oneTimeKeyAlgorithm = "signed_curve25519"; + const oneTimeKeyAlgorithm = "signed_curve25519"; return baseApis.claimOneTimeKeys( - devicesWithoutSession, oneTimeKeyAlgorithm + devicesWithoutSession, oneTimeKeyAlgorithm, ).then(function(res) { - let otk_res = res.one_time_keys || {}; - for (let userId in devicesByUser) { + const otk_res = res.one_time_keys || {}; + for (const userId in devicesByUser) { if (!devicesByUser.hasOwnProperty(userId)) { continue; } - let userRes = otk_res[userId] || {}; - let devices = devicesByUser[userId]; + const userRes = otk_res[userId] || {}; + const devices = devicesByUser[userId]; for (let j = 0; j < devices.length; j++) { - let deviceInfo = devices[j]; - let deviceId = deviceInfo.deviceId; + const deviceInfo = devices[j]; + const deviceId = deviceInfo.deviceId; if (result[userId][deviceId].sessionId) { // we already have a result for this device continue; } - let deviceRes = userRes[deviceId] || {}; + const deviceRes = userRes[deviceId] || {}; let oneTimeKey = null; - for (let keyId in deviceRes) { + for (const keyId in deviceRes) { if (keyId.indexOf(oneTimeKeyAlgorithm + ":") === 0) { oneTimeKey = deviceRes[keyId]; } @@ -187,13 +187,13 @@ module.exports.ensureOlmSessionsForDevices = function( if (!oneTimeKey) { console.warn( "No one-time keys (alg=" + oneTimeKeyAlgorithm + - ") for device " + userId + ":" + deviceId + ") for device " + userId + ":" + deviceId, ); continue; } - let sid = _verifyKeyAndStartSession( - olmDevice, oneTimeKey, userId, deviceInfo + const sid = _verifyKeyAndStartSession( + olmDevice, oneTimeKey, userId, deviceInfo, ); result[userId][deviceId].sessionId = sid; } @@ -204,16 +204,16 @@ module.exports.ensureOlmSessionsForDevices = function( function _verifyKeyAndStartSession(olmDevice, oneTimeKey, userId, deviceInfo) { - let deviceId = deviceInfo.deviceId; + const deviceId = deviceInfo.deviceId; try { _verifySignature( olmDevice, oneTimeKey, userId, deviceId, - deviceInfo.getFingerprint() + deviceInfo.getFingerprint(), ); } catch (e) { console.error( "Unable to verify signature on one-time key for device " + - userId + ":" + deviceId + ":", e + userId + ":" + deviceId + ":", e, ); return null; } @@ -221,7 +221,7 @@ function _verifyKeyAndStartSession(olmDevice, oneTimeKey, userId, deviceInfo) { let sid; try { sid = olmDevice.createOutboundSession( - deviceInfo.getIdentityKey(), oneTimeKey.key + deviceInfo.getIdentityKey(), oneTimeKey.key, ); } catch (e) { // possibly a bad key @@ -250,13 +250,13 @@ function _verifyKeyAndStartSession(olmDevice, oneTimeKey, userId, deviceInfo) { * * @param {string} signingKey base64-ed ed25519 public key */ -let _verifySignature = module.exports.verifySignature = function( - olmDevice, obj, signingUserId, signingDeviceId, signingKey +const _verifySignature = module.exports.verifySignature = function( + olmDevice, obj, signingUserId, signingDeviceId, signingKey, ) { - let signKeyId = "ed25519:" + signingDeviceId; - let signatures = obj.signatures || {}; - let userSigs = signatures[signingUserId] || {}; - let signature = userSigs[signKeyId]; + const signKeyId = "ed25519:" + signingDeviceId; + const signatures = obj.signatures || {}; + const userSigs = signatures[signingUserId] || {}; + const signature = userSigs[signKeyId]; if (!signature) { throw Error("No signature"); } @@ -265,9 +265,9 @@ let _verifySignature = module.exports.verifySignature = function( // anotherjson delete obj.unsigned; delete obj.signatures; - let json = anotherjson.stringify(obj); + const json = anotherjson.stringify(obj); olmDevice.verifySignature( - signingKey, json, signature + signingKey, json, signature, ); }; diff --git a/src/filter-component.js b/src/filter-component.js index b0c56479b..ebf1dd0f4 100644 --- a/src/filter-component.js +++ b/src/filter-component.js @@ -27,7 +27,7 @@ limitations under the License. */ function _matches_wildcard(actual_value, filter_value) { if (filter_value.endsWith("*")) { - let type_prefix = filter_value.slice(0, -1); + const type_prefix = filter_value.slice(0, -1); return actual_value.substr(0, type_prefix.length) === type_prefix; } else { return actual_value === filter_value; @@ -70,7 +70,7 @@ FilterComponent.prototype.check = function(event) { event.getRoomId(), event.getSender(), event.getType(), - event.getContent() ? event.getContent().url !== undefined : false + event.getContent() ? event.getContent().url !== undefined : false, ); }; @@ -84,7 +84,7 @@ FilterComponent.prototype.check = function(event) { */ FilterComponent.prototype._checkFields = function(room_id, sender, event_type, contains_url) { - let literal_keys = { + const literal_keys = { "rooms": function(v) { return room_id === v; }, @@ -96,16 +96,16 @@ FilterComponent.prototype._checkFields = }, }; - let self = this; + const self = this; Object.keys(literal_keys).forEach(function(name) { - let match_func = literal_keys[name]; - let not_name = "not_" + name; - let disallowed_values = self[not_name]; + const match_func = literal_keys[name]; + const not_name = "not_" + name; + const disallowed_values = self[not_name]; if (disallowed_values.map(match_func)) { return false; } - let allowed_values = self[name]; + const allowed_values = self[name]; if (allowed_values) { if (!allowed_values.map(match_func)) { return false; @@ -113,7 +113,7 @@ FilterComponent.prototype._checkFields = } }); - let contains_url_filter = this.filter_json.contains_url; + const contains_url_filter = this.filter_json.contains_url; if (contains_url_filter !== undefined) { if (contains_url_filter !== contains_url) { return false; diff --git a/src/filter.js b/src/filter.js index c64b7aff1..e0f03daa7 100644 --- a/src/filter.js +++ b/src/filter.js @@ -18,7 +18,7 @@ limitations under the License. * @module filter */ -let FilterComponent = require("./filter-component"); +const FilterComponent = require("./filter-component"); /** * @param {Object} obj @@ -26,7 +26,7 @@ let FilterComponent = require("./filter-component"); * @param {*} val */ function setProp(obj, keyNesting, val) { - let nestedKeys = keyNesting.split("."); + const nestedKeys = keyNesting.split("."); let currentObj = obj; for (let i = 0; i < (nestedKeys.length - 1); i++) { if (!currentObj[nestedKeys[i]]) { @@ -106,10 +106,10 @@ Filter.prototype.setDefinition = function(definition) { // "event_fields": ["type", "content", "sender"] // } - let room_filter_json = definition.room; + const room_filter_json = definition.room; // consider the top level rooms/not_rooms filter - let room_filter_fields = {}; + const room_filter_fields = {}; if (room_filter_json) { if (room_filter_json.rooms) { room_filter_fields.rooms = room_filter_json.rooms; @@ -123,7 +123,7 @@ Filter.prototype.setDefinition = function(definition) { this._room_filter = new FilterComponent(room_filter_fields); this._room_timeline_filter = new FilterComponent( - room_filter_json ? (room_filter_json.timeline || {}) : {} + room_filter_json ? (room_filter_json.timeline || {}) : {}, ); // don't bother porting this from synapse yet: @@ -183,7 +183,7 @@ Filter.prototype.setIncludeLeaveRooms = function(includeLeave) { * @return {Filter} */ Filter.fromJson = function(userId, filterId, jsonObj) { - let filter = new Filter(userId, filterId); + const filter = new Filter(userId, filterId); filter.setDefinition(jsonObj); return filter; }; diff --git a/src/http-api.js b/src/http-api.js index c26458690..761a55217 100644 --- a/src/http-api.js +++ b/src/http-api.js @@ -18,13 +18,13 @@ limitations under the License. * This is an internal module. See {@link MatrixHttpApi} for the public class. * @module http-api */ -let q = require("q"); -let utils = require("./utils"); +const q = require("q"); +const utils = require("./utils"); // we use our own implementation of setTimeout, so that if we get suspended in // the middle of a /sync, we cancel the sync as soon as we awake, rather than // waiting for the delay to elapse. -let callbacks = require("./realtime-callbacks"); +const callbacks = require("./realtime-callbacks"); /* TODO: @@ -91,7 +91,7 @@ module.exports.MatrixHttpApi.prototype = { * path and query parameters respectively. */ getContentUri: function() { - let params = { + const params = { access_token: this.opts.accessToken, }; return { @@ -145,12 +145,12 @@ module.exports.MatrixHttpApi.prototype = { // if the file doesn't have a mime type, use a default since // the HS errors if we don't supply one. - let contentType = opts.type || file.type || 'application/octet-stream'; - let fileName = opts.name || file.name; + const contentType = opts.type || file.type || 'application/octet-stream'; + const fileName = opts.name || file.name; // we used to recommend setting file.stream to the thing to upload on // nodejs. - let body = file.stream ? file.stream : file; + const body = file.stream ? file.stream : file; // backwards-compatibility hacks where we used to do different things // between browser and node. @@ -163,7 +163,7 @@ module.exports.MatrixHttpApi.prototype = { "Returning the raw JSON from uploadContent(). Future " + "versions of the js-sdk will change this default, to " + "return the parsed object. Set opts.rawResponse=false " + - "to change this behaviour now." + "to change this behaviour now.", ); rawResponse = true; } @@ -176,7 +176,7 @@ module.exports.MatrixHttpApi.prototype = { "Returning only the content-uri from uploadContent(). " + "Future versions of the js-sdk will change this " + "default, to return the whole response object. Set " + - "opts.onlyContentUri=false to change this behaviour now." + "opts.onlyContentUri=false to change this behaviour now.", ); onlyContentUri = true; } else { @@ -192,7 +192,7 @@ module.exports.MatrixHttpApi.prototype = { // (browser-request doesn't support progress either, which is also kind // of important here) - let upload = { loaded: 0, total: 0 }; + const upload = { loaded: 0, total: 0 }; let promise; // XMLHttpRequest doesn't parse JSON for us. request normally does, but @@ -214,12 +214,12 @@ module.exports.MatrixHttpApi.prototype = { } if (global.XMLHttpRequest) { - let defer = q.defer(); - let xhr = new global.XMLHttpRequest(); + const defer = q.defer(); + const xhr = new global.XMLHttpRequest(); upload.xhr = xhr; - let cb = requestCallback(defer, opts.callback, this.opts.onlyData); + const cb = requestCallback(defer, opts.callback, this.opts.onlyData); - let timeout_fn = function() { + const timeout_fn = function() { xhr.abort(); cb(new Error('Timeout')); }; @@ -269,7 +269,7 @@ module.exports.MatrixHttpApi.prototype = { // dirty hack (as per _request) to allow the upload to be cancelled. promise.abort = xhr.abort.bind(xhr); } else { - let queryParams = { + const queryParams = { filename: fileName, }; @@ -279,14 +279,14 @@ module.exports.MatrixHttpApi.prototype = { headers: {"Content-Type": contentType}, json: false, bodyParser: bodyParser, - } + }, ); } - let self = this; + const self = this; // remove the upload from the list on completion - let promise0 = promise.finally(function() { + const promise0 = promise.finally(function() { for (let i = 0; i < self.uploads.length; ++i) { if (self.uploads[i] === upload) { self.uploads.splice(i, 1); @@ -317,15 +317,15 @@ module.exports.MatrixHttpApi.prototype = { }, idServerRequest: function(callback, method, path, params, prefix) { - let fullUri = this.opts.idBaseUrl + prefix + path; + const fullUri = this.opts.idBaseUrl + prefix + path; if (callback !== undefined && !utils.isFunction(callback)) { throw Error( - "Expected callback to be a function but got " + typeof callback + "Expected callback to be a function but got " + typeof callback, ); } - let opts = { + const opts = { uri: fullUri, method: method, withCredentials: false, @@ -338,10 +338,10 @@ module.exports.MatrixHttpApi.prototype = { opts.form = params; } - let defer = q.defer(); + const defer = q.defer(); this.opts.request( opts, - requestCallback(defer, callback, this.opts.onlyData) + requestCallback(defer, callback, this.opts.onlyData), ); // ID server does not always take JSON, so we can't use requests' 'json' // option as we do with the home server, but it does return JSON, so @@ -389,11 +389,11 @@ module.exports.MatrixHttpApi.prototype = { queryParams.access_token = this.opts.accessToken; } - let request_promise = this.request( - callback, method, path, queryParams, data, opts + const request_promise = this.request( + callback, method, path, queryParams, data, opts, ); - let self = this; + const self = this; request_promise.catch(function(err) { if (err.errcode == 'M_UNKNOWN_TOKEN') { self.event_emitter.emit("Session.logged_out"); @@ -437,11 +437,11 @@ module.exports.MatrixHttpApi.prototype = { */ request: function(callback, method, path, queryParams, data, opts) { opts = opts || {}; - let prefix = opts.prefix !== undefined ? opts.prefix : this.opts.prefix; - let fullUri = this.opts.baseUrl + prefix + path; + const prefix = opts.prefix !== undefined ? opts.prefix : this.opts.prefix; + const fullUri = this.opts.baseUrl + prefix + path; return this.requestOtherUrl( - callback, method, fullUri, queryParams, data, opts + callback, method, fullUri, queryParams, data, opts, ); }, @@ -476,7 +476,7 @@ module.exports.MatrixHttpApi.prototype = { callback, method, path, queryParams, data, { localTimeoutMs: localTimeoutMs, prefix: prefix, - } + }, ); }, @@ -511,7 +511,7 @@ module.exports.MatrixHttpApi.prototype = { callback, method, path, queryParams, data, { localTimeoutMs: localTimeoutMs, prefix: prefix, - } + }, ); }, @@ -556,7 +556,7 @@ module.exports.MatrixHttpApi.prototype = { } return this._request( - callback, method, uri, queryParams, data, opts + callback, method, uri, queryParams, data, opts, ); }, @@ -608,14 +608,14 @@ module.exports.MatrixHttpApi.prototype = { _request: function(callback, method, uri, queryParams, data, opts) { if (callback !== undefined && !utils.isFunction(callback)) { throw Error( - "Expected callback to be a function but got " + typeof callback + "Expected callback to be a function but got " + typeof callback, ); } opts = opts || {}; - let self = this; + const self = this; if (this.opts.extraParams) { - for (let key in this.opts.extraParams) { + for (const key in this.opts.extraParams) { if (!this.opts.extraParams.hasOwnProperty(key)) { continue; } @@ -623,14 +623,14 @@ module.exports.MatrixHttpApi.prototype = { } } - let json = opts.json === undefined ? true : opts.json; + const json = opts.json === undefined ? true : opts.json; - let defer = q.defer(); + const defer = q.defer(); let timeoutId; let timedOut = false; let req; - let localTimeoutMs = opts.localTimeoutMs || this.opts.localTimeoutMs; + const localTimeoutMs = opts.localTimeoutMs || this.opts.localTimeoutMs; if (localTimeoutMs) { timeoutId = callbacks.setTimeout(function() { timedOut = true; @@ -645,7 +645,7 @@ module.exports.MatrixHttpApi.prototype = { }, localTimeoutMs); } - let reqPromise = defer.promise; + const reqPromise = defer.promise; try { req = this.opts.request( @@ -670,14 +670,14 @@ module.exports.MatrixHttpApi.prototype = { // if json is falsy, we won't parse any error response, so need // to do so before turning it into a MatrixError - let parseErrorJson = !json; - let handlerFn = requestCallback( + const parseErrorJson = !json; + const handlerFn = requestCallback( defer, callback, self.opts.onlyData, parseErrorJson, - opts.bodyParser + opts.bodyParser, ); handlerFn(err, response, body); - } + }, ); if (req && req.abort) { // FIXME: This is EVIL, but I can't think of a better way to expose @@ -705,9 +705,9 @@ module.exports.MatrixHttpApi.prototype = { * If parseErrorJson is true, we will JSON.parse the body if we get a 4xx error. * */ -let requestCallback = function( +const requestCallback = function( defer, userDefinedCallback, onlyData, - parseErrorJson, bodyParser + parseErrorJson, bodyParser, ) { userDefinedCallback = userDefinedCallback || function() {}; @@ -735,7 +735,7 @@ let requestCallback = function( defer.reject(err); userDefinedCallback(err); } else { - let res = { + const res = { code: response.statusCode, headers: response.headers, data: body, diff --git a/src/interactive-auth.js b/src/interactive-auth.js index d4e2d7f14..9efac4384 100644 --- a/src/interactive-auth.js +++ b/src/interactive-auth.js @@ -16,9 +16,9 @@ limitations under the License. "use strict"; /** @module interactive-auth */ -let q = require("q"); +const q = require("q"); -let utils = require("./utils"); +const utils = require("./utils"); /** * Abstracts the logic used to drive the interactive auth process. @@ -115,7 +115,7 @@ InteractiveAuth.prototype = { } // use the sessionid from the last request. - let auth = { + const auth = { session: this._data.session, }; utils.extend(auth, authData); @@ -131,7 +131,7 @@ InteractiveAuth.prototype = { * @param {object?} auth new auth dict, including session id */ _doRequest: function(auth) { - let self = this; + const self = this; // hackery to make sure that synchronous exceptions end up in the catch // handler (without the additional event loop entailed by q.fcall or an @@ -154,7 +154,7 @@ InteractiveAuth.prototype = { } self._data = error.data; self._startNextAuthStage(); - } + }, ).catch(this._completionDeferred.reject).done(); }, @@ -164,7 +164,7 @@ InteractiveAuth.prototype = { * @private */ _startNextAuthStage: function() { - let nextStage = this._chooseStage(); + const nextStage = this._chooseStage(); if (!nextStage) { throw new Error("No incomplete flows from the server"); } @@ -186,9 +186,9 @@ InteractiveAuth.prototype = { * @return {string?} login type */ _chooseStage: function() { - let flow = this._chooseFlow(); + const flow = this._chooseFlow(); console.log("Active flow => %s", JSON.stringify(flow)); - let nextStage = this._firstUncompletedStage(flow); + const nextStage = this._firstUncompletedStage(flow); console.log("Next stage: %s", nextStage); return nextStage; }, @@ -200,7 +200,7 @@ InteractiveAuth.prototype = { * @return {object} flow */ _chooseFlow: function() { - let flows = this._data.flows || []; + const flows = this._data.flows || []; // always use the first flow for now return flows[0]; }, @@ -213,9 +213,9 @@ InteractiveAuth.prototype = { * @return {string} login type */ _firstUncompletedStage: function(flow) { - let completed = (this._data || {}).completed || []; + const completed = (this._data || {}).completed || []; for (let i = 0; i < flow.stages.length; ++i) { - let stageType = flow.stages[i]; + const stageType = flow.stages[i]; if (completed.indexOf(stageType) === -1) { return stageType; } diff --git a/src/matrix.js b/src/matrix.js index da6e7c906..b744ae61b 100644 --- a/src/matrix.js +++ b/src/matrix.js @@ -96,7 +96,7 @@ module.exports.getRequest = function() { * @param {requestWrapperFunction} wrapper The wrapping function. */ module.exports.wrapRequest = function(wrapper) { - let origRequest = request; + const origRequest = request; request = function(options, callback) { return wrapper(origRequest, options, callback); }; diff --git a/src/models/event-timeline-set.js b/src/models/event-timeline-set.js index 911a4046d..927049e13 100644 --- a/src/models/event-timeline-set.js +++ b/src/models/event-timeline-set.js @@ -17,12 +17,12 @@ limitations under the License. /** * @module models/event-timeline-set */ -let EventEmitter = require("events").EventEmitter; -let utils = require("../utils"); -let EventTimeline = require("./event-timeline"); +const EventEmitter = require("events").EventEmitter; +const utils = require("../utils"); +const EventTimeline = require("./event-timeline"); // var DEBUG = false; -let DEBUG = true; +const DEBUG = true; let debuglog; if (DEBUG) { @@ -136,7 +136,7 @@ EventTimelineSet.prototype.eventIdToTimeline = function(eventId) { * @param {String} newEventId event ID of the replacement event */ EventTimelineSet.prototype.replaceEventId = function(oldEventId, newEventId) { - let existingTimeline = this._eventIdToTimeline[oldEventId]; + const existingTimeline = this._eventIdToTimeline[oldEventId]; if (existingTimeline) { delete this._eventIdToTimeline[oldEventId]; this._eventIdToTimeline[newEventId] = existingTimeline; @@ -166,13 +166,13 @@ EventTimelineSet.prototype.resetLiveTimeline = function(backPaginationToken, flu } // initialise the state in the new timeline from our last known state - let evMap = this._liveTimeline.getState(EventTimeline.FORWARDS).events; - let events = []; - for (let evtype in evMap) { + const evMap = this._liveTimeline.getState(EventTimeline.FORWARDS).events; + const events = []; + for (const evtype in evMap) { if (!evMap.hasOwnProperty(evtype)) { continue; } - for (let stateKey in evMap[evtype]) { + for (const stateKey in evMap[evtype]) { if (!evMap[evtype].hasOwnProperty(stateKey)) { continue; } @@ -198,7 +198,7 @@ EventTimelineSet.prototype.resetLiveTimeline = function(backPaginationToken, flu * the given event, or null if unknown */ EventTimelineSet.prototype.getTimelineForEvent = function(eventId) { - let res = this._eventIdToTimeline[eventId]; + const res = this._eventIdToTimeline[eventId]; return (res === undefined) ? null : res; }; @@ -209,7 +209,7 @@ EventTimelineSet.prototype.getTimelineForEvent = function(eventId) { * @return {?module:models/event~MatrixEvent} the given event, or undefined if unknown */ EventTimelineSet.prototype.findEventById = function(eventId) { - let tl = this.getTimelineForEvent(eventId); + const tl = this.getTimelineForEvent(eventId); if (!tl) { return undefined; } @@ -230,7 +230,7 @@ EventTimelineSet.prototype.addTimeline = function() { " it."); } - let timeline = new EventTimeline(this); + const timeline = new EventTimeline(this); this._timelines.push(timeline); return timeline; }; @@ -259,14 +259,14 @@ EventTimelineSet.prototype.addEventsToTimeline = function(events, toStartOfTimel timeline, paginationToken) { if (!timeline) { throw new Error( - "'timeline' not specified for EventTimelineSet.addEventsToTimeline" + "'timeline' not specified for EventTimelineSet.addEventsToTimeline", ); } if (!toStartOfTimeline && timeline == this._liveTimeline) { throw new Error( "EventTimelineSet.addEventsToTimeline cannot be used for adding events to " + - "the live timeline - use Room.addLiveEvents instead" + "the live timeline - use Room.addLiveEvents instead", ); } @@ -277,9 +277,9 @@ EventTimelineSet.prototype.addEventsToTimeline = function(events, toStartOfTimel } } - let direction = toStartOfTimeline ? EventTimeline.BACKWARDS : + const direction = toStartOfTimeline ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS; - let inverseDirection = toStartOfTimeline ? EventTimeline.FORWARDS : + const inverseDirection = toStartOfTimeline ? EventTimeline.FORWARDS : EventTimeline.BACKWARDS; // Adding events to timelines can be quite complicated. The following @@ -354,10 +354,10 @@ EventTimelineSet.prototype.addEventsToTimeline = function(events, toStartOfTimel let didUpdate = false; let lastEventWasNew = false; for (let i = 0; i < events.length; i++) { - let event = events[i]; - let eventId = event.getId(); + const event = events[i]; + const eventId = event.getId(); - let existingTimeline = this._eventIdToTimeline[eventId]; + const existingTimeline = this._eventIdToTimeline[eventId]; if (!existingTimeline) { // we don't know about this event yet. Just add it to the timeline. @@ -374,7 +374,7 @@ EventTimelineSet.prototype.addEventsToTimeline = function(events, toStartOfTimel continue; } - let neighbour = timeline.getNeighbouringTimeline(direction); + const neighbour = timeline.getNeighbouringTimeline(direction); if (neighbour) { // this timeline already has a neighbour in the relevant direction; // let's assume the timelines are already correctly linked up, and @@ -422,25 +422,25 @@ EventTimelineSet.prototype.addEventsToTimeline = function(events, toStartOfTimel */ EventTimelineSet.prototype.addLiveEvent = function(event, duplicateStrategy) { if (this._filter) { - let events = this._filter.filterRoomTimeline([event]); + const events = this._filter.filterRoomTimeline([event]); if (!events.length) { return; } } - let timeline = this._eventIdToTimeline[event.getId()]; + const timeline = this._eventIdToTimeline[event.getId()]; if (timeline) { if (duplicateStrategy === "replace") { debuglog("EventTimelineSet.addLiveEvent: replacing duplicate event " + event.getId()); - let tlEvents = timeline.getEvents(); + const tlEvents = timeline.getEvents(); for (let j = 0; j < tlEvents.length; j++) { if (tlEvents[j].getId() === event.getId()) { // still need to set the right metadata on this event EventTimeline.setEventMetadata( event, timeline.getState(EventTimeline.FORWARDS), - false + false, ); if (!tlEvents[j].encryptedType) { @@ -475,11 +475,11 @@ EventTimelineSet.prototype.addLiveEvent = function(event, duplicateStrategy) { */ EventTimelineSet.prototype.addEventToTimeline = function(event, timeline, toStartOfTimeline) { - let eventId = event.getId(); + const eventId = event.getId(); timeline.addEvent(event, toStartOfTimeline); this._eventIdToTimeline[eventId] = timeline; - let data = { + const data = { timeline: timeline, liveEvent: !toStartOfTimeline && timeline == this._liveTimeline, }; @@ -500,7 +500,7 @@ EventTimelineSet.prototype.addEventToTimeline = function(event, timeline, EventTimelineSet.prototype.handleRemoteEcho = function(localEvent, oldEventId, newEventId) { // XXX: why don't we infer newEventId from localEvent? - let existingTimeline = this._eventIdToTimeline[oldEventId]; + const existingTimeline = this._eventIdToTimeline[oldEventId]; if (existingTimeline) { delete this._eventIdToTimeline[oldEventId]; this._eventIdToTimeline[newEventId] = existingTimeline; @@ -524,15 +524,15 @@ EventTimelineSet.prototype.handleRemoteEcho = function(localEvent, oldEventId, * in this room. */ EventTimelineSet.prototype.removeEvent = function(eventId) { - let timeline = this._eventIdToTimeline[eventId]; + const timeline = this._eventIdToTimeline[eventId]; if (!timeline) { return null; } - let removed = timeline.removeEvent(eventId); + const removed = timeline.removeEvent(eventId); if (removed) { delete this._eventIdToTimeline[eventId]; - let data = { + const data = { timeline: timeline, }; this.emit("Room.timeline", removed, this.room, undefined, true, data); @@ -558,8 +558,8 @@ EventTimelineSet.prototype.compareEventOrdering = function(eventId1, eventId2) { return 0; } - let timeline1 = this._eventIdToTimeline[eventId1]; - let timeline2 = this._eventIdToTimeline[eventId2]; + const timeline1 = this._eventIdToTimeline[eventId1]; + const timeline2 = this._eventIdToTimeline[eventId2]; if (timeline1 === undefined) { return null; @@ -572,10 +572,10 @@ EventTimelineSet.prototype.compareEventOrdering = function(eventId1, eventId2) { // both events are in the same timeline - figure out their // relative indices let idx1, idx2; - let events = timeline1.getEvents(); + const events = timeline1.getEvents(); for (let idx = 0; idx < events.length && (idx1 === undefined || idx2 === undefined); idx++) { - let evId = events[idx].getId(); + const evId = events[idx].getId(); if (evId == eventId1) { idx1 = idx; } diff --git a/src/models/event-timeline.js b/src/models/event-timeline.js index e9b574bef..a3513cdc5 100644 --- a/src/models/event-timeline.js +++ b/src/models/event-timeline.js @@ -4,9 +4,9 @@ * @module models/event-timeline */ -let RoomState = require("./room-state"); -let utils = require("../utils"); -let MatrixEvent = require("./event").MatrixEvent; +const RoomState = require("./room-state"); +const utils = require("../utils"); +const MatrixEvent = require("./event").MatrixEvent; /** * Construct a new EventTimeline @@ -75,11 +75,11 @@ EventTimeline.prototype.initialiseState = function(stateEvents) { // we deep-copy the events here, in case they get changed later - we don't // want changes to the start state leaking through to the end state. - let oldStateEvents = utils.map( + const oldStateEvents = utils.map( utils.deepCopy( stateEvents.map(function(mxEvent) { return mxEvent.event; - }) + }), ), function(ev) { return new MatrixEvent(ev); @@ -237,10 +237,10 @@ EventTimeline.prototype.setNeighbouringTimeline = function(neighbour, direction) * @param {boolean} atStart true to insert new event at the start */ EventTimeline.prototype.addEvent = function(event, atStart) { - let stateContext = atStart ? this._startState : this._endState; + const stateContext = atStart ? this._startState : this._endState; // only call setEventMetadata on the unfiltered timelineSets - let timelineSet = this.getTimelineSet(); + const timelineSet = this.getTimelineSet(); if (timelineSet.room && timelineSet.room.getUnfilteredTimelineSet() === timelineSet) { EventTimeline.setEventMetadata(event, stateContext, atStart); @@ -288,11 +288,11 @@ EventTimeline.prototype.addEvent = function(event, atStart) { EventTimeline.setEventMetadata = function(event, stateContext, toStartOfTimeline) { // set sender and target properties event.sender = stateContext.getSentinelMember( - event.getSender() + event.getSender(), ); if (event.getType() === "m.room.member") { event.target = stateContext.getSentinelMember( - event.getStateKey() + event.getStateKey(), ); } if (event.isState()) { @@ -314,7 +314,7 @@ EventTimeline.setEventMetadata = function(event, stateContext, toStartOfTimeline */ EventTimeline.prototype.removeEvent = function(eventId) { for (let i = this._events.length - 1; i >= 0; i--) { - let ev = this._events[i]; + const ev = this._events[i]; if (ev.getId() == eventId) { this._events.splice(i, 1); if (i < this._baseIndex) { diff --git a/src/models/event.js b/src/models/event.js index 38686239c..0da0da745 100644 --- a/src/models/event.js +++ b/src/models/event.js @@ -21,9 +21,9 @@ limitations under the License. * @module models/event */ -let EventEmitter = require("events").EventEmitter; +const EventEmitter = require("events").EventEmitter; -let utils = require('../utils.js'); +const utils = require('../utils.js'); /** * Enum for event statuses. @@ -70,7 +70,7 @@ module.exports.EventStatus = { * Default: true. This property is experimental and may change. */ module.exports.MatrixEvent = function MatrixEvent( - event + event, ) { this.event = event || {}; this.sender = null; @@ -350,8 +350,8 @@ utils.extend(module.exports.MatrixEvent.prototype, { } } - let keeps = _REDACT_KEEP_CONTENT_MAP[this.getType()] || {}; - let content = this.getContent(); + const keeps = _REDACT_KEEP_CONTENT_MAP[this.getType()] || {}; + const content = this.getContent(); for (key in content) { if (!content.hasOwnProperty(key)) { continue; @@ -424,7 +424,7 @@ utils.extend(module.exports.MatrixEvent.prototype, { * m.room.aliases allows key aliases */ // a map giving the keys we keep when an event is redacted -let _REDACT_KEEP_KEY_MAP = [ +const _REDACT_KEEP_KEY_MAP = [ 'event_id', 'type', 'room_id', 'user_id', 'state_key', 'prev_state', 'content', 'unsigned', ].reduce(function(ret, val) { @@ -432,7 +432,7 @@ let _REDACT_KEEP_KEY_MAP = [ }, {}); // a map from event type to the .content keys we keep when an event is redacted -let _REDACT_KEEP_CONTENT_MAP = { +const _REDACT_KEEP_CONTENT_MAP = { 'm.room.member': {'membership': 1}, 'm.room.create': {'creator': 1}, 'm.room.join_rules': {'join_rule': 1}, diff --git a/src/models/room-member.js b/src/models/room-member.js index f749e92e0..512fb60ec 100644 --- a/src/models/room-member.js +++ b/src/models/room-member.js @@ -17,10 +17,10 @@ limitations under the License. /** * @module models/room-member */ -let EventEmitter = require("events").EventEmitter; -let ContentRepo = require("../content-repo"); +const EventEmitter = require("events").EventEmitter; +const ContentRepo = require("../content-repo"); -let utils = require("../utils"); +const utils = require("../utils"); /** * Construct a new room member. @@ -73,10 +73,10 @@ RoomMember.prototype.setMembershipEvent = function(event, roomState) { } this.events.member = event; - let oldMembership = this.membership; + const oldMembership = this.membership; this.membership = event.getDirectionalContent().membership; - let oldName = this.name; + const oldName = this.name; this.name = calculateDisplayName(this, event, roomState); if (oldMembership !== this.membership) { this._updateModifiedTime(); @@ -103,8 +103,8 @@ RoomMember.prototype.setPowerLevelEvent = function(powerLevelEvent) { utils.forEach(utils.values(powerLevelEvent.getContent().users), function(lvl) { maxLevel = Math.max(maxLevel, lvl); }); - let oldPowerLevel = this.powerLevel; - let oldPowerLevelNorm = this.powerLevelNorm; + const oldPowerLevel = this.powerLevel; + const oldPowerLevelNorm = this.powerLevelNorm; if (powerLevelEvent.getContent().users[this.userId] !== undefined) { this.powerLevel = powerLevelEvent.getContent().users[this.userId]; @@ -136,9 +136,9 @@ RoomMember.prototype.setTypingEvent = function(event) { if (event.getType() !== "m.typing") { return; } - let oldTyping = this.typing; + const oldTyping = this.typing; this.typing = false; - let typingList = event.getContent().user_ids; + const typingList = event.getContent().user_ids; if (!utils.isArray(typingList)) { // malformed event :/ bail early. TODO: whine? return; @@ -195,23 +195,23 @@ RoomMember.prototype.getAvatarUrl = if (!this.events.member && !allowDefault) { return null; } - let rawUrl = this.events.member ? this.events.member.getContent().avatar_url : null; - let httpUrl = ContentRepo.getHttpUriForMxc( - baseUrl, rawUrl, width, height, resizeMethod, allowDirectLinks + const rawUrl = this.events.member ? this.events.member.getContent().avatar_url : null; + const httpUrl = ContentRepo.getHttpUriForMxc( + baseUrl, rawUrl, width, height, resizeMethod, allowDirectLinks, ); if (httpUrl) { return httpUrl; } else if (allowDefault) { return ContentRepo.getIdenticonUri( - baseUrl, this.userId, width, height + baseUrl, this.userId, width, height, ); } return null; }; function calculateDisplayName(member, event, roomState) { - let displayName = event.getDirectionalContent().displayname; - let selfUserId = member.userId; + const displayName = event.getDirectionalContent().displayname; + const selfUserId = member.userId; if (!displayName) { return selfUserId; @@ -221,8 +221,8 @@ function calculateDisplayName(member, event, roomState) { return displayName; } - let userIds = roomState.getUserIdsWithDisplayName(displayName); - let otherUsers = userIds.filter(function(u) { + const userIds = roomState.getUserIdsWithDisplayName(displayName); + const otherUsers = userIds.filter(function(u) { return u !== selfUserId; }); if (otherUsers.length > 0) { diff --git a/src/models/room-state.js b/src/models/room-state.js index 6becc8bc3..6c9c2180e 100644 --- a/src/models/room-state.js +++ b/src/models/room-state.js @@ -17,10 +17,10 @@ limitations under the License. /** * @module models/room-state */ -let EventEmitter = require("events").EventEmitter; +const EventEmitter = require("events").EventEmitter; -let utils = require("../utils"); -let RoomMember = require("./room-member"); +const utils = require("../utils"); +const RoomMember = require("./room-member"); /** * Construct room state. @@ -100,7 +100,7 @@ RoomState.prototype.getStateEvents = function(eventType, stateKey) { if (stateKey === undefined) { // return all values return utils.values(this.events[eventType]); } - let event = this.events[eventType][stateKey]; + const event = this.events[eventType][stateKey]; return event ? event : null; }; @@ -115,7 +115,7 @@ RoomState.prototype.getStateEvents = function(eventType, stateKey) { * @fires module:client~MatrixClient#event:"RoomState.events" */ RoomState.prototype.setStateEvents = function(stateEvents) { - let self = this; + const self = this; this._updateModifiedTime(); // update the core event dict @@ -133,7 +133,7 @@ RoomState.prototype.setStateEvents = function(stateEvents) { self.events[event.getType()][event.getStateKey()] = event; if (event.getType() === "m.room.member") { _updateDisplayNameCache( - self, event.getStateKey(), event.getContent().displayname + self, event.getStateKey(), event.getContent().displayname, ); _updateThirdPartyTokenCache(self, event); } @@ -153,7 +153,7 @@ RoomState.prototype.setStateEvents = function(stateEvents) { } if (event.getType() === "m.room.member") { - let userId = event.getStateKey(); + const userId = event.getStateKey(); // leave events apparently elide the displayname or avatar_url, // so let's fake one up so that we don't leak user ids @@ -178,11 +178,11 @@ RoomState.prototype.setStateEvents = function(stateEvents) { // so we don't make assumptions about the properties of RoomMember // (e.g. and manage to break it because deep copying doesn't do // everything). - let sentinel = new RoomMember(event.getRoomId(), userId); + const sentinel = new RoomMember(event.getRoomId(), userId); utils.forEach([member, sentinel], function(roomMember) { roomMember.setMembershipEvent(event, self); // this member may have a power level already, so set it. - let pwrLvlEvent = self.getStateEvents("m.room.power_levels", ""); + const pwrLvlEvent = self.getStateEvents("m.room.power_levels", ""); if (pwrLvlEvent) { roomMember.setPowerLevelEvent(pwrLvlEvent); } @@ -192,7 +192,7 @@ RoomState.prototype.setStateEvents = function(stateEvents) { self.members[userId] = member; self.emit("RoomState.members", event, self, member); } else if (event.getType() === "m.room.power_levels") { - let members = utils.values(self.members); + const members = utils.values(self.members); utils.forEach(members, function(member) { member.setPowerLevelEvent(event); self.emit("RoomState.members", event, self, member); @@ -312,12 +312,12 @@ RoomState.prototype.maySendStateEvent = function(stateEventType, userId) { * according to the room's state. */ RoomState.prototype._maySendEventOfType = function(eventType, userId, state) { - let member = this.getMember(userId); + const member = this.getMember(userId); if (!member || member.membership == 'leave') { return false; } - let power_levels_event = this.getStateEvents('m.room.power_levels', ''); + const power_levels_event = this.getStateEvents('m.room.power_levels', ''); let power_levels; let events_levels = {}; @@ -355,12 +355,12 @@ function _updateThirdPartyTokenCache(roomState, memberEvent) { if (!memberEvent.getContent().third_party_invite) { return; } - let token = (memberEvent.getContent().third_party_invite.signed || {}).token; + const token = (memberEvent.getContent().third_party_invite.signed || {}).token; if (!token) { return; } - let threePidInvite = roomState.getStateEvents( - "m.room.third_party_invite", token + const threePidInvite = roomState.getStateEvents( + "m.room.third_party_invite", token, ); if (!threePidInvite) { return; @@ -369,14 +369,14 @@ function _updateThirdPartyTokenCache(roomState, memberEvent) { } function _updateDisplayNameCache(roomState, userId, displayName) { - let oldName = roomState._userIdsToDisplayNames[userId]; + const oldName = roomState._userIdsToDisplayNames[userId]; delete roomState._userIdsToDisplayNames[userId]; if (oldName) { // Remove the old name from the cache. // We clobber the user_id > name lookup but the name -> [user_id] lookup // means we need to remove that user ID from that array rather than nuking // the lot. - let existingUserIds = roomState._displayNameToUserIds[oldName] || []; + const existingUserIds = roomState._displayNameToUserIds[oldName] || []; for (let i = 0; i < existingUserIds.length; i++) { if (existingUserIds[i] === userId) { // remove this user ID from this array diff --git a/src/models/room.js b/src/models/room.js index bf4baddac..37cc9bdbb 100644 --- a/src/models/room.js +++ b/src/models/room.js @@ -17,22 +17,22 @@ limitations under the License. /** * @module models/room */ -let EventEmitter = require("events").EventEmitter; +const EventEmitter = require("events").EventEmitter; -let EventStatus = require("./event").EventStatus; -let RoomSummary = require("./room-summary"); -let MatrixEvent = require("./event").MatrixEvent; -let utils = require("../utils"); -let ContentRepo = require("../content-repo"); -let EventTimeline = require("./event-timeline"); -let EventTimelineSet = require("./event-timeline-set"); +const EventStatus = require("./event").EventStatus; +const RoomSummary = require("./room-summary"); +const MatrixEvent = require("./event").MatrixEvent; +const utils = require("../utils"); +const ContentRepo = require("../content-repo"); +const EventTimeline = require("./event-timeline"); +const EventTimelineSet = require("./event-timeline-set"); function synthesizeReceipt(userId, event, receiptType) { // console.log("synthesizing receipt for "+event.getId()); // This is really ugly because JS has no way to express an object literal // where the name of a key comes from an expression - let fakeReceipt = { + const fakeReceipt = { content: {}, type: "m.receipt", room_id: event.getRoomId(), @@ -108,7 +108,7 @@ function Room(roomId, opts) { if (["chronological", "detached"].indexOf(opts.pendingEventOrdering) === -1) { throw new Error( "opts.pendingEventOrdering MUST be either 'chronological' or " + - "'detached'. Got: '" + opts.pendingEventOrdering + "'" + "'detached'. Got: '" + opts.pendingEventOrdering + "'", ); } @@ -308,7 +308,7 @@ Room.prototype.setUnreadNotificationCount = function(type, count) { */ Room.prototype.getAvatarUrl = function(baseUrl, width, height, resizeMethod, allowDefault) { - let roomAvatarEvent = this.currentState.getStateEvents("m.room.avatar", ""); + const roomAvatarEvent = this.currentState.getStateEvents("m.room.avatar", ""); if (allowDefault === undefined) { allowDefault = true; } @@ -316,14 +316,14 @@ Room.prototype.getAvatarUrl = function(baseUrl, width, height, resizeMethod, return null; } - let mainUrl = roomAvatarEvent ? roomAvatarEvent.getContent().url : null; + const mainUrl = roomAvatarEvent ? roomAvatarEvent.getContent().url : null; if (mainUrl) { return ContentRepo.getHttpUriForMxc( - baseUrl, mainUrl, width, height, resizeMethod + baseUrl, mainUrl, width, height, resizeMethod, ); } else if (allowDefault) { return ContentRepo.getIdenticonUri( - baseUrl, this.roomId, width, height + baseUrl, this.roomId, width, height, ); } @@ -337,15 +337,15 @@ Room.prototype.getAvatarUrl = function(baseUrl, width, height, resizeMethod, * @return {array} The room's alias as an array of strings */ Room.prototype.getAliases = function() { - let alias_strings = []; + const alias_strings = []; - let alias_events = this.currentState.getStateEvents("m.room.aliases"); + const alias_events = this.currentState.getStateEvents("m.room.aliases"); if (alias_events) { for (let i = 0; i < alias_events.length; ++i) { - let alias_event = alias_events[i]; + const alias_event = alias_events[i]; if (utils.isArray(alias_event.getContent().aliases)) { Array.prototype.push.apply( - alias_strings, alias_event.getContent().aliases + alias_strings, alias_event.getContent().aliases, ); } } @@ -360,7 +360,7 @@ Room.prototype.getAliases = function() { * @return {?string} The room's canonical alias, or null if there is none */ Room.prototype.getCanonicalAlias = function() { - let canonicalAlias = this.currentState.getStateEvents("m.room.canonical_alias", ""); + const canonicalAlias = this.currentState.getStateEvents("m.room.canonical_alias", ""); if (canonicalAlias) { return canonicalAlias.getContent().alias; } @@ -390,7 +390,7 @@ Room.prototype.addEventsToTimeline = function(events, toStartOfTimeline, timeline, paginationToken) { timeline.getTimelineSet().addEventsToTimeline( events, toStartOfTimeline, - timeline, paginationToken + timeline, paginationToken, ); }; @@ -400,7 +400,7 @@ Room.prototype.addEventsToTimeline = function(events, toStartOfTimeline, * @return {RoomMember} The member or null. */ Room.prototype.getMember = function(userId) { - let member = this.currentState.members[userId]; + const member = this.currentState.members[userId]; if (!member) { return null; } @@ -445,7 +445,7 @@ Room.prototype.addEventsToTimeline = function(events, toStartOfTimeline, * @return {boolean} True if this user_id has the given membership state. */ Room.prototype.hasMembershipState = function(userId, membership) { - let member = this.getMember(userId); + const member = this.getMember(userId); if (!member) { return false; } @@ -461,8 +461,8 @@ Room.prototype.getOrCreateFilteredTimelineSet = function(filter) { if (this._filteredTimelineSets[filter.filterId]) { return this._filteredTimelineSets[filter.filterId]; } - let opts = Object.assign({ filter: filter }, this._opts); - let timelineSet = new EventTimelineSet(this, opts); + const opts = Object.assign({ filter: filter }, this._opts); + const timelineSet = new EventTimelineSet(this, opts); reEmit(this, timelineSet, ["Room.timeline", "Room.timelineReset"]); this._filteredTimelineSets[filter.filterId] = timelineSet; this._timelineSets.push(timelineSet); @@ -474,7 +474,7 @@ Room.prototype.getOrCreateFilteredTimelineSet = function(filter) { // may have grown huge and so take a long time to filter. // see https://github.com/vector-im/vector-web/issues/2109 - let unfilteredLiveTimeline = this.getLiveTimeline(); + const unfilteredLiveTimeline = this.getLiveTimeline(); unfilteredLiveTimeline.getEvents().forEach(function(event) { timelineSet.addLiveEvent(event); @@ -488,7 +488,7 @@ Room.prototype.getOrCreateFilteredTimelineSet = function(filter) { timelineSet.getLiveTimeline().setPaginationToken( timeline.getPaginationToken(EventTimeline.BACKWARDS), - EventTimeline.BACKWARDS + EventTimeline.BACKWARDS, ); // alternatively, we could try to do something like this to try and re-paginate @@ -508,9 +508,9 @@ Room.prototype.getOrCreateFilteredTimelineSet = function(filter) { * @param {Filter} filter the filter whose timelineSet is to be forgotten */ Room.prototype.removeFilteredTimelineSet = function(filter) { - let timelineSet = this._filteredTimelineSets[filter.filterId]; + const timelineSet = this._filteredTimelineSets[filter.filterId]; delete this._filteredTimelineSets[filter.filterId]; - let i = this._timelineSets.indexOf(timelineSet); + const i = this._timelineSets.indexOf(timelineSet); if (i > -1) { this._timelineSets.splice(i, 1); } @@ -528,10 +528,10 @@ Room.prototype.removeFilteredTimelineSet = function(filter) { Room.prototype._addLiveEvent = function(event, duplicateStrategy) { let i; if (event.getType() === "m.room.redaction") { - let redactId = event.event.redacts; + const redactId = event.event.redacts; // if we know about this event, redact its contents now. - let redactedEvent = this.getUnfilteredTimelineSet().findEventById(redactId); + const redactedEvent = this.getUnfilteredTimelineSet().findEventById(redactId); if (redactedEvent) { redactedEvent.makeRedacted(event); this.emit("Room.redaction", event, this); @@ -551,7 +551,7 @@ Room.prototype._addLiveEvent = function(event, duplicateStrategy) { } if (event.getUnsigned().transaction_id) { - let existingEvent = this._txnToEvent[event.getUnsigned().transaction_id]; + const existingEvent = this._txnToEvent[event.getUnsigned().transaction_id]; if (existingEvent) { // remote echo of an event we sent earlier this._handleRemoteEcho(event, existingEvent); @@ -569,7 +569,7 @@ Room.prototype._addLiveEvent = function(event, duplicateStrategy) { // pointing to an event that wasn't yet in the timeline if (event.sender) { this.addReceipt(synthesizeReceipt( - event.sender.userId, event, "m.read" + event.sender.userId, event, "m.read", ), true); // Any live events from a user could be taken as implicit @@ -616,7 +616,7 @@ Room.prototype.addPendingEvent = function(event, txnId) { EventTimeline.setEventMetadata( event, this.getLiveTimeline().getState(EventTimeline.FORWARDS), - false + false, ); this._txnToEvent[txnId] = event; @@ -625,7 +625,7 @@ Room.prototype.addPendingEvent = function(event, txnId) { this._pendingEventList.push(event); } else { for (let i = 0; i < this._timelineSets.length; i++) { - let timelineSet = this._timelineSets[i]; + const timelineSet = this._timelineSets[i]; if (timelineSet.getFilter()) { if (this._filter.filterRoomTimeline([event]).length) { timelineSet.addEventToTimeline(event, @@ -656,9 +656,9 @@ Room.prototype.addPendingEvent = function(event, txnId) { * @private */ Room.prototype._handleRemoteEcho = function(remoteEvent, localEvent) { - let oldEventId = localEvent.getId(); - let newEventId = remoteEvent.getId(); - let oldStatus = localEvent.status; + const oldEventId = localEvent.getId(); + const newEventId = remoteEvent.getId(); + const oldStatus = localEvent.status; // no longer pending delete this._txnToEvent[remoteEvent.transaction_id]; @@ -669,7 +669,7 @@ Room.prototype._handleRemoteEcho = function(remoteEvent, localEvent) { this._pendingEventList, function(ev) { return ev.getId() == oldEventId; - }, false + }, false, ); } @@ -678,7 +678,7 @@ Room.prototype._handleRemoteEcho = function(remoteEvent, localEvent) { localEvent.handleRemoteEcho(remoteEvent.event); for (let i = 0; i < this._timelineSets.length; i++) { - let timelineSet = this._timelineSets[i]; + const timelineSet = this._timelineSets[i]; // if it's already in the timeline, update the timeline map. If it's not, add it. timelineSet.handleRemoteEcho(localEvent, oldEventId, newEventId); @@ -690,7 +690,7 @@ Room.prototype._handleRemoteEcho = function(remoteEvent, localEvent) { /* a map from current event status to a list of allowed next statuses */ -let ALLOWED_TRANSITIONS = {}; +const ALLOWED_TRANSITIONS = {}; ALLOWED_TRANSITIONS[EventStatus.ENCRYPTING] = [ EventStatus.SENDING, @@ -737,7 +737,7 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) { // SENT races against /sync, so we have to special-case it. if (newStatus == EventStatus.SENT) { - let timeline = this.getUnfilteredTimelineSet().eventIdToTimeline(newEventId); + const timeline = this.getUnfilteredTimelineSet().eventIdToTimeline(newEventId); if (timeline) { // we've already received the event via the event stream. // nothing more to do here. @@ -745,15 +745,15 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) { } } - let oldStatus = event.status; - let oldEventId = event.getId(); + const oldStatus = event.status; + const oldEventId = event.getId(); if (!oldStatus) { throw new Error("updatePendingEventStatus called on an event which is " + "not a local echo."); } - let allowed = ALLOWED_TRANSITIONS[oldStatus]; + const allowed = ALLOWED_TRANSITIONS[oldStatus]; if (!allowed || allowed.indexOf(newStatus) < 0) { throw new Error("Invalid EventStatus transition " + oldStatus + "->" + newStatus); @@ -778,7 +778,7 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) { this._pendingEventList, function(ev) { return ev.getId() == oldEventId; - }, false + }, false, ); } this.removeEvent(oldEventId); @@ -812,17 +812,17 @@ Room.prototype.addLiveEvents = function(events, duplicateStrategy) { // sanity check that the live timeline is still live for (i = 0; i < this._timelineSets.length; i++) { - let liveTimeline = this._timelineSets[i].getLiveTimeline(); + const liveTimeline = this._timelineSets[i].getLiveTimeline(); if (liveTimeline.getPaginationToken(EventTimeline.FORWARDS)) { throw new Error( "live timeline " + i + " is no longer live - it has a pagination token " + - "(" + liveTimeline.getPaginationToken(EventTimeline.FORWARDS) + ")" + "(" + liveTimeline.getPaginationToken(EventTimeline.FORWARDS) + ")", ); } if (liveTimeline.getNeighbouringTimeline(EventTimeline.FORWARDS)) { throw new Error( "live timeline " + i + " is no longer live - " + - "it has a neighbouring timeline" + "it has a neighbouring timeline", ); } } @@ -863,7 +863,7 @@ Room.prototype.removeEvents = function(event_ids) { Room.prototype.removeEvent = function(eventId) { let removedAny = false; for (let i = 0; i < this._timelineSets.length; i++) { - let removed = this._timelineSets[i].removeEvent(eventId); + const removed = this._timelineSets[i].removeEvent(eventId); if (removed) { removedAny = true; } @@ -882,15 +882,15 @@ Room.prototype.removeEvent = function(eventId) { Room.prototype.recalculate = function(userId) { // set fake stripped state events if this is an invite room so logic remains // consistent elsewhere. - let self = this; - let membershipEvent = this.currentState.getStateEvents( - "m.room.member", userId + const self = this; + const membershipEvent = this.currentState.getStateEvents( + "m.room.member", userId, ); if (membershipEvent && membershipEvent.getContent().membership === "invite") { - let strippedStateEvents = membershipEvent.event.invite_room_state || []; + const strippedStateEvents = membershipEvent.event.invite_room_state || []; utils.forEach(strippedStateEvents, function(strippedEvent) { - let existingEvent = self.currentState.getStateEvents( - strippedEvent.type, strippedEvent.state_key + const existingEvent = self.currentState.getStateEvents( + strippedEvent.type, strippedEvent.state_key, ); if (!existingEvent) { // set the fake stripped event instead @@ -906,7 +906,7 @@ Room.prototype.recalculate = function(userId) { }); } - let oldName = this.name; + const oldName = this.name; this.name = calculateRoomName(this, userId); this.summary = new RoomSummary(this.roomId, { title: this.name, @@ -1004,18 +1004,18 @@ Room.prototype.addReceipt = function(event, fake) { * @param {Object} receipts The object to add receipts to */ Room.prototype._addReceiptsToStructure = function(event, receipts) { - let self = this; + const self = this; utils.keys(event.getContent()).forEach(function(eventId) { utils.keys(event.getContent()[eventId]).forEach(function(receiptType) { utils.keys(event.getContent()[eventId][receiptType]).forEach( function(userId) { - let receipt = event.getContent()[eventId][receiptType][userId]; + const receipt = event.getContent()[eventId][receiptType][userId]; if (!receipts[receiptType]) { receipts[receiptType] = {}; } - let existingReceipt = receipts[receiptType][userId]; + const existingReceipt = receipts[receiptType][userId]; if (!existingReceipt) { receipts[receiptType][userId] = {}; @@ -1024,7 +1024,7 @@ Room.prototype._addReceiptsToStructure = function(event, receipts) { // than the one we already have. (This is managed // server-side, but because we synthesize RRs locally we // have to do it here too.) - let ordering = self.getUnfilteredTimelineSet().compareEventOrdering( + const ordering = self.getUnfilteredTimelineSet().compareEventOrdering( existingReceipt.eventId, eventId); if (ordering !== null && ordering >= 0) { return; @@ -1046,10 +1046,10 @@ Room.prototype._addReceiptsToStructure = function(event, receipts) { * @return {Object} Map of receipts by event ID */ Room.prototype._buildReceiptCache = function(receipts) { - let receiptCacheByEventId = {}; + const receiptCacheByEventId = {}; utils.keys(receipts).forEach(function(receiptType) { utils.keys(receipts[receiptType]).forEach(function(userId) { - let receipt = receipts[receiptType][userId]; + const receipt = receipts[receiptType][userId]; if (!receiptCacheByEventId[receipt.eventId]) { receiptCacheByEventId[receipt.eventId] = []; } @@ -1102,7 +1102,7 @@ Room.prototype.addTags = function(event) { */ Room.prototype.addAccountData = function(events) { for (let i = 0; i < events.length; i++) { - let event = events[i]; + const event = events[i]; if (event.getType() === "m.tag") { this.addTags(event); } @@ -1134,7 +1134,7 @@ function calculateRoomName(room, userId, ignoreRoomNameEvent) { if (!ignoreRoomNameEvent) { // check for an alias, if any. for now, assume first alias is the // official one. - let mRoomName = room.currentState.getStateEvents("m.room.name", ""); + const mRoomName = room.currentState.getStateEvents("m.room.name", ""); if (mRoomName && mRoomName.getContent() && mRoomName.getContent().name) { return mRoomName.getContent().name; } @@ -1143,7 +1143,7 @@ function calculateRoomName(room, userId, ignoreRoomNameEvent) { let alias = room.getCanonicalAlias(); if (!alias) { - let aliases = room.getAliases(); + const aliases = room.getAliases(); if (aliases.length) { alias = aliases[0]; @@ -1154,16 +1154,16 @@ function calculateRoomName(room, userId, ignoreRoomNameEvent) { } // get members that are NOT ourselves and are actually in the room. - let otherMembers = utils.filter(room.currentState.getMembers(), function(m) { + const otherMembers = utils.filter(room.currentState.getMembers(), function(m) { return (m.userId !== userId && m.membership !== "leave"); }); - let allMembers = utils.filter(room.currentState.getMembers(), function(m) { + const allMembers = utils.filter(room.currentState.getMembers(), function(m) { return (m.membership !== "leave"); }); - let myMemberEventArray = utils.filter(room.currentState.getMembers(), function(m) { + const myMemberEventArray = utils.filter(room.currentState.getMembers(), function(m) { return (m.userId == userId); }); - let myMemberEvent = ( + const myMemberEvent = ( (myMemberEventArray.length && myMemberEventArray[0].events) ? myMemberEventArray[0].events.member.event : undefined ); @@ -1173,7 +1173,7 @@ function calculateRoomName(room, userId, ignoreRoomNameEvent) { if (room.currentState.getMember(myMemberEvent.sender)) { // extract who invited us to the room return "Invite from " + room.currentState.getMember( - myMemberEvent.sender + myMemberEvent.sender, ).name; } else if (allMembers[0].events.member) { // use the sender field from the invite event, although this only @@ -1190,7 +1190,7 @@ function calculateRoomName(room, userId, ignoreRoomNameEvent) { // self-chat, peeked room with 1 participant, // or inbound invite, or outbound 3PID invite. if (allMembers[0].userId === userId) { - let thirdPartyInvites = + const thirdPartyInvites = room.currentState.getStateEvents("m.room.third_party_invite"); if (thirdPartyInvites && thirdPartyInvites.length > 0) { let name = "Inviting " + @@ -1238,7 +1238,7 @@ function reEmit(reEmitEntity, emittableEntity, eventNames) { // Transformation Example: // listener on "foo" => function(a,b) { ... } // Re-emit on "thing" => thing.emit("foo", a, b) - let newArgs = [eventName]; + const newArgs = [eventName]; for (let i = 0; i < arguments.length; i++) { newArgs.push(arguments[i]); } diff --git a/src/models/search-result.js b/src/models/search-result.js index 3c36cc8d9..bab76fa83 100644 --- a/src/models/search-result.js +++ b/src/models/search-result.js @@ -19,8 +19,8 @@ limitations under the License. * @module models/search-result */ -let EventContext = require("./event-context"); -let utils = require("../utils"); +const EventContext = require("./event-context"); +const utils = require("../utils"); /** * Construct a new SearchResult @@ -45,11 +45,11 @@ function SearchResult(rank, eventContext) { */ SearchResult.fromJson = function(jsonObj, eventMapper) { - let jsonContext = jsonObj.context || {}; - let events_before = jsonContext.events_before || []; - let events_after = jsonContext.events_after || []; + const jsonContext = jsonObj.context || {}; + const events_before = jsonContext.events_before || []; + const events_after = jsonContext.events_after || []; - let context = new EventContext(eventMapper(jsonObj.result)); + const context = new EventContext(eventMapper(jsonObj.result)); context.setPaginateToken(jsonContext.start, true); context.addEvents(utils.map(events_before, eventMapper), true); diff --git a/src/models/user.js b/src/models/user.js index f89404503..dbfaeb791 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -17,8 +17,8 @@ limitations under the License. /** * @module models/user */ - let EventEmitter = require("events").EventEmitter; - let utils = require("../utils"); + const EventEmitter = require("events").EventEmitter; + const utils = require("../utils"); /** * Construct a new User. A User must have an ID and can optionally have extra @@ -73,10 +73,10 @@ User.prototype.setPresenceEvent = function(event) { if (event.getType() !== "m.presence") { return; } - let firstFire = this.events.presence === null; + const firstFire = this.events.presence === null; this.events.presence = event; - let eventsToFire = []; + const eventsToFire = []; if (event.getContent().presence !== this.presence || firstFire) { eventsToFire.push("User.presence"); } @@ -122,7 +122,7 @@ User.prototype.setPresenceEvent = function(event) { * @param {string} name The new display name. */ User.prototype.setDisplayName = function(name) { - let oldName = this.displayName; + const oldName = this.displayName; this.displayName = name; if (name !== oldName) { this._updateModifiedTime(); @@ -146,7 +146,7 @@ User.prototype.setRawDisplayName = function(name) { * @param {string} url The new avatar URL. */ User.prototype.setAvatarUrl = function(url) { - let oldUrl = this.avatarUrl; + const oldUrl = this.avatarUrl; this.avatarUrl = url; if (url !== oldUrl) { this._updateModifiedTime(); diff --git a/src/pushprocessor.js b/src/pushprocessor.js index f8cb110c4..5b35ccdf4 100644 --- a/src/pushprocessor.js +++ b/src/pushprocessor.js @@ -23,25 +23,25 @@ limitations under the License. * @param {Object} client The Matrix client object to use */ function PushProcessor(client) { - let escapeRegExp = function(string) { + const escapeRegExp = function(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); }; - let matchingRuleFromKindSet = function(ev, kindset, device) { - let rulekinds_in_order = ['override', 'content', 'room', 'sender', 'underride']; + const matchingRuleFromKindSet = function(ev, kindset, device) { + const rulekinds_in_order = ['override', 'content', 'room', 'sender', 'underride']; for (let ruleKindIndex = 0; ruleKindIndex < rulekinds_in_order.length; ++ruleKindIndex) { - let kind = rulekinds_in_order[ruleKindIndex]; - let ruleset = kindset[kind]; + const kind = rulekinds_in_order[ruleKindIndex]; + const ruleset = kindset[kind]; for (let ruleIndex = 0; ruleIndex < ruleset.length; ++ruleIndex) { - let rule = ruleset[ruleIndex]; + const rule = ruleset[ruleIndex]; if (!rule.enabled) { continue; } - let rawrule = templateRuleToRaw(kind, rule, device); + const rawrule = templateRuleToRaw(kind, rule, device); if (!rawrule) { continue; } @@ -55,8 +55,8 @@ function PushProcessor(client) { return null; }; - let templateRuleToRaw = function(kind, tprule, device) { - let rawrule = { + const templateRuleToRaw = function(kind, tprule, device) { + const rawrule = { 'rule_id': tprule.rule_id, 'actions': tprule.actions, 'conditions': [], @@ -106,18 +106,18 @@ function PushProcessor(client) { return rawrule; }; - let ruleMatchesEvent = function(rule, ev) { + const ruleMatchesEvent = function(rule, ev) { let ret = true; for (let i = 0; i < rule.conditions.length; ++i) { - let cond = rule.conditions[i]; + const cond = rule.conditions[i]; ret &= eventFulfillsCondition(cond, ev); } //console.log("Rule "+rule.rule_id+(ret ? " matches" : " doesn't match")); return ret; }; - let eventFulfillsCondition = function(cond, ev) { - let condition_functions = { + const eventFulfillsCondition = function(cond, ev) { + const condition_functions = { "event_match": eventFulfillsEventMatchCondition, "device": eventFulfillsDeviceCondition, "contains_display_name": eventFulfillsDisplayNameCondition, @@ -129,26 +129,26 @@ function PushProcessor(client) { return true; }; - let eventFulfillsRoomMemberCountCondition = function(cond, ev) { + const eventFulfillsRoomMemberCountCondition = function(cond, ev) { if (!cond.is) { return false; } - let room = client.getRoom(ev.getRoomId()); + const room = client.getRoom(ev.getRoomId()); if (!room || !room.currentState || !room.currentState.members) { return false; } - let memberCount = Object.keys(room.currentState.members).filter(function(m) { + const memberCount = Object.keys(room.currentState.members).filter(function(m) { return room.currentState.members[m].membership == 'join'; }).length; - let m = cond.is.match(/^([=<>]*)([0-9]*)$/); + const m = cond.is.match(/^([=<>]*)([0-9]*)$/); if (!m) { return false; } - let ineq = m[1]; - let rhs = parseInt(m[2]); + const ineq = m[1]; + const rhs = parseInt(m[2]); if (isNaN(rhs)) { return false; } @@ -169,32 +169,32 @@ function PushProcessor(client) { } }; - let eventFulfillsDisplayNameCondition = function(cond, ev) { - let content = ev.getContent(); + const eventFulfillsDisplayNameCondition = function(cond, ev) { + const content = ev.getContent(); if (!content || !content.body || typeof content.body != 'string') { return false; } - let room = client.getRoom(ev.getRoomId()); + const room = client.getRoom(ev.getRoomId()); if (!room || !room.currentState || !room.currentState.members || !room.currentState.getMember(client.credentials.userId)) { return false; } - let displayName = room.currentState.getMember(client.credentials.userId).name; + const displayName = room.currentState.getMember(client.credentials.userId).name; // N.B. we can't use \b as it chokes on unicode. however \W seems to be okay // as shorthand for [^0-9A-Za-z_]. - let pat = new RegExp("(^|\\W)" + escapeRegExp(displayName) + "(\\W|$)", 'i'); + const pat = new RegExp("(^|\\W)" + escapeRegExp(displayName) + "(\\W|$)", 'i'); return content.body.search(pat) > -1; }; - let eventFulfillsDeviceCondition = function(cond, ev) { + const eventFulfillsDeviceCondition = function(cond, ev) { return false; // XXX: Allow a profile tag to be set for the web client instance }; - let eventFulfillsEventMatchCondition = function(cond, ev) { - let val = valueForDottedKey(cond.key, ev); + const eventFulfillsEventMatchCondition = function(cond, ev) { + const val = valueForDottedKey(cond.key, ev); if (!val || typeof val != 'string') { return false; } @@ -205,11 +205,11 @@ function PushProcessor(client) { } else { pat = '^' + globToRegexp(cond.pattern) + '$'; } - let regex = new RegExp(pat, 'i'); + const regex = new RegExp(pat, 'i'); return !!val.match(regex); }; - let globToRegexp = function(glob) { + const globToRegexp = function(glob) { // From // https://github.com/matrix-org/synapse/blob/abbee6b29be80a77e05730707602f3bbfc3f38cb/synapse/push/__init__.py#L132 // Because micromatch is about 130KB with dependencies, @@ -218,19 +218,19 @@ function PushProcessor(client) { pat = pat.replace(/\\\*/, '.*'); pat = pat.replace(/\?/, '.'); pat = pat.replace(/\\\[(!|)(.*)\\]/, function(match, p1, p2, offset, string) { - let first = p1 && '^' || ''; - let second = p2.replace(/\\\-/, '-'); + const first = p1 && '^' || ''; + const second = p2.replace(/\\\-/, '-'); return '[' + first + second + ']'; }); return pat; }; - let valueForDottedKey = function(key, ev) { - let parts = key.split('.'); + const valueForDottedKey = function(key, ev) { + const parts = key.split('.'); let val; // special-case the first component to deal with encrypted messages - let firstPart = parts[0]; + const firstPart = parts[0]; if (firstPart == 'content') { val = ev.getContent(); parts.shift(); @@ -243,7 +243,7 @@ function PushProcessor(client) { } while (parts.length > 0) { - let thispart = parts.shift(); + const thispart = parts.shift(); if (!val[thispart]) { return null; } @@ -252,7 +252,7 @@ function PushProcessor(client) { return val; }; - let matchingRuleForEventWithRulesets = function(ev, rulesets) { + const matchingRuleForEventWithRulesets = function(ev, rulesets) { if (!rulesets || !rulesets.device) { return null; } @@ -260,12 +260,12 @@ function PushProcessor(client) { return null; } - let allDevNames = Object.keys(rulesets.device); + const allDevNames = Object.keys(rulesets.device); for (let i = 0; i < allDevNames.length; ++i) { - let devname = allDevNames[i]; - let devrules = rulesets.device[devname]; + const devname = allDevNames[i]; + const devrules = rulesets.device[devname]; - let matchingRule = matchingRuleFromKindSet(devrules, devname); + const matchingRule = matchingRuleFromKindSet(devrules, devname); if (matchingRule) { return matchingRule; } @@ -273,13 +273,13 @@ function PushProcessor(client) { return matchingRuleFromKindSet(ev, rulesets.global); }; - let pushActionsForEventAndRulesets = function(ev, rulesets) { - let rule = matchingRuleForEventWithRulesets(ev, rulesets); + const pushActionsForEventAndRulesets = function(ev, rulesets) { + const rule = matchingRuleForEventWithRulesets(ev, rulesets); if (!rule) { return {}; } - let actionObj = PushProcessor.actionListToActionsObject(rule.actions); + const actionObj = PushProcessor.actionListToActionsObject(rule.actions); // Some actions are implicit in some situations: we add those here if (actionObj.tweaks.highlight === undefined) { @@ -312,9 +312,9 @@ function PushProcessor(client) { * @return {object} A object with key 'notify' (true or false) and an object of actions */ PushProcessor.actionListToActionsObject = function(actionlist) { - let actionobj = { 'notify': false, 'tweaks': {} }; + const actionobj = { 'notify': false, 'tweaks': {} }; for (let i = 0; i < actionlist.length; ++i) { - let action = actionlist[i]; + const action = actionlist[i]; if (action === 'notify') { actionobj.notify = true; } else if (typeof action === 'object') { diff --git a/src/realtime-callbacks.js b/src/realtime-callbacks.js index 63f75e155..6ac002d91 100644 --- a/src/realtime-callbacks.js +++ b/src/realtime-callbacks.js @@ -27,7 +27,7 @@ limitations under the License. // we schedule a callback at least this often, to check if we've missed out on // some wall-clock time due to being suspended. -let TIMER_CHECK_PERIOD_MS = 1000; +const TIMER_CHECK_PERIOD_MS = 1000; // counter, for making up ids to return from setTimeout let _count = 0; @@ -37,10 +37,10 @@ let _realCallbackKey; // a sorted list of the callbacks to be run. // each is an object with keys [runAt, func, params, key]. -let _callbackList = []; +const _callbackList = []; // var debuglog = console.log.bind(console); -let debuglog = function() {}; +const debuglog = function() {}; /** * Replace the function used by this module to get the current time. @@ -72,12 +72,12 @@ module.exports.setTimeout = function(func, delayMs) { delayMs = 0; } - let params = Array.prototype.slice.call(arguments, 2); - let runAt = _now() + delayMs; - let key = _count++; + const params = Array.prototype.slice.call(arguments, 2); + const runAt = _now() + delayMs; + const key = _count++; debuglog("setTimeout: scheduling cb", key, "at", runAt, "(delay", delayMs, ")"); - let data = { + const data = { runAt: runAt, func: func, params: params, @@ -85,10 +85,10 @@ module.exports.setTimeout = function(func, delayMs) { }; // figure out where it goes in the list - let idx = binarySearch( + const idx = binarySearch( _callbackList, function(el) { return el.runAt - runAt; - } + }, ); _callbackList.splice(idx, 0, data); @@ -110,7 +110,7 @@ module.exports.clearTimeout = function(key) { // remove the element from the list let i; for (i = 0; i < _callbackList.length; i++) { - let cb = _callbackList[i]; + const cb = _callbackList[i]; if (cb.key == key) { _callbackList.splice(i, 1); break; @@ -129,15 +129,15 @@ function _scheduleRealCallback() { global.clearTimeout(_realCallbackKey); } - let first = _callbackList[0]; + const first = _callbackList[0]; if (!first) { debuglog("_scheduleRealCallback: no more callbacks, not rescheduling"); return; } - let now = _now(); - let delayMs = Math.min(first.runAt - now, TIMER_CHECK_PERIOD_MS); + const now = _now(); + const delayMs = Math.min(first.runAt - now, TIMER_CHECK_PERIOD_MS); debuglog("_scheduleRealCallback: now:", now, "delay:", delayMs); _realCallbackKey = global.setTimeout(_runCallbacks, delayMs); @@ -145,13 +145,13 @@ function _scheduleRealCallback() { function _runCallbacks() { let cb; - let now = _now(); + const now = _now(); debuglog("_runCallbacks: now:", now); // get the list of things to call - let callbacksToRun = []; + const callbacksToRun = []; while (true) { - let first = _callbackList[0]; + const first = _callbackList[0]; if (!first || first.runAt > now) { break; } @@ -188,8 +188,8 @@ function binarySearch(array, func) { max = array.length; while (min < max) { - let mid = (min + max) >> 1; - let res = func(array[mid]); + const mid = (min + max) >> 1; + const res = func(array[mid]); if (res > 0) { // the element at 'mid' is too big; set it as the new max. max = mid; diff --git a/src/scheduler.js b/src/scheduler.js index de77524bb..aa72e4967 100644 --- a/src/scheduler.js +++ b/src/scheduler.js @@ -19,10 +19,10 @@ limitations under the License. * of requests. * @module scheduler */ -let utils = require("./utils"); -let q = require("q"); +const utils = require("./utils"); +const q = require("q"); -let DEBUG = false; // set true to enable console logging. +const DEBUG = false; // set true to enable console logging. /** * Construct a scheduler for Matrix. Requires @@ -60,7 +60,7 @@ function MatrixScheduler(retryAlgorithm, queueAlgorithm) { * @see MatrixScheduler.removeEventFromQueue To remove an event from the queue. */ MatrixScheduler.prototype.getQueueForEvent = function(event) { - let name = this.queueAlgorithm(event); + const name = this.queueAlgorithm(event); if (!name || !this._queues[name]) { return null; } @@ -76,7 +76,7 @@ MatrixScheduler.prototype.getQueueForEvent = function(event) { * @return {boolean} True if this event was removed. */ MatrixScheduler.prototype.removeEventFromQueue = function(event) { - let name = this.queueAlgorithm(event); + const name = this.queueAlgorithm(event); if (!name || !this._queues[name]) { return false; } @@ -110,7 +110,7 @@ MatrixScheduler.prototype.setProcessFunction = function(fn) { * resolved or rejected in due time, else null. */ MatrixScheduler.prototype.queueEvent = function(event) { - let queueName = this.queueAlgorithm(event); + const queueName = this.queueAlgorithm(event); if (!queueName) { return null; } @@ -118,7 +118,7 @@ MatrixScheduler.prototype.queueEvent = function(event) { if (!this._queues[queueName]) { this._queues[queueName] = []; } - let defer = q.defer(); + const defer = q.defer(); this._queues[queueName].push({ event: event, defer: defer, @@ -126,7 +126,7 @@ MatrixScheduler.prototype.queueEvent = function(event) { }); debuglog( "Queue algorithm dumped event %s into queue '%s'", - event.getId(), queueName + event.getId(), queueName, ); _startProcessingQueues(this); return defer.promise; @@ -155,7 +155,7 @@ MatrixScheduler.RETRY_BACKOFF_RATELIMIT = function(event, attempts, err) { } if (err.name === "M_LIMIT_EXCEEDED") { - let waitTime = err.data.retry_after_ms; + const waitTime = err.data.retry_after_ms; if (waitTime) { return waitTime; } @@ -201,10 +201,10 @@ function _startProcessingQueues(scheduler) { function _processQueue(scheduler, queueName) { // get head of queue - let obj = _peekNextEvent(scheduler, queueName); + const obj = _peekNextEvent(scheduler, queueName); if (!obj) { // queue is empty. Mark as inactive and stop recursing. - let index = scheduler._activeQueues.indexOf(queueName); + const index = scheduler._activeQueues.indexOf(queueName); if (index >= 0) { scheduler._activeQueues.splice(index, 1); } @@ -213,7 +213,7 @@ function _processQueue(scheduler, queueName) { } debuglog( "Queue '%s' has %s pending events", - queueName, scheduler._queues[queueName].length + queueName, scheduler._queues[queueName].length, ); // fire the process function and if it resolves, resolve the deferred. Else // invoke the retry algorithm. @@ -227,14 +227,14 @@ function _processQueue(scheduler, queueName) { }, function(err) { obj.attempts += 1; // ask the retry algorithm when/if we should try again - let waitTimeMs = scheduler.retryAlgorithm(obj.event, obj.attempts, err); + const waitTimeMs = scheduler.retryAlgorithm(obj.event, obj.attempts, err); debuglog( "retry(%s) err=%s event_id=%s waitTime=%s", - obj.attempts, err, obj.event.getId(), waitTimeMs + obj.attempts, err, obj.event.getId(), waitTimeMs, ); if (waitTimeMs === -1) { // give up (you quitter!) debuglog( - "Queue '%s' giving up on event %s", queueName, obj.event.getId() + "Queue '%s' giving up on event %s", queueName, obj.event.getId(), ); // remove this from the queue _removeNextEvent(scheduler, queueName); @@ -250,7 +250,7 @@ function _processQueue(scheduler, queueName) { } function _peekNextEvent(scheduler, queueName) { - let queue = scheduler._queues[queueName]; + const queue = scheduler._queues[queueName]; if (!utils.isArray(queue)) { return null; } @@ -258,7 +258,7 @@ function _peekNextEvent(scheduler, queueName) { } function _removeNextEvent(scheduler, queueName) { - let queue = scheduler._queues[queueName]; + const queue = scheduler._queues[queueName]; if (!utils.isArray(queue)) { return null; } diff --git a/src/store/memory.js b/src/store/memory.js index d138e3a14..cf52f8074 100644 --- a/src/store/memory.js +++ b/src/store/memory.js @@ -18,8 +18,8 @@ limitations under the License. * This is an internal module. See {@link MatrixInMemoryStore} for the public class. * @module store/memory */ - let utils = require("../utils"); - let User = require("../models/user"); + const utils = require("../utils"); + const User = require("../models/user"); /** * Construct a new in-memory data store for the Matrix Client. @@ -77,7 +77,7 @@ module.exports.MatrixInMemoryStore.prototype = { // map up-to-date. room.currentState.on("RoomState.members", this._onRoomMember.bind(this)); // add existing members - let self = this; + const self = this; room.currentState.getMembers().forEach(function(m) { self._onRoomMember(null, room.currentState, m); }); @@ -97,12 +97,12 @@ module.exports.MatrixInMemoryStore.prototype = { return; } - let user = this.users[member.userId] || new User(member.userId); + const user = this.users[member.userId] || new User(member.userId); if (member.name) { user.setDisplayName(member.name); if (member.events.member) { user.setRawDisplayName( - member.events.member.getDirectionalContent().displayname + member.events.member.getDirectionalContent().displayname, ); } } @@ -260,7 +260,7 @@ module.exports.MatrixInMemoryStore.prototype = { * @param {Array} events The events to store. */ storeAccountDataEvents: function(events) { - let self = this; + const self = this; events.forEach(function(event) { self.accountData[event.getType()] = event; }); diff --git a/src/store/session/webstorage.js b/src/store/session/webstorage.js index 155bb5652..d8aa828c3 100644 --- a/src/store/session/webstorage.js +++ b/src/store/session/webstorage.js @@ -19,10 +19,10 @@ limitations under the License. * @module store/session/webstorage */ -let utils = require("../../utils"); +const utils = require("../../utils"); -let DEBUG = false; // set true to enable console logging. -let E2E_PREFIX = "session.e2e."; +const DEBUG = false; // set true to enable console logging. +const E2E_PREFIX = "session.e2e."; /** * Construct a web storage session store, capable of storing account keys, @@ -37,9 +37,12 @@ function WebStorageSessionStore(webStore) { this.store = webStore; if (!utils.isFunction(webStore.getItem) || !utils.isFunction(webStore.setItem) || - !utils.isFunction(webStore.removeItem)) { + !utils.isFunction(webStore.removeItem) || + !utils.isFunction(webStore.key) || + typeof(webStore.length) !== 'number' + ) { throw new Error( - "Supplied webStore does not meet the WebStorage API interface" + "Supplied webStore does not meet the WebStorage API interface", ); } } @@ -103,10 +106,10 @@ WebStorageSessionStore.prototype = { * @param {string} session Base64 encoded end-to-end session. */ storeEndToEndSession: function(deviceKey, sessionId, session) { - let sessions = this.getEndToEndSessions(deviceKey) || {}; + const sessions = this.getEndToEndSessions(deviceKey) || {}; sessions[sessionId] = session; setJsonItem( - this.store, keyEndToEndSessions(deviceKey), sessions + this.store, keyEndToEndSessions(deviceKey), sessions, ); }, @@ -120,13 +123,39 @@ WebStorageSessionStore.prototype = { return getJsonItem(this.store, keyEndToEndSessions(deviceKey)); }, + /** + * Retrieve a list of all known inbound group sessions + * + * @return {{senderKey: string, sessionId: string}} + */ + getAllEndToEndInboundGroupSessionKeys: function() { + const prefix = E2E_PREFIX + 'inboundgroupsessions/'; + const result = []; + for (let i = 0; i < this.store.length; i++) { + const key = this.store.key(i); + if (!key.startsWith(prefix)) { + continue; + } + // we can't use split, as the components we are trying to split out + // might themselves contain '/' characters. We rely on the + // senderKey being a (32-byte) curve25519 key, base64-encoded + // (hence 43 characters long). + + result.push({ + senderKey: key.substr(prefix.length, 43), + sessionId: key.substr(prefix.length + 44), + }); + } + return result; + }, + getEndToEndInboundGroupSession: function(senderKey, sessionId) { - let key = keyEndToEndInboundGroupSession(senderKey, sessionId); + const key = keyEndToEndInboundGroupSession(senderKey, sessionId); return this.store.getItem(key); }, storeEndToEndInboundGroupSession: function(senderKey, sessionId, pickledSession) { - let key = keyEndToEndInboundGroupSession(senderKey, sessionId); + const key = keyEndToEndInboundGroupSession(senderKey, sessionId); return this.store.setItem(key, pickledSession); }, @@ -149,8 +178,8 @@ WebStorageSessionStore.prototype = { }, }; -let KEY_END_TO_END_ACCOUNT = E2E_PREFIX + "account"; -let KEY_END_TO_END_ANNOUNCED = E2E_PREFIX + "announced"; +const KEY_END_TO_END_ACCOUNT = E2E_PREFIX + "account"; +const KEY_END_TO_END_ANNOUNCED = E2E_PREFIX + "announced"; function keyEndToEndDevicesForUser(userId) { return E2E_PREFIX + "devices/" + userId; diff --git a/src/sync.js b/src/sync.js index f0a00eb20..90ba408d3 100644 --- a/src/sync.js +++ b/src/sync.js @@ -23,20 +23,20 @@ limitations under the License. * an alternative syncing API, we may want to have a proper syncing interface * for HTTP and WS at some point. */ -let q = require("q"); -let User = require("./models/user"); -let Room = require("./models/room"); -let utils = require("./utils"); -let Filter = require("./filter"); -let EventTimeline = require("./models/event-timeline"); +const q = require("q"); +const User = require("./models/user"); +const Room = require("./models/room"); +const utils = require("./utils"); +const Filter = require("./filter"); +const EventTimeline = require("./models/event-timeline"); -let DEBUG = true; +const DEBUG = true; // /sync requests allow you to set a timeout= but the request may continue // beyond that and wedge forever, so we need to track how long we are willing // to keep open the connection. This constant is *ADDED* to the timeout= value // to determine the max time we're willing to wait. -let BUFFER_PERIOD_MS = 80 * 1000; +const BUFFER_PERIOD_MS = 80 * 1000; function getFilterName(userId, suffix) { // scope this on the user ID because people may login on many accounts @@ -88,8 +88,8 @@ function SyncApi(client, opts) { * @return {Room} */ SyncApi.prototype.createRoom = function(roomId) { - let client = this.client; - let room = new Room(roomId, { + const client = this.client; + const room = new Room(roomId, { pendingEventOrdering: this.opts.pendingEventOrdering, timelineSupport: client.timelineSupport, }); @@ -108,7 +108,7 @@ SyncApi.prototype.createRoom = function(roomId) { * @private */ SyncApi.prototype._registerStateListeners = function(room) { - let client = this.client; + const client = this.client; // we need to also re-emit room state and room member events, so hook it up // to the client now. We need to add a listener for RoomState.members in // order to hook them correctly. (TODO: find a better way?) @@ -122,7 +122,7 @@ SyncApi.prototype._registerStateListeners = function(room) { [ "RoomMember.name", "RoomMember.typing", "RoomMember.powerLevel", "RoomMember.membership", - ] + ], ); }); }; @@ -144,34 +144,34 @@ SyncApi.prototype._deregisterStateListeners = function(room) { * @return {Promise} Resolved when they've been added to the store. */ SyncApi.prototype.syncLeftRooms = function() { - let client = this.client; - let self = this; + const client = this.client; + const self = this; // grab a filter with limit=1 and include_leave=true - let filter = new Filter(this.client.credentials.userId); + const filter = new Filter(this.client.credentials.userId); filter.setTimelineLimit(1); filter.setIncludeLeaveRooms(true); - let localTimeoutMs = this.opts.pollTimeout + BUFFER_PERIOD_MS; - let qps = { + const localTimeoutMs = this.opts.pollTimeout + BUFFER_PERIOD_MS; + const qps = { timeout: 0, // don't want to block since this is a single isolated req }; return client.getOrCreateFilter( - getFilterName(client.credentials.userId, "LEFT_ROOMS"), filter + getFilterName(client.credentials.userId, "LEFT_ROOMS"), filter, ).then(function(filterId) { qps.filter = filterId; return client._http.authedRequest( - undefined, "GET", "/sync", qps, undefined, localTimeoutMs + undefined, "GET", "/sync", qps, undefined, localTimeoutMs, ); }).then(function(data) { let leaveRooms = []; if (data.rooms && data.rooms.leave) { leaveRooms = self._mapSyncResponseToRoomArray(data.rooms.leave); } - let rooms = []; + const rooms = []; leaveRooms.forEach(function(leaveObj) { - let room = leaveObj.room; + const room = leaveObj.room; rooms.push(room); if (!leaveObj.isBrandNewRoom) { // the intention behind syncLeftRooms is to add in rooms which were @@ -185,9 +185,9 @@ SyncApi.prototype.syncLeftRooms = function() { return; } leaveObj.timeline = leaveObj.timeline || {}; - let timelineEvents = + const timelineEvents = self._mapSyncEventsFormat(leaveObj.timeline, room); - let stateEvents = self._mapSyncEventsFormat(leaveObj.state, room); + const stateEvents = self._mapSyncEventsFormat(leaveObj.state, room); // set the back-pagination token. Do this *before* adding any // events so that clients can start back-paginating. @@ -212,8 +212,8 @@ SyncApi.prototype.syncLeftRooms = function() { * store. */ SyncApi.prototype.peek = function(roomId) { - let self = this; - let client = this.client; + const self = this; + const client = this.client; this._peekRoomId = roomId; return this.client.roomInitialSync(roomId, 20).then(function(response) { // make sure things are init'd @@ -221,18 +221,18 @@ SyncApi.prototype.peek = function(roomId) { response.messages.chunk = response.messages.chunk || []; response.state = response.state || []; - let peekRoom = self.createRoom(roomId); + const peekRoom = self.createRoom(roomId); // FIXME: Mostly duplicated from _processRoomEvents but not entirely // because "state" in this API is at the BEGINNING of the chunk - let oldStateEvents = utils.map( - utils.deepCopy(response.state), client.getEventMapper() + const oldStateEvents = utils.map( + utils.deepCopy(response.state), client.getEventMapper(), ); - let stateEvents = utils.map( - response.state, client.getEventMapper() + const stateEvents = utils.map( + response.state, client.getEventMapper(), ); - let messages = utils.map( - response.messages.chunk, client.getEventMapper() + const messages = utils.map( + response.messages.chunk, client.getEventMapper(), ); // XXX: copypasted from /sync until we kill off this @@ -301,7 +301,7 @@ SyncApi.prototype._peekPoll = function(roomId, token) { return; } - let self = this; + const self = this; // FIXME: gut wrenching; hard-coded timeout values this.client._http.authedRequest(undefined, "GET", "/events", { room_id: roomId, @@ -332,10 +332,10 @@ SyncApi.prototype._peekPoll = function(roomId, token) { }); // strip out events which aren't for the given room_id (e.g presence) - let events = res.chunk.filter(function(e) { + const events = res.chunk.filter(function(e) { return e.room_id === roomId; }).map(self.client.getEventMapper()); - let room = self.client.getRoom(roomId); + const room = self.client.getRoom(roomId); room.addLiveEvents(events); self._peekPoll(roomId, res.end); }, function(err) { @@ -362,8 +362,8 @@ SyncApi.prototype.sync = function() { debuglog("SyncApi.sync: starting with sync token " + this.client.store.getSyncToken()); - let client = this.client; - let self = this; + const client = this.client; + const self = this; this._running = true; @@ -401,7 +401,7 @@ SyncApi.prototype.sync = function() { } client.getOrCreateFilter( - getFilterName(client.credentials.userId), filter + getFilterName(client.credentials.userId), filter, ).done(function(filterId) { // reset the notifications timeline to prepare it to paginate from // the current point in time. @@ -465,8 +465,8 @@ SyncApi.prototype.retryImmediately = function() { * @param {boolean} syncOptions.hasSyncedBefore */ SyncApi.prototype._sync = function(syncOptions) { - let client = this.client; - let self = this; + const client = this.client; + const self = this; if (!this._running) { debuglog("Sync no longer running: exiting."); @@ -483,9 +483,9 @@ SyncApi.prototype._sync = function(syncOptions) { filterId = this._getGuestFilter(); } - let syncToken = client.store.getSyncToken(); + const syncToken = client.store.getSyncToken(); - let qps = { + const qps = { filter: filterId, timeout: this.opts.pollTimeout, }; @@ -508,10 +508,10 @@ SyncApi.prototype._sync = function(syncOptions) { } // normal timeout= plus buffer time - let clientSideTimeoutMs = this.opts.pollTimeout + BUFFER_PERIOD_MS; + const clientSideTimeoutMs = this.opts.pollTimeout + BUFFER_PERIOD_MS; this._currentSyncRequest = client._http.authedRequest( - undefined, "GET", "/sync", qps, undefined, clientSideTimeoutMs + undefined, "GET", "/sync", qps, undefined, clientSideTimeoutMs, ); this._currentSyncRequest.done(function(data) { @@ -576,8 +576,8 @@ SyncApi.prototype._sync = function(syncOptions) { * @param {Object} data The response from /sync */ SyncApi.prototype._processSyncResponse = function(syncToken, data) { - let client = this.client; - let self = this; + const client = this.client; + const self = this; // data looks like: // { @@ -635,7 +635,7 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) { // handle non-room account_data if (data.account_data && utils.isArray(data.account_data.events)) { - let events = data.account_data.events.map(client.getEventMapper()); + const events = data.account_data.events.map(client.getEventMapper()); client.store.storeAccountDataEvents(events); events.forEach( function(accountDataEvent) { @@ -644,7 +644,7 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) { } client.emit("accountData", accountDataEvent); return accountDataEvent; - } + }, ); } @@ -654,19 +654,19 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) { .map(client.getEventMapper()) .forEach( function(toDeviceEvent) { - let content = toDeviceEvent.getContent(); + const content = toDeviceEvent.getContent(); if ( toDeviceEvent.getType() == "m.room.message" && content.msgtype == "m.bad.encrypted" ) { console.warn( - "Unable to decrypt to-device event: " + content.body + "Unable to decrypt to-device event: " + content.body, ); return; } client.emit("toDeviceEvent", toDeviceEvent); - } + }, ); } @@ -693,8 +693,8 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) { // Handle invites inviteRooms.forEach(function(inviteObj) { - let room = inviteObj.room; - let stateEvents = + const room = inviteObj.room; + const stateEvents = self._mapSyncEventsFormat(inviteObj.invite_state, room); self._processRoomEvents(room, stateEvents); if (inviteObj.isBrandNewRoom) { @@ -709,19 +709,19 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) { // Handle joins joinRooms.forEach(function(joinObj) { - let room = joinObj.room; - let stateEvents = self._mapSyncEventsFormat(joinObj.state, room); - let timelineEvents = self._mapSyncEventsFormat(joinObj.timeline, room); - let ephemeralEvents = self._mapSyncEventsFormat(joinObj.ephemeral); - let accountDataEvents = self._mapSyncEventsFormat(joinObj.account_data); + const room = joinObj.room; + const stateEvents = self._mapSyncEventsFormat(joinObj.state, room); + const timelineEvents = self._mapSyncEventsFormat(joinObj.timeline, room); + const ephemeralEvents = self._mapSyncEventsFormat(joinObj.ephemeral); + const accountDataEvents = self._mapSyncEventsFormat(joinObj.account_data); // we do this first so it's correct when any of the events fire if (joinObj.unread_notifications) { room.setUnreadNotificationCount( - 'total', joinObj.unread_notifications.notification_count + 'total', joinObj.unread_notifications.notification_count, ); room.setUnreadNotificationCount( - 'highlight', joinObj.unread_notifications.highlight_count + 'highlight', joinObj.unread_notifications.highlight_count, ); } @@ -748,7 +748,7 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) { // will stop us linking the empty timeline into the chain). // for (let i = timelineEvents.length - 1; i >= 0; i--) { - let eventId = timelineEvents[i].getId(); + const eventId = timelineEvents[i].getId(); if (room.getTimelineForEvent(eventId)) { debuglog("Already have event " + eventId + " in limited " + "sync - not resetting"); @@ -818,12 +818,12 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) { // Handle leaves (e.g. kicked rooms) leaveRooms.forEach(function(leaveObj) { - let room = leaveObj.room; - let stateEvents = + const room = leaveObj.room; + const stateEvents = self._mapSyncEventsFormat(leaveObj.state, room); - let timelineEvents = + const timelineEvents = self._mapSyncEventsFormat(leaveObj.timeline, room); - let accountDataEvents = + const accountDataEvents = self._mapSyncEventsFormat(leaveObj.account_data); self._processRoomEvents(room, stateEvents, timelineEvents); @@ -876,11 +876,11 @@ SyncApi.prototype._startKeepAlives = function(delay) { if (this._keepAliveTimer !== null) { clearTimeout(this._keepAliveTimer); } - let self = this; + const self = this; if (delay > 0) { self._keepAliveTimer = setTimeout( self._pokeKeepAlive.bind(self), - delay + delay, ); } else { self._pokeKeepAlive(); @@ -895,7 +895,7 @@ SyncApi.prototype._startKeepAlives = function(delay) { * */ SyncApi.prototype._pokeKeepAlive = function() { - let self = this; + const self = this; function success() { clearTimeout(self._keepAliveTimer); if (self._connectionReturnedDefer) { @@ -912,7 +912,7 @@ SyncApi.prototype._pokeKeepAlive = function() { { prefix: '', localTimeoutMs: 15 * 1000, - } + }, ).done(function() { success(); }, function(err) { @@ -926,7 +926,7 @@ SyncApi.prototype._pokeKeepAlive = function() { } else { self._keepAliveTimer = setTimeout( self._pokeKeepAlive.bind(self), - 5000 + Math.floor(Math.random() * 5000) + 5000 + Math.floor(Math.random() * 5000), ); // A keepalive has failed, so we emit the // error state (whether or not this is the @@ -947,10 +947,10 @@ SyncApi.prototype._mapSyncResponseToRoomArray = function(obj) { // Maps { roomid: {stuff}, roomid: {stuff} } // to // [{stuff+Room+isBrandNewRoom}, {stuff+Room+isBrandNewRoom}] - let client = this.client; - let self = this; + const client = this.client; + const self = this; return utils.keys(obj).map(function(roomId) { - let arrObj = obj[roomId]; + const arrObj = obj[roomId]; let room = client.store.getRoom(roomId); let isBrandNewRoom = false; if (!room) { @@ -972,7 +972,7 @@ SyncApi.prototype._mapSyncEventsFormat = function(obj, room) { if (!obj || !utils.isArray(obj.events)) { return []; } - let mapper = this.client.getEventMapper(); + const mapper = this.client.getEventMapper(); return obj.events.map(function(e) { if (room) { e.room_id = room.roomId; @@ -988,7 +988,7 @@ SyncApi.prototype._resolveInvites = function(room) { if (!room || !this.opts.resolveInvitesToProfiles) { return; } - let client = this.client; + const client = this.client; // For each invited room member we want to give them a displayname/avatar url // if they have one (the m.room.member invites don't contain this). room.getMembersWithMembership("invite").forEach(function(member) { @@ -997,7 +997,7 @@ SyncApi.prototype._resolveInvites = function(room) { } member._requestedProfileInfo = true; // try to get a cached copy first. - let user = client.getUser(member.userId); + const user = client.getUser(member.userId); let promise; if (user) { promise = q({ @@ -1011,7 +1011,7 @@ SyncApi.prototype._resolveInvites = function(room) { // slightly naughty by doctoring the invite event but this means all // the code paths remain the same between invite/join display name stuff // which is a worthy trade-off for some minor pollution. - let inviteEvent = member.events.member; + const inviteEvent = member.events.member; if (inviteEvent.getContent().membership !== "invite") { // between resolving and now they have since joined, so don't clobber return; @@ -1036,19 +1036,19 @@ SyncApi.prototype._resolveInvites = function(room) { SyncApi.prototype._processRoomEvents = function(room, stateEventList, timelineEventList) { timelineEventList = timelineEventList || []; - let client = this.client; + const client = this.client; // "old" and "current" state are the same initially; they // start diverging if the user paginates. // We must deep copy otherwise membership changes in old state // will leak through to current state! - let oldStateEvents = utils.map( + const oldStateEvents = utils.map( utils.deepCopy( stateEventList.map(function(mxEvent) { return mxEvent.event; - }) - ), client.getEventMapper() + }), + ), client.getEventMapper(), ); - let stateEvents = stateEventList; + const stateEvents = stateEventList; // set the state of the room to as it was before the timeline executes // @@ -1068,7 +1068,7 @@ SyncApi.prototype._processRoomEvents = function(room, stateEventList, // gather our notifications into this._notifEvents if (client.getNotifTimelineSet()) { for (let i = 0; i < timelineEventList.length; i++) { - let pushActions = client.getPushActionsForEvent(timelineEventList[i]); + const pushActions = client.getPushActionsForEvent(timelineEventList[i]); if (pushActions && pushActions.notify && pushActions.tweaks && pushActions.tweaks.highlight) { this._notifEvents.push(timelineEventList[i]); @@ -1085,7 +1085,7 @@ SyncApi.prototype._processRoomEvents = function(room, stateEventList, * @return {string} */ SyncApi.prototype._getGuestFilter = function() { - let guestRooms = this.client._guestRooms; // FIXME: horrible gut-wrenching + const guestRooms = this.client._guestRooms; // FIXME: horrible gut-wrenching if (!guestRooms) { return "{}"; } @@ -1106,7 +1106,7 @@ SyncApi.prototype._getGuestFilter = function() { * @param {Object} data Object of additional data to emit in the event */ SyncApi.prototype._updateSyncState = function(newState, data) { - let old = this._syncState; + const old = this._syncState; this._syncState = newState; this.client.emit("sync", this._syncState, old, data); }; @@ -1123,7 +1123,7 @@ SyncApi.prototype._onOnline = function() { }; function createNewUser(client, userId) { - let user = new User(userId); + const user = new User(userId); reEmit(client, user, [ "User.avatarUrl", "User.displayName", "User.presence", "User.currentlyActive", "User.lastPresenceTs", @@ -1140,7 +1140,7 @@ function reEmit(reEmitEntity, emittableEntity, eventNames) { // Transformation Example: // listener on "foo" => function(a,b) { ... } // Re-emit on "thing" => thing.emit("foo", a, b) - let newArgs = [eventName]; + const newArgs = [eventName]; for (let i = 0; i < arguments.length; i++) { newArgs.push(arguments[i]); } diff --git a/src/timeline-window.js b/src/timeline-window.js index 72d7ca431..523f8fcda 100644 --- a/src/timeline-window.js +++ b/src/timeline-window.js @@ -17,25 +17,25 @@ limitations under the License. /** @module timeline-window */ -let q = require("q"); -let EventTimeline = require("./models/event-timeline"); +const q = require("q"); +const EventTimeline = require("./models/event-timeline"); /** * @private */ -let DEBUG = false; +const DEBUG = false; /** * @private */ -let debuglog = DEBUG ? console.log.bind(console) : function() {}; +const debuglog = DEBUG ? console.log.bind(console) : function() {}; /** * the number of times we ask the server for more events before giving up * * @private */ -let DEFAULT_PAGINATE_LOOP_LIMIT = 5; +const DEFAULT_PAGINATE_LOOP_LIMIT = 5; /** * Construct a TimelineWindow. @@ -92,15 +92,15 @@ function TimelineWindow(client, timelineSet, opts) { * @return {module:client.Promise} */ TimelineWindow.prototype.load = function(initialEventId, initialWindowSize) { - let self = this; + const self = this; initialWindowSize = initialWindowSize || 20; // given an EventTimeline, and an event index within it, initialise our // fields so that the event in question is in the middle of the window. - let initFields = function(timeline, eventIndex) { - let endIndex = Math.min(timeline.getEvents().length, + const initFields = function(timeline, eventIndex) { + const endIndex = Math.min(timeline.getEvents().length, eventIndex + Math.ceil(initialWindowSize / 2)); - let startIndex = Math.max(0, endIndex - initialWindowSize); + const startIndex = Math.max(0, endIndex - initialWindowSize); self._start = new TimelineIndex(timeline, startIndex - timeline.getBaseIndex()); self._end = new TimelineIndex(timeline, endIndex - timeline.getBaseIndex()); self._eventCount = endIndex - startIndex; @@ -126,7 +126,7 @@ TimelineWindow.prototype.load = function(initialEventId, initialWindowSize) { }); } else { // start with the most recent events - let tl = this._timelineSet.getLiveTimeline(); + const tl = this._timelineSet.getLiveTimeline(); initFields(tl, tl.getEvents().length); return q(); } @@ -228,7 +228,7 @@ TimelineWindow.prototype.paginate = function(direction, size, makeRequest, } // try moving the cap - let count = (direction == EventTimeline.BACKWARDS) ? + const count = (direction == EventTimeline.BACKWARDS) ? tl.retreat(size) : tl.advance(size); if (count) { @@ -236,7 +236,7 @@ TimelineWindow.prototype.paginate = function(direction, size, makeRequest, debuglog("TimelineWindow: increased cap by " + count + " (now " + this._eventCount + ")"); // remove some events from the other end, if necessary - let excess = this._eventCount - this._windowLimit; + const excess = this._eventCount - this._windowLimit; if (excess > 0) { this.unpaginate(excess, direction != EventTimeline.BACKWARDS); } @@ -250,16 +250,16 @@ TimelineWindow.prototype.paginate = function(direction, size, makeRequest, } // try making a pagination request - let token = tl.timeline.getPaginationToken(direction); + const token = tl.timeline.getPaginationToken(direction); if (!token) { debuglog("TimelineWindow: no token"); return q(false); } debuglog("TimelineWindow: starting request"); - let self = this; + const self = this; - let prom = this._client.paginateEventTimeline(tl.timeline, { + const prom = this._client.paginateEventTimeline(tl.timeline, { backwards: direction == EventTimeline.BACKWARDS, limit: size, }).finally(function() { @@ -298,7 +298,7 @@ TimelineWindow.prototype.paginate = function(direction, size, makeRequest, * of the timeline. */ TimelineWindow.prototype.unpaginate = function(delta, startOfTimeline) { - let tl = startOfTimeline ? this._start : this._end; + const tl = startOfTimeline ? this._start : this._end; // sanity-check the delta if (delta > this._eventCount || delta < 0) { @@ -307,7 +307,7 @@ TimelineWindow.prototype.unpaginate = function(delta, startOfTimeline) { } while (delta > 0) { - let count = startOfTimeline ? tl.advance(delta) : tl.retreat(delta); + const count = startOfTimeline ? tl.advance(delta) : tl.retreat(delta); if (count <= 0) { // sadness. This shouldn't be possible. throw new Error( @@ -334,13 +334,13 @@ TimelineWindow.prototype.getEvents = function() { return []; } - let result = []; + const result = []; // iterate through each timeline between this._start and this._end // (inclusive). let timeline = this._start.timeline; while (true) { - let events = timeline.getEvents(); + const events = timeline.getEvents(); // For the first timeline in the chain, we want to start at // this._start.index. For the last timeline in the chain, we want to @@ -447,7 +447,7 @@ TimelineIndex.prototype.advance = function(delta) { // the index is already at the start/end of the current timeline. // // next see if there is a neighbouring timeline to switch to. - let neighbour = this.timeline.getNeighbouringTimeline( + const neighbour = this.timeline.getNeighbouringTimeline( delta < 0 ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS); if (neighbour) { this.timeline = neighbour; diff --git a/src/utils.js b/src/utils.js index 8f13716f8..06f34f91a 100644 --- a/src/utils.js +++ b/src/utils.js @@ -27,7 +27,7 @@ limitations under the License. */ module.exports.encodeParams = function(params) { let qs = ""; - for (let key in params) { + for (const key in params) { if (!params.hasOwnProperty(key)) { continue; } @@ -46,12 +46,12 @@ module.exports.encodeParams = function(params) { * @return {string} The result of replacing all template variables e.g. '/foo/baz'. */ module.exports.encodeUri = function(pathTemplate, variables) { - for (let key in variables) { + for (const key in variables) { if (!variables.hasOwnProperty(key)) { continue; } pathTemplate = pathTemplate.replace( - key, encodeURIComponent(variables[key]) + key, encodeURIComponent(variables[key]), ); } return pathTemplate; @@ -65,7 +65,7 @@ module.exports.encodeUri = function(pathTemplate, variables) { * @return {Array} A new array with the results of the function. */ module.exports.map = function(array, fn) { - let results = new Array(array.length); + const results = new Array(array.length); for (let i = 0; i < array.length; i++) { results[i] = fn(array[i]); } @@ -81,7 +81,7 @@ module.exports.map = function(array, fn) { * @return {Array} A new array with the results of the function. */ module.exports.filter = function(array, fn) { - let results = []; + const results = []; for (let i = 0; i < array.length; i++) { if (fn(array[i], i, array)) { results.push(array[i]); @@ -96,8 +96,8 @@ module.exports.filter = function(array, fn) { * @return {string[]} The keys of the object. */ module.exports.keys = function(obj) { - let keys = []; - for (let key in obj) { + const keys = []; + for (const key in obj) { if (!obj.hasOwnProperty(key)) { continue; } @@ -112,8 +112,8 @@ module.exports.keys = function(obj) { * @return {Array<*>} The values of the object. */ module.exports.values = function(obj) { - let values = []; - for (let key in obj) { + const values = []; + for (const key in obj) { if (!obj.hasOwnProperty(key)) { continue; } @@ -235,7 +235,7 @@ module.exports.checkObjectHasKeys = function(obj, keys) { * @throws If there are extra keys. */ module.exports.checkObjectHasNoAdditionalKeys = function(obj, allowedKeys) { - for (let key in obj) { + for (const key in obj) { if (!obj.hasOwnProperty(key)) { continue; } @@ -263,7 +263,7 @@ module.exports.deepCopy = function(obj) { * * @return {boolean} true if the two objects are equal */ -let deepCompare = module.exports.deepCompare = function(x, y) { +const deepCompare = module.exports.deepCompare = function(x, y) { // Inspired by // http://stackoverflow.com/questions/1068834/object-comparison-in-javascript#1144249 @@ -355,10 +355,10 @@ let deepCompare = module.exports.deepCompare = function(x, y) { * @return {Object} target */ module.exports.extend = function() { - let target = arguments[0] || {}; + const target = arguments[0] || {}; for (let i = 1; i < arguments.length; i++) { - let source = arguments[i]; - for (let propName in source) { // eslint-disable-line guard-for-in + const source = arguments[i]; + for (const propName in source) { // eslint-disable-line guard-for-in target[propName] = source[propName]; } } @@ -379,17 +379,17 @@ module.exports.runPolyfills = function() { throw new TypeError(); } - let t = Object(this); - let len = t.length >>> 0; + const t = Object(this); + const len = t.length >>> 0; if (typeof fun !== 'function') { throw new TypeError(); } - let res = []; - let thisArg = arguments.length >= 2 ? arguments[1] : void 0; + const res = []; + const thisArg = arguments.length >= 2 ? arguments[1] : void 0; for (let i = 0; i < len; i++) { if (i in t) { - let val = t[i]; + const val = t[i]; // NOTE: Technically this should Object.defineProperty at // the next index, as push can be affected by @@ -414,7 +414,7 @@ module.exports.runPolyfills = function() { // Reference: http://es5.github.io/#x15.4.4.19 if (!Array.prototype.map) { Array.prototype.map = function(callback, thisArg) { - let T, A, k; + let T, k; if (this === null || this === undefined) { throw new TypeError(' this is null or not defined'); @@ -422,12 +422,12 @@ module.exports.runPolyfills = function() { // 1. Let O be the result of calling ToObject passing the |this| // value as the argument. - let O = Object(this); + const O = Object(this); // 2. Let lenValue be the result of calling the Get internal // method of O with the argument "length". // 3. Let len be ToUint32(lenValue). - let len = O.length >>> 0; + const len = O.length >>> 0; // 4. If IsCallable(callback) is false, throw a TypeError exception. // See: http://es5.github.com/#x9.11 @@ -443,7 +443,7 @@ module.exports.runPolyfills = function() { // 6. Let A be a new array created as if by the expression new Array(len) // where Array is the standard built-in constructor with that name and // len is the value of len. - A = new Array(len); + const A = new Array(len); // 7. Let k be 0 k = 0; @@ -512,12 +512,12 @@ module.exports.runPolyfills = function() { // 1. Let O be the result of calling ToObject passing the |this| value as the // argument. - let O = Object(this); + const O = Object(this); // 2. Let lenValue be the result of calling the Get internal method of O with the // argument "length". // 3. Let len be ToUint32(lenValue). - let len = O.length >>> 0; + const len = O.length >>> 0; // 4. If IsCallable(callback) is false, throw a TypeError exception. // See: http://es5.github.com/#x9.11 @@ -582,7 +582,7 @@ module.exports.inherits = function(ctor, superCtor) { function Temp() {} // make a safe reference to Object.prototype.hasOwnProperty - let hasOwn = Object.prototype.hasOwnProperty; + const hasOwn = Object.prototype.hasOwnProperty; return function(O) { // 1. If Type(O) is not Object or Null throw a TypeError exception. @@ -595,7 +595,7 @@ module.exports.inherits = function(ctor, superCtor) { // constructor with that name // 3. Set the [[Prototype]] internal property of obj to O. Temp.prototype = O; - let obj = new Temp(); + const obj = new Temp(); Temp.prototype = null; // Let's not keep a stray reference to O... // 4. If the argument Properties is present and not undefined, add @@ -604,8 +604,8 @@ module.exports.inherits = function(ctor, superCtor) { // Properties. if (arguments.length > 1) { // Object.defineProperties does ToObject on its first argument. - let Properties = Object(arguments[1]); - for (let prop in Properties) { + const Properties = Object(arguments[1]); + for (const prop in Properties) { if (hasOwn.call(Properties, prop)) { obj[prop] = Properties[prop]; } diff --git a/src/webrtc/call.js b/src/webrtc/call.js index 1ad12c8d2..59ff3a5ec 100644 --- a/src/webrtc/call.js +++ b/src/webrtc/call.js @@ -18,9 +18,9 @@ limitations under the License. * This is an internal module. See {@link createNewMatrixCall} for the public API. * @module webrtc/call */ -let utils = require("../utils"); -let EventEmitter = require("events").EventEmitter; -let DEBUG = true; // set true to enable console logging. +const utils = require("../utils"); +const EventEmitter = require("events").EventEmitter; +const DEBUG = true; // set true to enable console logging. // events: hangup, error(err), replaced(call), state(state, oldState) @@ -125,24 +125,24 @@ MatrixCall.prototype.placeScreenSharingCall = function(remoteVideoElement, localVideoElement) { debuglog("placeScreenSharingCall"); checkForErrorListener(this); - let screenConstraints = _getChromeScreenSharingConstraints(this); + const screenConstraints = _getChromeScreenSharingConstraints(this); if (!screenConstraints) { return; } this.localVideoElement = localVideoElement; this.remoteVideoElement = remoteVideoElement; - let self = this; + const self = this; this.webRtc.getUserMedia(screenConstraints, function(stream) { self.screenSharingStream = stream; debuglog("Got screen stream, requesting audio stream..."); - let audioConstraints = _getUserMediaVideoContraints('voice'); + const audioConstraints = _getUserMediaVideoContraints('voice'); _placeCallWithConstraints(self, audioConstraints); }, function(err) { self.emit("error", callError( MatrixCall.ERR_NO_USER_MEDIA, - "Failed to get screen-sharing stream: " + err - ) + "Failed to get screen-sharing stream: " + err, + ), ); }); this.type = 'video'; @@ -266,9 +266,9 @@ MatrixCall.prototype.setLocalVideoElement = function(element) { this.URL.createObjectURL(this.localAVStream), "localVideo"); element.muted = true; - let self = this; + const self = this; setTimeout(function() { - let vel = self.getLocalVideoElement(); + const vel = self.getLocalVideoElement(); if (vel.play) { self.playElement(vel, "localVideo"); } @@ -306,12 +306,12 @@ MatrixCall.prototype.setRemoteAudioElement = function(element) { MatrixCall.prototype._initWithInvite = function(event) { this.msg = event.getContent(); this.peerConn = _createPeerConnection(this); - let self = this; + const self = this; if (this.peerConn) { this.peerConn.setRemoteDescription( new this.webRtc.RtcSessionDescription(this.msg.offer), hookCallback(self, self._onSetRemoteDescriptionSuccess), - hookCallback(self, self._onSetRemoteDescriptionError) + hookCallback(self, self._onSetRemoteDescriptionError), ); } setState(this, 'ringing'); @@ -364,13 +364,13 @@ MatrixCall.prototype._initWithHangup = function(event) { */ MatrixCall.prototype.answer = function() { debuglog("Answering call %s of type %s", this.callId, this.type); - let self = this; + const self = this; if (!this.localAVStream && !this.waitForLocalAVStream) { this.webRtc.getUserMedia( _getUserMediaVideoContraints(this.type), hookCallback(self, self._gotUserMediaForAnswer), - hookCallback(self, self._getUserMediaFailed) + hookCallback(self, self._getUserMediaFailed), ); setState(this, 'wait_local_media'); } else if (this.localAVStream) { @@ -416,7 +416,7 @@ MatrixCall.prototype._replacedBy = function(newCall) { MatrixCall.prototype.hangup = function(reason, suppressEvent) { debuglog("Ending call " + this.callId); terminate(this, "local", reason, !suppressEvent); - let content = { + const content = { version: 0, call_id: this.callId, reason: reason, @@ -492,8 +492,8 @@ MatrixCall.prototype._gotUserMediaForInvite = function(stream) { return; } debuglog("_gotUserMediaForInvite -> " + this.type); - let self = this; - let videoEl = this.getLocalVideoElement(); + const self = this; + const videoEl = this.getLocalVideoElement(); if (videoEl && this.type == 'video') { videoEl.autoplay = true; @@ -509,15 +509,17 @@ MatrixCall.prototype._gotUserMediaForInvite = function(stream) { } videoEl.muted = true; setTimeout(function() { - let vel = self.getLocalVideoElement(); + const vel = self.getLocalVideoElement(); if (vel.play) { self.playElement(vel, "localVideo"); } }, 0); } - this.screenSharingStream.addTrack(stream.getAudioTracks()[0]); - stream = this.screenSharingStream; + if (this.screenSharingStream) { + this.screenSharingStream.addTrack(stream.getAudioTracks()[0]); + stream = this.screenSharingStream; + } this.localAVStream = stream; // why do we enable audio (and only audio) tracks here? -- matthew @@ -526,7 +528,7 @@ MatrixCall.prototype._gotUserMediaForInvite = function(stream) { this.peerConn.addStream(stream); this.peerConn.createOffer( hookCallback(self, self._gotLocalOffer), - hookCallback(self, self._getLocalOfferFailed) + hookCallback(self, self._getLocalOfferFailed), ); setState(self, 'create_offer'); }; @@ -537,11 +539,11 @@ MatrixCall.prototype._gotUserMediaForInvite = function(stream) { * @param {Object} stream */ MatrixCall.prototype._gotUserMediaForAnswer = function(stream) { - let self = this; + const self = this; if (self.state == 'ended') { return; } - let localVidEl = self.getLocalVideoElement(); + const localVidEl = self.getLocalVideoElement(); if (localVidEl && self.type == 'video') { localVidEl.autoplay = true; @@ -550,7 +552,7 @@ MatrixCall.prototype._gotUserMediaForAnswer = function(stream) { "localVideo"); localVidEl.muted = true; setTimeout(function() { - let vel = self.getLocalVideoElement(); + const vel = self.getLocalVideoElement(); if (vel.play) { self.playElement(vel, "localVideo"); } @@ -561,7 +563,7 @@ MatrixCall.prototype._gotUserMediaForAnswer = function(stream) { setTracksEnabled(stream.getAudioTracks(), true); self.peerConn.addStream(stream); - let constraints = { + const constraints = { 'mandatory': { 'OfferToReceiveAudio': true, 'OfferToReceiveVideo': self.type == 'video', @@ -570,7 +572,7 @@ MatrixCall.prototype._gotUserMediaForAnswer = function(stream) { self.peerConn.createAnswer(function(description) { debuglog("Created answer: " + description); self.peerConn.setLocalDescription(description, function() { - let content = { + const content = { version: 0, call_id: self.callId, answer: { @@ -598,11 +600,11 @@ MatrixCall.prototype._gotLocalIceCandidate = function(event) { if (event.candidate) { debuglog( "Got local ICE " + event.candidate.sdpMid + " candidate: " + - event.candidate.candidate + event.candidate.candidate, ); // As with the offer, note we need to make a copy of this object, not // pass the original: that broke in Chrome ~m43. - let c = { + const c = { candidate: event.candidate.candidate, sdpMid: event.candidate.sdpMid, sdpMLineIndex: event.candidate.sdpMLineIndex, @@ -625,7 +627,7 @@ MatrixCall.prototype._gotRemoteIceCandidate = function(cand) { this.peerConn.addIceCandidate( new this.webRtc.RtcIceCandidate(cand), function() {}, - function(e) {} + function(e) {}, ); }; @@ -639,11 +641,11 @@ MatrixCall.prototype._receivedAnswer = function(msg) { return; } - let self = this; + const self = this; this.peerConn.setRemoteDescription( new this.webRtc.RtcSessionDescription(msg.answer), hookCallback(self, self._onSetRemoteDescriptionSuccess), - hookCallback(self, self._onSetRemoteDescriptionError) + hookCallback(self, self._onSetRemoteDescriptionError), ); setState(self, 'connecting'); }; @@ -654,7 +656,7 @@ MatrixCall.prototype._receivedAnswer = function(msg) { * @param {Object} description */ MatrixCall.prototype._gotLocalOffer = function(description) { - let self = this; + const self = this; debuglog("Created offer: " + description); if (self.state == 'ended') { @@ -664,7 +666,7 @@ MatrixCall.prototype._gotLocalOffer = function(description) { } self.peerConn.setLocalDescription(description, function() { - let content = { + const content = { version: 0, call_id: self.callId, // OpenWebRTC appears to add extra stuff (like the DTLS fingerprint) @@ -703,7 +705,7 @@ MatrixCall.prototype._gotLocalOffer = function(description) { MatrixCall.prototype._getLocalOfferFailed = function(error) { this.emit( "error", - callError(MatrixCall.ERR_LOCAL_OFFER_FAILED, "Failed to start audio for call!") + callError(MatrixCall.ERR_LOCAL_OFFER_FAILED, "Failed to start audio for call!"), ); }; @@ -718,8 +720,8 @@ MatrixCall.prototype._getUserMediaFailed = function(error) { callError( MatrixCall.ERR_NO_USER_MEDIA, "Couldn't start capturing media! Is your microphone set up and " + - "does this app have permission?" - ) + "does this app have permission?", + ), ); this.hangup("user_media_failed"); }; @@ -733,7 +735,7 @@ MatrixCall.prototype._onIceConnectionStateChanged = function() { return; // because ICE can still complete as we're ending the call } debuglog( - "Ice connection state changed to: " + this.peerConn.iceConnectionState + "Ice connection state changed to: " + this.peerConn.iceConnectionState, ); // ideally we'd consider the call to be connected when we get media but // chrome doesn't implement any of the 'onstarted' events yet @@ -753,7 +755,7 @@ MatrixCall.prototype._onIceConnectionStateChanged = function() { MatrixCall.prototype._onSignallingStateChanged = function() { debuglog( "call " + this.callId + ": Signalling state changed to: " + - this.peerConn.signalingState + this.peerConn.signalingState, ); }; @@ -782,7 +784,7 @@ MatrixCall.prototype._onSetRemoteDescriptionError = function(e) { MatrixCall.prototype._onAddStream = function(event) { debuglog("Stream id " + event.stream.id + " added"); - let s = event.stream; + const s = event.stream; if (s.getVideoTracks().length > 0) { this.type = 'video'; @@ -793,7 +795,7 @@ MatrixCall.prototype._onAddStream = function(event) { this.remoteAStream = s; } - let self = this; + const self = this; forAllTracksOnStream(s, function(t) { debuglog("Track id " + t.id + " added"); // not currently implemented in chrome @@ -872,13 +874,13 @@ MatrixCall.prototype._onAnsweredElsewhere = function(msg) { terminate(this, "remote", "answered_elsewhere", true); }; -let setTracksEnabled = function(tracks, enabled) { +const setTracksEnabled = function(tracks, enabled) { for (let i = 0; i < tracks.length; i++) { tracks[i].enabled = enabled; } }; -let isTracksEnabled = function(tracks) { +const isTracksEnabled = function(tracks) { for (let i = 0; i < tracks.length; i++) { if (tracks[i].enabled) { return true; // at least one track is enabled @@ -887,8 +889,8 @@ let isTracksEnabled = function(tracks) { return false; }; -let setState = function(self, state) { - let oldState = self.state; +const setState = function(self, state) { + const oldState = self.state; self.state = state; self.emit("state", state, oldState); }; @@ -900,11 +902,11 @@ let setState = function(self, state) { * @param {Object} content * @return {Promise} */ -let sendEvent = function(self, eventType, content) { +const sendEvent = function(self, eventType, content) { return self.client.sendEvent(self.roomId, eventType, content); }; -let sendCandidate = function(self, content) { +const sendCandidate = function(self, content) { // Sends candidates with are sent in a special way because we try to amalgamate // them into one message self.candidateSendQueue.push(content); @@ -915,7 +917,7 @@ let sendCandidate = function(self, content) { } }; -let terminate = function(self, hangupParty, hangupReason, shouldEmit) { +const terminate = function(self, hangupParty, hangupReason, shouldEmit) { if (self.getRemoteVideoElement()) { if (self.getRemoteVideoElement().pause) { self.pauseElement(self.getRemoteVideoElement(), "remoteVideo"); @@ -946,7 +948,7 @@ let terminate = function(self, hangupParty, hangupReason, shouldEmit) { } }; -let stopAllMedia = function(self) { +const stopAllMedia = function(self) { debuglog("stopAllMedia (stream=%s)", self.localAVStream); if (self.localAVStream) { forAllTracksOnStream(self.localAVStream, function(t) { @@ -986,15 +988,15 @@ let stopAllMedia = function(self) { } }; -let _tryPlayRemoteStream = function(self) { +const _tryPlayRemoteStream = function(self) { if (self.getRemoteVideoElement() && self.remoteAVStream) { - let player = self.getRemoteVideoElement(); + const player = self.getRemoteVideoElement(); player.autoplay = true; self.assignElement(player, self.URL.createObjectURL(self.remoteAVStream), "remoteVideo"); setTimeout(function() { - let vel = self.getRemoteVideoElement(); + const vel = self.getRemoteVideoElement(); if (vel.play) { self.playElement(vel, "remoteVideo"); } @@ -1006,15 +1008,15 @@ let _tryPlayRemoteStream = function(self) { } }; -let _tryPlayRemoteAudioStream = function(self) { +const _tryPlayRemoteAudioStream = function(self) { if (self.getRemoteAudioElement() && self.remoteAStream) { - let player = self.getRemoteAudioElement(); + const player = self.getRemoteAudioElement(); player.autoplay = true; self.assignElement(player, self.URL.createObjectURL(self.remoteAStream), "remoteAudio"); setTimeout(function() { - let ael = self.getRemoteAudioElement(); + const ael = self.getRemoteAudioElement(); if (ael.play) { self.playElement(ael, "remoteAudio"); } @@ -1026,35 +1028,35 @@ let _tryPlayRemoteAudioStream = function(self) { } }; -let checkForErrorListener = function(self) { +const checkForErrorListener = function(self) { if (self.listeners("error").length === 0) { throw new Error( - "You MUST attach an error listener using call.on('error', function() {})" + "You MUST attach an error listener using call.on('error', function() {})", ); } }; -let callError = function(code, msg) { - let e = new Error(msg); +const callError = function(code, msg) { + const e = new Error(msg); e.code = code; return e; }; -let debuglog = function() { +const debuglog = function() { if (DEBUG) { console.log(...arguments); } }; -let _sendCandidateQueue = function(self) { +const _sendCandidateQueue = function(self) { if (self.candidateSendQueue.length === 0) { return; } - let cands = self.candidateSendQueue; + const cands = self.candidateSendQueue; self.candidateSendQueue = []; ++self.candidateSendTries; - let content = { + const content = { version: 0, call_id: self.callId, candidates: cands, @@ -1071,13 +1073,13 @@ let _sendCandidateQueue = function(self) { if (self.candidateSendTries > 5) { debuglog( "Failed to send candidates on attempt %s. Giving up for now.", - self.candidateSendTries + self.candidateSendTries, ); self.candidateSendTries = 0; return; } - let delayMs = 500 * Math.pow(2, self.candidateSendTries); + const delayMs = 500 * Math.pow(2, self.candidateSendTries); ++self.candidateSendTries; debuglog("Failed to send candidates. Retrying in " + delayMs + "ms"); setTimeout(function() { @@ -1086,19 +1088,19 @@ let _sendCandidateQueue = function(self) { }); }; -let _placeCallWithConstraints = function(self, constraints) { +const _placeCallWithConstraints = function(self, constraints) { self.client.callList[self.callId] = self; self.webRtc.getUserMedia( constraints, hookCallback(self, self._gotUserMediaForInvite), - hookCallback(self, self._getUserMediaFailed) + hookCallback(self, self._getUserMediaFailed), ); setState(self, 'wait_local_media'); self.direction = 'outbound'; self.config = constraints; }; -let _createPeerConnection = function(self) { +const _createPeerConnection = function(self) { let servers = self.turnServers; if (self.webRtc.vendor === "mozilla") { // modify turnServers struct to match what mozilla expects. @@ -1114,7 +1116,7 @@ let _createPeerConnection = function(self) { } } - let pc = new self.webRtc.RtcPeerConnection({ + const pc = new self.webRtc.RtcPeerConnection({ iceServers: servers, }); pc.oniceconnectionstatechange = hookCallback(self, self._onIceConnectionStateChanged); @@ -1124,12 +1126,12 @@ let _createPeerConnection = function(self) { return pc; }; -let _getChromeScreenSharingConstraints = function(call) { - let screen = global.screen; +const _getChromeScreenSharingConstraints = function(call) { + const screen = global.screen; if (!screen) { call.emit("error", callError( MatrixCall.ERR_NO_USER_MEDIA, - "Couldn't determine screen sharing constaints." + "Couldn't determine screen sharing constaints.", )); return; } @@ -1148,7 +1150,7 @@ let _getChromeScreenSharingConstraints = function(call) { }; }; -let _getUserMediaVideoContraints = function(callType) { +const _getUserMediaVideoContraints = function(callType) { switch (callType) { case 'voice': return ({audio: true, video: false}); @@ -1164,27 +1166,27 @@ let _getUserMediaVideoContraints = function(callType) { } }; -let hookCallback = function(call, fn) { +const hookCallback = function(call, fn) { return function() { return fn.apply(call, arguments); }; }; -let forAllVideoTracksOnStream = function(s, f) { - let tracks = s.getVideoTracks(); +const forAllVideoTracksOnStream = function(s, f) { + const tracks = s.getVideoTracks(); for (let i = 0; i < tracks.length; i++) { f(tracks[i]); } }; -let forAllAudioTracksOnStream = function(s, f) { - let tracks = s.getAudioTracks(); +const forAllAudioTracksOnStream = function(s, f) { + const tracks = s.getAudioTracks(); for (let i = 0; i < tracks.length; i++) { f(tracks[i]); } }; -let forAllTracksOnStream = function(s, f) { +const forAllTracksOnStream = function(s, f) { forAllVideoTracksOnStream(s, f); forAllAudioTracksOnStream(s, f); }; @@ -1200,14 +1202,14 @@ module.exports.MatrixCall = MatrixCall; * @return {MatrixCall} the call or null if the browser doesn't support calling. */ module.exports.createNewMatrixCall = function(client, roomId) { - let w = global.window; - let doc = global.document; + const w = global.window; + const doc = global.document; if (!w || !doc) { return null; } - let webRtc = {}; + const webRtc = {}; webRtc.isOpenWebRTC = function() { - let scripts = doc.getElementById("script"); + const scripts = doc.getElementById("script"); if (!scripts || !scripts.length) { return false; } @@ -1218,7 +1220,7 @@ module.exports.createNewMatrixCall = function(client, roomId) { } return false; }; - let getUserMedia = ( + const getUserMedia = ( w.navigator.getUserMedia || w.navigator.webkitGetUserMedia || w.navigator.mozGetUserMedia ); @@ -1249,7 +1251,7 @@ module.exports.createNewMatrixCall = function(client, roomId) { !webRtc.RtcPeerConnection || !webRtc.getUserMedia) { return null; // WebRTC is not supported. } - let opts = { + const opts = { webRtc: webRtc, client: client, URL: w.URL,