diff --git a/.eslintrc.js b/.eslintrc.js index bfb17bd1f..1e4509d9b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -36,6 +36,9 @@ const rules = { // useful for unused or internal fields 'no-underscore-dangle': 'off', + // Temp: We have because TypeScript's `allowUnreachableCode` option is on. + 'no-unreachable': 'error', + // though we have a logger, we still remap console to log to disk 'no-console': 'error', diff --git a/ts/ConversationController.ts b/ts/ConversationController.ts index 17cadc722..a33f2fcc2 100644 --- a/ts/ConversationController.ts +++ b/ts/ConversationController.ts @@ -18,7 +18,7 @@ import * as log from './logging/log'; import * as Errors from './types/errors'; import { getContactId } from './messages/helpers'; import { maybeDeriveGroupV2Id } from './groups'; -import { assert, strictAssert } from './util/assert'; +import { assertDev, strictAssert } from './util/assert'; import { isGroupV1, isGroupV2 } from './util/whatTypeOfConversation'; import { getConversationUnreadCountForAppBadge } from './util/getConversationUnreadCountForAppBadge'; import { UUID, isValidUuid, UUIDKind } from './types/UUID'; @@ -686,7 +686,7 @@ export class ConversationController { // conflict case, to keep the one with activity the most recently. for (let i = models.length - 1; i >= 0; i -= 1) { const conversation = models[i]; - assert( + assertDev( conversation, 'Expected conversation to be found in array during iteration' ); @@ -781,7 +781,7 @@ export class ConversationController { if (isGroupV1(conversation.attributes)) { maybeDeriveGroupV2Id(conversation); groupV2Id = conversation.get('derivedGroupV2Id'); - assert( + assertDev( groupV2Id, 'checkForConflicts: expected the group V2 ID to have been derived, but it was falsy' ); @@ -842,7 +842,7 @@ export class ConversationController { } if (obsolete.get('type') !== conversationType) { - assert( + assertDev( false, `${logId}: cannot combine a private and group conversation. Doing nothing` ); diff --git a/ts/SignalProtocolStore.ts b/ts/SignalProtocolStore.ts index 7d3f777ef..55c0a6849 100644 --- a/ts/SignalProtocolStore.ts +++ b/ts/SignalProtocolStore.ts @@ -18,7 +18,7 @@ import { import * as Bytes from './Bytes'; import { constantTimeEqual, sha256 } from './Crypto'; -import { assert, strictAssert } from './util/assert'; +import { assertDev, strictAssert } from './util/assert'; import { isNotNil } from './util/isNotNil'; import { Zone } from './util/Zone'; import { isMoreRecentThan } from './util/timestamp'; @@ -836,13 +836,16 @@ export class SignalProtocolStore extends EventsMixin { // Apply changes to in-memory storage after successful DB write. const { sessions } = this; - assert(sessions !== undefined, "Can't commit unhydrated session storage"); + assertDev( + sessions !== undefined, + "Can't commit unhydrated session storage" + ); pendingSessions.forEach((value, key) => { sessions.set(key, value); }); const { senderKeys } = this; - assert( + assertDev( senderKeys !== undefined, "Can't commit unhydrated sender key storage" ); @@ -871,7 +874,7 @@ export class SignalProtocolStore extends EventsMixin { private enterZone(zone: Zone, name: string): void { this.currentZoneDepth += 1; if (this.currentZoneDepth === 1) { - assert(this.currentZone === undefined, 'Should not be in the zone'); + assertDev(this.currentZone === undefined, 'Should not be in the zone'); this.currentZone = zone; if (zone !== GLOBAL_ZONE) { @@ -881,10 +884,13 @@ export class SignalProtocolStore extends EventsMixin { } private leaveZone(zone: Zone): void { - assert(this.currentZone === zone, 'Should be in the correct zone'); + assertDev(this.currentZone === zone, 'Should be in the correct zone'); this.currentZoneDepth -= 1; - assert(this.currentZoneDepth >= 0, 'Unmatched number of leaveZone calls'); + assertDev( + this.currentZoneDepth >= 0, + 'Unmatched number of leaveZone calls' + ); // Since we allow re-entering zones we might actually be in two overlapping // async calls. Leave the zone and yield to another one only if there are @@ -908,7 +914,7 @@ export class SignalProtocolStore extends EventsMixin { while (this.zoneQueue[0]?.zone === next.zone) { const elem = this.zoneQueue.shift(); - assert(elem, 'Zone element should be present'); + assertDev(elem, 'Zone element should be present'); toEnter.push(elem); } @@ -1080,7 +1086,7 @@ export class SignalProtocolStore extends EventsMixin { item: record, }; - assert(this.currentZone, 'Must run in the zone'); + assertDev(this.currentZone, 'Must run in the zone'); this.pendingSessions.set(id, newSession); @@ -1388,7 +1394,7 @@ export class SignalProtocolStore extends EventsMixin { const conversation = window.ConversationController.lookupOrCreate({ uuid: uuid.toString(), }); - assert(conversation, `lightSessionReset/${id}: missing conversation`); + assertDev(conversation, `lightSessionReset/${id}: missing conversation`); log.warn(`lightSessionReset/${id}: Resetting session`); diff --git a/ts/background.ts b/ts/background.ts index 0abc9ea34..fdbe76eb2 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -35,7 +35,7 @@ import { ChallengeHandler } from './challenge'; import * as durations from './util/durations'; import { explodePromise } from './util/explodePromise'; import { isWindowDragElement } from './util/isWindowDragElement'; -import { assert, strictAssert } from './util/assert'; +import { assertDev, strictAssert } from './util/assert'; import { normalizeUuid } from './util/normalizeUuid'; import { filter } from './util/iterables'; import { isNotNil } from './util/isNotNil'; @@ -3359,7 +3359,7 @@ export async function startApp(): Promise { data: MessageEventData, descriptor: MessageDescriptor ) { - assert( + assertDev( Boolean(data.receivedAtCounter), `Did not receive receivedAtCounter for message: ${data.timestamp}` ); diff --git a/ts/challenge.ts b/ts/challenge.ts index fb702ff8f..9d1fe2cdf 100644 --- a/ts/challenge.ts +++ b/ts/challenge.ts @@ -12,7 +12,7 @@ // are not immediately retried, however, until `.onOnline()` is called from // when we are actually online. -import { assert } from './util/assert'; +import { assertDev } from './util/assert'; import { isOlderThan } from './util/timestamp'; import { parseRetryAfterWithDefault } from './util/parseRetryAfter'; import { clearTimeoutIfNecessary } from './util/clearTimeoutIfNecessary'; @@ -311,7 +311,7 @@ export class ChallengeHandler { } private async persist(): Promise { - assert( + assertDev( this.isLoaded, 'ChallengeHandler has to be loaded before persisting new data' ); diff --git a/ts/components/Avatar.tsx b/ts/components/Avatar.tsx index 980a8e04f..d04e0b9c9 100644 --- a/ts/components/Avatar.tsx +++ b/ts/components/Avatar.tsx @@ -20,7 +20,7 @@ import { BadgeImageTheme } from '../badges/BadgeImageTheme'; import { HasStories } from '../types/Stories'; import { Spinner } from './Spinner'; import { ThemeType } from '../types/Util'; -import { assert } from '../util/assert'; +import { assertDev } from '../util/assert'; import { getBadgeImageFileLocalPath } from '../badges/getBadgeImageFileLocalPath'; import { getInitials } from '../util/getInitials'; import { isBadgeVisible } from '../badges/isBadgeVisible'; @@ -169,9 +169,9 @@ export const Avatar: FunctionComponent = ({ ); } else if (hasImage) { - assert(avatarPath, 'avatarPath should be defined here'); + assertDev(avatarPath, 'avatarPath should be defined here'); - assert( + assertDev( blur !== AvatarBlur.BlurPictureWithClickToView || size >= 100, 'Rendering "click to view" for a small avatar. This may not render correctly' ); diff --git a/ts/components/Button.tsx b/ts/components/Button.tsx index 36fd5e799..93d3aa188 100644 --- a/ts/components/Button.tsx +++ b/ts/components/Button.tsx @@ -11,7 +11,7 @@ import React from 'react'; import classNames from 'classnames'; import type { Theme } from '../util/theme'; -import { assert } from '../util/assert'; +import { assertDev } from '../util/assert'; import { themeClassName } from '../util/theme'; export enum ButtonSize { @@ -126,10 +126,10 @@ export const Button = React.forwardRef( } const sizeClassName = SIZE_CLASS_NAMES.get(size); - assert(sizeClassName, '