tsc:allowUnreachableCode, eslint:no-unreachable, assert->assertDev

This commit is contained in:
Jamie Kyle 2022-09-15 12:17:15 -07:00 committed by GitHub
parent f627a05cf8
commit eb10aafd7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 213 additions and 176 deletions

View File

@ -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',

View File

@ -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`
);

View File

@ -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`);

View File

@ -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<void> {
data: MessageEventData,
descriptor: MessageDescriptor
) {
assert(
assertDev(
Boolean(data.receivedAtCounter),
`Did not receive receivedAtCounter for message: ${data.timestamp}`
);

View File

@ -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<void> {
assert(
assertDev(
this.isLoaded,
'ChallengeHandler has to be loaded before persisting new data'
);

View File

@ -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<Props> = ({
</div>
);
} 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'
);

View File

@ -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<HTMLButtonElement, PropsType>(
}
const sizeClassName = SIZE_CLASS_NAMES.get(size);
assert(sizeClassName, '<Button> size not found');
assertDev(sizeClassName, '<Button> size not found');
const variantClassName = VARIANT_CLASS_NAMES.get(variant);
assert(variantClassName, '<Button> variant not found');
assertDev(variantClassName, '<Button> variant not found');
const buttonElement = (
<button

View File

@ -9,7 +9,7 @@ import classNames from 'classnames';
import { get, pick } from 'lodash';
import { missingCaseError } from '../util/missingCaseError';
import { assert } from '../util/assert';
import { assertDev } from '../util/assert';
import type { ParsedE164Type } from '../util/libphonenumberInstance';
import type { LocalizerType, ThemeType } from '../types/Util';
import { ScrollBehavior } from '../types/Util';
@ -205,7 +205,7 @@ export const ConversationList: React.FC<PropsType> = ({
({ index }: { index: number }): number => {
const row = getRow(index);
if (!row) {
assert(false, `Expected a row at index ${index}`);
assertDev(false, `Expected a row at index ${index}`);
return NORMAL_ROW_HEIGHT;
}
switch (row.type) {
@ -223,7 +223,7 @@ export const ConversationList: React.FC<PropsType> = ({
({ key, index, style }) => {
const row = getRow(index);
if (!row) {
assert(false, `Expected a row at index ${index}`);
assertDev(false, `Expected a row at index ${index}`);
return <div key={key} style={style} />;
}

View File

@ -129,7 +129,6 @@ const GroupCallMessage = ({
}}
/>
);
break;
case 3:
return (
<Intl
@ -142,7 +141,6 @@ const GroupCallMessage = ({
}}
/>
);
break;
default:
return (
<Intl

View File

@ -20,7 +20,7 @@ import { ContactSpoofingReviewDialogPerson } from './ContactSpoofingReviewDialog
import { Button, ButtonVariant } from '../Button';
import { Intl } from '../Intl';
import { Emojify } from './Emojify';
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
import { missingCaseError } from '../../util/missingCaseError';
import { isInSystemContacts } from '../../util/isInSystemContacts';
@ -133,7 +133,7 @@ export const ContactSpoofingReviewDialog: FunctionComponent<
});
break;
case MessageRequestState.unblocking:
assert(
assertDev(
false,
'Got unexpected MessageRequestState.unblocking state. Clearing confiration state'
);
@ -175,11 +175,11 @@ export const ContactSpoofingReviewDialog: FunctionComponent<
switch (props.type) {
case ContactSpoofingType.DirectConversationWithSameTitle: {
const { possiblyUnsafeConversation, safeConversation } = props;
assert(
assertDev(
possiblyUnsafeConversation.type === 'direct',
'<ContactSpoofingReviewDialog> expected a direct conversation for the "possibly unsafe" conversation'
);
assert(
assertDev(
safeConversation.type === 'direct',
'<ContactSpoofingReviewDialog> expected a direct conversation for the "safe" conversation'
);

View File

@ -7,7 +7,7 @@ import React from 'react';
import type { ConversationType } from '../../state/ducks/conversations';
import type { LocalizerType, ThemeType } from '../../types/Util';
import type { PreferredBadgeSelectorType } from '../../state/selectors/badges';
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
import { Avatar, AvatarSize } from '../Avatar';
import { ContactName } from './ContactName';
@ -25,7 +25,7 @@ type PropsType = {
export const ContactSpoofingReviewDialogPerson: FunctionComponent<
PropsType
> = ({ children, conversation, getPreferredBadge, i18n, onClick, theme }) => {
assert(
assertDev(
conversation.type === 'direct',
'<ContactSpoofingReviewDialogPerson> expected a direct conversation'
);

View File

@ -11,7 +11,7 @@ import React, {
import classNames from 'classnames';
import { noop } from 'lodash';
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
import type { LocalizerType } from '../../types/Util';
import type { AttachmentType } from '../../types/Attachment';
import { isDownloaded } from '../../types/Attachment';
@ -226,7 +226,7 @@ export const MessageAudio: React.FC<Props> = (props: Props) => {
setActiveAudioID,
} = props;
assert(audio != null, 'GlobalAudioContext always provides audio');
assertDev(audio != null, 'GlobalAudioContext always provides audio');
const isActive =
activeAudioID === id && activeAudioContext === renderingContext;
@ -365,7 +365,7 @@ export const MessageAudio: React.FC<Props> = (props: Props) => {
};
const onLoadedMetadata = () => {
assert(
assertDev(
!Number.isNaN(audio.duration),
'Audio should have definite duration on `loadedmetadata` event'
);

View File

@ -13,7 +13,7 @@ import { ScrollDownButton } from './ScrollDownButton';
import type { AssertProps, LocalizerType, ThemeType } from '../../types/Util';
import type { ConversationType } from '../../state/ducks/conversations';
import type { PreferredBadgeSelectorType } from '../../state/selectors/badges';
import { assert, strictAssert } from '../../util/assert';
import { assertDev, strictAssert } from '../../util/assert';
import { missingCaseError } from '../../util/missingCaseError';
import { clearTimeoutIfNecessary } from '../../util/clearTimeoutIfNecessary';
import { WidthBreakpoint } from '../_util';
@ -522,7 +522,7 @@ export class Timeline extends React.Component<
this.intersectionObserver = new IntersectionObserver(
(entries, observer) => {
assert(
assertDev(
this.intersectionObserver === observer,
'observer.disconnect() should prevent callbacks from firing'
);
@ -630,7 +630,7 @@ export class Timeline extends React.Component<
return { scrollBottom: 0 };
case ScrollAnchor.ScrollToIndex:
if (scrollToIndex === undefined) {
assert(
assertDev(
false,
'<Timeline> got "scroll to index" scroll anchor, but no index'
);
@ -674,7 +674,7 @@ export class Timeline extends React.Component<
lastSeenIndicatorEl.scrollIntoView();
} else {
scrollToBottom(containerEl);
assert(
assertDev(
false,
'<Timeline> expected a last seen indicator but it was not found'
);
@ -942,7 +942,7 @@ export class Timeline extends React.Component<
const messageId = items[itemIndex];
if (!messageId) {
assert(
assertDev(
false,
'<Timeline> iterated through items and got an empty message ID'
);
@ -1058,7 +1058,7 @@ export class Timeline extends React.Component<
bounds
onResize={({ bounds }) => {
if (!bounds) {
assert(false, 'We should be measuring the bounds');
assertDev(false, 'We should be measuring the bounds');
return;
}
this.setState({ lastMeasuredWarningHeight: bounds.height });

View File

@ -5,7 +5,7 @@ import type { FunctionComponent, ReactNode } from 'react';
import React from 'react';
import type { LocalizerType } from '../../../../types/Util';
import { assert } from '../../../../util/assert';
import { assertDev } from '../../../../util/assert';
import { ModalHost } from '../../../ModalHost';
import { Button, ButtonVariant } from '../../../Button';
import { Spinner } from '../../../Spinner';
@ -35,7 +35,7 @@ export const ConfirmAdditionsModal: FunctionComponent<PropsType> = ({
selectedContacts,
}) => {
const firstContact = selectedContacts[0];
assert(
assertDev(
firstContact,
'Expected at least one conversation to be selected but none were picked'
);

View File

@ -10,7 +10,7 @@ import type { ConversationType } from '../../../state/ducks/conversations';
import type { PreferredBadgeSelectorType } from '../../../state/selectors/badges';
import type { SmartChooseGroupMembersModalPropsType } from '../../../state/smart/ChooseGroupMembersModal';
import type { SmartConfirmAdditionsModalPropsType } from '../../../state/smart/ConfirmAdditionsModal';
import { assert } from '../../../util/assert';
import { assertDev } from '../../../util/assert';
import { getMutedUntilText } from '../../../util/getMutedUntilText';
import type { LocalizerType, ThemeType } from '../../../types/Util';
@ -237,7 +237,7 @@ export const ConversationDetails: React.ComponentType<Props> = ({
renderConfirmAdditionsModal={renderConfirmAdditionsModal}
clearRequestError={() => {
setAddGroupMembersRequestState(oldRequestState => {
assert(
assertDev(
oldRequestState !== RequestState.Active,
'Should not be clearing an active request state'
);

View File

@ -8,7 +8,7 @@ import { escapeRegExp } from 'lodash';
import { MessageBodyHighlight } from './MessageBodyHighlight';
import { ContactName } from '../conversation/ContactName';
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
import type {
BodyRangesType,
LocalizerType,
@ -99,7 +99,7 @@ function getFilteredBodyRanges(
const rx = new RegExp(escapeRegExp(stripped));
const match = rx.exec(body);
assert(Boolean(match), `No match found for "${snippet}" inside "${body}"`);
assertDev(Boolean(match), `No match found for "${snippet}" inside "${body}"`);
const delta = match ? match.index + snippet.length : 0;
@ -125,7 +125,7 @@ function getFilteredBodyRanges(
start: bodyRangeMatch.index,
});
} else {
assert(
assertDev(
false,
`Body range does not exist? Count: ${i}, Length: ${filteredBodyRanges.length}`
);

View File

@ -251,6 +251,7 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
),
};
// eslint-disable-next-line no-unreachable -- Why is this here, its unreachable
virtualRowIndex -= 1;
}
}
@ -275,6 +276,7 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
),
};
// eslint-disable-next-line no-unreachable -- Why is this here, its unreachable
virtualRowIndex -= 1;
}
}

View File

@ -19,7 +19,7 @@ import { LeftPaneSearchInput } from '../LeftPaneSearchInput';
import { Intl } from '../Intl';
import { Emojify } from '../conversation/Emojify';
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
// The "correct" thing to do is to measure the size of the left pane and render enough
// search results for the container height. But (1) that's slow (2) the list is
@ -228,7 +228,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
i18nKey: 'conversationsHeader',
};
}
assert(
assertDev(
!conversationResults.isLoading,
"We shouldn't get here with conversation results still loading"
);
@ -249,7 +249,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
i18nKey: 'contactsHeader',
};
}
assert(
assertDev(
!contactResults.isLoading,
"We shouldn't get here with contact results still loading"
);
@ -273,7 +273,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
i18nKey: 'messagesHeader',
};
}
assert(
assertDev(
!messageResults.isLoading,
"We shouldn't get here with message results still loading"
);
@ -379,7 +379,7 @@ function getRowCountForLoadedSearchResults(
// We could change the parameter of this function, but that adds a bunch of redundant
// checks that are, in the author's opinion, less clear.
if (searchResults.isLoading) {
assert(
assertDev(
false,
'getRowCountForLoadedSearchResults: Expected this to be called with loaded search results. Returning 0'
);

View File

@ -20,7 +20,7 @@ import {
} from './services/groupCredentialFetcher';
import dataInterface from './sql/Client';
import { toWebSafeBase64, fromWebSafeBase64 } from './util/webSafeBase64';
import { assert, strictAssert } from './util/assert';
import { assertDev, strictAssert } from './util/assert';
import { isMoreRecentThan } from './util/timestamp';
import * as durations from './util/durations';
import { normalizeUuid } from './util/normalizeUuid';
@ -671,7 +671,7 @@ export async function buildAddMembersChange(
conversationIds.map(async conversationId => {
const contact = window.ConversationController.get(conversationId);
if (!contact) {
assert(
assertDev(
false,
`buildAddMembersChange/${logId}: missing local contact, skipping`
);
@ -680,7 +680,10 @@ export async function buildAddMembersChange(
const uuid = contact.getUuid();
if (!uuid) {
assert(false, `buildAddMembersChange/${logId}: missing UUID; skipping`);
assertDev(
false,
`buildAddMembersChange/${logId}: missing UUID; skipping`
);
return;
}
@ -1788,7 +1791,7 @@ export async function createGroupV2(
...conversationIds.map(async conversationId => {
const contact = window.ConversationController.get(conversationId);
if (!contact) {
assert(
assertDev(
false,
`createGroupV2/${logId}: missing local contact, skipping`
);
@ -1797,7 +1800,7 @@ export async function createGroupV2(
const contactUuid = contact.get('uuid');
if (!contactUuid) {
assert(false, `createGroupV2/${logId}: missing UUID; skipping`);
assertDev(false, `createGroupV2/${logId}: missing UUID; skipping`);
return;
}
@ -4143,7 +4146,7 @@ async function integrateGroupChange({
canApplyChange &&
(groupChangeMessages.length !== 0 || newMembers.length !== 0)
) {
assert(
assertDev(
groupChangeMessages.length === 0,
'Fallback group state processing should not kick in'
);

View File

@ -4,7 +4,7 @@
import type { KeyboardEvent } from 'react';
import React, { useState } from 'react';
import classNames from 'classnames';
import { assert } from '../util/assert';
import { assertDev } from '../util/assert';
import { getClassNamesFor } from '../util/getClassNamesFor';
type Tab = {
@ -28,7 +28,7 @@ export function useTabs({
selectedTab: string;
tabsHeaderElement: JSX.Element;
} {
assert(tabs.length, 'Tabs needs more than 1 tab present');
assertDev(tabs.length, 'Tabs needs more than 1 tab present');
const getClassName = getClassNamesFor('Tabs', moduleClassName);

View File

@ -8,7 +8,7 @@ import { noop } from 'lodash';
import { Job } from './Job';
import { JobError } from './JobError';
import type { ParsedJob, StoredJob, JobQueueStore } from './types';
import { assert } from '../util/assert';
import { assertDev } from '../util/assert';
import * as log from '../logging/log';
import { JobLogger } from './JobLogger';
import * as Errors from '../types/errors';
@ -67,15 +67,15 @@ export abstract class JobQueue<T> {
private started = false;
constructor(options: Readonly<JobQueueOptions>) {
assert(
assertDev(
Number.isInteger(options.maxAttempts) && options.maxAttempts >= 1,
'maxAttempts should be a positive integer'
);
assert(
assertDev(
options.maxAttempts <= Number.MAX_SAFE_INTEGER,
'maxAttempts is too large'
);
assert(
assertDev(
options.queueType.trim().length,
'queueType should be a non-blank string'
);
@ -188,7 +188,7 @@ export abstract class JobQueue<T> {
}
private async enqueueStoredJob(storedJob: Readonly<StoredJob>) {
assert(
assertDev(
storedJob.queueType === this.queueType,
'Received a mis-matched queue type'
);
@ -265,7 +265,7 @@ export abstract class JobQueue<T> {
await this.store.delete(storedJob.id);
assert(
assertDev(
result,
'The job never ran. This indicates a developer error in the job queue'
);

View File

@ -1,7 +1,7 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
import * as log from '../../logging/log';
import type { ConversationType } from '../../state/ducks/conversations';
import type { reportSpamJobQueue } from '../reportSpamJobQueue';
@ -17,7 +17,7 @@ export async function addReportSpamJob({
) => Promise<Array<string>>;
jobQueue: Pick<typeof reportSpamJobQueue, 'add'>;
}>): Promise<void> {
assert(
assertDev(
conversation.type === 'direct',
'addReportSpamJob: cannot report spam for non-direct conversations'
);

View File

@ -92,7 +92,6 @@ function logAtLevel(level: LogLevel, ...args: ReadonlyArray<unknown>): void {
if (!globalLogger) {
throw new Error('Logger has not been initialized yet');
return;
}
globalLogger[levelString](msg);

View File

@ -5,7 +5,7 @@ import { isNil, sortBy } from 'lodash';
import PQueue from 'p-queue';
import * as log from './logging/log';
import { assert } from './util/assert';
import { assertDev } from './util/assert';
import { sleep } from './util/sleep';
import { missingCaseError } from './util/missingCaseError';
import { isNormalNumber } from './util/isNormalNumber';
@ -177,7 +177,7 @@ function timeUntilNextRefresh(storage: Pick<StorageInterface, 'get'>): number {
return Math.min(Math.max(0, planned - now), WEEK);
}
assert(
assertDev(
false,
`An invalid value was stored in ${STORAGE_KEY}; treating it as nil`
);

View File

@ -99,7 +99,7 @@ import {
FALLBACK_NOTIFICATION_TITLE,
} from './notifications';
import * as log from '../logging/log';
import { assert } from '../util/assert';
import { assertDev } from '../util/assert';
const {
processGroupCallRingRequest,
@ -433,7 +433,7 @@ export class CallingClass {
switch (callMode) {
case CallMode.Direct:
// We could easily support this in the future if we need to.
assert(
assertDev(
hasLocalAudio,
'Expected local audio to be enabled for direct call lobbies'
);

View File

@ -86,6 +86,7 @@ export async function runWithRetry(
// It's important to schedule our next run here instead of the level above; otherwise we
// could end up with multiple endlessly-retrying runs.
// eslint-disable-next-line no-unreachable -- Why is this here, its unreachable
const duration = options.scheduleAnother;
if (duration) {
log.info(

View File

@ -1,7 +1,7 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from '../util/assert';
import { assertDev } from '../util/assert';
import * as log from '../logging/log';
import type { StorageInterface } from '../types/Storage.d';
@ -40,7 +40,7 @@ export class OurProfileKeyService {
async set(newValue: undefined | Uint8Array): Promise<void> {
log.info('Our profile key service: updating profile key');
assert(this.storage, 'OurProfileKeyService was not initialized');
assertDev(this.storage, 'OurProfileKeyService was not initialized');
if (newValue) {
await this.storage.put('profileKey', newValue);
} else {
@ -62,7 +62,7 @@ export class OurProfileKeyService {
delete this.getPromise;
assert(this.storage, 'OurProfileKeyService was not initialized');
assertDev(this.storage, 'OurProfileKeyService was not initialized');
log.info('Our profile key service: fetching profile key from storage');
const result = this.storage.get('profileKey');
@ -70,7 +70,7 @@ export class OurProfileKeyService {
return result;
}
assert(
assertDev(
false,
'Profile key in storage was defined, but not an Uint8Array. Returning undefined'
);

View File

@ -7,7 +7,7 @@ import {
serializedCertificateSchema,
} from '../textsecure/OutgoingMessage';
import * as Bytes from '../Bytes';
import { assert } from '../util/assert';
import { assertDev } from '../util/assert';
import { missingCaseError } from '../util/missingCaseError';
import { waitForOnline } from '../util/waitForOnline';
import * as log from '../logging/log';
@ -84,7 +84,7 @@ export class SenderCertificateService {
await Promise.all(this.fetchPromises.values());
const { storage } = this;
assert(
assertDev(
storage,
'Sender certificate service method was called before it was initialized'
);
@ -96,7 +96,7 @@ export class SenderCertificateService {
mode: SenderCertificateMode
): undefined | SerializedCertificateType {
const { storage } = this;
assert(
assertDev(
storage,
'Sender certificate service method was called before it was initialized'
);
@ -129,7 +129,7 @@ export class SenderCertificateService {
let promise: Promise<undefined | SerializedCertificateType>;
const doFetch = async () => {
const result = await this.fetchAndSaveCertificate(mode);
assert(
assertDev(
this.fetchPromises.get(mode) === promise,
'Sender certificate service was deleting a different promise than expected'
);
@ -138,7 +138,7 @@ export class SenderCertificateService {
};
promise = doFetch();
assert(
assertDev(
!this.fetchPromises.has(mode),
'Sender certificate service somehow already had a promise for this mode'
);
@ -150,7 +150,7 @@ export class SenderCertificateService {
mode: SenderCertificateMode
): Promise<undefined | SerializedCertificateType> {
const { storage, navigator, onlineEventTarget } = this;
assert(
assertDev(
storage && navigator && onlineEventTarget,
'Sender certificate service method was called before it was initialized'
);
@ -205,7 +205,7 @@ export class SenderCertificateService {
mode: SenderCertificateMode
): Promise<string> {
const { server } = this;
assert(
assertDev(
server,
'Sender certificate service method was called before it was initialized'
);

View File

@ -15,7 +15,7 @@ import {
waitThenMaybeUpdateGroup,
waitThenRespondToGroupV2Migration,
} from '../groups';
import { assert } from '../util/assert';
import { assertDev } from '../util/assert';
import { dropNull } from '../util/dropNull';
import { normalizeUuid } from '../util/normalizeUuid';
import { missingCaseError } from '../util/missingCaseError';
@ -1098,7 +1098,7 @@ export async function mergeAccountRecord(
phoneNumberSharingModeToStore = PhoneNumberSharingMode.Nobody;
break;
default:
assert(
assertDev(
false,
`storageService.mergeAccountRecord: Got an unexpected phone number sharing mode: ${phoneNumberSharingMode}. Falling back to default`
);
@ -1505,14 +1505,14 @@ export async function mergeStickerPackRecord(
);
if (localStickerPack && !wasUninstalled && isUninstalled) {
assert(localStickerPack.key, 'Installed sticker pack has no key');
assertDev(localStickerPack.key, 'Installed sticker pack has no key');
window.reduxActions.stickers.uninstallStickerPack(
localStickerPack.id,
localStickerPack.key,
{ fromStorageService: true }
);
} else if ((!localStickerPack || wasUninstalled) && !isUninstalled) {
assert(stickerPack.key, 'Sticker pack does not have key');
assertDev(stickerPack.key, 'Sticker pack does not have key');
const status = Stickers.getStickerPackStatus(stickerPack.id);
if (status === 'downloaded') {

View File

@ -27,7 +27,7 @@ import { tapToViewMessagesDeletionService } from '../services/tapToViewMessagesD
import * as Bytes from '../Bytes';
import { CURRENT_SCHEMA_VERSION } from '../types/Message2';
import { createBatcher } from '../util/batcher';
import { assert, softAssert, strictAssert } from '../util/assert';
import { assertDev, softAssert, strictAssert } from '../util/assert';
import { mapObjectWithSpec } from '../util/mapObjectWithSpec';
import type { ObjectMappingSpecType } from '../util/mapObjectWithSpec';
import { cleanDataForIpc } from './cleanDataForIpc';
@ -460,7 +460,7 @@ export function _cleanMessageData(data: MessageType): MessageType {
const result = { ...data };
// Ensure that all messages have the received_at set properly
if (!data.received_at) {
assert(false, 'received_at was not set on the message');
assertDev(false, 'received_at was not set on the message');
result.received_at = window.Signal.Util.incrementMessageCounter();
}
if (data.attachments) {
@ -1052,7 +1052,7 @@ const updateConversationBatcher = createBatcher<ConversationType>({
const ids = Object.keys(byId);
const mostRecent = ids.map((id: string): ConversationType => {
const maybeLast = last(byId[id]);
assert(maybeLast !== undefined, 'Empty array in `groupBy` result');
assertDev(maybeLast !== undefined, 'Empty array in `groupBy` result');
return maybeLast;
});
@ -1068,7 +1068,7 @@ async function updateConversations(
array: Array<ConversationType>
): Promise<void> {
const { cleaned, pathsChanged } = cleanDataForIpc(array);
assert(
assertDev(
!pathsChanged.length,
`Paths were cleaned: ${JSON.stringify(pathsChanged)}`
);

View File

@ -34,7 +34,7 @@ import { STORAGE_UI_KEYS } from '../types/StorageUIKeys';
import { UUID } from '../types/UUID';
import type { UUIDStringType } from '../types/UUID';
import type { StoredJob } from '../jobs/types';
import { assert, assertSync, strictAssert } from '../util/assert';
import { assertDev, assertSync, strictAssert } from '../util/assert';
import { combineNames } from '../util/combineNames';
import { consoleLogger } from '../util/consoleLogger';
import { dropNull } from '../util/dropNull';
@ -376,7 +376,7 @@ function rowToConversation(row: ConversationRow): ConversationType {
if (isNormalNumber(row.profileLastFetchedAt)) {
profileLastFetchedAt = row.profileLastFetchedAt;
} else {
assert(
assertDev(
isNil(row.profileLastFetchedAt),
'profileLastFetchedAt contained invalid data; defaulting to undefined'
);

View File

@ -7,7 +7,7 @@ import { omit } from 'lodash';
import type { LoggerType } from '../../types/Logging';
import type { UUIDStringType } from '../../types/UUID';
import { isNotNil } from '../../util/isNotNil';
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
import {
TableIterator,
getCountFromTable,
@ -225,7 +225,7 @@ export default function updateToSchemaVersion43(
let result = message;
if (groupV2Change) {
assert(result.groupV2Change, 'Pacify typescript');
assertDev(result.groupV2Change, 'Pacify typescript');
const from: UUIDStringType | undefined = getConversationUuid.get({
conversationId: groupV2Change.from,
@ -250,7 +250,7 @@ export default function updateToSchemaVersion43(
const details = groupV2Change.details
.map((legacyDetail, i) => {
const oldDetail = result.groupV2Change?.details[i];
assert(oldDetail, 'Pacify typescript');
assertDev(oldDetail, 'Pacify typescript');
let newDetail = oldDetail;
for (const key of ['conversationId' as const, 'inviter' as const]) {
@ -276,7 +276,10 @@ export default function updateToSchemaVersion43(
return undefined;
}
assert(newDetail.type === legacyDetail.type, 'Pacify typescript');
assertDev(
newDetail.type === legacyDetail.type,
'Pacify typescript'
);
newDetail = {
...omit(newDetail, key),
[newKey]: newValue,
@ -319,7 +322,7 @@ export default function updateToSchemaVersion43(
});
const oldMember =
result.invitedGV2Members && result.invitedGV2Members[i];
assert(oldMember !== undefined, 'Pacify typescript');
assertDev(oldMember !== undefined, 'Pacify typescript');
if (!uuid) {
logger.warn(

View File

@ -19,7 +19,7 @@ import * as groups from '../../groups';
import * as log from '../../logging/log';
import { calling } from '../../services/calling';
import { getOwn } from '../../util/getOwn';
import { assert, strictAssert } from '../../util/assert';
import { assertDev, strictAssert } from '../../util/assert';
import * as universalExpireTimer from '../../util/universalExpireTimer';
import type {
ShowSendAnywayDialogActiontype,
@ -1533,7 +1533,7 @@ function createGroup(
composer?.step !== ComposerStep.SetGroupMetadata ||
composer.isCreating
) {
assert(false, 'Cannot create group in this stage; doing nothing');
assertDev(false, 'Cannot create group in this stage; doing nothing');
return;
}
@ -1915,7 +1915,7 @@ function toggleConversationInChooseMembers(
maxRecommendedGroupSize + 1
);
assert(
assertDev(
maxGroupSize > maxRecommendedGroupSize,
'Expected the hard max group size to be larger than the recommended maximum'
);
@ -2157,7 +2157,10 @@ function closeComposerModal(
): ConversationsStateType {
const { composer } = state;
if (composer?.step !== ComposerStep.ChooseGroupMembers) {
assert(false, "Can't close the modal in this composer step. Doing nothing");
assertDev(
false,
"Can't close the modal in this composer step. Doing nothing"
);
return state;
}
if (composer[modalToClose] !== OneTimeModalState.Showing) {
@ -2292,7 +2295,7 @@ export function reducer(
if (action.type === 'CLEAR_GROUP_CREATION_ERROR') {
const { composer } = state;
if (composer?.step !== ComposerStep.SetGroupMetadata) {
assert(
assertDev(
false,
"Can't clear group creation error in this composer state. Doing nothing"
);
@ -3263,7 +3266,7 @@ export function reducer(
case ComposerStep.SetGroupMetadata:
return state;
default:
assert(
assertDev(
false,
'Cannot transition to setting group metadata from this state'
);
@ -3285,7 +3288,10 @@ export function reducer(
},
};
default:
assert(false, 'Setting compose group avatar at this step is a no-op');
assertDev(
false,
'Setting compose group avatar at this step is a no-op'
);
return state;
}
}
@ -3304,7 +3310,7 @@ export function reducer(
},
};
default:
assert(false, 'Setting compose group name at this step is a no-op');
assertDev(false, 'Setting compose group name at this step is a no-op');
return state;
}
}
@ -3323,7 +3329,7 @@ export function reducer(
},
};
default:
assert(false, 'Setting compose group name at this step is a no-op');
assertDev(false, 'Setting compose group name at this step is a no-op');
return state;
}
}
@ -3331,7 +3337,7 @@ export function reducer(
if (action.type === 'SET_COMPOSE_SEARCH_TERM') {
const { composer } = state;
if (!composer) {
assert(
assertDev(
false,
'Setting compose search term with the composer closed is a no-op'
);
@ -3341,7 +3347,7 @@ export function reducer(
composer.step !== ComposerStep.StartDirectConversation &&
composer.step !== ComposerStep.ChooseGroupMembers
) {
assert(
assertDev(
false,
`Setting compose search term at step ${composer.step} is a no-op`
);
@ -3360,7 +3366,7 @@ export function reducer(
if (action.type === 'SET_IS_FETCHING_UUID') {
const { composer } = state;
if (!composer) {
assert(
assertDev(
false,
'Setting compose uuid fetch state with the composer closed is a no-op'
);
@ -3370,7 +3376,10 @@ export function reducer(
composer.step !== ComposerStep.StartDirectConversation &&
composer.step !== ComposerStep.ChooseGroupMembers
) {
assert(false, 'Setting compose uuid fetch state at this step is a no-op');
assertDev(
false,
'Setting compose uuid fetch state at this step is a no-op'
);
return state;
}
const { identifier, isFetching } = action.payload;
@ -3404,7 +3413,7 @@ export function reducer(
},
};
default:
assert(false, 'Setting editing avatar at this step is a no-op');
assertDev(false, 'Setting editing avatar at this step is a no-op');
return state;
}
}
@ -3430,7 +3439,7 @@ export function reducer(
},
};
default:
assert(false, 'Adding an avatar at this step is a no-op');
assertDev(false, 'Adding an avatar at this step is a no-op');
return state;
}
}
@ -3450,7 +3459,7 @@ export function reducer(
},
};
default:
assert(false, 'Removing an avatar at this step is a no-op');
assertDev(false, 'Removing an avatar at this step is a no-op');
return state;
}
}
@ -3478,7 +3487,7 @@ export function reducer(
},
};
default:
assert(false, 'Replacing an avatar at this step is a no-op');
assertDev(false, 'Replacing an avatar at this step is a no-op');
return state;
}
}
@ -3486,7 +3495,7 @@ export function reducer(
if (action.type === 'TOGGLE_CONVERSATION_IN_CHOOSE_MEMBERS') {
const { composer } = state;
if (composer?.step !== ComposerStep.ChooseGroupMembers) {
assert(
assertDev(
false,
'Toggling conversation members is a no-op in this composer step'
);

View File

@ -25,7 +25,7 @@ import { SafetyNumberChangeSource } from '../../components/SafetyNumberChangeDia
import { StoryViewDirectionType, StoryViewModeType } from '../../types/Stories';
import { StoryRecipientUpdateEvent } from '../../textsecure/messageReceiverEvents';
import { ToastReactionFailed } from '../../components/ToastReactionFailed';
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
import { blockSendUntilConversationsAreVerified } from '../../util/blockSendUntilConversationsAreVerified';
import { enqueueReactionForSend } from '../../reactions/enqueueReactionForSend';
import { getMessageById } from '../../messages/getMessageById';
@ -611,11 +611,11 @@ function sendStoryMessage(
return async (dispatch, getState) => {
const { stories } = getState();
const { openedAtTimestamp, sendStoryModalData } = stories;
assert(
assertDev(
openedAtTimestamp,
'sendStoryMessage: openedAtTimestamp is undefined, cannot send'
);
assert(
assertDev(
sendStoryModalData,
'sendStoryMessage: sendStoryModalData is not defined, cannot send'
);

View File

@ -28,7 +28,7 @@ import type { UUIDFetchStateType } from '../../util/uuidFetchState';
import { deconstructLookup } from '../../util/deconstructLookup';
import type { PropsDataType as TimelinePropsType } from '../../components/conversation/Timeline';
import type { TimelineItemType } from '../../components/conversation/TimelineItem';
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
import { isConversationUnregistered } from '../../util/isConversationUnregistered';
import { filterAndSortConversationsByRecent } from '../../util/filterAndSortConversations';
import type { ContactNameColorType } from '../../types/Colors';
@ -344,7 +344,7 @@ export const getMaximumGroupSizeModalState = createSelector(
case ComposerStep.SetGroupMetadata:
return composerState.maximumGroupSizeModalState;
default:
assert(
assertDev(
false,
'Can\'t get the maximum group size modal state in this composer state; returning "never shown"'
);
@ -361,7 +361,7 @@ export const getRecommendedGroupSizeModalState = createSelector(
case ComposerStep.SetGroupMetadata:
return composerState.recommendedGroupSizeModalState;
default:
assert(
assertDev(
false,
'Can\'t get the recommended group size modal state in this composer state; returning "never shown"'
);
@ -388,11 +388,14 @@ export const getComposerConversationSearchTerm = createSelector(
getComposerState,
(composer): string => {
if (!composer) {
assert(false, 'getComposerConversationSearchTerm: composer is not open');
assertDev(
false,
'getComposerConversationSearchTerm: composer is not open'
);
return '';
}
if (composer.step === ComposerStep.SetGroupMetadata) {
assert(
assertDev(
false,
'getComposerConversationSearchTerm: composer does not have a search term'
);
@ -406,14 +409,14 @@ export const getComposerUUIDFetchState = createSelector(
getComposerState,
(composer): UUIDFetchStateType => {
if (!composer) {
assert(false, 'getIsFetchingUsername: composer is not open');
assertDev(false, 'getIsFetchingUsername: composer is not open');
return {};
}
if (
composer.step !== ComposerStep.StartDirectConversation &&
composer.step !== ComposerStep.ChooseGroupMembers
) {
assert(
assertDev(
false,
`getComposerUUIDFetchState: step ${composer.step} ` +
'has no uuidFetchState key'
@ -583,7 +586,7 @@ const getGroupCreationComposerState = createSelector(
case ComposerStep.SetGroupMetadata:
return composerState;
default:
assert(
assertDev(
false,
'getSetGroupMetadataComposerState: expected step to be SetGroupMetadata'
);

View File

@ -3,7 +3,7 @@
import { createSelector } from 'reselect';
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
import { getDomain } from '../../types/LinkPreview';
import type { LinkPreviewSourceType } from '../../types/LinkPreview';
@ -22,7 +22,10 @@ export const getLinkPreview = createSelector(
}
const domain = getDomain(linkPreview.url);
assert(domain !== undefined, "Domain of linkPreview can't be undefined");
assertDev(
domain !== undefined,
"Domain of linkPreview can't be undefined"
);
return {
...linkPreview,

View File

@ -21,7 +21,7 @@ import {
getBadgesSelector,
getPreferredBadgeSelector,
} from '../selectors/badges';
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
import { SignalService as Proto } from '../../protobuf';
import { getConversationColorAttributes } from '../../util/getConversationColorAttributes';
import type { SmartChooseGroupMembersModalPropsType } from './ChooseGroupMembersModal';
@ -78,7 +78,7 @@ const mapStateToProps = (
): StateProps => {
const conversationSelector = getConversationByIdSelector(state);
const conversation = conversationSelector(props.conversationId);
assert(
assertDev(
conversation,
'<SmartConversationDetails> expected a conversation to be found'
);

View File

@ -10,7 +10,7 @@ import { getIntl } from '../selectors/user';
import * as log from '../../logging/log';
import type { Loadable } from '../../util/loadable';
import { LoadingState } from '../../util/loadable';
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
import { explodePromise } from '../../util/explodePromise';
import { missingCaseError } from '../../util/missingCaseError';
import {
@ -134,7 +134,7 @@ export function SmartInstallScreen(): ReactElement {
let deviceName: string = normalizeDeviceName(state.deviceName);
if (!deviceName.length) {
// This should be impossible, but we have it here just in case.
assert(
assertDev(
false,
'Unexpected empty device name. Falling back to placeholder value'
);
@ -149,7 +149,7 @@ export function SmartInstallScreen(): ReactElement {
let hasCleanedUp = false;
const accountManager = window.getAccountManager();
assert(accountManager, 'Expected an account manager');
assertDev(accountManager, 'Expected an account manager');
const updateProvisioningUrl = (value: string): void => {
if (hasCleanedUp) {

View File

@ -14,7 +14,7 @@ import {
getConversationByUuidSelector,
} from '../selectors/conversations';
import { getGroupMemberships } from '../../util/getGroupMemberships';
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
import type { UUIDStringType } from '../../types/UUID';
export type SmartPendingInvitesProps = {
@ -32,7 +32,7 @@ const mapStateToProps = (
const conversationByUuidSelector = getConversationByUuidSelector(state);
const conversation = conversationSelector(props.conversationId);
assert(
assertDev(
conversation,
'<SmartPendingInvites> expected a conversation to be found'
);

View File

@ -38,7 +38,7 @@ import { renderEmojiPicker } from './renderEmojiPicker';
import { renderReactionPicker } from './renderReactionPicker';
import { getOwn } from '../../util/getOwn';
import { assert } from '../../util/assert';
import { assertDev } from '../../util/assert';
import { missingCaseError } from '../../util/missingCaseError';
import { getGroupMemberships } from '../../util/getGroupMemberships';
import {
@ -177,7 +177,7 @@ const getWarning = (
const conversationsWithSameTitle = getConversationsWithTitle(
conversation.title
);
assert(
assertDev(
conversationsWithSameTitle.length,
'Expected at least 1 conversation with the same title (this one)'
);

View File

@ -3,17 +3,17 @@
import { assert as chaiAssert } from 'chai';
import { assert, strictAssert } from '../../util/assert';
import { assertDev, strictAssert } from '../../util/assert';
describe('assert utilities', () => {
describe('assert', () => {
it('does nothing if the assertion passes', () => {
assert(true, 'foo bar');
assertDev(true, 'foo bar');
});
it("throws if the assertion fails, because we're in a test environment", () => {
chaiAssert.throws(() => {
assert(false, 'foo bar');
assertDev(false, 'foo bar');
}, 'foo bar');
});
});

View File

@ -304,7 +304,6 @@ describe('JobQueue', () => {
case 'bar':
barAttempts += 1;
throw new Error('bar job always fails in this test');
break;
default:
throw missingCaseError(data);
}

View File

@ -30,7 +30,7 @@ import {
import { UUID, UUIDKind } from '../types/UUID';
import { isMoreRecentThan, isOlderThan } from '../util/timestamp';
import { ourProfileKeyService } from '../services/ourProfileKey';
import { assert, strictAssert } from '../util/assert';
import { assertDev, strictAssert } from '../util/assert';
import { getRegionCodeForNumber } from '../util/libphonenumberUtil';
import { getProvisioningUrl } from '../util/getProvisioningUrl';
import { isNotNil } from '../util/isNotNil';
@ -114,7 +114,7 @@ export default class AccountManager extends EventTarget {
const bytes = Bytes.fromBase64(base64);
const proto = Proto.DeviceName.decode(bytes);
assert(
assertDev(
proto.ephemeralPublic && proto.syntheticIv && proto.ciphertext,
'Missing required fields in DeviceName'
);

View File

@ -16,7 +16,7 @@ import {
import type { QuotedMessageType } from '../model-types.d';
import type { ConversationModel } from '../models/conversations';
import { GLOBAL_ZONE } from '../SignalProtocolStore';
import { assert, strictAssert } from '../util/assert';
import { assertDev, strictAssert } from '../util/assert';
import { parseIntOrThrow } from '../util/parseIntOrThrow';
import { Address } from '../types/Address';
import { QualifiedAddress } from '../types/QualifiedAddress';
@ -673,7 +673,7 @@ export default class MessageSender {
Pick<AttachmentType, 'data' | 'size' | 'contentType'>
>
): Promise<Proto.IAttachmentPointer> {
assert(
assertDev(
typeof attachment === 'object' && attachment != null,
'Got null attachment in `makeAttachmentPointer`'
);
@ -1300,7 +1300,7 @@ export default class MessageSender {
timestamp: number;
urgent: boolean;
}>): Promise<CallbackResultType> {
assert(identifier, "Identifier can't be undefined");
assertDev(identifier, "Identifier can't be undefined");
return new Promise((resolve, reject) => {
const callback = (res: CallbackResultType) => {
if (res && res.errors && res.errors.length > 0) {

View File

@ -8,7 +8,7 @@ import type {
import { User } from './storage/User';
import { Blocked } from './storage/Blocked';
import { assert } from '../util/assert';
import { assertDev } from '../util/assert';
import Data from '../sql/Client';
import type { SignalProtocolStore } from '../SignalProtocolStore';
import * as log from '../logging/log';
@ -34,7 +34,7 @@ export class Storage implements StorageInterface {
}
get protocol(): SignalProtocolStore {
assert(
assertDev(
this.privProtocol !== undefined,
'SignalProtocolStore not initialized'
);

View File

@ -9,7 +9,7 @@ import EventTarget from './EventTarget';
import MessageReceiver from './MessageReceiver';
import type { ContactSyncEvent, GroupSyncEvent } from './messageReceiverEvents';
import MessageSender from './SendMessage';
import { assert } from '../util/assert';
import { assertDev } from '../util/assert';
import * as log from '../logging/log';
import { singleProtoJobQueue } from '../jobs/singleProtoJobQueue';
import * as Errors from '../types/errors';
@ -49,7 +49,10 @@ class SyncRequestInner extends EventTarget {
async start(): Promise<void> {
if (this.started) {
assert(false, 'SyncRequestInner: started more than once. Doing nothing');
assertDev(
false,
'SyncRequestInner: started more than once. Doing nothing'
);
return;
}
this.started = true;

View File

@ -18,7 +18,7 @@ import { v4 as getGuid } from 'uuid';
import { z } from 'zod';
import type { Readable } from 'stream';
import { assert, strictAssert } from '../util/assert';
import { assertDev, strictAssert } from '../util/assert';
import { isRecord } from '../util/isRecord';
import * as durations from '../util/durations';
import type { ExplodePromiseResultType } from '../util/explodePromise';
@ -391,7 +391,7 @@ async function _promiseAjax(
log.info(logId, response.status, 'Success');
if (options.responseType === 'byteswithdetails') {
assert(result instanceof Uint8Array, 'Expected Uint8Array result');
assertDev(result instanceof Uint8Array, 'Expected Uint8Array result');
const fullResult: BytesWithDetailsType = {
data: result,
contentType: getContentType(response),

View File

@ -5,7 +5,7 @@ import Long from 'long';
import { ReceiptCredentialPresentation } from '@signalapp/libsignal-client/zkgroup';
import { isNumber } from 'lodash';
import { assert, strictAssert } from '../util/assert';
import { assertDev, strictAssert } from '../util/assert';
import { dropNull, shallowDropNull } from '../util/dropNull';
import { SignalService as Proto } from '../protobuf';
import { deriveGroupFields } from '../groups';
@ -331,7 +331,7 @@ export async function processDataMessage(
isExpirationTimerUpdate,
isProfileKeyUpdate,
].filter(Boolean).length;
assert(
assertDev(
flagCount <= 1,
`Expected exactly <=1 flags to be set, but got ${flagCount}`
);

View File

@ -4,7 +4,7 @@
import type { ConversationController } from './ConversationController';
import type { ConversationModel } from './models/conversations';
import type { WebAPIType } from './textsecure/WebAPI';
import { assert } from './util/assert';
import { assertDev } from './util/assert';
import { isNotNil } from './util/isNotNil';
import { getUuidsForE164s } from './util/getUuidsForE164s';
@ -47,7 +47,7 @@ export async function updateConversationsWithUuidLookup({
e164,
reason: 'updateConversationsWithUuidLookup',
});
assert(
assertDev(
maybeFinalConversation,
'updateConversationsWithUuidLookup: expected a conversation to be found or created'
);

View File

@ -22,7 +22,10 @@ export function softAssert(condition: unknown, message: string): void {
/**
* In production, logs an error and continues. In all other environments, throws an error.
*/
export function assert(condition: unknown, message: string): asserts condition {
export function assertDev(
condition: unknown,
message: string
): asserts condition {
if (!condition) {
const err = new Error(message);
if (getEnvironment() !== Environment.Production) {

View File

@ -31,7 +31,7 @@ import { renderClearingDataView } from '../shims/renderClearingDataView';
import * as universalExpireTimer from './universalExpireTimer';
import { PhoneNumberDiscoverability } from './phoneNumberDiscoverability';
import { PhoneNumberSharingMode } from './phoneNumberSharingMode';
import { assert } from './assert';
import { assertDev } from './assert';
import * as durations from './durations';
import { isPhoneNumberSharingEnabled } from './isPhoneNumberSharingEnabled';
import { parseE164FromSignalDotMeHash } from './sgnlHref';
@ -360,7 +360,7 @@ export function createIPCEvents(
const conversationId =
window.ConversationController.getOurConversationIdOrThrow();
const account = window.ConversationController.get(conversationId);
assert(account, "Account wasn't found");
assertDev(account, "Account wasn't found");
account.captureChange('universalExpireTimer');
@ -369,7 +369,7 @@ export function createIPCEvents(
const selectedId = state.conversations.selectedConversationId;
if (selectedId) {
const conversation = window.ConversationController.get(selectedId);
assert(conversation, "Conversation wasn't found");
assertDev(conversation, "Conversation wasn't found");
await conversation.updateLastMessage();
}

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
import { getOwn } from './getOwn';
import { assert } from './assert';
import { assertDev } from './assert';
export const deconstructLookup = <T>(
lookup: Record<string, T>,
@ -14,7 +14,7 @@ export const deconstructLookup = <T>(
if (value) {
result.push(value);
} else {
assert(false, `deconstructLookup: lookup failed for ${key}; dropping`);
assertDev(false, `deconstructLookup: lookup failed for ${key}; dropping`);
}
});
return result;

View File

@ -3,7 +3,7 @@
import emojiRegex from 'emoji-regex';
import { assert } from './assert';
import { assertDev } from './assert';
import { take } from './iterables';
const REGEXP = emojiRegex();
@ -31,7 +31,7 @@ export function splitByEmoji(value: string): ReadonlyArray<SplitElement> {
result.push({ type: 'emoji', value: match[0] });
assert(match.index !== undefined, '`matchAll` should provide indices');
assertDev(match.index !== undefined, '`matchAll` should provide indices');
lastIndex = match.index + match[0].length;
}

View File

@ -3,7 +3,7 @@
import type { ConversationType } from '../state/ducks/conversations';
import type { ProfileRequestDataType } from '../textsecure/WebAPI';
import { assert } from './assert';
import { assertDev } from './assert';
import * as Bytes from '../Bytes';
import {
PaddedLengths,
@ -27,8 +27,8 @@ export async function encryptProfileData(
uuid,
} = conversation;
assert(profileKey, 'profileKey');
assert(uuid, 'uuid');
assertDev(profileKey, 'profileKey');
assertDev(uuid, 'uuid');
const keyBuffer = Bytes.fromBase64(profileKey);

View File

@ -5,7 +5,7 @@ import { PublicKey, Fingerprint } from '@signalapp/libsignal-client';
import type { ConversationType } from '../state/ducks/conversations';
import { UUID } from '../types/UUID';
import { assert } from './assert';
import { assertDev } from './assert';
import * as log from '../logging/log';
export async function generateSecurityNumber(
@ -63,7 +63,7 @@ export async function generateSecurityNumberBlock(
return [];
}
assert(ourNumber, 'Should have our number');
assertDev(ourNumber, 'Should have our number');
const securityNumber = await generateSecurityNumber(
ourNumber,
ourKey,

View File

@ -1,10 +1,10 @@
// Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from './assert';
import { assertDev } from './assert';
export function shouldNeverBeCalled(..._args: ReadonlyArray<unknown>): void {
assert(false, 'This should never be called. Doing nothing');
assertDev(false, 'This should never be called. Doing nothing');
}
export async function asyncShouldNeverBeCalled(

View File

@ -29,6 +29,8 @@
// As a temporary measure
"useUnknownInCatchVariables": false,
// Temp: The `assertDev()` function doesn't run in production so we can't rely on this
"allowUnreachableCode": true,
// Additional Checks
"noUnusedLocals": true, // Report errors on unused locals.