From 4d657fb741f7f6f35f713c7d0a3db4a67204e4e3 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 07:15:49 +0000 Subject: [PATCH 01/38] Removes IE8 related comment --- src/common/lib/transport/connectionmanager.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/lib/transport/connectionmanager.ts b/src/common/lib/transport/connectionmanager.ts index 48fec7bd78..19ba4b3125 100644 --- a/src/common/lib/transport/connectionmanager.ts +++ b/src/common/lib/transport/connectionmanager.ts @@ -346,7 +346,6 @@ class ConnectionManager extends EventEmitter { if (addEventListener) { /* intercept close event in browser to persist connection id if requested */ if (haveSessionStorage() && typeof options.recover === 'function') { - /* Usually can't use bind as not supported in IE8, but IE doesn't support sessionStorage, so... */ addEventListener('beforeunload', this.persistConnection.bind(this)); } From e55a33b713c30859af62db7794790522fb816ff8 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 07:16:48 +0000 Subject: [PATCH 02/38] Removes Date.now polyfill for IE8 --- src/common/lib/util/utils.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index c211e833d4..1fd2d64c28 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -357,12 +357,7 @@ export function parseQueryString(query: string): Record { return result; } -export const now = - Date.now || - function () { - /* IE 8 */ - return new Date().getTime(); - }; +export const now = Date.now; export function isErrorInfoOrPartialErrorInfo(err: unknown): err is ErrorInfo | PartialErrorInfo { return typeof err == 'object' && err !== null && (err instanceof ErrorInfo || err instanceof PartialErrorInfo); From 29984da7b7cb5be7ac1e73b4e106d3aedc35cbee Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 07:18:19 +0000 Subject: [PATCH 03/38] Removes `Utils.now` function --- src/common/lib/client/auth.ts | 2 +- src/common/lib/client/realtimepresence.ts | 2 +- src/common/lib/client/rest.ts | 2 +- src/common/lib/transport/connectionmanager.ts | 12 ++++++------ src/common/lib/transport/transport.ts | 4 ++-- src/common/lib/util/utils.ts | 2 -- src/platform/nativescript/lib/util/webstorage.js | 5 ++--- src/platform/web/lib/util/webstorage.ts | 5 ++--- test/realtime/presence.test.js | 4 ++-- test/realtime/resume.test.js | 2 +- test/rest/auth.test.js | 2 +- test/rest/fallbacks.test.js | 3 +-- test/rest/time.test.js | 3 +-- 13 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/common/lib/client/auth.ts b/src/common/lib/client/auth.ts index a211fc2ef1..b0d819921c 100644 --- a/src/common/lib/client/auth.ts +++ b/src/common/lib/client/auth.ts @@ -830,7 +830,7 @@ class Auth { } getTimestampUsingOffset() { - return Utils.now() + (this.client.serverTimeOffset || 0); + return Date.now() + (this.client.serverTimeOffset || 0); } isTimeOffsetSet() { diff --git a/src/common/lib/client/realtimepresence.ts b/src/common/lib/client/realtimepresence.ts index 435ecf5c87..3b7098c9b2 100644 --- a/src/common/lib/client/realtimepresence.ts +++ b/src/common/lib/client/realtimepresence.ts @@ -452,7 +452,7 @@ class RealtimePresence extends EventEmitter { clientId: item.clientId, data: item.data, encoding: item.encoding, - timestamp: Utils.now(), + timestamp: Date.now(), }); subscriptions.emit('leave', presence); }); diff --git a/src/common/lib/client/rest.ts b/src/common/lib/client/rest.ts index c7f506f5d3..b8ab1d66d5 100644 --- a/src/common/lib/client/rest.ts +++ b/src/common/lib/client/rest.ts @@ -86,7 +86,7 @@ export class Rest { throw new ErrorInfo('Internal error (unexpected result type from GET /time)', 50000, 500); } /* calculate time offset only once for this device by adding to the prototype */ - this.client.serverTimeOffset = time - Utils.now(); + this.client.serverTimeOffset = time - Date.now(); return time; } diff --git a/src/common/lib/transport/connectionmanager.ts b/src/common/lib/transport/connectionmanager.ts index 19ba4b3125..5d6b357d6f 100644 --- a/src/common/lib/transport/connectionmanager.ts +++ b/src/common/lib/transport/connectionmanager.ts @@ -1131,7 +1131,7 @@ class ConnectionManager extends EventEmitter { return; } - const sinceLast = Utils.now() - this.lastActivity; + const sinceLast = Date.now() - this.lastActivity; if (sinceLast > this.connectionStateTtl + (this.maxIdleInterval as number)) { Logger.logAction( Logger.LOG_MINOR, @@ -1153,7 +1153,7 @@ class ConnectionManager extends EventEmitter { if (recoveryKey) { setSessionRecoverData({ recoveryKey: recoveryKey, - disconnectedAt: Utils.now(), + disconnectedAt: Date.now(), location: globalObject.location, clientId: this.realtime.auth.clientId, }); @@ -1357,11 +1357,11 @@ class ConnectionManager extends EventEmitter { if (retryImmediately) { const autoReconnect = () => { if (this.state === this.states.disconnected) { - this.lastAutoReconnectAttempt = Utils.now(); + this.lastAutoReconnectAttempt = Date.now(); this.requestState({ state: 'connecting' }); } }; - const sinceLast = this.lastAutoReconnectAttempt && Utils.now() - this.lastAutoReconnectAttempt + 1; + const sinceLast = this.lastAutoReconnectAttempt && Date.now() - this.lastAutoReconnectAttempt + 1; if (sinceLast && sinceLast < 1000) { Logger.logAction( Logger.LOG_MICRO, @@ -2058,14 +2058,14 @@ class ConnectionManager extends EventEmitter { callback(new ErrorInfo('Timeout waiting for heartbeat response', 50000, 500)); }; - const pingStart = Utils.now(), + const pingStart = Date.now(), id = Utils.cheapRandStr(); const onHeartbeat = function (responseId: string) { if (responseId === id) { transport.off('heartbeat', onHeartbeat); clearTimeout(timer); - const responseTime = Utils.now() - pingStart; + const responseTime = Date.now() - pingStart; callback(null, responseTime); } }; diff --git a/src/common/lib/transport/transport.ts b/src/common/lib/transport/transport.ts index 5153cd63bf..a18bfcb830 100644 --- a/src/common/lib/transport/transport.ts +++ b/src/common/lib/transport/transport.ts @@ -257,7 +257,7 @@ abstract class Transport extends EventEmitter { if (!this.maxIdleInterval) { return; } - this.lastActivity = this.connectionManager.lastActivity = Utils.now(); + this.lastActivity = this.connectionManager.lastActivity = Date.now(); this.setIdleTimer(this.maxIdleInterval + 100); } @@ -274,7 +274,7 @@ abstract class Transport extends EventEmitter { throw new Error('Transport.onIdleTimerExpire(): lastActivity/maxIdleInterval not set'); } this.idleTimer = null; - const sinceLast = Utils.now() - this.lastActivity; + const sinceLast = Date.now() - this.lastActivity; const timeRemaining = this.maxIdleInterval - sinceLast; if (timeRemaining <= 0) { const msg = 'No activity seen from realtime in ' + sinceLast + 'ms; assuming connection has dropped'; diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index 1fd2d64c28..153dd6a686 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -357,8 +357,6 @@ export function parseQueryString(query: string): Record { return result; } -export const now = Date.now; - export function isErrorInfoOrPartialErrorInfo(err: unknown): err is ErrorInfo | PartialErrorInfo { return typeof err == 'object' && err !== null && (err instanceof ErrorInfo || err instanceof PartialErrorInfo); } diff --git a/src/platform/nativescript/lib/util/webstorage.js b/src/platform/nativescript/lib/util/webstorage.js index cfb874d02c..90d169a615 100644 --- a/src/platform/nativescript/lib/util/webstorage.js +++ b/src/platform/nativescript/lib/util/webstorage.js @@ -1,4 +1,3 @@ -import * as Utils from '../../../../common/lib/util/utils'; import appSettings from '@nativescript/core/application-settings'; var WebStorage = (function () { @@ -7,7 +6,7 @@ var WebStorage = (function () { function set(name, value, ttl) { var wrappedValue = { value: value }; if (ttl) { - wrappedValue.expires = Utils.now() + ttl; + wrappedValue.expires = Date.now() + ttl; } return appSettings.setString(name, JSON.stringify(wrappedValue)); } @@ -16,7 +15,7 @@ var WebStorage = (function () { var rawItem = appSettings.getString(name); if (!rawItem) return null; var wrappedValue = JSON.parse(rawItem); - if (wrappedValue.expires && wrappedValue.expires < Utils.now()) { + if (wrappedValue.expires && wrappedValue.expires < Date.now()) { appSettings.remove(name); return null; } diff --git a/src/platform/web/lib/util/webstorage.ts b/src/platform/web/lib/util/webstorage.ts index 010bff419b..a87300417a 100644 --- a/src/platform/web/lib/util/webstorage.ts +++ b/src/platform/web/lib/util/webstorage.ts @@ -1,4 +1,3 @@ -import * as Utils from 'common/lib/util/utils'; import IWebStorage from 'common/types/IWebStorage'; const test = 'ablyjs-storage-test'; @@ -59,7 +58,7 @@ class Webstorage implements IWebStorage { private _set(name: string, value: string, ttl: number | undefined, session: any) { const wrappedValue: Record = { value: value }; if (ttl) { - wrappedValue.expires = Utils.now() + ttl; + wrappedValue.expires = Date.now() + ttl; } return this.storageInterface(session).setItem(name, JSON.stringify(wrappedValue)); } @@ -70,7 +69,7 @@ class Webstorage implements IWebStorage { const rawItem = this.storageInterface(session).getItem(name); if (!rawItem) return null; const wrappedValue = JSON.parse(rawItem); - if (wrappedValue.expires && wrappedValue.expires < Utils.now()) { + if (wrappedValue.expires && wrappedValue.expires < Date.now()) { this.storageInterface(session).removeItem(name); return null; } diff --git a/test/realtime/presence.test.js b/test/realtime/presence.test.js index 1046e2d43e..137b56f69a 100644 --- a/test/realtime/presence.test.js +++ b/test/realtime/presence.test.js @@ -1810,7 +1810,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async action: 14, id: 'messageid:0', connectionId: 'connid', - timestamp: utils.now(), + timestamp: Date.now(), presence: [ { clientId: goneClientId, @@ -1899,7 +1899,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async action: 14, id: 'messageid:0', connectionId: 'connid', - timestamp: utils.now(), + timestamp: Date.now(), presence: [ { clientId: fakeClientId, diff --git a/test/realtime/resume.test.js b/test/realtime/resume.test.js index 26104d9aa2..ba1931765b 100644 --- a/test/realtime/resume.test.js +++ b/test/realtime/resume.test.js @@ -553,7 +553,7 @@ define(['shared_helper', 'async', 'chai'], function (helper, async, chai) { connectionManager = connection.connectionManager; connection.once('connected', function () { - connectionManager.lastActivity = helper.Utils.now() - 10000000; + connectionManager.lastActivity = Date.now() - 10000000; /* noop-out onProtocolMessage so that a DISCONNECTED message doesn't * reset the last activity timer */ connectionManager.activeProtocol.getTransport().onProtocolMessage = function () {}; diff --git a/test/rest/auth.test.js b/test/rest/auth.test.js index 0824bcca8d..8f735add2a 100644 --- a/test/rest/auth.test.js +++ b/test/rest/auth.test.js @@ -59,7 +59,7 @@ define(['chai', 'shared_helper', 'async', 'globals'], function (chai, helper, as }); it('Token generation with invalid timestamp', async function () { - var badTime = utils.now() - 30 * 60 * 1000; + var badTime = Date.now() - 30 * 60 * 1000; try { var tokenDetails = await rest.auth.requestToken({ timestamp: badTime }); } catch (err) { diff --git a/test/rest/fallbacks.test.js b/test/rest/fallbacks.test.js index 209b519291..bef0f13184 100644 --- a/test/rest/fallbacks.test.js +++ b/test/rest/fallbacks.test.js @@ -2,7 +2,6 @@ define(['shared_helper', 'async', 'chai'], function (helper, async, chai) { var expect = chai.expect; - var utils = helper.Utils; var goodHost; describe('rest/fallbacks', function () { @@ -43,7 +42,7 @@ define(['shared_helper', 'async', 'chai'], function (helper, async, chai) { 'Check validUntil is the same (implying currentFallback has not been re-set)' ); /* set the validUntil to the past and check that the stored fallback is forgotten */ - var now = utils.now(); + var now = Date.now(); rest._currentFallback.validUntil = now - 1000; var serverTime = await rest.time(); expect(serverTime, 'Check serverTime returned').to.be.ok; diff --git a/test/rest/time.test.js b/test/rest/time.test.js index 71d0ee28ab..43b3799a99 100644 --- a/test/rest/time.test.js +++ b/test/rest/time.test.js @@ -2,7 +2,6 @@ define(['shared_helper', 'chai'], function (helper, chai) { var rest; - var utils = helper.Utils; var expect = chai.expect; describe('rest/time', function () { @@ -19,7 +18,7 @@ define(['shared_helper', 'chai'], function (helper, chai) { it('time0', async function () { var serverTime = await rest.time(); - var localFiveMinutesAgo = utils.now() - 5 * 60 * 1000; + var localFiveMinutesAgo = Date.now() - 5 * 60 * 1000; expect( serverTime > localFiveMinutesAgo, 'Verify returned time matches current local time with 5 minute leeway for badly synced local clocks' From 2a9fd381ce33f2e2e2613394a8a8993ccf962a25 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 07:25:52 +0000 Subject: [PATCH 04/38] Removes IE10 specific needJsonEnvelope check from web xhrrequest --- .../web/lib/http/request/xhrrequest.ts | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/platform/web/lib/http/request/xhrrequest.ts b/src/platform/web/lib/http/request/xhrrequest.ts index 99801578fd..5c10ec38b1 100644 --- a/src/platform/web/lib/http/request/xhrrequest.ts +++ b/src/platform/web/lib/http/request/xhrrequest.ts @@ -19,27 +19,10 @@ function getAblyError(responseBody: unknown, headers: Record) { } } -declare const global: { - XDomainRequest: unknown; -}; - const noop = function () {}; let idCounter = 0; const pendingRequests: Record = {}; -const isIE = typeof global !== 'undefined' && global.XDomainRequest; - -function ieVersion() { - const match = navigator.userAgent.toString().match(/MSIE\s([\d.]+)/); - return match && Number(match[1]); -} - -function needJsonEnvelope() { - /* IE 10 xhr bug: http://stackoverflow.com/a/16320339 */ - let version; - return isIE && (version = ieVersion()) && version === 10; -} - function getHeader(xhr: XMLHttpRequest, header: string) { return xhr.getResponseHeader && xhr.getResponseHeader(header); } @@ -91,7 +74,6 @@ class XHRRequest extends EventEmitter implements IXHRRequest { super(); params = params || {}; params.rnd = Utils.cheapRandStr(); - if (needJsonEnvelope() && !params.envelope) params.envelope = 'json'; this.uri = uri + Utils.toQueryString(params); this.headers = headers || {}; this.body = body; From c92c2837e72a397103b871f10152f418695a1f5f Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 07:27:16 +0000 Subject: [PATCH 05/38] Removes IE specific statusCode check from web xhrrequest --- src/platform/web/lib/http/request/xhrrequest.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/platform/web/lib/http/request/xhrrequest.ts b/src/platform/web/lib/http/request/xhrrequest.ts index 5c10ec38b1..d4f2aaa85d 100644 --- a/src/platform/web/lib/http/request/xhrrequest.ts +++ b/src/platform/web/lib/http/request/xhrrequest.ts @@ -309,8 +309,6 @@ class XHRRequest extends EventEmitter implements IXHRRequest { if (xhr.status !== 0) { if (statusCode === undefined) { statusCode = xhr.status; - /* IE returns 1223 for 204: http://bugs.jquery.com/ticket/1450 */ - if (statusCode === 1223) statusCode = 204; onResponse(); } if (readyState == 3 && streaming) { From 3b68aeb249ffa9510dadfc952868471292d3bcf2 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 07:32:39 +0000 Subject: [PATCH 06/38] Removes IE specific console checks from logger --- src/common/lib/util/logger.ts | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/common/lib/util/logger.ts b/src/common/lib/util/logger.ts index c2a9f406c2..c3dee7f129 100644 --- a/src/common/lib/util/logger.ts +++ b/src/common/lib/util/logger.ts @@ -45,27 +45,19 @@ const getDefaultLoggers = (): [Function, Function] => { let consoleLogger; let errorLogger; - /* Can't just check for console && console.log; fails in IE <=9 */ - if ( - (typeof Window === 'undefined' && typeof WorkerGlobalScope === 'undefined') /* node */ || - typeof globalObject?.console?.log?.apply === 'function' /* sensible browsers */ - ) { + // we expect ably-js to be run in environments which have `console` object available with its `log` function + if (typeof globalObject?.console?.log === 'function') { consoleLogger = function (...args: unknown[]) { console.log.apply(console, args); }; + errorLogger = console.warn ? function (...args: unknown[]) { console.warn.apply(console, args); } : consoleLogger; - } else if (globalObject?.console.log as unknown) { - /* IE <= 9 with the console open -- console.log does not - * inherit from Function, so has no apply method */ - consoleLogger = errorLogger = function () { - Function.prototype.apply.call(console.log, console, arguments); - }; } else { - /* IE <= 9 when dev tools are closed - window.console not even defined */ + // otherwise we should fallback to noop for log functions consoleLogger = errorLogger = function () {}; } From c49fc760516b312ad935e5790be241f8a774bdd0 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 07:33:55 +0000 Subject: [PATCH 07/38] Removes IE msCrypto from web config --- src/platform/web/config.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/platform/web/config.ts b/src/platform/web/config.ts index 6e6a4b8867..54720764b8 100644 --- a/src/platform/web/config.ts +++ b/src/platform/web/config.ts @@ -4,8 +4,6 @@ import * as Utils from 'common/lib/util/utils'; // Workaround for salesforce lightning locker compat const globalObject = Utils.getGlobalObject(); -declare var msCrypto: typeof crypto; // for IE11 - if (typeof Window === 'undefined' && typeof WorkerGlobalScope === 'undefined') { console.log( "Warning: this distribution of Ably is intended for browsers. On nodejs, please use the 'ably' package on npm" @@ -78,7 +76,7 @@ const Config: IPlatformConfig = { return async function (arr: ArrayBufferView) { crypto.getRandomValues(arr); }; - })(globalObject.crypto || msCrypto), + })(globalObject.crypto), isWebworker: isWebWorkerContext(), }; From 2fb51287afc5f832cf92104a2b32714047e04a09 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 07:38:00 +0000 Subject: [PATCH 08/38] Removes IE8 only `noUpgrade` Platform.Config option --- src/common/types/IPlatformConfig.d.ts | 1 - src/platform/nativescript/config.js | 1 - src/platform/react-native/config.ts | 1 - src/platform/web/config.ts | 1 - src/platform/web/index.ts | 8 -------- src/platform/web/modules.ts | 8 -------- 6 files changed, 20 deletions(-) diff --git a/src/common/types/IPlatformConfig.d.ts b/src/common/types/IPlatformConfig.d.ts index 1517f485f1..9663325a91 100644 --- a/src/common/types/IPlatformConfig.d.ts +++ b/src/common/types/IPlatformConfig.d.ts @@ -27,7 +27,6 @@ export interface ISpecificPlatformConfig { userAgent?: string | null; inherits?: typeof import('util').inherits; currentUrl?: string; - noUpgrade?: boolean | string; fetchSupported?: boolean; xhrSupported?: boolean; allowComet?: boolean; diff --git a/src/platform/nativescript/config.js b/src/platform/nativescript/config.js index 256467d846..ffa52e16c6 100644 --- a/src/platform/nativescript/config.js +++ b/src/platform/nativescript/config.js @@ -20,7 +20,6 @@ if (global.android) { var Config = { agent: 'nativescript', logTimestamps: true, - noUpgrade: false, binaryType: 'arraybuffer', WebSocket: WebSocket, xhrSupported: XMLHttpRequest, diff --git a/src/platform/react-native/config.ts b/src/platform/react-native/config.ts index 038682021c..9ce31030bc 100644 --- a/src/platform/react-native/config.ts +++ b/src/platform/react-native/config.ts @@ -5,7 +5,6 @@ export default function (bufferUtils: typeof BufferUtils): IPlatformConfig { return { agent: 'reactnative', logTimestamps: true, - noUpgrade: false, binaryType: 'arraybuffer', WebSocket: WebSocket, xhrSupported: true, diff --git a/src/platform/web/config.ts b/src/platform/web/config.ts index 54720764b8..4d5f3ef411 100644 --- a/src/platform/web/config.ts +++ b/src/platform/web/config.ts @@ -36,7 +36,6 @@ const Config: IPlatformConfig = { logTimestamps: true, userAgent: userAgent, currentUrl: currentUrl, - noUpgrade: userAgent && !!userAgent.match(/MSIE\s8\.0/), binaryType: 'arraybuffer', WebSocket: globalObject.WebSocket, fetchSupported: !!globalObject.fetch, diff --git a/src/platform/web/index.ts b/src/platform/web/index.ts index a598774244..dcb55cd178 100644 --- a/src/platform/web/index.ts +++ b/src/platform/web/index.ts @@ -50,14 +50,6 @@ if (Platform.Config.agent) { Platform.Defaults.agent += ' ' + Platform.Config.agent; } -/* If using IE8, don't attempt to upgrade from xhr_polling to xhr_streaming - - * while it can do streaming, the low max http-connections-per-host limit means - * that the polling transport is crippled during the upgrade process. So just - * leave it at the base transport */ -if (Platform.Config.noUpgrade) { - Platform.Defaults.upgradeTransports = []; -} - export { DefaultRest as Rest, DefaultRealtime as Realtime, msgpack, protocolMessageFromDeserialized }; export default { diff --git a/src/platform/web/modules.ts b/src/platform/web/modules.ts index 16c8343efb..33a3aa81a8 100644 --- a/src/platform/web/modules.ts +++ b/src/platform/web/modules.ts @@ -35,14 +35,6 @@ if (Platform.Config.agent) { Platform.Defaults.agent += ' ' + Platform.Config.agent; } -/* If using IE8, don't attempt to upgrade from xhr_polling to xhr_streaming - - * while it can do streaming, the low max http-connections-per-host limit means - * that the polling transport is crippled during the upgrade process. So just - * leave it at the base transport */ -if (Platform.Config.noUpgrade) { - Platform.Defaults.upgradeTransports = []; -} - export * from './modules/crypto'; export * from './modules/message'; export * from './modules/presencemessage'; From 5106b006944d06e66adc477f66e158a4752d70f1 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 09:07:28 +0000 Subject: [PATCH 09/38] Make IPlatformConfig.getRandomArrayBuffer non-optional This is in preparation for unifying IPlatformConfig.getRandomValues and IConfig.getRandomArrayBuffer functions into one. `getRandomArrayBuffer` implementation details for each platform: - for `nativescript` - based on nativescript's `getRandomValues` function - for `nodejs` - based on `generateRandom` function from our nodejs crypto code [1] - for `react-native` - was already implemented - for `web` - based on `generateRandom` function from our web crypto code [2]. After fccd4ac950858634ccb7e0120ad5520261be63b8 it is possible to simplify this code by removing `DEFAULT_BLOCKLENGTH_WORDS` and using Uint8Array directly instead of Uint32Array and calculating words [1] https://github.com/ably/ably-js/blob/d0e9fbe4797ebb8520286592ba7b5d82a139eb39/src/platform/nodejs/lib/util/crypto.ts#L32 [2] https://github.com/ably/ably-js/blob/d0e9fbe4797ebb8520286592ba7b5d82a139eb39/src/platform/web/lib/util/crypto.ts#L35 --- src/common/types/IPlatformConfig.d.ts | 2 +- src/platform/nativescript/config.js | 4 ++++ src/platform/nodejs/config.ts | 3 +++ src/platform/react-native/config.ts | 8 ++++++-- src/platform/web/config.ts | 5 +++++ 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/common/types/IPlatformConfig.d.ts b/src/common/types/IPlatformConfig.d.ts index 9663325a91..5b0f1cbeec 100644 --- a/src/common/types/IPlatformConfig.d.ts +++ b/src/common/types/IPlatformConfig.d.ts @@ -14,6 +14,7 @@ export interface ICommonPlatformConfig { nextTick: process.nextTick; inspect: (value: unknown) => string; stringByteSize: Buffer.byteLength; + getRandomArrayBuffer: (byteLength: number) => Promise; } /** @@ -35,7 +36,6 @@ export interface ISpecificPlatformConfig { atob?: typeof atob | null; TextEncoder?: typeof TextEncoder; TextDecoder?: typeof TextDecoder; - getRandomArrayBuffer?: (byteLength: number) => Promise; isWebworker?: boolean; } diff --git a/src/platform/nativescript/config.js b/src/platform/nativescript/config.js index ffa52e16c6..c4da80eee0 100644 --- a/src/platform/nativescript/config.js +++ b/src/platform/nativescript/config.js @@ -50,6 +50,10 @@ var Config = { arr[i] = bytes[i]; } }, + getRandomArrayBuffer: async function (byteLength) { + var bytes = randomBytes(byteLength); + return bytes; + }, }; export default Config; diff --git a/src/platform/nodejs/config.ts b/src/platform/nodejs/config.ts index 27952ff76b..69416efbcc 100644 --- a/src/platform/nodejs/config.ts +++ b/src/platform/nodejs/config.ts @@ -25,6 +25,9 @@ const Config: IPlatformConfig = { dataView.setUint8(i, bytes[i]); } }, + getRandomArrayBuffer: async function (byteLength: number): Promise { + return util.promisify(crypto.randomBytes)(byteLength); + }, }; export default Config; diff --git a/src/platform/react-native/config.ts b/src/platform/react-native/config.ts index 9ce31030bc..7e92eaa59c 100644 --- a/src/platform/react-native/config.ts +++ b/src/platform/react-native/config.ts @@ -1,6 +1,10 @@ import { IPlatformConfig } from '../../common/types/IPlatformConfig'; import BufferUtils from '../web/lib/util/bufferutils'; +type RNRandomBytes = { + randomBytes: (byteLength: number, cb: (err: Error | null, base64String: string | null) => void) => void; +}; + export default function (bufferUtils: typeof BufferUtils): IPlatformConfig { return { agent: 'reactnative', @@ -29,10 +33,10 @@ export default function (bufferUtils: typeof BufferUtils): IPlatformConfig { }, TextEncoder: global.TextEncoder, TextDecoder: global.TextDecoder, - getRandomArrayBuffer: (function (RNRandomBytes) { + getRandomArrayBuffer: (function (RNRandomBytes: RNRandomBytes) { return async function (byteLength: number) { return new Promise((resolve, reject) => { - RNRandomBytes.randomBytes(byteLength, function (err: Error | null, base64String: string | null) { + RNRandomBytes.randomBytes(byteLength, (err, base64String) => { err ? reject(err) : resolve(bufferUtils.toArrayBuffer(bufferUtils.base64Decode(base64String!))); }); }); diff --git a/src/platform/web/config.ts b/src/platform/web/config.ts index 4d5f3ef411..51e7bc662c 100644 --- a/src/platform/web/config.ts +++ b/src/platform/web/config.ts @@ -76,6 +76,11 @@ const Config: IPlatformConfig = { crypto.getRandomValues(arr); }; })(globalObject.crypto), + getRandomArrayBuffer: async function (byteLength: number): Promise { + const byteArray = new Uint8Array(byteLength); + globalObject.crypto.getRandomValues(byteArray); + return byteArray.buffer; + }, isWebworker: isWebWorkerContext(), }; From a7a962033ecfd589e8d37f1f22eea58025f14442 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 09:15:11 +0000 Subject: [PATCH 10/38] Removes fallbacks to `Math.random` in utils and web crypto In #1537 we established browser versions we intend to support in ably-js v2 going forward, and all of them support `Crypto.getRandomValues`, thus there is no need to have fallbacks to `Math.random` anymore. This commit removes such code and changes corresponding places to always call IPlatformConfig.getRandomArrayBuffer instead. Resolves #1332 --- src/common/lib/client/restchannel.ts | 2 +- src/common/lib/util/utils.ts | 20 ++----------- src/platform/web/lib/util/crypto.ts | 43 ++-------------------------- 3 files changed, 7 insertions(+), 58 deletions(-) diff --git a/src/common/lib/client/restchannel.ts b/src/common/lib/client/restchannel.ts index 23c4e9b9d6..be33ac264f 100644 --- a/src/common/lib/client/restchannel.ts +++ b/src/common/lib/client/restchannel.ts @@ -88,7 +88,7 @@ class RestChannel { Utils.mixin(headers, options.headers); if (idempotentRestPublishing && allEmptyIds(messages)) { - const msgIdBase = Utils.randomString(MSG_ID_ENTROPY_BYTES); + const msgIdBase = await Utils.randomString(MSG_ID_ENTROPY_BYTES); Utils.arrForEach(messages, function (message, index) { message.id = msgIdBase + ':' + index.toString(); }); diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index 153dd6a686..ac91a95998 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -399,23 +399,9 @@ export function cheapRandStr(): string { /* Takes param the minimum number of bytes of entropy the string must * include, not the length of the string. String length produced is not * guaranteed. */ -export const randomString = (numBytes: number): string => { - if (Platform.Config.getRandomValues && typeof Uint8Array !== 'undefined') { - const uIntArr = new Uint8Array(numBytes); - (Platform.Config.getRandomValues as Function)(uIntArr); - return Platform.BufferUtils.base64Encode(uIntArr); - } - /* No secure random generator available; fall back to Math.random. - * TODO we should no longer end up in this scenario — and hence should be able to remove this code — given that all supported platforms should now have a random generator — see https://github.com/ably/ably-js/issues/1332 - */ - const charset = Platform.BufferUtils.base64CharSet; - /* base64 has 33% overhead; round length up */ - const length = Math.round((numBytes * 4) / 3); - let result = ''; - for (let i = 0; i < length; i++) { - result += charset[randomPosn(charset)]; - } - return result; +export const randomString = async (numBytes: number): Promise => { + const buffer = await Platform.Config.getRandomArrayBuffer(numBytes); + return Platform.BufferUtils.base64Encode(buffer); }; /* Pick n elements at random without replacement from an array */ diff --git a/src/platform/web/lib/util/crypto.ts b/src/platform/web/lib/util/crypto.ts index c54c565a3d..f4fa628292 100644 --- a/src/platform/web/lib/util/crypto.ts +++ b/src/platform/web/lib/util/crypto.ts @@ -21,40 +21,6 @@ var createCryptoClass = function (config: IPlatformConfig, bufferUtils: typeof B var DEFAULT_KEYLENGTH = 256; // bits var DEFAULT_MODE = 'cbc'; var DEFAULT_BLOCKLENGTH = 16; // bytes - var DEFAULT_BLOCKLENGTH_WORDS = 4; // 32-bit words - var UINT32_SUP = 0x100000000; - - /** - * Internal: generate an array of secure random data corresponding to the given length of bytes - * @param bytes - */ - var generateRandom: (byteLength: number) => Promise; - if (config.getRandomArrayBuffer) { - generateRandom = config.getRandomArrayBuffer; - } else if (typeof Uint32Array !== 'undefined' && config.getRandomValues) { - generateRandom = async function (bytes) { - var blockRandomArray = new Uint32Array(DEFAULT_BLOCKLENGTH_WORDS); - var words = bytes / 4, - nativeArray = words == DEFAULT_BLOCKLENGTH_WORDS ? blockRandomArray : new Uint32Array(words); - await config.getRandomValues!(nativeArray); - return bufferUtils.toArrayBuffer(nativeArray); - }; - } else { - generateRandom = async function (bytes) { - Logger.logAction( - Logger.LOG_MAJOR, - 'Ably.Crypto.generateRandom()', - 'Warning: the browser you are using does not support secure cryptographically secure randomness generation; falling back to insecure Math.random()' - ); - var words = bytes / 4, - array = new Uint32Array(words); - for (var i = 0; i < words; i++) { - array[i] = Math.floor(Math.random() * UINT32_SUP); - } - - return bufferUtils.toArrayBuffer(array); - }; - } /** * Internal: checks that the cipherParams are a valid combination. Currently @@ -117,10 +83,7 @@ var createCryptoClass = function (config: IPlatformConfig, bufferUtils: typeof B * classes and interfaces here. *- * Secure random data for creation of Initialization Vectors (IVs) and keys - * is obtained from window.crypto.getRandomValues if available, or from - * Math.random() if not. Clients who do not want to depend on Math.random() - * should polyfill window.crypto.getRandomValues with a library that seeds - * a PRNG with real entropy. + * is obtained from window.crypto.getRandomValues. * * Each message payload is encrypted with an IV in CBC mode, and the IV is * concatenated with the resulting raw ciphertext to construct the "ciphertext" @@ -178,7 +141,7 @@ var createCryptoClass = function (config: IPlatformConfig, bufferUtils: typeof B */ static async generateRandomKey(keyLength?: number): Promise { try { - return await generateRandom((keyLength || DEFAULT_KEYLENGTH) / 8); + return config.getRandomArrayBuffer((keyLength || DEFAULT_KEYLENGTH) / 8); } catch (err) { throw new ErrorInfo('Failed to generate random key: ' + (err as Error).message, 400, 50000, err as Error); } @@ -271,7 +234,7 @@ var createCryptoClass = function (config: IPlatformConfig, bufferUtils: typeof B return iv; } - const randomBlock = await generateRandom(DEFAULT_BLOCKLENGTH); + const randomBlock = await config.getRandomArrayBuffer(DEFAULT_BLOCKLENGTH); return bufferUtils.toArrayBuffer(randomBlock); } } From 59ce70a001dc0886453bf253ad4f94cc44c52668 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 09:20:11 +0000 Subject: [PATCH 11/38] Removes IPlatformConfig.getRandomValues function in favour of getRandomArrayBuffer --- src/common/types/IPlatformConfig.d.ts | 1 - src/platform/nativescript/config.js | 6 ------ src/platform/nodejs/config.ts | 8 -------- src/platform/web/config.ts | 8 -------- 4 files changed, 23 deletions(-) diff --git a/src/common/types/IPlatformConfig.d.ts b/src/common/types/IPlatformConfig.d.ts index 5b0f1cbeec..65b757b7dc 100644 --- a/src/common/types/IPlatformConfig.d.ts +++ b/src/common/types/IPlatformConfig.d.ts @@ -24,7 +24,6 @@ export interface ICommonPlatformConfig { */ export interface ISpecificPlatformConfig { addEventListener?: typeof window.addEventListener | typeof global.addEventListener | null; - getRandomValues?: (arr: ArrayBufferView) => Promise; userAgent?: string | null; inherits?: typeof import('util').inherits; currentUrl?: string; diff --git a/src/platform/nativescript/config.js b/src/platform/nativescript/config.js index c4da80eee0..842b8af527 100644 --- a/src/platform/nativescript/config.js +++ b/src/platform/nativescript/config.js @@ -44,12 +44,6 @@ var Config = { }, TextEncoder: global.TextEncoder, TextDecoder: global.TextDecoder, - getRandomValues: async function (arr) { - var bytes = randomBytes(arr.length); - for (var i = 0; i < arr.length; i++) { - arr[i] = bytes[i]; - } - }, getRandomArrayBuffer: async function (byteLength) { var bytes = randomBytes(byteLength); return bytes; diff --git a/src/platform/nodejs/config.ts b/src/platform/nodejs/config.ts index 69416efbcc..fc116ce086 100644 --- a/src/platform/nodejs/config.ts +++ b/src/platform/nodejs/config.ts @@ -17,14 +17,6 @@ const Config: IPlatformConfig = { stringByteSize: Buffer.byteLength, inherits: util.inherits, addEventListener: null, - getRandomValues: async function (arr: ArrayBufferView): Promise { - const bytes = crypto.randomBytes(arr.byteLength); - const dataView = new DataView(arr.buffer, arr.byteOffset, arr.byteLength); - - for (let i = 0; i < bytes.length; i++) { - dataView.setUint8(i, bytes[i]); - } - }, getRandomArrayBuffer: async function (byteLength: number): Promise { return util.promisify(crypto.randomBytes)(byteLength); }, diff --git a/src/platform/web/config.ts b/src/platform/web/config.ts index 51e7bc662c..977ae102c0 100644 --- a/src/platform/web/config.ts +++ b/src/platform/web/config.ts @@ -68,14 +68,6 @@ const Config: IPlatformConfig = { }, TextEncoder: globalObject.TextEncoder, TextDecoder: globalObject.TextDecoder, - getRandomValues: (function (crypto) { - if (crypto === undefined) { - return undefined; - } - return async function (arr: ArrayBufferView) { - crypto.getRandomValues(arr); - }; - })(globalObject.crypto), getRandomArrayBuffer: async function (byteLength: number): Promise { const byteArray = new Uint8Array(byteLength); globalObject.crypto.getRandomValues(byteArray); From 103f8efc64b6405617ea63c7f89f446480a5b19c Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 09:20:26 +0000 Subject: [PATCH 12/38] Fix comment --- src/platform/web/lib/util/crypto.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/web/lib/util/crypto.ts b/src/platform/web/lib/util/crypto.ts index f4fa628292..a324f3557b 100644 --- a/src/platform/web/lib/util/crypto.ts +++ b/src/platform/web/lib/util/crypto.ts @@ -81,7 +81,7 @@ var createCryptoClass = function (config: IPlatformConfig, bufferUtils: typeof B * but supporting other keylengths. Other algorithms and chaining modes are * not supported directly, but supportable by extending/implementing the base * classes and interfaces here. - *- + * * Secure random data for creation of Initialization Vectors (IVs) and keys * is obtained from window.crypto.getRandomValues. * From 07601b5ece84c0d3445d59a242fc65f874474d4a Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 09:38:22 +0000 Subject: [PATCH 13/38] Removes unnecessary hasOwnProperty is nullish check --- src/common/lib/util/utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index ac91a95998..9b5063e62a 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -22,9 +22,9 @@ export function mixin( if (!source) { break; } - const hasOwnProperty = Object.prototype.hasOwnProperty; + for (const key in source) { - if (!hasOwnProperty || hasOwnProperty.call(source, key)) { + if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = (source as Record)[key]; } } From ad0857e02a5b3bc2f16956971f09bdba27162cfa Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 09:42:59 +0000 Subject: [PATCH 14/38] Improves comments in utils --- src/common/lib/util/utils.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index 9b5063e62a..daef5703fe 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -7,11 +7,12 @@ function randomPosn(arrOrStr: Array | string) { return Math.floor(Math.random() * arrOrStr.length); } -/* +/** * Add a set of properties to a target object - * target: the target object - * props: an object whose enumerable properties are - * added, by reference only + * + * @param target the target object + * @param args objects, which enumerable properties are added to target, by reference only + * @returns target object with added properties */ export function mixin( target: Record, @@ -32,11 +33,11 @@ export function mixin( return target; } -/* - * Add a set of properties to a target object - * target: the target object - * props: an object whose enumerable properties are - * added, by reference only +/** + * Creates a copy of enumerable properties of the source object + * + * @param src object to copy + * @returns copy of src */ export function copy>(src: T | Record | null | undefined): T { return mixin({}, src as Record) as T; From b88ec14354731cc62875920ada280d220301f7e1 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 09:45:44 +0000 Subject: [PATCH 15/38] Remove polyfill for Array.isArray in utils --- src/common/lib/util/utils.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index daef5703fe..43200f6362 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -47,11 +47,7 @@ export function copy>(src: T | Record { - return Object.prototype.toString.call(value) == '[object Array]'; - }; +export const isArray = Array.isArray; /* * Ensures that an Array object is always returned From 397523baa8739089239930b2f4f17fe795010343 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 09:49:30 +0000 Subject: [PATCH 16/38] Remove Utils.isArray function in favour of Array.isArray --- src/common/lib/client/auth.ts | 2 +- src/common/lib/client/realtimechannel.ts | 6 +++--- src/common/lib/client/rest.ts | 2 +- src/common/lib/client/restchannel.ts | 2 +- src/common/lib/types/devicedetails.ts | 2 +- src/common/lib/types/message.ts | 2 +- src/common/lib/types/pushchannelsubscription.ts | 2 +- src/common/lib/util/eventemitter.ts | 10 +++++----- src/common/lib/util/utils.ts | 10 ++-------- .../nodejs/lib/transport/nodecomettransport.js | 2 +- src/platform/web/lib/http/request/xhrrequest.ts | 2 +- test/rest/push.test.js | 6 +++--- test/rest/request.test.js | 2 +- 13 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/common/lib/client/auth.ts b/src/common/lib/client/auth.ts index b0d819921c..806930e822 100644 --- a/src/common/lib/client/auth.ts +++ b/src/common/lib/client/auth.ts @@ -441,7 +441,7 @@ class Auth { ); } else { const contentTypeHeaderOrHeaders = result.headers!['content-type'] ?? null; - if (Utils.isArray(contentTypeHeaderOrHeaders)) { + if (Array.isArray(contentTypeHeaderOrHeaders)) { // Combine multiple header values into a comma-separated list per https://datatracker.ietf.org/doc/html/rfc9110#section-5.2; see https://github.com/ably/ably-js/issues/1616 for doing this consistently across the codebase. contentType = contentTypeHeaderOrHeaders.join(', '); } else { diff --git a/src/common/lib/client/realtimechannel.ts b/src/common/lib/client/realtimechannel.ts index 5306ff15e5..c53290a229 100644 --- a/src/common/lib/client/realtimechannel.ts +++ b/src/common/lib/client/realtimechannel.ts @@ -45,7 +45,7 @@ function validateChannelOptions(options?: API.ChannelOptions) { return new ErrorInfo('options.params must be an object', 40000, 400); } if (options && 'modes' in options) { - if (!Utils.isArray(options.modes)) { + if (!Array.isArray(options.modes)) { return new ErrorInfo('options.modes must be an array', 40000, 400); } for (let i = 0; i < options.modes.length; i++) { @@ -222,7 +222,7 @@ class RealtimeChannel extends EventEmitter { } if (argCount == 1) { if (Utils.isObject(messages)) messages = [messageFromValues(messages)]; - else if (Utils.isArray(messages)) messages = messagesFromValuesArray(messages); + else if (Array.isArray(messages)) messages = messagesFromValuesArray(messages); else throw new ErrorInfo( 'The single-argument form of publish() expects a message object or an array of message objects', @@ -467,7 +467,7 @@ class RealtimeChannel extends EventEmitter { const msg = protocolMessageFromValues({ action: actions.PRESENCE, channel: this.name, - presence: Utils.isArray(presence) + presence: Array.isArray(presence) ? this.client._RealtimePresence!.presenceMessagesFromValuesArray(presence) : [this.client._RealtimePresence!.presenceMessageFromValues(presence)], }); diff --git a/src/common/lib/client/rest.ts b/src/common/lib/client/rest.ts index b8ab1d66d5..516cb0a51a 100644 --- a/src/common/lib/client/rest.ts +++ b/src/common/lib/client/rest.ts @@ -154,7 +154,7 @@ export class Rest { ): Promise { let requestBodyDTO: BatchPublishSpec[]; let singleSpecMode: boolean; - if (Utils.isArray(specOrSpecs)) { + if (Array.isArray(specOrSpecs)) { requestBodyDTO = specOrSpecs; singleSpecMode = false; } else { diff --git a/src/common/lib/client/restchannel.ts b/src/common/lib/client/restchannel.ts index be33ac264f..dbbf8725fb 100644 --- a/src/common/lib/client/restchannel.ts +++ b/src/common/lib/client/restchannel.ts @@ -63,7 +63,7 @@ class RestChannel { } else if (Utils.isObject(first)) { messages = [messageFromValues(first)]; params = args[1]; - } else if (Utils.isArray(first)) { + } else if (Array.isArray(first)) { messages = messagesFromValuesArray(first); params = args[1]; } else { diff --git a/src/common/lib/types/devicedetails.ts b/src/common/lib/types/devicedetails.ts index 4b93cac560..6027a089d9 100644 --- a/src/common/lib/types/devicedetails.ts +++ b/src/common/lib/types/devicedetails.ts @@ -84,7 +84,7 @@ class DeviceDetails { body = Utils.decodeBody(body, MsgPack, format); } - if (Utils.isArray(body)) { + if (Array.isArray(body)) { return DeviceDetails.fromValuesArray(body); } else { return DeviceDetails.fromValues(body); diff --git a/src/common/lib/types/message.ts b/src/common/lib/types/message.ts index 837ab7c0fd..e52a40a38e 100644 --- a/src/common/lib/types/message.ts +++ b/src/common/lib/types/message.ts @@ -123,7 +123,7 @@ export async function encode(msg: T, option typeof data == 'string' || Platform.BufferUtils.isBuffer(data) || data === null || data === undefined; if (!nativeDataType) { - if (Utils.isObject(data) || Utils.isArray(data)) { + if (Utils.isObject(data) || Array.isArray(data)) { msg.data = JSON.stringify(data); msg.encoding = msg.encoding ? msg.encoding + '/json' : 'json'; } else { diff --git a/src/common/lib/types/pushchannelsubscription.ts b/src/common/lib/types/pushchannelsubscription.ts index 48190f25af..8a9d90ff1c 100644 --- a/src/common/lib/types/pushchannelsubscription.ts +++ b/src/common/lib/types/pushchannelsubscription.ts @@ -44,7 +44,7 @@ class PushChannelSubscription { body = Utils.decodeBody(body, MsgPack, format) as Record; } - if (Utils.isArray(body)) { + if (Array.isArray(body)) { return PushChannelSubscription.fromValuesArray(body); } else { return PushChannelSubscription.fromValues(body); diff --git a/src/common/lib/util/eventemitter.ts b/src/common/lib/util/eventemitter.ts index 4044343b31..b1a3ece94c 100644 --- a/src/common/lib/util/eventemitter.ts +++ b/src/common/lib/util/eventemitter.ts @@ -32,7 +32,7 @@ function removeListener(targetListeners: any, listener: Function, eventFilter?: listeners = listeners[eventFilter] as Record; } - if (Utils.isArray(listeners)) { + if (Array.isArray(listeners)) { while ((index = Utils.arrIndexOf(listeners, listener)) !== -1) { listeners.splice(index, 1); } @@ -44,7 +44,7 @@ function removeListener(targetListeners: any, listener: Function, eventFilter?: } else if (Utils.isObject(listeners)) { /* events */ for (eventName in listeners) { - if (Object.prototype.hasOwnProperty.call(listeners, eventName) && Utils.isArray(listeners[eventName])) { + if (Object.prototype.hasOwnProperty.call(listeners, eventName) && Array.isArray(listeners[eventName])) { removeListener([listeners], listener, eventName); } } @@ -94,7 +94,7 @@ class EventEmitter { } if (Utils.isEmptyArg(event)) { this.any.push(listener); - } else if (Utils.isArray(event)) { + } else if (Array.isArray(event)) { event.forEach((eventName) => { this.on(eventName, listener); }); @@ -156,7 +156,7 @@ class EventEmitter { return; } - if (Utils.isArray(event)) { + if (Array.isArray(event)) { event.forEach((eventName) => { this.off(eventName, listener); }); @@ -256,7 +256,7 @@ class EventEmitter { throw new Error('EventEmitter.once(): Invalid arguments:' + Platform.Config.inspect(args)); } this.anyOnce.push(secondArg); - } else if (Utils.isArray(firstArg)) { + } else if (Array.isArray(firstArg)) { const self = this; const listenerWrapper = function (this: any) { const innerArgs = Array.prototype.slice.call(arguments); diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index 43200f6362..2d55efd561 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -43,12 +43,6 @@ export function copy>(src: T | Record) as T; } -/* - * Determine whether or not a given object is - * an array. - */ -export const isArray = Array.isArray; - /* * Ensures that an Array object is always returned * returning the original Array of obj is an Array @@ -58,7 +52,7 @@ export function ensureArray(obj: Record): unknown[] { if (isEmptyArg(obj)) { return []; } - if (isArray(obj)) { + if (Array.isArray(obj)) { return obj; } return [obj]; @@ -154,7 +148,7 @@ export function containsValue(ob: Record, val: unknown): boolea } export function intersect(arr: Array, ob: K[] | Partial>): K[] { - return isArray(ob) ? arrIntersect(arr, ob) : arrIntersectOb(arr, ob); + return Array.isArray(ob) ? arrIntersect(arr, ob) : arrIntersectOb(arr, ob); } export function arrIntersect(arr1: Array, arr2: Array): Array { diff --git a/src/platform/nodejs/lib/transport/nodecomettransport.js b/src/platform/nodejs/lib/transport/nodecomettransport.js index 9a1c29411d..83236045a4 100644 --- a/src/platform/nodejs/lib/transport/nodecomettransport.js +++ b/src/platform/nodejs/lib/transport/nodecomettransport.js @@ -265,7 +265,7 @@ var NodeCometTransport = function (transportStorage) { * is contains an error action (hence the nonsuccess statuscode), we can * consider the request to have succeeded, just pass it on to * onProtocolMessage to decide what to do */ - if (statusCode < 400 || Utils.isArray(body)) { + if (statusCode < 400 || Array.isArray(body)) { self.complete(null, body); return; } diff --git a/src/platform/web/lib/http/request/xhrrequest.ts b/src/platform/web/lib/http/request/xhrrequest.ts index d4f2aaa85d..dd219938c1 100644 --- a/src/platform/web/lib/http/request/xhrrequest.ts +++ b/src/platform/web/lib/http/request/xhrrequest.ts @@ -255,7 +255,7 @@ class XHRRequest extends EventEmitter implements IXHRRequest { * is contains an error action (hence the nonsuccess statuscode), we can * consider the request to have succeeded, just pass it on to * onProtocolMessage to decide what to do */ - if (successResponse || Utils.isArray(parsedResponse)) { + if (successResponse || Array.isArray(parsedResponse)) { this.complete(null, parsedResponse, headers, unpacked, statusCode); return; } diff --git a/test/rest/push.test.js b/test/rest/push.test.js index 9d251ffe68..926d534ef5 100644 --- a/test/rest/push.test.js +++ b/test/rest/push.test.js @@ -315,8 +315,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async * includesUnordered(x, y) -> string | true */ function includesUnordered(x, y) { - if (Utils.isArray(x)) { - if (!Utils.isArray(y)) { + if (Array.isArray(x)) { + if (!Array.isArray(y)) { return 'not both arrays'; } @@ -351,7 +351,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async return true; } else if (x instanceof Object) { - if (!(x instanceof Object) || Utils.isArray(y)) { + if (!(x instanceof Object) || Array.isArray(y)) { return 'not both objects'; } diff --git a/test/rest/request.test.js b/test/rest/request.test.js index 7aa04f9db9..0af1d35335 100644 --- a/test/rest/request.test.js +++ b/test/rest/request.test.js @@ -45,7 +45,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async const res = await rest.request('get', '/time', Defaults.protocolVersion, null, null, null); expect(res.statusCode).to.equal(200, 'Check statusCode'); expect(res.success).to.equal(true, 'Check success'); - expect(utils.isArray(res.items), true, 'Check array returned').to.be.ok; + expect(Array.isArray(res.items), true, 'Check array returned').to.be.ok; expect(res.items.length).to.equal(1, 'Check array was of length 1'); }); From 37fe7381af2f9c15b0b13ec99d720cc5a1bf836a Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 09:58:49 +0000 Subject: [PATCH 17/38] Change Utils.isEmptyArg to Utils.isNil --- src/common/lib/util/eventemitter.ts | 8 ++++---- src/common/lib/util/utils.ts | 16 ++++++---------- .../web/lib/http/request/fetchrequest.ts | 2 +- src/platform/web/lib/http/request/xhrrequest.ts | 2 +- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/common/lib/util/eventemitter.ts b/src/common/lib/util/eventemitter.ts index b1a3ece94c..2aaa89a54e 100644 --- a/src/common/lib/util/eventemitter.ts +++ b/src/common/lib/util/eventemitter.ts @@ -92,7 +92,7 @@ class EventEmitter { if (typeof listener !== 'function') { throw new Error('EventListener.on(): Invalid arguments: ' + Platform.Config.inspect(args)); } - if (Utils.isEmptyArg(event)) { + if (Utils.isNil(event)) { this.any.push(listener); } else if (Array.isArray(event)) { event.forEach((eventName) => { @@ -126,7 +126,7 @@ class EventEmitter { off(event: string | string[] | null, listener?: Function | null): void; off(...args: unknown[]) { - if (args.length == 0 || (Utils.isEmptyArg(args[0]) && Utils.isEmptyArg(args[1]))) { + if (args.length == 0 || (Utils.isNil(args[0]) && Utils.isNil(args[1]))) { this.any = []; this.events = Object.create(null); this.anyOnce = []; @@ -151,7 +151,7 @@ class EventEmitter { [event, listener] = [firstArg, secondArg]; } - if (listener && Utils.isEmptyArg(event)) { + if (listener && Utils.isNil(event)) { removeListener([this.any, this.events, this.anyOnce, this.eventsOnce], listener); return; } @@ -251,7 +251,7 @@ class EventEmitter { const [firstArg, secondArg] = args; if (args.length === 1 && typeof firstArg === 'function') { this.anyOnce.push(firstArg); - } else if (Utils.isEmptyArg(firstArg)) { + } else if (Utils.isNil(firstArg)) { if (typeof secondArg !== 'function') { throw new Error('EventEmitter.once(): Invalid arguments:' + Platform.Config.inspect(args)); } diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index 2d55efd561..c31d903f9f 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -49,7 +49,7 @@ export function copy>(src: T | Record): unknown[] { - if (isEmptyArg(obj)) { + if (isNil(obj)) { return []; } if (Array.isArray(obj)) { @@ -72,16 +72,12 @@ export function isEmpty(ob: Record | unknown[]): boolean { return true; } -/* - * Determine whether or not an argument to an overloaded function is - * undefined (missing) or null. - * This method is useful when constructing functions such as (WebIDL terminology): - * off([TreatUndefinedAs=Null] DOMString? event) - * as you can then confirm the argument using: - * Utils.isEmptyArg(event) +/** + * Checks if `value` is `null` or `undefined`. + * + * Source: https://github.com/lodash/lodash/blob/main/src/isNil.ts */ - -export function isEmptyArg(arg: unknown): arg is null | undefined { +export function isNil(arg: unknown): arg is null | undefined { return arg === null || arg === undefined; } diff --git a/src/platform/web/lib/http/request/fetchrequest.ts b/src/platform/web/lib/http/request/fetchrequest.ts index 22cee07069..5ab1924e0f 100644 --- a/src/platform/web/lib/http/request/fetchrequest.ts +++ b/src/platform/web/lib/http/request/fetchrequest.ts @@ -35,7 +35,7 @@ export default async function fetchRequest( body: RequestBody | null ): Promise { const fetchHeaders = new Headers(headers || {}); - const _method = method ? method.toUpperCase() : Utils.isEmptyArg(body) ? 'GET' : 'POST'; + const _method = method ? method.toUpperCase() : Utils.isNil(body) ? 'GET' : 'POST'; const controller = new AbortController(); diff --git a/src/platform/web/lib/http/request/xhrrequest.ts b/src/platform/web/lib/http/request/xhrrequest.ts index dd219938c1..b6774a9663 100644 --- a/src/platform/web/lib/http/request/xhrrequest.ts +++ b/src/platform/web/lib/http/request/xhrrequest.ts @@ -77,7 +77,7 @@ class XHRRequest extends EventEmitter implements IXHRRequest { this.uri = uri + Utils.toQueryString(params); this.headers = headers || {}; this.body = body; - this.method = method ? method.toUpperCase() : Utils.isEmptyArg(body) ? 'GET' : 'POST'; + this.method = method ? method.toUpperCase() : Utils.isNil(body) ? 'GET' : 'POST'; this.requestMode = requestMode; this.timeouts = timeouts; this.timedOut = false; From d9ec0af1f11c787745aeb966d679d0b4cc772ac0 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 09:59:23 +0000 Subject: [PATCH 18/38] Change Utils.isNil to shorter check --- src/common/lib/util/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index c31d903f9f..a772ea3735 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -78,7 +78,7 @@ export function isEmpty(ob: Record | unknown[]): boolean { * Source: https://github.com/lodash/lodash/blob/main/src/isNil.ts */ export function isNil(arg: unknown): arg is null | undefined { - return arg === null || arg === undefined; + return arg == null; } /* From fc9698e53f205f8179d7178f2ac9c8d3dbd98a0f Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:08:32 +0000 Subject: [PATCH 19/38] Remove polyfill for Array.prototype.indexOf in Utils --- src/common/lib/util/utils.ts | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index a772ea3735..462fc48eca 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -174,20 +174,9 @@ export function arrSubtract(arr1: Array, arr2: Array): Array { return result; } -export const arrIndexOf = (Array.prototype.indexOf as unknown) - ? function (arr: Array, elem: unknown, fromIndex?: number) { - return arr.indexOf(elem, fromIndex); - } - : function (arr: Array, elem: unknown, fromIndex?: number) { - fromIndex = fromIndex || 0; - const len = arr.length; - for (; fromIndex < len; fromIndex++) { - if (arr[fromIndex] === elem) { - return fromIndex; - } - } - return -1; - }; +export const arrIndexOf = function (arr: Array, elem: unknown, fromIndex?: number) { + return arr.indexOf(elem, fromIndex); +}; export function arrIn(arr: Array, val: unknown): boolean { return arrIndexOf(arr, val) !== -1; From 1836bdd03e66b4eaf4f59d15b059d384887dd1fa Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:12:36 +0000 Subject: [PATCH 20/38] Change Transport.shortName type to TransportName from string --- src/common/lib/transport/transport.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/common/lib/transport/transport.ts b/src/common/lib/transport/transport.ts index a18bfcb830..adb8a6f0e6 100644 --- a/src/common/lib/transport/transport.ts +++ b/src/common/lib/transport/transport.ts @@ -12,6 +12,7 @@ import Auth from '../client/auth'; import * as API from '../../../../ably'; import ConnectionManager, { TransportParams } from './connectionmanager'; import Platform from 'common/platform'; +import TransportName from '../../constants/TransportName'; export type TryConnectCallback = ( wrappedErr: { error: ErrorInfo; event: string } | null, @@ -72,7 +73,7 @@ abstract class Transport extends EventEmitter { this.lastActivity = null; } - abstract shortName: string; + abstract shortName: TransportName; abstract send(message: ProtocolMessage): void; connect(): void {} From bc4a49499e4231fabda0d38b763ddd9c150059ef Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:19:18 +0000 Subject: [PATCH 21/38] Remove Utils.arrIndexOf in favour of native Array.prototype.indexOf --- src/common/lib/transport/connectionmanager.ts | 8 ++++---- src/common/lib/util/eventemitter.ts | 2 +- src/common/lib/util/utils.ts | 12 ++++-------- test/realtime/event_emitter.test.js | 4 ++-- test/realtime/message.test.js | 2 +- 5 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/common/lib/transport/connectionmanager.ts b/src/common/lib/transport/connectionmanager.ts index 5d6b357d6f..9f6d361f13 100644 --- a/src/common/lib/transport/connectionmanager.ts +++ b/src/common/lib/transport/connectionmanager.ts @@ -44,8 +44,8 @@ function clearSessionRecoverData() { function betterTransportThan(a: Transport, b: Transport) { return ( - Utils.arrIndexOf(Platform.Defaults.transportPreferenceOrder, a.shortName) > - Utils.arrIndexOf(Platform.Defaults.transportPreferenceOrder, b.shortName) + Platform.Defaults.transportPreferenceOrder.indexOf(a.shortName) > + Platform.Defaults.transportPreferenceOrder.indexOf(b.shortName) ); } @@ -1695,7 +1695,7 @@ class ConnectionManager extends EventEmitter { * transport in upgradeTransports (if it's in there - if not, currentSerial * will be -1, so return upgradeTransports.slice(0) == upgradeTransports */ const current = (this.activeProtocol as Protocol).getTransport().shortName; - const currentSerial = Utils.arrIndexOf(this.upgradeTransports, current); + const currentSerial = this.upgradeTransports.indexOf(current); return this.upgradeTransports.slice(currentSerial + 1); } @@ -2036,7 +2036,7 @@ class ConnectionManager extends EventEmitter { // Message came in on a defunct transport. Allow only acks, nacks, & errors for outstanding // messages, no new messages (as sync has been sent on new transport so new messages will // be resent there, or connection has been closed so don't want new messages) - if (Utils.arrIndexOf([actions.ACK, actions.NACK, actions.ERROR], message.action) > -1) { + if ([actions.ACK, actions.NACK, actions.ERROR].includes(message.action!)) { await this.realtime.channels.processChannelMessage(message); } else { Logger.logAction( diff --git a/src/common/lib/util/eventemitter.ts b/src/common/lib/util/eventemitter.ts index 2aaa89a54e..f86ead2bc4 100644 --- a/src/common/lib/util/eventemitter.ts +++ b/src/common/lib/util/eventemitter.ts @@ -33,7 +33,7 @@ function removeListener(targetListeners: any, listener: Function, eventFilter?: } if (Array.isArray(listeners)) { - while ((index = Utils.arrIndexOf(listeners, listener)) !== -1) { + while ((index = listeners.indexOf(listener)) !== -1) { listeners.splice(index, 1); } /* If events object has an event name key with no listeners then diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index 462fc48eca..0da1943405 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -151,7 +151,7 @@ export function arrIntersect(arr1: Array, arr2: Array): Array { const result = []; for (let i = 0; i < arr1.length; i++) { const member = arr1[i]; - if (arrIndexOf(arr2, member) != -1) result.push(member); + if (arr2.indexOf(member) != -1) result.push(member); } return result; } @@ -169,21 +169,17 @@ export function arrSubtract(arr1: Array, arr2: Array): Array { const result = []; for (let i = 0; i < arr1.length; i++) { const element = arr1[i]; - if (arrIndexOf(arr2, element) == -1) result.push(element); + if (arr2.indexOf(element) == -1) result.push(element); } return result; } -export const arrIndexOf = function (arr: Array, elem: unknown, fromIndex?: number) { - return arr.indexOf(elem, fromIndex); -}; - export function arrIn(arr: Array, val: unknown): boolean { - return arrIndexOf(arr, val) !== -1; + return arr.indexOf(val) !== -1; } export function arrDeleteValue(arr: Array, val: T): boolean { - const idx = arrIndexOf(arr, val); + const idx = arr.indexOf(val); const res = idx != -1; if (res) arr.splice(idx, 1); return res; diff --git a/test/realtime/event_emitter.test.js b/test/realtime/event_emitter.test.js index 1fac46d249..3c4d9be3ce 100644 --- a/test/realtime/event_emitter.test.js +++ b/test/realtime/event_emitter.test.js @@ -33,7 +33,7 @@ define(['shared_helper', 'chai'], function (helper, chai) { expectedConnectionEvents = ['connecting', 'connected', 'closing', 'closed'], expectedChannelEvents = ['attaching', 'attached', 'detaching', 'detached']; realtime.connection.on(function () { - if ((index = utils.arrIndexOf(expectedConnectionEvents, this.event)) > -1) { + if ((index = expectedConnectionEvents.indexOf(this.event)) > -1) { delete expectedConnectionEvents[index]; if (this.event == 'closed') { done(); @@ -45,7 +45,7 @@ define(['shared_helper', 'chai'], function (helper, chai) { realtime.connection.on('connected', function () { var channel = realtime.channels.get('channel'); channel.on(function () { - if ((index = utils.arrIndexOf(expectedChannelEvents, this.event)) > -1) { + if ((index = expectedChannelEvents.indexOf(this.event)) > -1) { delete expectedChannelEvents[index]; switch (this.event) { case 'detached': diff --git a/test/realtime/message.test.js b/test/realtime/message.test.js index f80d4e1e8e..4905870b70 100644 --- a/test/realtime/message.test.js +++ b/test/realtime/message.test.js @@ -572,7 +572,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async /* subscribe to event */ recvchannel.subscribe('event0', function (msg) { try { - expect(-1).to.not.equal(utils.arrIndexOf(messagesSent, msg.data), 'Received unexpected message text'); + expect(-1).to.not.equal(messagesSent.indexOf(msg.data), 'Received unexpected message text'); } catch (err) { closeAndFinish(done, realtime, err); return; From e5961ead813a6435988679f22911ec232b41ef9e Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:22:21 +0000 Subject: [PATCH 22/38] Remove Utils.arrIn in favour of native Array.prototype.includes --- src/common/lib/client/baserealtime.ts | 2 +- src/common/lib/client/realtimechannel.ts | 4 ++-- src/common/lib/client/rest.ts | 4 ++-- src/common/lib/transport/comettransport.ts | 2 +- src/common/lib/transport/connectionmanager.ts | 8 ++++---- src/common/lib/util/utils.ts | 4 ---- src/platform/web/lib/http/request/xhrrequest.ts | 2 +- 7 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/common/lib/client/baserealtime.ts b/src/common/lib/client/baserealtime.ts index 2b4acacf80..237f08a1e7 100644 --- a/src/common/lib/client/baserealtime.ts +++ b/src/common/lib/client/baserealtime.ts @@ -154,7 +154,7 @@ class Channels extends EventEmitter { for (const channelId in this.all) { const channel = this.all[channelId]; - if (Utils.arrIn(fromChannelStates, channel.state)) { + if (fromChannelStates.includes(channel.state)) { channel.notifyState(toChannelState, reason); } } diff --git a/src/common/lib/client/realtimechannel.ts b/src/common/lib/client/realtimechannel.ts index c53290a229..87decff1b6 100644 --- a/src/common/lib/client/realtimechannel.ts +++ b/src/common/lib/client/realtimechannel.ts @@ -53,7 +53,7 @@ function validateChannelOptions(options?: API.ChannelOptions) { if ( !currentMode || typeof currentMode !== 'string' || - !Utils.arrIn(channelModes, String.prototype.toUpperCase.call(currentMode)) + !channelModes.includes(String.prototype.toUpperCase.call(currentMode)) ) { return new ErrorInfo('Invalid channel mode: ' + currentMode, 40000, 400); } @@ -696,7 +696,7 @@ class RealtimeChannel extends EventEmitter { this.clearStateTimer(); // RTP5a1 - if (Utils.arrIn(['detached', 'suspended', 'failed'], state)) { + if (['detached', 'suspended', 'failed'].includes(state)) { this.properties.channelSerial = null; } diff --git a/src/common/lib/client/rest.ts b/src/common/lib/client/rest.ts index 516cb0a51a..b0040c57dd 100644 --- a/src/common/lib/client/rest.ts +++ b/src/common/lib/client/rest.ts @@ -134,11 +134,11 @@ export class Rest { /* useHttpPaginatedResponse: */ true ); - if (!Utils.arrIn(Platform.Http.methods, _method)) { + if (!Platform.Http.methods.includes(_method)) { throw new ErrorInfo('Unsupported method ' + _method, 40500, 405); } - if (Utils.arrIn(Platform.Http.methodsWithBody, _method)) { + if (Platform.Http.methodsWithBody.includes(_method)) { return paginatedResource[_method as HttpMethods.Post](params, body as RequestBody) as Promise< HttpPaginatedResponse >; diff --git a/src/common/lib/transport/comettransport.ts b/src/common/lib/transport/comettransport.ts index 88e094cd8e..b58e43d831 100644 --- a/src/common/lib/transport/comettransport.ts +++ b/src/common/lib/transport/comettransport.ts @@ -21,7 +21,7 @@ function shouldBeErrorAction(err: ErrorInfo) { const UNRESOLVABLE_ERROR_CODES = [80015, 80017, 80030]; if (err.code) { if (Auth.isTokenErr(err)) return false; - if (Utils.arrIn(UNRESOLVABLE_ERROR_CODES, err.code)) return true; + if (UNRESOLVABLE_ERROR_CODES.includes(err.code)) return true; return err.code >= 40000 && err.code < 50000; } else { /* Likely a network or transport error of some kind. Certainly not fatal to the connection */ diff --git a/src/common/lib/transport/connectionmanager.ts b/src/common/lib/transport/connectionmanager.ts index 9f6d361f13..39ef8aa0b0 100644 --- a/src/common/lib/transport/connectionmanager.ts +++ b/src/common/lib/transport/connectionmanager.ts @@ -590,7 +590,7 @@ class ConnectionManager extends EventEmitter { /* if ws and xhrs are connecting in parallel, delay xhrs activation to let ws go ahead */ if ( transport.shortName !== optimalTransport && - Utils.arrIn(this.getUpgradePossibilities(), optimalTransport) && + this.getUpgradePossibilities().includes(optimalTransport) && this.activeProtocol ) { setTimeout(() => { @@ -1558,7 +1558,7 @@ class ConnectionManager extends EventEmitter { const preference = this.getTransportPreference(); let preferenceTimeoutExpired = false; - if (!Utils.arrIn(this.transports, preference)) { + if (!this.transports.includes(preference)) { this.unpersistTransportPreference(); this.connectImpl(transportParams, connectCount); } @@ -2025,7 +2025,7 @@ class ConnectionManager extends EventEmitter { private async processChannelMessage(message: ProtocolMessage, transport: Transport) { const onActiveTransport = this.activeProtocol && transport === this.activeProtocol.getTransport(), - onUpgradeTransport = Utils.arrIn(this.pendingTransports, transport) && this.state == this.states.synchronizing; + onUpgradeTransport = this.pendingTransports.includes(transport) && this.state == this.states.synchronizing; /* As the lib now has a period where the upgrade transport is synced but * before it's become active (while waiting for the old one to become @@ -2123,7 +2123,7 @@ class ConnectionManager extends EventEmitter { } persistTransportPreference(transport: Transport): void { - if (Utils.arrIn(Defaults.upgradeTransports, transport.shortName)) { + if (Defaults.upgradeTransports.includes(transport.shortName)) { this.transportPreference = transport.shortName; if (haveWebStorage()) { Platform.WebStorage?.set?.(transportPreferenceName, transport.shortName); diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index 0da1943405..f6e035074a 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -174,10 +174,6 @@ export function arrSubtract(arr1: Array, arr2: Array): Array { return result; } -export function arrIn(arr: Array, val: unknown): boolean { - return arr.indexOf(val) !== -1; -} - export function arrDeleteValue(arr: Array, val: T): boolean { const idx = arr.indexOf(val); const res = idx != -1; diff --git a/src/platform/web/lib/http/request/xhrrequest.ts b/src/platform/web/lib/http/request/xhrrequest.ts index b6774a9663..7646cfd186 100644 --- a/src/platform/web/lib/http/request/xhrrequest.ts +++ b/src/platform/web/lib/http/request/xhrrequest.ts @@ -10,7 +10,7 @@ import XHRStates from 'common/constants/XHRStates'; import Platform from 'common/platform'; function isAblyError(responseBody: unknown, headers: Record): responseBody is { error?: ErrorInfo } { - return Utils.arrIn(Utils.allToLowerCase(Utils.keysArray(headers)), 'x-ably-errorcode'); + return Utils.allToLowerCase(Utils.keysArray(headers)).includes('x-ably-errorcode'); } function getAblyError(responseBody: unknown, headers: Record) { From 011310a61d3a7f5c5a071135041aabedc3070338 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:29:18 +0000 Subject: [PATCH 23/38] Remove polyfill for Array.prototype.forEach in Utils --- src/common/lib/util/utils.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index f6e035074a..2907ddcc7b 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -227,16 +227,12 @@ export function forInOwnNonNullProperties(ob: Record, fn: (prop } } -export const arrForEach = (Array.prototype.forEach as unknown) - ? function (arr: Array, fn: (value: T, index: number, arr: Array) => unknown) { - arr.forEach(fn); - } - : function (arr: Array, fn: (value: T, index: number, arr: Array) => unknown) { - const len = arr.length; - for (let i = 0; i < len; i++) { - fn(arr[i], i, arr); - } - }; +export const arrForEach = function ( + arr: Array, + fn: (value: T, index: number, arr: Array) => unknown +) { + arr.forEach(fn); +}; /* Useful when the function may mutate the array */ export function safeArrForEach( From 42ab6cce77cadd43c7a20dff1b8a1320828036f7 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:34:31 +0000 Subject: [PATCH 24/38] Remove Utils.arrForEach in favour of native Array.prototype.forEach --- src/common/lib/client/realtimepresence.ts | 2 +- src/common/lib/client/restchannel.ts | 2 +- src/common/lib/transport/connectionmanager.ts | 4 ++-- src/common/lib/util/defaults.ts | 2 +- src/common/lib/util/eventemitter.ts | 6 +++--- src/common/lib/util/utils.ts | 9 +-------- test/common/modules/shared_helper.js | 4 ++-- test/realtime/auth.test.js | 2 +- test/realtime/failure.test.js | 4 ++-- test/rest/history.test.js | 4 ++-- test/rest/request.test.js | 2 +- 11 files changed, 17 insertions(+), 24 deletions(-) diff --git a/src/common/lib/client/realtimepresence.ts b/src/common/lib/client/realtimepresence.ts index 3b7098c9b2..0144522e09 100644 --- a/src/common/lib/client/realtimepresence.ts +++ b/src/common/lib/client/realtimepresence.ts @@ -445,7 +445,7 @@ class RealtimePresence extends EventEmitter { _synthesizeLeaves(items: PresenceMessage[]): void { const subscriptions = this.subscriptions; - Utils.arrForEach(items, function (item) { + items.forEach(function (item) { const presence = presenceMessageFromValues({ action: 'leave', connectionId: item.connectionId, diff --git a/src/common/lib/client/restchannel.ts b/src/common/lib/client/restchannel.ts index dbbf8725fb..8b5ae6ae57 100644 --- a/src/common/lib/client/restchannel.ts +++ b/src/common/lib/client/restchannel.ts @@ -89,7 +89,7 @@ class RestChannel { if (idempotentRestPublishing && allEmptyIds(messages)) { const msgIdBase = await Utils.randomString(MSG_ID_ENTROPY_BYTES); - Utils.arrForEach(messages, function (message, index) { + messages.forEach(function (message, index) { message.id = msgIdBase + ':' + index.toString(); }); } diff --git a/src/common/lib/transport/connectionmanager.ts b/src/common/lib/transport/connectionmanager.ts index 39ef8aa0b0..6431133010 100644 --- a/src/common/lib/transport/connectionmanager.ts +++ b/src/common/lib/transport/connectionmanager.ts @@ -415,7 +415,7 @@ class ConnectionManager extends EventEmitter { if (initialiseWebSocketTransport) { initialiseWebSocketTransport(storage); } - Utils.arrForEach(Platform.Transports.order, function (transportName) { + Platform.Transports.order.forEach(function (transportName) { const initFn = implementations[transportName]; if (initFn) { initFn(storage); @@ -1711,7 +1711,7 @@ class ConnectionManager extends EventEmitter { return; } - Utils.arrForEach(upgradePossibilities, (upgradeTransport: TransportName) => { + upgradePossibilities.forEach((upgradeTransport: TransportName) => { /* Note: the transport may mutate the params, so give each transport a fresh one */ const upgradeTransportParams = this.createTransportParams(transportParams.host, 'upgrade'); this.tryATransport(upgradeTransportParams, upgradeTransport, noop); diff --git a/src/common/lib/util/defaults.ts b/src/common/lib/util/defaults.ts index 2be603152a..752cc841ab 100644 --- a/src/common/lib/util/defaults.ts +++ b/src/common/lib/util/defaults.ts @@ -217,7 +217,7 @@ export function normaliseOptions(options: InternalClientOptions, MsgPack: MsgPac const restHost = options.restHost || (production ? Defaults.REST_HOST : environment + '-' + Defaults.REST_HOST); const realtimeHost = getRealtimeHost(options, production, environment); - Utils.arrForEach((options.fallbackHosts || []).concat(restHost, realtimeHost), checkHost); + (options.fallbackHosts || []).concat(restHost, realtimeHost).forEach(checkHost); options.port = options.port || Defaults.PORT; options.tlsPort = options.tlsPort || Defaults.TLS_PORT; diff --git a/src/common/lib/util/eventemitter.ts b/src/common/lib/util/eventemitter.ts index f86ead2bc4..5df3c7ee12 100644 --- a/src/common/lib/util/eventemitter.ts +++ b/src/common/lib/util/eventemitter.ts @@ -215,7 +215,7 @@ class EventEmitter { Array.prototype.push.apply(listeners, eventsListeners); } - Utils.arrForEach(listeners, function (listener) { + listeners.forEach(function (listener) { callListener(eventThis, listener, args); }); } @@ -260,7 +260,7 @@ class EventEmitter { const self = this; const listenerWrapper = function (this: any) { const innerArgs = Array.prototype.slice.call(arguments); - Utils.arrForEach(firstArg, function (eventName) { + firstArg.forEach(function (eventName) { self.off(eventName, listenerWrapper); }); if (typeof secondArg !== 'function') { @@ -268,7 +268,7 @@ class EventEmitter { } secondArg.apply(this, innerArgs); }; - Utils.arrForEach(firstArg, function (eventName) { + firstArg.forEach(function (eventName) { self.on(eventName, listenerWrapper); }); } else { diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index 2907ddcc7b..1d3794c096 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -227,19 +227,12 @@ export function forInOwnNonNullProperties(ob: Record, fn: (prop } } -export const arrForEach = function ( - arr: Array, - fn: (value: T, index: number, arr: Array) => unknown -) { - arr.forEach(fn); -}; - /* Useful when the function may mutate the array */ export function safeArrForEach( arr: Array, fn: (value: T, index: number, arr: Array) => unknown ): void { - return arrForEach(arr.slice(), fn); + return arr.slice().forEach(fn); } export const arrMap = (Array.prototype.map as unknown) diff --git a/test/common/modules/shared_helper.js b/test/common/modules/shared_helper.js index 6a6cfd43c5..5a836bb04d 100644 --- a/test/common/modules/shared_helper.js +++ b/test/common/modules/shared_helper.js @@ -34,7 +34,7 @@ define([ } function monitorConnection(done, realtime, states) { - utils.arrForEach(states || ['failed', 'suspended'], function (state) { + (states || ['failed', 'suspended']).forEach(function (state) { realtime.connection.on(state, function () { done(new Error('Connection monitoring: state changed to ' + state + ', aborting test')); realtime.close(); @@ -141,7 +141,7 @@ define([ function testOnAllTransports(name, testFn, excludeUpgrade, skip) { var itFn = skip ? it.skip : it; let transports = availableTransports; - utils.arrForEach(transports, function (transport) { + transports.forEach(function (transport) { itFn( name + '_with_' + transport + '_binary_transport', testFn({ transports: [transport], useBinaryProtocol: true }) diff --git a/test/realtime/auth.test.js b/test/realtime/auth.test.js index 47e4ee60f2..a70144a413 100644 --- a/test/realtime/auth.test.js +++ b/test/realtime/auth.test.js @@ -885,7 +885,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async * established, before realtime sends error response. So token error * goes through the same path as a connected transport, so goes to * disconnected first */ - utils.arrForEach(['connected', 'suspended'], function (state) { + ['connected', 'suspended'].forEach(function (state) { realtime.connection.on(state, function () { done(new Error('State changed to ' + state + ', should have gone to failed')); realtime.close(); diff --git a/test/realtime/failure.test.js b/test/realtime/failure.test.js index ef488fc2f7..8a5d47a908 100644 --- a/test/realtime/failure.test.js +++ b/test/realtime/failure.test.js @@ -191,7 +191,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async expect(value).to.be.below(max); } - utils.arrForEach(availableTransports, function (transport) { + availableTransports.forEach(function (transport) { it('disconnected_backoff_' + transport, function (done) { var disconnectedRetryTimeout = 150; var realtime = helper.AblyRealtime({ @@ -373,7 +373,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async }); }); - utils.arrForEach(availableTransports, function (transport) { + availableTransports.forEach(function (transport) { it('channel_backoff_' + transport, function (done) { var channelRetryTimeout = 150; var realtime = helper.AblyRealtime({ diff --git a/test/rest/history.test.js b/test/rest/history.test.js index 33b91b11c5..e7e1485e4f 100644 --- a/test/rest/history.test.js +++ b/test/rest/history.test.js @@ -44,7 +44,7 @@ define(['shared_helper', 'async', 'chai'], function (helper, async, chai) { /* verify message ids are unique */ var ids = {}; - utils.arrForEach(messages, function (msg) { + messages.forEach(function (msg) { ids[msg.id] = msg; }); expect(utils.keysArray(ids).length).to.equal( @@ -67,7 +67,7 @@ define(['shared_helper', 'async', 'chai'], function (helper, async, chai) { /* verify message ids are unique */ var ids = {}; - utils.arrForEach(messages, function (msg) { + messages.forEach(function (msg) { ids[msg.id] = msg; }); expect(utils.keysArray(ids).length).to.equal( diff --git a/test/rest/request.test.js b/test/rest/request.test.js index 0af1d35335..da17d252eb 100644 --- a/test/rest/request.test.js +++ b/test/rest/request.test.js @@ -167,7 +167,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async ); }); - utils.arrForEach(['put', 'patch', 'delete'], function (method) { + ['put', 'patch', 'delete'].forEach(function (method) { it('check' + method, async function () { var restEcho = helper.AblyRest({ useBinaryProtocol: false, restHost: echoServerHost, tls: true }); var res = await restEcho.request(method, '/methods', Defaults.protocolVersion, {}, {}, {}); From 8a8e93f3caf4416575d49327cbd549fdf5508e02 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:36:01 +0000 Subject: [PATCH 25/38] Remove Utils.safeArrForEach --- src/common/lib/transport/connectionmanager.ts | 21 ++++++++++++------- src/common/lib/util/utils.ts | 8 ------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/common/lib/transport/connectionmanager.ts b/src/common/lib/transport/connectionmanager.ts index 6431133010..f8697df962 100644 --- a/src/common/lib/transport/connectionmanager.ts +++ b/src/common/lib/transport/connectionmanager.ts @@ -929,9 +929,9 @@ class ConnectionManager extends EventEmitter { } } - /* Terminate any other pending transport(s), and - * abort any not-yet-pending transport attempts */ - Utils.safeArrForEach(this.pendingTransports, (pendingTransport) => { + // terminate any other pending transport(s), and abort any not-yet-pending transport attempts + // need to use .slice() here, since we intend to mutate the array during .forEach() iteration + this.pendingTransports.slice().forEach((pendingTransport) => { if (pendingTransport === transport) { const msg = 'Assumption violated: activating a transport that is still marked as a pending transport; transport = ' + @@ -944,7 +944,8 @@ class ConnectionManager extends EventEmitter { pendingTransport.disconnect(); } }); - Utils.safeArrForEach(this.proposedTransports, (proposedTransport: Transport) => { + // need to use .slice() here, since we intend to mutate the array during .forEach() iteration + this.proposedTransports.slice().forEach((proposedTransport: Transport) => { if (proposedTransport === transport) { Logger.logAction( Logger.LOG_ERROR, @@ -1723,12 +1724,14 @@ class ConnectionManager extends EventEmitter { this.cancelSuspendTimer(); this.startTransitionTimer(this.states.closing); - Utils.safeArrForEach(this.pendingTransports, function (transport) { + // need to use .slice() here, since we intend to mutate the array during .forEach() iteration + this.pendingTransports.slice().forEach(function (transport) { Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.closeImpl()', 'Closing pending transport: ' + transport); if (transport) transport.close(); }); - Utils.safeArrForEach(this.proposedTransports, function (transport) { + // need to use .slice() here, since we intend to mutate the array during .forEach() iteration + this.proposedTransports.slice().forEach(function (transport) { Logger.logAction( Logger.LOG_MICRO, 'ConnectionManager.closeImpl()', @@ -1864,7 +1867,8 @@ class ConnectionManager extends EventEmitter { /* This will prevent any connection procedure in an async part of one of its early stages from continuing */ this.connectCounter++; - Utils.safeArrForEach(this.pendingTransports, function (transport) { + // need to use .slice() here, since we intend to mutate the array during .forEach() iteration + this.pendingTransports.slice().forEach(function (transport) { Logger.logAction( Logger.LOG_MICRO, 'ConnectionManager.disconnectAllTransports()', @@ -1874,7 +1878,8 @@ class ConnectionManager extends EventEmitter { }); this.pendingTransports = []; - Utils.safeArrForEach(this.proposedTransports, function (transport) { + // need to use .slice() here, since we intend to mutate the array during .forEach() iteration + this.proposedTransports.slice().forEach(function (transport) { Logger.logAction( Logger.LOG_MICRO, 'ConnectionManager.disconnectAllTransports()', diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index 1d3794c096..75c725e822 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -227,14 +227,6 @@ export function forInOwnNonNullProperties(ob: Record, fn: (prop } } -/* Useful when the function may mutate the array */ -export function safeArrForEach( - arr: Array, - fn: (value: T, index: number, arr: Array) => unknown -): void { - return arr.slice().forEach(fn); -} - export const arrMap = (Array.prototype.map as unknown) ? function (arr: Array, fn: (value: T1, index?: number, arr?: Array) => T2) { return arr.map(fn); From fcda7d31e917d0f592f63d8f91fb694a44241bd6 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:38:17 +0000 Subject: [PATCH 26/38] Remove polyfill for Array.prototype.map in Utils --- src/common/lib/util/utils.ts | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index 75c725e822..227b154f6d 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -227,18 +227,9 @@ export function forInOwnNonNullProperties(ob: Record, fn: (prop } } -export const arrMap = (Array.prototype.map as unknown) - ? function (arr: Array, fn: (value: T1, index?: number, arr?: Array) => T2) { - return arr.map(fn); - } - : function (arr: Array, fn: (value: T, index?: number, arr?: Array) => unknown) { - const result = []; - const len = arr.length; - for (let i = 0; i < len; i++) { - result.push(fn(arr[i], i, arr)); - } - return result; - }; +export const arrMap = function (arr: Array, fn: (value: T1, index?: number, arr?: Array) => T2) { + return arr.map(fn); +}; export const arrFilter = (Array.prototype.filter as unknown) ? function (arr: Array, fn: (value: T, index?: number, arr?: Array) => boolean) { From 7d2ed227748cebdefbd6f26846d9a286a569f00a Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:42:27 +0000 Subject: [PATCH 27/38] Remove Utils.arrMap in favour of native Array.prototype.map --- src/common/lib/util/utils.ts | 4 ---- test/realtime/failure.test.js | 12 ++++++------ test/realtime/history.test.js | 7 ++++--- test/realtime/presence.test.js | 12 ++++++------ test/realtime/sync.test.js | 4 ++-- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index 227b154f6d..1b800fd068 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -227,10 +227,6 @@ export function forInOwnNonNullProperties(ob: Record, fn: (prop } } -export const arrMap = function (arr: Array, fn: (value: T1, index?: number, arr?: Array) => T2) { - return arr.map(fn); -}; - export const arrFilter = (Array.prototype.filter as unknown) ? function (arr: Array, fn: (value: T, index?: number, arr?: Array) => boolean) { return arr.filter(fn); diff --git a/test/realtime/failure.test.js b/test/realtime/failure.test.js index 8a5d47a908..a4e9601ad2 100644 --- a/test/realtime/failure.test.js +++ b/test/realtime/failure.test.js @@ -56,8 +56,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async }; }; async.parallel( - utils - .arrMap(availableTransports, function (transport) { + availableTransports + .map(function (transport) { return failure_test([transport]); }) .concat(failure_test(null)), // to test not specifying a transport (so will use upgrade mechanism) @@ -94,8 +94,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async }; }; async.parallel( - utils - .arrMap(availableTransports, function (transport) { + availableTransports + .map(function (transport) { return break_test([transport]); }) .concat(break_test(null)), // to test not specifying a transport (so will use upgrade mechanism) @@ -169,8 +169,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async }; }; async.parallel( - utils - .arrMap(availableTransports, function (transport) { + availableTransports + .map(function (transport) { return lifecycleTest([transport]); }) .concat(lifecycleTest(null)), // to test not specifying a transport (so will use upgrade mechanism) diff --git a/test/realtime/history.test.js b/test/realtime/history.test.js index a32ad2c72a..43368cd456 100644 --- a/test/realtime/history.test.js +++ b/test/realtime/history.test.js @@ -3,10 +3,11 @@ define(['shared_helper', 'async', 'chai'], function (helper, async, chai) { var expect = chai.expect; var utils = helper.Utils; - var preAttachMessages = utils.arrMap([1, 2, 3, 4, 5], function (i) { + var indexes = [1, 2, 3, 4, 5]; + var preAttachMessages = indexes.map(function (i) { return { name: 'pre-attach-' + i, data: 'some data' }; }); - var postAttachMessages = utils.arrMap([1, 2, 3, 4, 5], function (i) { + var postAttachMessages = indexes.map(function (i) { return { name: 'post-attach-' + i, data: 'some data' }; }); var closeAndFinish = helper.closeAndFinish; @@ -14,7 +15,7 @@ define(['shared_helper', 'async', 'chai'], function (helper, async, chai) { var whenPromiseSettles = helper.whenPromiseSettles; var parallelPublishMessages = function (done, channel, messages, callback) { - var publishTasks = utils.arrMap(messages, function (event) { + var publishTasks = messages.map(function (event) { return function (publishCb) { whenPromiseSettles(channel.publish(event.name, event.data), publishCb); }; diff --git a/test/realtime/presence.test.js b/test/realtime/presence.test.js index 137b56f69a..d938fb0dbc 100644 --- a/test/realtime/presence.test.js +++ b/test/realtime/presence.test.js @@ -10,8 +10,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async var whenPromiseSettles = helper.whenPromiseSettles; function extractClientIds(presenceSet) { - return utils - .arrMap(presenceSet, function (presmsg) { + return presenceSet + .map(function (presmsg) { return presmsg.clientId; }) .sort(); @@ -780,8 +780,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async var presenceMessages = resultPage.items; expect(presenceMessages.length).to.equal(2, 'Verify correct number of presence messages found'); - var actions = utils - .arrMap(presenceMessages, function (msg) { + var actions = presenceMessages + .map(function (msg) { return msg.action; }) .sort(); @@ -1372,8 +1372,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async function checkPresence(first, second, cb) { whenPromiseSettles(observerChannel.presence.get(), function (err, presenceMembers) { - var clientIds = utils - .arrMap(presenceMembers, function (msg) { + var clientIds = presenceMembers + .map(function (msg) { return msg.clientId; }) .sort(); diff --git a/test/realtime/sync.test.js b/test/realtime/sync.test.js index 7b29fd4d27..e7ac1d92b6 100644 --- a/test/realtime/sync.test.js +++ b/test/realtime/sync.test.js @@ -22,8 +22,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async }); function extractClientIds(presenceSet) { - return utils - .arrMap(presenceSet, function (presmsg) { + return presenceSet + .map(function (presmsg) { return presmsg.clientId; }) .sort(); From ea6992c7b95c8c690dee78ec673ea47faca60754 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:43:13 +0000 Subject: [PATCH 28/38] Remove polyfill for Array.prototype.filter in Utils --- src/common/lib/util/utils.ts | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index 1b800fd068..8eff63a9cd 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -227,20 +227,9 @@ export function forInOwnNonNullProperties(ob: Record, fn: (prop } } -export const arrFilter = (Array.prototype.filter as unknown) - ? function (arr: Array, fn: (value: T, index?: number, arr?: Array) => boolean) { - return arr.filter(fn); - } - : function (arr: Array, fn: (value: T, index?: number, arr?: Array) => boolean) { - const result = [], - len = arr.length; - for (let i = 0; i < len; i++) { - if (fn(arr[i])) { - result.push(arr[i]); - } - } - return result; - }; +export const arrFilter = function (arr: Array, fn: (value: T, index?: number, arr?: Array) => boolean) { + return arr.filter(fn); +}; export const arrEvery = (Array.prototype.every as unknown) ? function (arr: Array, fn: (value: T, index: number, arr: Array) => boolean) { From 218a6cd130338899e9cf930a12b87e57db9a6dc2 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:46:35 +0000 Subject: [PATCH 29/38] Remove Utils.arrFilter in favour of native Array.prototype.filter --- src/common/lib/util/utils.ts | 4 ---- test/common/modules/shared_helper.js | 17 +---------------- test/realtime/encoding.test.js | 2 +- 3 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index 8eff63a9cd..d586b65ac9 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -227,10 +227,6 @@ export function forInOwnNonNullProperties(ob: Record, fn: (prop } } -export const arrFilter = function (arr: Array, fn: (value: T, index?: number, arr?: Array) => boolean) { - return arr.filter(fn); -}; - export const arrEvery = (Array.prototype.every as unknown) ? function (arr: Array, fn: (value: T, index: number, arr: Array) => boolean) { return arr.every(fn); diff --git a/test/common/modules/shared_helper.js b/test/common/modules/shared_helper.js index 5a836bb04d..965f7206c7 100644 --- a/test/common/modules/shared_helper.js +++ b/test/common/modules/shared_helper.js @@ -50,7 +50,7 @@ define([ return; } if (Object.prototype.toString.call(realtime) == '[object Array]') { - var realtimes = utils.arrFilter(realtime, function (rt) { + var realtimes = realtime.filter(function (rt) { return rt !== undefined; }); closeAndFinishSeveral(done, realtimes, err); @@ -208,20 +208,6 @@ define([ return undefined; }; - var arrFilter = Array.prototype.filter - ? function (arr, predicate) { - return arr.filter(predicate); - } - : function (arr, predicate) { - var res = []; - for (var i = 0; i < arr.length; i++) { - if (predicate(arr[i])) { - res.push(arr[i]); - } - } - return res; - }; - function randomString() { return Math.random().toString().slice(2); } @@ -280,7 +266,6 @@ define([ unroutableHost: unroutableHost, unroutableAddress: unroutableAddress, arrFind: arrFind, - arrFilter: arrFilter, whenPromiseSettles: whenPromiseSettles, randomString: randomString, testMessageEquality: testMessageEquality, diff --git a/test/realtime/encoding.test.js b/test/realtime/encoding.test.js index f7c9e49c10..084702ef75 100644 --- a/test/realtime/encoding.test.js +++ b/test/realtime/encoding.test.js @@ -187,7 +187,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async return; } try { - var msgs = helper.arrFilter(resultPage.items, function (m) { + var msgs = resultPage.items.filter(function (m) { return m.name === name; }); expect(msgs.length).to.equal( From 7f275ce380fa7ee658aef91ad11e519451ebb4b0 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:47:45 +0000 Subject: [PATCH 30/38] Remove Array.prototype.find polyfill from shared_helper --- test/common/modules/shared_helper.js | 16 ---------------- test/realtime/presence.test.js | 2 +- test/realtime/sync.test.js | 2 +- test/rest/presence.test.js | 11 +++++------ 4 files changed, 7 insertions(+), 24 deletions(-) diff --git a/test/common/modules/shared_helper.js b/test/common/modules/shared_helper.js index 965f7206c7..2f984bec83 100644 --- a/test/common/modules/shared_helper.js +++ b/test/common/modules/shared_helper.js @@ -193,21 +193,6 @@ define([ return !!transport.toString().match(/wss?\:/); } - var arrFind = Array.prototype.find - ? function (arr, predicate) { - return arr.find(predicate); - } - : function (arr, predicate) { - var value; - for (var i = 0; i < arr.length; i++) { - value = arr[i]; - if (predicate(value)) { - return value; - } - } - return undefined; - }; - function randomString() { return Math.random().toString().slice(2); } @@ -265,7 +250,6 @@ define([ isWebsocket: isWebsocket, unroutableHost: unroutableHost, unroutableAddress: unroutableAddress, - arrFind: arrFind, whenPromiseSettles: whenPromiseSettles, randomString: randomString, testMessageEquality: testMessageEquality, diff --git a/test/realtime/presence.test.js b/test/realtime/presence.test.js index d938fb0dbc..a0e327f4ea 100644 --- a/test/realtime/presence.test.js +++ b/test/realtime/presence.test.js @@ -18,7 +18,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async } function extractMember(presenceSet, clientId) { - return helper.arrFind(presenceSet, function (member) { + return presenceSet.find(function (member) { return member.clientId === clientId; }); } diff --git a/test/realtime/sync.test.js b/test/realtime/sync.test.js index e7ac1d92b6..7bd493e1b0 100644 --- a/test/realtime/sync.test.js +++ b/test/realtime/sync.test.js @@ -30,7 +30,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async } function extractMember(presenceSet, clientId) { - return helper.arrFind(presenceSet, function (member) { + return presenceSet.find(function (member) { return member.clientId === clientId; }); } diff --git a/test/rest/presence.test.js b/test/rest/presence.test.js index 1c9640631f..d0e6d98a74 100644 --- a/test/rest/presence.test.js +++ b/test/rest/presence.test.js @@ -6,7 +6,6 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async var expect = chai.expect; var Crypto = Ably.Realtime.Platform.Crypto; var BufferUtils = Ably.Realtime.Platform.BufferUtils; - var arrFind = helper.arrFind; function cipherParamsFromConfig(cipherConfig) { var cipherParams = new Crypto.CipherParams(); @@ -41,16 +40,16 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async if (presenceMessages.length != 6) { console.log('presenceMessages: ', JSON.stringify(presenceMessages)); } - var encodedMessage = arrFind(presenceMessages, function (msg) { + var encodedMessage = presenceMessages.find(function (msg) { return msg.clientId == 'client_encoded'; }); - var decodedMessage = arrFind(presenceMessages, function (msg) { + var decodedMessage = presenceMessages.find(function (msg) { return msg.clientId == 'client_decoded'; }); - var boolMessage = arrFind(presenceMessages, function (msg) { + var boolMessage = presenceMessages.find(function (msg) { return msg.clientId == 'client_bool'; }); - var intMessage = arrFind(presenceMessages, function (msg) { + var intMessage = presenceMessages.find(function (msg) { return msg.clientId == 'client_int'; }); expect(encodedMessage.data).to.deep.equal(decodedMessage.data, 'Verify message decoding works correctly'); @@ -71,7 +70,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async var channel = rest.channels.get('persisted:presence_fixtures'); var resultPage = await channel.presence.get(); var presenceMessages = resultPage.items; - var presenceBool = arrFind(presenceMessages, function (msg) { + var presenceBool = presenceMessages.find(function (msg) { return msg.clientId == 'client_bool'; }); expect(JSON.parse(JSON.stringify(presenceBool)).action).to.equal(1); // present From e5aa106b5763f42b1d7c84d8c1a83369b8903c8e Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:48:06 +0000 Subject: [PATCH 31/38] Remove polyfill for Array.prototype.every in Utils --- src/common/lib/util/utils.ts | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index d586b65ac9..be62130db8 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -227,19 +227,9 @@ export function forInOwnNonNullProperties(ob: Record, fn: (prop } } -export const arrEvery = (Array.prototype.every as unknown) - ? function (arr: Array, fn: (value: T, index: number, arr: Array) => boolean) { - return arr.every(fn); - } - : function (arr: Array, fn: (value: T, index: number, arr: Array) => boolean) { - const len = arr.length; - for (let i = 0; i < len; i++) { - if (!fn(arr[i], i, arr)) { - return false; - } - } - return true; - }; +export const arrEvery = function (arr: Array, fn: (value: T, index: number, arr: Array) => boolean) { + return arr.every(fn); +}; export function allSame(arr: Array>, prop: string): boolean { if (arr.length === 0) { From 2072302bbe7fef76788e32c3cb189c94ad5ebf8c Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 10:49:41 +0000 Subject: [PATCH 32/38] Remove Utils.arrEvery in favour of native Array.prototype.every --- src/common/lib/client/restchannel.ts | 2 +- src/common/lib/transport/connectionmanager.ts | 2 +- src/common/lib/util/utils.ts | 8 ++------ test/common/modules/client_module.js | 2 +- test/realtime/history.test.js | 2 +- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/common/lib/client/restchannel.ts b/src/common/lib/client/restchannel.ts index 8b5ae6ae57..4f0d1ace37 100644 --- a/src/common/lib/client/restchannel.ts +++ b/src/common/lib/client/restchannel.ts @@ -22,7 +22,7 @@ import { RequestBody } from 'common/types/http'; const MSG_ID_ENTROPY_BYTES = 9; function allEmptyIds(messages: Array) { - return Utils.arrEvery(messages, function (message: Message) { + return messages.every(function (message: Message) { return !message.id; }); } diff --git a/src/common/lib/transport/connectionmanager.ts b/src/common/lib/transport/connectionmanager.ts index f8697df962..c6ae8914e4 100644 --- a/src/common/lib/transport/connectionmanager.ts +++ b/src/common/lib/transport/connectionmanager.ts @@ -75,7 +75,7 @@ function bundleWith(dest: ProtocolMessage, src: ProtocolMessage, maxSize: number return false; } if ( - !Utils.arrEvery(proposed, function (msg: Message) { + !proposed.every(function (msg: Message) { return !msg.id; }) ) { diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index be62130db8..dd527d31ce 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -227,16 +227,12 @@ export function forInOwnNonNullProperties(ob: Record, fn: (prop } } -export const arrEvery = function (arr: Array, fn: (value: T, index: number, arr: Array) => boolean) { - return arr.every(fn); -}; - export function allSame(arr: Array>, prop: string): boolean { if (arr.length === 0) { return true; } const first = arr[0][prop]; - return arrEvery(arr, function (item) { + return arr.every(function (item) { return item[prop] === first; }); } @@ -461,7 +457,7 @@ export function toBase64(str: string) { export function arrEquals(a: any[], b: any[]) { return ( a.length === b.length && - arrEvery(a, function (val, i) { + a.every(function (val, i) { return val === b[i]; }) ); diff --git a/test/common/modules/client_module.js b/test/common/modules/client_module.js index 88458b2212..5ea3c37ba6 100644 --- a/test/common/modules/client_module.js +++ b/test/common/modules/client_module.js @@ -12,7 +12,7 @@ define(['ably', 'globals', 'test/common/modules/testapp_module'], function (Ably /* Use a default api key if no auth methods provided */ if ( - utils.arrEvery(authMethods, function (method) { + authMethods.every(function (method) { return !(method in clientOptions); }) ) { diff --git a/test/realtime/history.test.js b/test/realtime/history.test.js index 43368cd456..24cdfab606 100644 --- a/test/realtime/history.test.js +++ b/test/realtime/history.test.js @@ -121,7 +121,7 @@ define(['shared_helper', 'async', 'chai'], function (helper, async, chai) { 'Verify right number of messages returned when untilAttached is true' ); expect( - utils.arrEvery(messages, function (message) { + messages.every(function (message) { return message.name.substring(0, 10) == 'pre-attach'; }), 'Verify all returned messages were pre-attach ones' From 335007da4a3dea0b270f2a54fdb4b76f821da915 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 11:02:41 +0000 Subject: [PATCH 33/38] Remove polyfill for String.prototype.trim in Utils --- src/common/lib/util/utils.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index dd527d31ce..e0a8d1de68 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -322,13 +322,9 @@ export function arrChooseN(arr: Array, n: number): Array { return result; } -export const trim = (String.prototype.trim as unknown) - ? function (str: string) { - return str.trim(); - } - : function (str: string) { - return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); - }; +export const trim = function (str: string) { + return str.trim(); +}; /** * Uses a callback to communicate the result of a `Promise`. The first argument passed to the callback will be either an error (when the promise is rejected) or `null` (when the promise is fulfilled). In the case where the promise is fulfilled, the resulting value will be passed to the callback as a second argument. From d5fcd672aea0251c13293aa392de14b5c6eb940f Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 11:04:01 +0000 Subject: [PATCH 34/38] Remove Utils.trim in favour of native String.prototype.trim --- src/common/lib/util/utils.ts | 4 ---- src/platform/web/lib/http/request/xhrrequest.ts | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/common/lib/util/utils.ts b/src/common/lib/util/utils.ts index e0a8d1de68..10c5f5ecf0 100644 --- a/src/common/lib/util/utils.ts +++ b/src/common/lib/util/utils.ts @@ -322,10 +322,6 @@ export function arrChooseN(arr: Array, n: number): Array { return result; } -export const trim = function (str: string) { - return str.trim(); -}; - /** * Uses a callback to communicate the result of a `Promise`. The first argument passed to the callback will be either an error (when the promise is rejected) or `null` (when the promise is fulfilled). In the case where the promise is fulfilled, the resulting value will be passed to the callback as a second argument. */ diff --git a/src/platform/web/lib/http/request/xhrrequest.ts b/src/platform/web/lib/http/request/xhrrequest.ts index 7646cfd186..8e1af6f0ae 100644 --- a/src/platform/web/lib/http/request/xhrrequest.ts +++ b/src/platform/web/lib/http/request/xhrrequest.ts @@ -39,10 +39,10 @@ function isEncodingChunked(xhr: XMLHttpRequest) { } function getHeadersAsObject(xhr: XMLHttpRequest) { - const headerPairs = Utils.trim(xhr.getAllResponseHeaders()).split('\r\n'); + const headerPairs = xhr.getAllResponseHeaders().trim().split('\r\n'); const headers: Record = {}; for (let i = 0; i < headerPairs.length; i++) { - const parts = headerPairs[i].split(':').map(Utils.trim); + const parts = headerPairs[i].split(':').map((x) => x.trim()); headers[parts[0].toLowerCase()] = parts[1]; } return headers; From 85f046919bb8c468850cc8b2f054b2aee684808f Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 21 Feb 2024 11:10:51 +0000 Subject: [PATCH 35/38] Change minimal raw bundle size threshold to 95 KiB --- scripts/moduleReport.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/moduleReport.ts b/scripts/moduleReport.ts index 80665b205f..440ab77bcf 100644 --- a/scripts/moduleReport.ts +++ b/scripts/moduleReport.ts @@ -6,7 +6,7 @@ import { gzip } from 'zlib'; import Table from 'cli-table'; // The maximum size we allow for a minimal useful Realtime bundle (i.e. one that can subscribe to a channel) -const minimalUsefulRealtimeBundleSizeThresholdsKiB = { raw: 96, gzip: 29 }; +const minimalUsefulRealtimeBundleSizeThresholdsKiB = { raw: 95, gzip: 29 }; const baseClientNames = ['BaseRest', 'BaseRealtime']; From 809aced61e9f7254e6a37ec2aa0f75f1666057d3 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Fri, 23 Feb 2024 01:11:31 +0000 Subject: [PATCH 36/38] Remove IE specific code from tests --- test/browser/connection.test.js | 8 -------- test/common/modules/testapp_manager.js | 13 +------------ 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/test/browser/connection.test.js b/test/browser/connection.test.js index d615c133c8..8455cd66c3 100644 --- a/test/browser/connection.test.js +++ b/test/browser/connection.test.js @@ -18,14 +18,6 @@ define(['shared_helper', 'chai'], function (helper, chai) { return false; } - // IE doesn't support creating your own events with new - try { - var testEvent = new Event('foo'); - } catch (e) { - console.log('On IE; skipping connection.test.js'); - return false; - } - return true; } diff --git a/test/common/modules/testapp_manager.js b/test/common/modules/testapp_manager.js index 41724490e3..de8fb32661 100644 --- a/test/common/modules/testapp_manager.js +++ b/test/common/modules/testapp_manager.js @@ -30,17 +30,6 @@ define(['globals', 'ably'], function (ablyGlobals, ably) { } } - function createXHR() { - var result = new XMLHttpRequest(); - if ('withCredentials' in result) return result; - if (typeof XDomainRequest !== 'undefined') { - var xdr = new XDomainRequest(); /* Use IE-specific "CORS" code with XDR */ - xdr.isXDR = true; - return xdr; - } - return null; - } - function toBase64(str) { var bufferUtils = ably.Realtime.Platform.BufferUtils; var buffer = bufferUtils.utf8Encode(str); @@ -70,7 +59,7 @@ define(['globals', 'ably'], function (ablyGlobals, ably) { }; } else if (isBrowser) { return function (options, callback) { - var xhr = createXHR(); + var xhr = new XMLHttpRequest(); var uri; uri = options.scheme + '://' + options.host + ':' + options.port + options.path; From 9a05dc86846c00b3f69e82e16086143db9325dc7 Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Fri, 23 Feb 2024 01:16:27 +0000 Subject: [PATCH 37/38] Remove "comma-dangle" eslint rule used for old browsers compatibility --- .eslintrc.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 2e93a299ed..a45654db34 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -19,8 +19,6 @@ module.exports = { "plugin:security/recommended", ], rules: { - // comma-dangle used for browser compatibility for browsers that don't support trailing commas - "comma-dangle": ["error", "always-multiline"], "eol-last": "error", // security/detect-object-injection just gives a lot of false positives // see https://github.com/nodesecurity/eslint-plugin-security/issues/21 @@ -35,7 +33,6 @@ module.exports = { { files: ["**/*.{ts,tsx}"], rules: { - "comma-dangle": ["error", "only-multiline"], "@typescript-eslint/no-unused-vars": ["error", { "varsIgnorePattern": "^_" }], // TypeScript already enforces these rules better than any eslint setup can "no-undef": "off", From 2fc88a33cd6ef5fbf8b5147460bf13fabbcc7e1c Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Tue, 27 Feb 2024 13:29:15 +0000 Subject: [PATCH 38/38] Remove node 0.8.x specific code from node platform crypto --- src/platform/nodejs/lib/util/crypto.ts | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/platform/nodejs/lib/util/crypto.ts b/src/platform/nodejs/lib/util/crypto.ts index 330f70a598..e785ad8557 100644 --- a/src/platform/nodejs/lib/util/crypto.ts +++ b/src/platform/nodejs/lib/util/crypto.ts @@ -76,15 +76,6 @@ var createCryptoClass = function (bufferUtils: typeof BufferUtils) { var pkcs5Padding = [filledBuffer(16, 16)]; for (var i = 1; i <= 16; i++) pkcs5Padding.push(filledBuffer(i, i)); - /** - * Internal: convert a binary string to Buffer (for node 0.8.x) - * @param bufferOrString - * @returns {Buffer} - */ - function toBuffer(bufferOrString: Buffer | string) { - return typeof bufferOrString == 'string' ? Buffer.from(bufferOrString, 'binary') : bufferOrString; - } - /** * A class encapsulating the client-specifiable parameters for * the cipher. @@ -236,19 +227,19 @@ var createCryptoClass = function (bufferUtils: typeof BufferUtils) { var cipherOut = this.encryptCipher.update( Buffer.concat([plaintextBuffer, pkcs5Padding[paddedLength - plaintextLength]]) ); - var ciphertext = Buffer.concat([iv, toBuffer(cipherOut)]); + var ciphertext = Buffer.concat([iv, cipherOut]); return ciphertext; } async decrypt(ciphertext: InputCiphertext): Promise { var decryptCipher = crypto.createDecipheriv(this.algorithm, this.key, ciphertext.slice(0, DEFAULT_BLOCKLENGTH)), - plaintext = toBuffer(decryptCipher.update(ciphertext.slice(DEFAULT_BLOCKLENGTH))), + plaintext = decryptCipher.update(ciphertext.slice(DEFAULT_BLOCKLENGTH)), final = decryptCipher.final(); - if (final && final.length) plaintext = Buffer.concat([plaintext, toBuffer(final)]); + if (final && final.length) plaintext = Buffer.concat([plaintext, final]); return plaintext; } - async getIv() { + async getIv(): Promise { if (this.iv) { var iv = this.iv; this.iv = null; @@ -263,7 +254,7 @@ var createCryptoClass = function (bufferUtils: typeof BufferUtils) { /* Since the iv for a new block is the ciphertext of the last, this * sets a new iv (= aes(randomBlock XOR lastCipherText)) as well as * returning it */ - return toBuffer(this.encryptCipher.update(randomBlock)); + return this.encryptCipher.update(randomBlock); } } }