Use esbuild

This commit is contained in:
Fedor Indutny 2022-02-11 13:38:52 -08:00 committed by GitHub
parent 3c1ccce9bd
commit 0174687542
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 528 additions and 906 deletions

1
.gitignore vendored
View file

@ -42,3 +42,4 @@ sticker-creator/dist/*
/.idea /.idea
/.vscode /.vscode
*.sublime* *.sublime*
*.map

View file

@ -37,8 +37,11 @@ if (getEnvironment() === Environment.Production) {
} }
// We load config after we've made our modifications to NODE_ENV // We load config after we've made our modifications to NODE_ENV
// eslint-disable-next-line import/order, import/first // Note: we use `require()` because esbuild moves the imports to the top of
import config from 'config'; // the module regardless of their actual placement in the file.
// See: https://github.com/evanw/esbuild/issues/2011
// eslint-disable-next-line @typescript-eslint/no-var-requires
const config: IConfig = require('config');
// Log resulting env vars in use by config // Log resulting env vars in use by config
[ [

View file

@ -480,9 +480,9 @@ async function createWindow() {
contextIsolation: false, contextIsolation: false,
preload: join( preload: join(
__dirname, __dirname,
enableCI || getEnvironment() === Environment.Production isTestEnvironment(getEnvironment())
? '../preload.bundle.js' ? '../preload.js'
: '../preload.js' : '../preload.bundle.js'
), ),
nativeWindowOpen: true, nativeWindowOpen: true,
spellcheck: await getSpellCheckSetting(), spellcheck: await getSpellCheckSetting(),

View file

@ -42,14 +42,17 @@
"lint-deps": "node ts/util/lint/linter.js", "lint-deps": "node ts/util/lint/linter.js",
"lint-license-comments": "ts-node ts/util/lint/license_comments.ts", "lint-license-comments": "ts-node ts/util/lint/license_comments.ts",
"format": "prettier --write \"*.{html,css,js,json,md,scss,ts,tsx}\" \"./**/*.{html,css,js,json,md,scss,ts,tsx}\"", "format": "prettier --write \"*.{html,css,js,json,md,scss,ts,tsx}\" \"./**/*.{html,css,js,json,md,scss,ts,tsx}\"",
"transpile": "tsc", "transpile": "run-p check:types build:esbuild",
"check:types": "tsc --noEmit",
"clean-transpile-once": "rimraf app/**/*.js app/*.js ts/**/*.js ts/*.js tsconfig.tsbuildinfo", "clean-transpile-once": "rimraf app/**/*.js app/*.js ts/**/*.js ts/*.js tsconfig.tsbuildinfo",
"clean-transpile": "yarn run clean-transpile-once && yarn run clean-transpile-once", "clean-transpile": "yarn run clean-transpile-once && yarn run clean-transpile-once",
"open-coverage": "open coverage/lcov-report/index.html", "open-coverage": "open coverage/lcov-report/index.html",
"ready": "npm-run-all --print-label clean-transpile generate --parallel lint lint-deps test-node test-electron", "ready": "npm-run-all --print-label clean-transpile generate --parallel lint lint-deps test-node test-electron",
"dev": "run-p --print-label dev:*", "dev": "run-p --print-label dev:*",
"dev:transpile": "yarn run transpile --watch --preserveWatchOutput", "dev:transpile": "run-p \"check:types --watch\" dev:esbuild",
"dev:webpack": "cross-env NODE_ENV=development webpack serve --mode development", "dev:webpack": "run-p dev:esbuild dev:webpack:sticker-creator",
"dev:webpack:sticker-creator": "cross-env NODE_ENV=development webpack serve --mode development",
"dev:esbuild": "node scripts/esbuild.js --watch",
"dev:typed-scss": "yarn build:typed-scss -w", "dev:typed-scss": "yarn build:typed-scss -w",
"dev:storybook": "cross-env SIGNAL_ENV=storybook start-storybook -p 6006 -s ./", "dev:storybook": "cross-env SIGNAL_ENV=storybook start-storybook -p 6006 -s ./",
"dev:sass": "yarn sass --watch", "dev:sass": "yarn sass --watch",
@ -58,11 +61,9 @@
"build:acknowledgments": "node scripts/generate-acknowledgments.js", "build:acknowledgments": "node scripts/generate-acknowledgments.js",
"build:dev": "run-s --print-label generate build:typed-scss build:webpack", "build:dev": "run-s --print-label generate build:typed-scss build:webpack",
"build:typed-scss": "tsm sticker-creator", "build:typed-scss": "tsm sticker-creator",
"build:webpack": "run-p build:webpack:sticker-creator build:webpack:preload build:webpack:sql-worker build:webpack:heic-worker", "build:webpack": "run-p build:webpack:sticker-creator \"build:esbuild --prod\"",
"build:webpack:sticker-creator": "cross-env NODE_ENV=production webpack", "build:webpack:sticker-creator": "cross-env NODE_ENV=production webpack",
"build:webpack:preload": "cross-env NODE_ENV=production webpack -c webpack-preload.config.ts", "build:esbuild": "node scripts/esbuild.js",
"build:webpack:sql-worker": "cross-env NODE_ENV=production webpack -c webpack-sql-worker.config.ts",
"build:webpack:heic-worker": "cross-env NODE_ENV=production webpack -c webpack-heic-worker.config.ts",
"build:electron": "electron-builder --config.extraMetadata.environment=$SIGNAL_ENV", "build:electron": "electron-builder --config.extraMetadata.environment=$SIGNAL_ENV",
"build:release": "cross-env SIGNAL_ENV=production yarn build:electron -- --config.directories.output=release", "build:release": "cross-env SIGNAL_ENV=production yarn build:electron -- --config.directories.output=release",
"build:zip": "node ts/scripts/zip-macos-release.js", "build:zip": "node ts/scripts/zip-macos-release.js",
@ -78,7 +79,7 @@
"@evanhahn/lottie-web-light": "5.8.1", "@evanhahn/lottie-web-light": "5.8.1",
"@popperjs/core": "2.9.2", "@popperjs/core": "2.9.2",
"@react-spring/web": "9.4.1", "@react-spring/web": "9.4.1",
"@signalapp/signal-client": "0.11.1", "@signalapp/signal-client": "0.12.4",
"@sindresorhus/is": "0.8.0", "@sindresorhus/is": "0.8.0",
"@types/fabric": "4.5.3", "@types/fabric": "4.5.3",
"abort-controller": "3.0.0", "abort-controller": "3.0.0",
@ -258,6 +259,7 @@
"electron-builder": "22.14.5", "electron-builder": "22.14.5",
"electron-mocha": "11.0.2", "electron-mocha": "11.0.2",
"electron-notarize": "0.1.1", "electron-notarize": "0.1.1",
"esbuild": "0.14.3",
"eslint": "7.7.0", "eslint": "7.7.0",
"eslint-config-airbnb-typescript-prettier": "4.2.0", "eslint-config-airbnb-typescript-prettier": "4.2.0",
"eslint-config-prettier": "6.11.0", "eslint-config-prettier": "6.11.0",

View file

@ -70,7 +70,7 @@ index 262776b..156cf0f 100644
this._cellHeightCache[key] = height; this._cellHeightCache[key] = height;
this._cellWidthCache[key] = width; this._cellWidthCache[key] = width;
diff --git a/node_modules/react-virtualized/dist/commonjs/Grid/Grid.js b/node_modules/react-virtualized/dist/commonjs/Grid/Grid.js diff --git a/node_modules/react-virtualized/dist/commonjs/Grid/Grid.js b/node_modules/react-virtualized/dist/commonjs/Grid/Grid.js
index e1b959a..97d6ef9 100644 index e1b959a..09c16c5 100644
--- a/node_modules/react-virtualized/dist/commonjs/Grid/Grid.js --- a/node_modules/react-virtualized/dist/commonjs/Grid/Grid.js
+++ b/node_modules/react-virtualized/dist/commonjs/Grid/Grid.js +++ b/node_modules/react-virtualized/dist/commonjs/Grid/Grid.js
@@ -132,6 +132,9 @@ var Grid = function (_React$PureComponent) { @@ -132,6 +132,9 @@ var Grid = function (_React$PureComponent) {
@ -442,3 +442,13 @@ index b5ad0eb..efb2cd7 100644
}, _this._onSectionRendered = function (_ref4) { }, _this._onSectionRendered = function (_ref4) {
var rowOverscanStartIndex = _ref4.rowOverscanStartIndex, var rowOverscanStartIndex = _ref4.rowOverscanStartIndex,
rowOverscanStopIndex = _ref4.rowOverscanStopIndex, rowOverscanStopIndex = _ref4.rowOverscanStopIndex,
diff --git a/node_modules/react-virtualized/dist/es/WindowScroller/utils/onScroll.js b/node_modules/react-virtualized/dist/es/WindowScroller/utils/onScroll.js
index 6418a78..afbc3c3 100644
--- a/node_modules/react-virtualized/dist/es/WindowScroller/utils/onScroll.js
+++ b/node_modules/react-virtualized/dist/es/WindowScroller/utils/onScroll.js
@@ -72,4 +72,3 @@ export function unregisterScrollListener(component, element) {
}
}
}
-import { bpfrpt_proptype_WindowScroller } from '../WindowScroller.js';
\ No newline at end of file

111
scripts/esbuild.js Normal file
View file

@ -0,0 +1,111 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
const esbuild = require('esbuild');
const path = require('path');
const glob = require('glob');
const ROOT_DIR = path.join(__dirname, '..');
const watch = process.argv.some(argv => argv === '-w' || argv === '--watch');
const isProd = process.argv.some(argv => argv === '-prod' || argv === '--prod');
const nodeDefaults = {
platform: 'node',
target: 'node16',
sourcemap: isProd ? false : 'inline',
// Otherwise React components get renamed
// See: https://github.com/evanw/esbuild/issues/1147
keepNames: true,
logLevel: 'info',
watch,
};
const bundleDefaults = {
...nodeDefaults,
bundle: true,
external: [
'@signalapp/signal-client',
'@signalapp/signal-client/zkgroup',
'backbone',
'better-sqlite3',
'fs-xattr',
'fsevents',
'got',
'jquery',
'mac-screen-capture-permissions',
'node-fetch',
'sass',
'pino',
'proxy-agent',
'ringrtc',
'sharp',
'websocket',
'electron',
// Uses fast-glob and dynamic requires
'./preload_test',
],
};
// App, tests, and scripts
esbuild.build({
...nodeDefaults,
format: 'cjs',
mainFields: ['browser', 'main'],
entryPoints: glob
.sync('{app,ts}/**/*.{ts,tsx}', {
nodir: true,
root: ROOT_DIR,
})
.filter(file => !file.endsWith('.d.ts')),
outdir: path.join(ROOT_DIR),
});
// Preload bundle
esbuild.build({
...bundleDefaults,
mainFields: ['browser', 'main'],
entryPoints: [path.join(ROOT_DIR, 'preload.js')],
outfile: path.join(ROOT_DIR, 'preload.bundle.js'),
});
// HEIC worker
esbuild.build({
...bundleDefaults,
entryPoints: [path.join(ROOT_DIR, 'ts', 'workers', 'heicConverterWorker.ts')],
outfile: path.join(ROOT_DIR, 'ts', 'workers', 'heicConverter.bundle.js'),
});
// SQL worker
const libDir = path.join('..', '..', 'node_modules', 'better-sqlite3');
const bindingFile = path.join(
libDir,
'build',
'Release',
'better_sqlite3.node'
);
esbuild.build({
...nodeDefaults,
bundle: true,
plugins: [
{
name: 'bindings',
setup(build) {
build.onResolve({ filter: /^bindings$/ }, () => ({
path: path.join(ROOT_DIR, 'ts', 'sql', 'mainWorkerBindings.ts'),
}));
build.onResolve({ filter: /^better_sqlite3\.node$/ }, () => ({
path: bindingFile,
external: true,
}));
},
},
],
entryPoints: [path.join(ROOT_DIR, 'ts', 'sql', 'mainWorker.ts')],
outfile: path.join(ROOT_DIR, 'ts', 'sql', 'mainWorker.bundle.js'),
});

View file

@ -1,4 +1,4 @@
// Copyright 2020-2021 Signal Messenger, LLC // Copyright 2020-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import type { RequestInit, Response } from 'node-fetch'; import type { RequestInit, Response } from 'node-fetch';
@ -13,6 +13,7 @@ import {
IMAGE_WEBP, IMAGE_WEBP,
stringToMIMEType, stringToMIMEType,
} from '../types/MIME'; } from '../types/MIME';
import type { LoggerType } from '../types/Logging';
import * as log from '../logging/log'; import * as log from '../logging/log';
const USER_AGENT = 'WhatsApp/2'; const USER_AGENT = 'WhatsApp/2';
@ -76,14 +77,15 @@ type ParsedContentType =
async function fetchWithRedirects( async function fetchWithRedirects(
fetchFn: FetchFn, fetchFn: FetchFn,
href: string, href: string,
options: RequestInit options: RequestInit,
logger: Pick<LoggerType, 'warn'> = log
): Promise<Response> { ): Promise<Response> {
const urlsSeen = new Set<string>(); const urlsSeen = new Set<string>();
let nextHrefToLoad = href; let nextHrefToLoad = href;
for (let i = 0; i < MAX_REQUEST_COUNT_WITH_REDIRECTS; i += 1) { for (let i = 0; i < MAX_REQUEST_COUNT_WITH_REDIRECTS; i += 1) {
if (urlsSeen.has(nextHrefToLoad)) { if (urlsSeen.has(nextHrefToLoad)) {
log.warn('fetchWithRedirects: found a redirect loop'); logger.warn('fetchWithRedirects: found a redirect loop');
throw new Error('redirect loop'); throw new Error('redirect loop');
} }
urlsSeen.add(nextHrefToLoad); urlsSeen.add(nextHrefToLoad);
@ -101,7 +103,7 @@ async function fetchWithRedirects(
const location = response.headers.get('location'); const location = response.headers.get('location');
if (!location) { if (!location) {
log.warn( logger.warn(
'fetchWithRedirects: got a redirect status code but no Location header; bailing' 'fetchWithRedirects: got a redirect status code but no Location header; bailing'
); );
throw new Error('no location with redirect'); throw new Error('no location with redirect');
@ -109,7 +111,7 @@ async function fetchWithRedirects(
const newUrl = maybeParseUrl(location, nextHrefToLoad); const newUrl = maybeParseUrl(location, nextHrefToLoad);
if (newUrl?.protocol !== 'https:') { if (newUrl?.protocol !== 'https:') {
log.warn( logger.warn(
'fetchWithRedirects: got a redirect status code and an invalid Location header' 'fetchWithRedirects: got a redirect status code and an invalid Location header'
); );
throw new Error('invalid location'); throw new Error('invalid location');
@ -118,7 +120,7 @@ async function fetchWithRedirects(
nextHrefToLoad = newUrl.href; nextHrefToLoad = newUrl.href;
} }
log.warn('fetchWithRedirects: too many redirects'); logger.warn('fetchWithRedirects: too many redirects');
throw new Error('too many redirects'); throw new Error('too many redirects');
} }
@ -284,7 +286,8 @@ const parseHtmlBytes = (
const getHtmlDocument = async ( const getHtmlDocument = async (
body: AsyncIterable<string | Uint8Array>, body: AsyncIterable<string | Uint8Array>,
httpCharset: string | null, httpCharset: string | null,
abortSignal: AbortSignal abortSignal: AbortSignal,
logger: Pick<LoggerType, 'warn'> = log
): Promise<HTMLDocument> => { ): Promise<HTMLDocument> => {
let result: HTMLDocument = emptyHtmlDocument(); let result: HTMLDocument = emptyHtmlDocument();
@ -317,7 +320,7 @@ const getHtmlDocument = async (
} }
} }
} catch (err) { } catch (err) {
log.warn( logger.warn(
'getHtmlDocument: error when reading body; continuing with what we got' 'getHtmlDocument: error when reading body; continuing with what we got'
); );
} }
@ -361,12 +364,13 @@ const getLinkHrefAttribute = (
const parseMetadata = ( const parseMetadata = (
document: HTMLDocument, document: HTMLDocument,
href: string href: string,
logger: Pick<LoggerType, 'warn'> = log
): LinkPreviewMetadata | null => { ): LinkPreviewMetadata | null => {
const title = const title =
getOpenGraphContent(document, ['og:title']) || document.title.trim(); getOpenGraphContent(document, ['og:title']) || document.title.trim();
if (!title) { if (!title) {
log.warn("parseMetadata: HTML document doesn't have a title; bailing"); logger.warn("parseMetadata: HTML document doesn't have a title; bailing");
return null; return null;
} }
@ -431,40 +435,46 @@ const parseMetadata = (
export async function fetchLinkPreviewMetadata( export async function fetchLinkPreviewMetadata(
fetchFn: FetchFn, fetchFn: FetchFn,
href: string, href: string,
abortSignal: AbortSignal abortSignal: AbortSignal,
logger: Pick<LoggerType, 'warn'> = log
): Promise<null | LinkPreviewMetadata> { ): Promise<null | LinkPreviewMetadata> {
let response: Response; let response: Response;
try { try {
response = await fetchWithRedirects(fetchFn, href, { response = await fetchWithRedirects(
headers: { fetchFn,
Accept: 'text/html,application/xhtml+xml', href,
'User-Agent': USER_AGENT, {
headers: {
Accept: 'text/html,application/xhtml+xml',
'User-Agent': USER_AGENT,
},
signal: abortSignal as AbortSignalForNodeFetch,
}, },
signal: abortSignal as AbortSignalForNodeFetch, logger
}); );
} catch (err) { } catch (err) {
log.warn( logger.warn(
'fetchLinkPreviewMetadata: failed to fetch link preview HTML; bailing' 'fetchLinkPreviewMetadata: failed to fetch link preview HTML; bailing'
); );
return null; return null;
} }
if (!response.ok) { if (!response.ok) {
log.warn( logger.warn(
`fetchLinkPreviewMetadata: got a ${response.status} status code; bailing` `fetchLinkPreviewMetadata: got a ${response.status} status code; bailing`
); );
return null; return null;
} }
if (!response.body) { if (!response.body) {
log.warn('fetchLinkPreviewMetadata: no response body; bailing'); logger.warn('fetchLinkPreviewMetadata: no response body; bailing');
return null; return null;
} }
if ( if (
!isInlineContentDisposition(response.headers.get('Content-Disposition')) !isInlineContentDisposition(response.headers.get('Content-Disposition'))
) { ) {
log.warn( logger.warn(
'fetchLinkPreviewMetadata: Content-Disposition header is not inline; bailing' 'fetchLinkPreviewMetadata: Content-Disposition header is not inline; bailing'
); );
return null; return null;
@ -478,20 +488,23 @@ export async function fetchLinkPreviewMetadata(
response.headers.get('Content-Length') response.headers.get('Content-Length')
); );
if (contentLength < MIN_HTML_CONTENT_LENGTH) { if (contentLength < MIN_HTML_CONTENT_LENGTH) {
log.warn('fetchLinkPreviewMetadata: Content-Length is too short; bailing'); logger.warn(
'fetchLinkPreviewMetadata: Content-Length is too short; bailing'
);
return null; return null;
} }
const contentType = parseContentType(response.headers.get('Content-Type')); const contentType = parseContentType(response.headers.get('Content-Type'));
if (contentType.type !== 'text/html') { if (contentType.type !== 'text/html') {
log.warn('fetchLinkPreviewMetadata: Content-Type is not HTML; bailing'); logger.warn('fetchLinkPreviewMetadata: Content-Type is not HTML; bailing');
return null; return null;
} }
const document = await getHtmlDocument( const document = await getHtmlDocument(
response.body, response.body,
contentType.charset, contentType.charset,
abortSignal abortSignal,
logger
); );
// [The Node docs about `ReadableStream.prototype[Symbol.asyncIterator]`][0] say that // [The Node docs about `ReadableStream.prototype[Symbol.asyncIterator]`][0] say that
@ -511,7 +524,7 @@ export async function fetchLinkPreviewMetadata(
return null; return null;
} }
return parseMetadata(document, response.url); return parseMetadata(document, response.url, logger);
} }
/** /**
@ -523,19 +536,25 @@ export async function fetchLinkPreviewMetadata(
export async function fetchLinkPreviewImage( export async function fetchLinkPreviewImage(
fetchFn: FetchFn, fetchFn: FetchFn,
href: string, href: string,
abortSignal: AbortSignal abortSignal: AbortSignal,
logger: Pick<LoggerType, 'warn'> = log
): Promise<null | LinkPreviewImage> { ): Promise<null | LinkPreviewImage> {
let response: Response; let response: Response;
try { try {
response = await fetchWithRedirects(fetchFn, href, { response = await fetchWithRedirects(
headers: { fetchFn,
'User-Agent': USER_AGENT, href,
{
headers: {
'User-Agent': USER_AGENT,
},
size: MAX_IMAGE_CONTENT_LENGTH,
signal: abortSignal as AbortSignalForNodeFetch,
}, },
size: MAX_IMAGE_CONTENT_LENGTH, logger
signal: abortSignal as AbortSignalForNodeFetch, );
});
} catch (err) { } catch (err) {
log.warn('fetchLinkPreviewImage: failed to fetch image; bailing'); logger.warn('fetchLinkPreviewImage: failed to fetch image; bailing');
return null; return null;
} }
@ -544,7 +563,7 @@ export async function fetchLinkPreviewImage(
} }
if (!response.ok) { if (!response.ok) {
log.warn( logger.warn(
`fetchLinkPreviewImage: got a ${response.status} status code; bailing` `fetchLinkPreviewImage: got a ${response.status} status code; bailing`
); );
return null; return null;
@ -554,11 +573,11 @@ export async function fetchLinkPreviewImage(
response.headers.get('Content-Length') response.headers.get('Content-Length')
); );
if (contentLength < MIN_IMAGE_CONTENT_LENGTH) { if (contentLength < MIN_IMAGE_CONTENT_LENGTH) {
log.warn('fetchLinkPreviewImage: Content-Length is too short; bailing'); logger.warn('fetchLinkPreviewImage: Content-Length is too short; bailing');
return null; return null;
} }
if (contentLength > MAX_IMAGE_CONTENT_LENGTH) { if (contentLength > MAX_IMAGE_CONTENT_LENGTH) {
log.warn( logger.warn(
'fetchLinkPreviewImage: Content-Length is too large or is unset; bailing' 'fetchLinkPreviewImage: Content-Length is too large or is unset; bailing'
); );
return null; return null;
@ -568,7 +587,7 @@ export async function fetchLinkPreviewImage(
response.headers.get('Content-Type') response.headers.get('Content-Type')
); );
if (!contentType || !VALID_IMAGE_MIME_TYPES.has(contentType)) { if (!contentType || !VALID_IMAGE_MIME_TYPES.has(contentType)) {
log.warn('fetchLinkPreviewImage: Content-Type is not an image; bailing'); logger.warn('fetchLinkPreviewImage: Content-Type is not an image; bailing');
return null; return null;
} }
@ -576,7 +595,7 @@ export async function fetchLinkPreviewImage(
try { try {
data = await response.buffer(); data = await response.buffer();
} catch (err) { } catch (err) {
log.warn('fetchLinkPreviewImage: failed to read body; bailing'); logger.warn('fetchLinkPreviewImage: failed to read body; bailing');
return null; return null;
} }

View file

@ -1,4 +1,4 @@
// Copyright 2021 Signal Messenger, LLC // Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import { isNil, sortBy } from 'lodash'; import { isNil, sortBy } from 'lodash';
@ -12,8 +12,7 @@ import { take } from './util/iterables';
import { isOlderThan } from './util/timestamp'; import { isOlderThan } from './util/timestamp';
import type { ConversationModel } from './models/conversations'; import type { ConversationModel } from './models/conversations';
import type { StorageInterface } from './types/Storage.d'; import type { StorageInterface } from './types/Storage.d';
// Imported this way so that sinon.sandbox can stub this properly import { getProfile } from './util/getProfile';
import * as profileGetter from './util/getProfile';
const STORAGE_KEY = 'lastAttemptedToRefreshProfilesAt'; const STORAGE_KEY = 'lastAttemptedToRefreshProfilesAt';
const MAX_AGE_TO_BE_CONSIDERED_ACTIVE = 30 * 24 * 60 * 60 * 1000; const MAX_AGE_TO_BE_CONSIDERED_ACTIVE = 30 * 24 * 60 * 60 * 1000;
@ -25,10 +24,14 @@ export async function routineProfileRefresh({
allConversations, allConversations,
ourConversationId, ourConversationId,
storage, storage,
// Only for tests
getProfileFn = getProfile,
}: { }: {
allConversations: Array<ConversationModel>; allConversations: Array<ConversationModel>;
ourConversationId: string; ourConversationId: string;
storage: Pick<StorageInterface, 'get' | 'put'>; storage: Pick<StorageInterface, 'get' | 'put'>;
getProfileFn?: typeof getProfile;
}): Promise<void> { }): Promise<void> {
log.info('routineProfileRefresh: starting'); log.info('routineProfileRefresh: starting');
@ -59,10 +62,7 @@ export async function routineProfileRefresh({
totalCount += 1; totalCount += 1;
try { try {
await profileGetter.getProfile( await getProfileFn(conversation.get('uuid'), conversation.get('e164'));
conversation.get('uuid'),
conversation.get('e164')
);
log.info( log.info(
`routineProfileRefresh: refreshed profile for ${conversation.idForLogging()}` `routineProfileRefresh: refreshed profile for ${conversation.idForLogging()}`
); );

View file

@ -1439,7 +1439,9 @@ function conversationUnloaded(id: string): ConversationUnloadedActionType {
}; };
} }
function createGroup(): ThunkAction< function createGroup(
createGroupV2 = groups.createGroupV2
): ThunkAction<
void, void,
RootStateType, RootStateType,
unknown, unknown,
@ -1461,7 +1463,7 @@ function createGroup(): ThunkAction<
dispatch({ type: 'CREATE_GROUP_PENDING' }); dispatch({ type: 'CREATE_GROUP_PENDING' });
try { try {
const conversation = await groups.createGroupV2({ const conversation = await createGroupV2({
name: composer.groupName.trim(), name: composer.groupName.trim(),
avatar: composer.groupAvatar, avatar: composer.groupAvatar,
avatars: composer.userAvatarData.map(avatarData => avatars: composer.userAvatarData.map(avatarData =>

View file

@ -1,34 +1,19 @@
// Copyright 2021 Signal Messenger, LLC // Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai'; import { assert } from 'chai';
import * as sinon from 'sinon';
import { times } from 'lodash'; import { times } from 'lodash';
import * as remoteConfig from '../../RemoteConfig'; import { updateRemoteConfig } from '../helpers/RemoteConfigStub';
import { UUID } from '../../types/UUID'; import { UUID } from '../../types/UUID';
import { isConversationTooBigToRing } from '../../conversations/isConversationTooBigToRing'; import { isConversationTooBigToRing } from '../../conversations/isConversationTooBigToRing';
const CONFIG_KEY = 'global.calling.maxGroupCallRingSize';
describe('isConversationTooBigToRing', () => { describe('isConversationTooBigToRing', () => {
let sinonSandbox: sinon.SinonSandbox;
let getMaxGroupCallRingSizeStub: sinon.SinonStub;
beforeEach(() => {
sinonSandbox = sinon.createSandbox();
const getValueStub = sinonSandbox.stub(remoteConfig, 'getValue');
getMaxGroupCallRingSizeStub = getValueStub.withArgs(
'global.calling.maxGroupCallRingSize'
);
});
const fakeMemberships = (count: number) => const fakeMemberships = (count: number) =>
times(count, () => ({ uuid: UUID.generate().toString(), isAdmin: false })); times(count, () => ({ uuid: UUID.generate().toString(), isAdmin: false }));
afterEach(() => {
sinonSandbox.restore();
});
it('returns false if there are no memberships (i.e., for a direct conversation)', () => { it('returns false if there are no memberships (i.e., for a direct conversation)', () => {
assert.isFalse(isConversationTooBigToRing({})); assert.isFalse(isConversationTooBigToRing({}));
assert.isFalse(isConversationTooBigToRing({ memberships: [] })); assert.isFalse(isConversationTooBigToRing({ memberships: [] }));
@ -45,17 +30,20 @@ describe('isConversationTooBigToRing', () => {
} }
}; };
it('returns whether there are 16 or more people in the group, if there is nothing in remote config', () => { it('returns whether there are 16 or more people in the group, if there is nothing in remote config', async () => {
await updateRemoteConfig([]);
textMaximum(16); textMaximum(16);
}); });
it('returns whether there are 16 or more people in the group, if the remote config value is bogus', () => { it('returns whether there are 16 or more people in the group, if the remote config value is bogus', async () => {
getMaxGroupCallRingSizeStub.returns('uh oh'); await updateRemoteConfig([
{ name: CONFIG_KEY, value: 'uh oh', enabled: true },
]);
textMaximum(16); textMaximum(16);
}); });
it('returns whether there are 9 or more people in the group, if the remote config value is 9', () => { it('returns whether there are 9 or more people in the group, if the remote config value is 9', async () => {
getMaxGroupCallRingSizeStub.returns('9'); await updateRemoteConfig([{ name: CONFIG_KEY, value: '9', enabled: true }]);
textMaximum(9); textMaximum(9);
}); });
}); });

View file

@ -1,66 +1,56 @@
// Copyright 2021 Signal Messenger, LLC // Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai'; import { assert } from 'chai';
import * as sinon from 'sinon'; import { updateRemoteConfig } from '../helpers/RemoteConfigStub';
import * as remoteConfig from '../../RemoteConfig';
import { import {
getGroupSizeRecommendedLimit, getGroupSizeRecommendedLimit,
getGroupSizeHardLimit, getGroupSizeHardLimit,
} from '../../groups/limits'; } from '../../groups/limits';
const RECOMMENDED_SIZE_KEY = 'global.groupsv2.maxGroupSize';
const HARD_LIMIT_KEY = 'global.groupsv2.groupSizeHardLimit';
describe('group limit utilities', () => { describe('group limit utilities', () => {
let sinonSandbox: sinon.SinonSandbox;
let getRecommendedLimitStub: sinon.SinonStub;
let getHardLimitStub: sinon.SinonStub;
beforeEach(() => {
sinonSandbox = sinon.createSandbox();
const getValueStub = sinonSandbox.stub(remoteConfig, 'getValue');
getRecommendedLimitStub = getValueStub.withArgs(
'global.groupsv2.maxGroupSize'
);
getHardLimitStub = getValueStub.withArgs(
'global.groupsv2.groupSizeHardLimit'
);
});
afterEach(() => {
sinonSandbox.restore();
});
describe('getGroupSizeRecommendedLimit', () => { describe('getGroupSizeRecommendedLimit', () => {
it('throws if the value in remote config is not defined', () => { it('throws if the value in remote config is not defined', async () => {
getRecommendedLimitStub.returns(undefined); await updateRemoteConfig([]);
assert.throws(getGroupSizeRecommendedLimit); assert.throws(getGroupSizeRecommendedLimit);
}); });
it('throws if the value in remote config is not a parseable integer', () => { it('throws if the value in remote config is not a parseable integer', async () => {
getRecommendedLimitStub.returns('uh oh'); await updateRemoteConfig([
{ name: RECOMMENDED_SIZE_KEY, value: 'uh oh', enabled: true },
]);
assert.throws(getGroupSizeRecommendedLimit); assert.throws(getGroupSizeRecommendedLimit);
}); });
it('returns the value in remote config, parsed as an integer', () => { it('returns the value in remote config, parsed as an integer', async () => {
getRecommendedLimitStub.returns('123'); await updateRemoteConfig([
{ name: RECOMMENDED_SIZE_KEY, value: '123', enabled: true },
]);
assert.strictEqual(getGroupSizeRecommendedLimit(), 123); assert.strictEqual(getGroupSizeRecommendedLimit(), 123);
}); });
}); });
describe('getGroupSizeHardLimit', () => { describe('getGroupSizeHardLimit', () => {
it('throws if the value in remote config is not defined', () => { it('throws if the value in remote config is not defined', async () => {
getHardLimitStub.returns(undefined); await updateRemoteConfig([]);
assert.throws(getGroupSizeHardLimit); assert.throws(getGroupSizeHardLimit);
}); });
it('throws if the value in remote config is not a parseable integer', () => { it('throws if the value in remote config is not a parseable integer', async () => {
getHardLimitStub.returns('uh oh'); await updateRemoteConfig([
{ name: HARD_LIMIT_KEY, value: 'uh oh', enabled: true },
]);
assert.throws(getGroupSizeHardLimit); assert.throws(getGroupSizeHardLimit);
}); });
it('returns the value in remote config, parsed as an integer', () => { it('returns the value in remote config, parsed as an integer', async () => {
getHardLimitStub.returns('123'); await updateRemoteConfig([
{ name: HARD_LIMIT_KEY, value: '123', enabled: true },
]);
assert.strictEqual(getGroupSizeHardLimit(), 123); assert.strictEqual(getGroupSizeHardLimit(), 123);
}); });
}); });

View file

@ -0,0 +1,18 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { refreshRemoteConfig } from '../../RemoteConfig';
import type { WebAPIType } from '../../textsecure/WebAPI';
import type { UnwrapPromise } from '../../types/Util';
export async function updateRemoteConfig(
newConfig: UnwrapPromise<ReturnType<WebAPIType['getConfig']>>
): Promise<void> {
const fakeServer = {
async getConfig() {
return newConfig;
},
} as Partial<WebAPIType> as unknown as WebAPIType;
await refreshRemoteConfig(fakeServer);
}

View file

@ -1,4 +1,4 @@
// Copyright 2020-2021 Signal Messenger, LLC // Copyright 2020-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai'; import { assert } from 'chai';
@ -8,7 +8,7 @@ import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import AbortController from 'abort-controller'; import AbortController from 'abort-controller';
import { IMAGE_JPEG, stringToMIMEType } from '../../types/MIME'; import { IMAGE_JPEG, stringToMIMEType } from '../../types/MIME';
import * as log from '../../logging/log'; import type { LoggerType } from '../../types/Logging';
import { import {
fetchLinkPreviewImage, fetchLinkPreviewImage,
@ -24,16 +24,12 @@ describe('link preview fetching', () => {
return sinon.stub(); return sinon.stub();
} }
let sandbox: sinon.SinonSandbox;
let warn: sinon.SinonStub; let warn: sinon.SinonStub;
let logger: Pick<LoggerType, 'warn'>;
beforeEach(() => { beforeEach(() => {
sandbox = sinon.createSandbox(); warn = sinon.stub();
warn = sandbox.stub(log, 'warn'); logger = { warn };
});
afterEach(() => {
sandbox.restore();
}); });
describe('fetchLinkPreviewMetadata', () => { describe('fetchLinkPreviewMetadata', () => {
@ -196,7 +192,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewMetadata( await fetchLinkPreviewMetadata(
fakeFetch, fakeFetch,
'https://example.com', 'https://example.com',
new AbortController().signal new AbortController().signal,
logger
); );
sinon.assert.notCalled(warn); sinon.assert.notCalled(warn);
@ -229,7 +226,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewMetadata( await fetchLinkPreviewMetadata(
fakeFetch, fakeFetch,
'https://example.com', 'https://example.com',
new AbortController().signal new AbortController().signal,
logger
) )
); );
@ -249,7 +247,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewMetadata( await fetchLinkPreviewMetadata(
fakeFetch, fakeFetch,
'https://example.com', 'https://example.com',
new AbortController().signal new AbortController().signal,
logger
) )
); );
@ -434,7 +433,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewMetadata( await fetchLinkPreviewMetadata(
fakeFetch, fakeFetch,
'https://example.com', 'https://example.com',
new AbortController().signal new AbortController().signal,
logger
) )
); );
@ -451,7 +451,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewMetadata( await fetchLinkPreviewMetadata(
fakeFetch, fakeFetch,
'https://example.com', 'https://example.com',
new AbortController().signal new AbortController().signal,
logger
) )
); );
@ -473,7 +474,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewMetadata( await fetchLinkPreviewMetadata(
fakeFetch, fakeFetch,
'https://example.com', 'https://example.com',
new AbortController().signal new AbortController().signal,
logger
) )
); );
@ -517,7 +519,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewMetadata( await fetchLinkPreviewMetadata(
fakeFetch, fakeFetch,
'https://example.com', 'https://example.com',
new AbortController().signal new AbortController().signal,
logger
) )
); );
@ -798,7 +801,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewMetadata( await fetchLinkPreviewMetadata(
fakeFetch, fakeFetch,
'https://example.com', 'https://example.com',
new AbortController().signal new AbortController().signal,
logger
), ),
'title', 'title',
'foo bar' 'foo bar'
@ -893,7 +897,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewMetadata( await fetchLinkPreviewMetadata(
fakeFetch, fakeFetch,
'https://example.com', 'https://example.com',
new AbortController().signal new AbortController().signal,
logger
) )
); );
@ -1166,7 +1171,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewImage( await fetchLinkPreviewImage(
fakeFetch, fakeFetch,
'https://example.com/img', 'https://example.com/img',
new AbortController().signal new AbortController().signal,
logger
) )
); );
@ -1196,7 +1202,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewImage( await fetchLinkPreviewImage(
fakeFetch, fakeFetch,
'https://example.com/img', 'https://example.com/img',
new AbortController().signal new AbortController().signal,
logger
) )
); );
@ -1264,7 +1271,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewImage( await fetchLinkPreviewImage(
fakeFetch, fakeFetch,
'https://example.com/img', 'https://example.com/img',
new AbortController().signal new AbortController().signal,
logger
) )
); );
@ -1289,7 +1297,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewImage( await fetchLinkPreviewImage(
fakeFetch, fakeFetch,
'https://example.com/img', 'https://example.com/img',
new AbortController().signal new AbortController().signal,
logger
) )
); );
@ -1319,7 +1328,8 @@ describe('link preview fetching', () => {
await fetchLinkPreviewImage( await fetchLinkPreviewImage(
fakeFetch, fakeFetch,
'https://example.com/img', 'https://example.com/img',
new AbortController().signal new AbortController().signal,
logger
) )
); );

View file

@ -1,4 +1,4 @@
// Copyright 2020-2021 Signal Messenger, LLC // Copyright 2020-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai'; import { assert } from 'chai';
@ -580,7 +580,12 @@ describe('Message', () => {
}); });
it("shows a notification's emoji on non-Linux", function test() { it("shows a notification's emoji on non-Linux", function test() {
this.sandbox.stub(window.Signal.OS, 'isLinux').returns(false); this.sandbox.replace(window.Signal, 'OS', {
...window.Signal.OS,
isLinux() {
return false;
},
});
assert.strictEqual( assert.strictEqual(
createMessage({ createMessage({
@ -597,7 +602,12 @@ describe('Message', () => {
}); });
it('hides emoji on Linux', function test() { it('hides emoji on Linux', function test() {
this.sandbox.stub(window.Signal.OS, 'isLinux').returns(true); this.sandbox.replace(window.Signal, 'OS', {
...window.Signal.OS,
isLinux() {
return true;
},
});
assert.strictEqual( assert.strictEqual(
createMessage({ createMessage({

View file

@ -1,4 +1,4 @@
// Copyright 2021 Signal Messenger, LLC // Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as sinon from 'sinon'; import * as sinon from 'sinon';
@ -8,14 +8,14 @@ import type { ConversationAttributesType } from '../model-types.d';
import { UUID } from '../types/UUID'; import { UUID } from '../types/UUID';
import { routineProfileRefresh } from '../routineProfileRefresh'; import { routineProfileRefresh } from '../routineProfileRefresh';
import * as getProfileStub from '../util/getProfile';
describe('routineProfileRefresh', () => { describe('routineProfileRefresh', () => {
let sinonSandbox: sinon.SinonSandbox; let sinonSandbox: sinon.SinonSandbox;
let getProfileFn: sinon.SinonStub;
beforeEach(() => { beforeEach(() => {
sinonSandbox = sinon.createSandbox(); sinonSandbox = sinon.createSandbox();
sinonSandbox.stub(getProfileStub, 'getProfile').resolves(undefined); getProfileFn = sinon.stub();
}); });
afterEach(() => { afterEach(() => {
@ -87,9 +87,10 @@ describe('routineProfileRefresh', () => {
allConversations: [conversation1, conversation2], allConversations: [conversation1, conversation2],
ourConversationId: UUID.generate().toString(), ourConversationId: UUID.generate().toString(),
storage, storage,
getProfileFn,
}); });
sinon.assert.notCalled(getProfileStub.getProfile as sinon.SinonStub); sinon.assert.notCalled(getProfileFn);
sinon.assert.notCalled(storage.put); sinon.assert.notCalled(storage.put);
}); });
@ -101,15 +102,16 @@ describe('routineProfileRefresh', () => {
allConversations: [conversation1, conversation2], allConversations: [conversation1, conversation2],
ourConversationId: UUID.generate().toString(), ourConversationId: UUID.generate().toString(),
storage: makeStorage(), storage: makeStorage(),
getProfileFn,
}); });
sinon.assert.calledWith( sinon.assert.calledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
conversation1.get('uuid'), conversation1.get('uuid'),
conversation1.get('e164') conversation1.get('e164')
); );
sinon.assert.calledWith( sinon.assert.calledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
conversation2.get('uuid'), conversation2.get('uuid'),
conversation2.get('e164') conversation2.get('e164')
); );
@ -126,21 +128,22 @@ describe('routineProfileRefresh', () => {
allConversations: [recentlyActive, inactive, neverActive], allConversations: [recentlyActive, inactive, neverActive],
ourConversationId: UUID.generate().toString(), ourConversationId: UUID.generate().toString(),
storage: makeStorage(), storage: makeStorage(),
getProfileFn,
}); });
sinon.assert.calledOnce(getProfileStub.getProfile as sinon.SinonStub); sinon.assert.calledOnce(getProfileFn);
sinon.assert.calledWith( sinon.assert.calledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
recentlyActive.get('uuid'), recentlyActive.get('uuid'),
recentlyActive.get('e164') recentlyActive.get('e164')
); );
sinon.assert.neverCalledWith( sinon.assert.neverCalledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
inactive.get('uuid'), inactive.get('uuid'),
inactive.get('e164') inactive.get('e164')
); );
sinon.assert.neverCalledWith( sinon.assert.neverCalledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
neverActive.get('uuid'), neverActive.get('uuid'),
neverActive.get('e164') neverActive.get('e164')
); );
@ -154,18 +157,11 @@ describe('routineProfileRefresh', () => {
allConversations: [notMe, me], allConversations: [notMe, me],
ourConversationId: me.id, ourConversationId: me.id,
storage: makeStorage(), storage: makeStorage(),
getProfileFn,
}); });
sinon.assert.calledWith( sinon.assert.calledWith(getProfileFn, notMe.get('uuid'), notMe.get('e164'));
getProfileStub.getProfile as sinon.SinonStub, sinon.assert.neverCalledWith(getProfileFn, me.get('uuid'), me.get('e164'));
notMe.get('uuid'),
notMe.get('e164')
);
sinon.assert.neverCalledWith(
getProfileStub.getProfile as sinon.SinonStub,
me.get('uuid'),
me.get('e164')
);
}); });
it('skips conversations that were refreshed in the last hour', async () => { it('skips conversations that were refreshed in the last hour', async () => {
@ -178,16 +174,17 @@ describe('routineProfileRefresh', () => {
allConversations: [neverRefreshed, recentlyFetched], allConversations: [neverRefreshed, recentlyFetched],
ourConversationId: UUID.generate().toString(), ourConversationId: UUID.generate().toString(),
storage: makeStorage(), storage: makeStorage(),
getProfileFn,
}); });
sinon.assert.calledOnce(getProfileStub.getProfile as sinon.SinonStub); sinon.assert.calledOnce(getProfileFn);
sinon.assert.calledWith( sinon.assert.calledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
neverRefreshed.get('uuid'), neverRefreshed.get('uuid'),
neverRefreshed.get('e164') neverRefreshed.get('e164')
); );
sinon.assert.neverCalledWith( sinon.assert.neverCalledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
recentlyFetched.get('uuid'), recentlyFetched.get('uuid'),
recentlyFetched.get('e164') recentlyFetched.get('e164')
); );
@ -220,30 +217,31 @@ describe('routineProfileRefresh', () => {
], ],
ourConversationId: UUID.generate().toString(), ourConversationId: UUID.generate().toString(),
storage: makeStorage(), storage: makeStorage(),
getProfileFn,
}); });
sinon.assert.calledWith( sinon.assert.calledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
privateConversation.get('uuid'), privateConversation.get('uuid'),
privateConversation.get('e164') privateConversation.get('e164')
); );
sinon.assert.calledWith( sinon.assert.calledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
recentlyActiveGroupMember.get('uuid'), recentlyActiveGroupMember.get('uuid'),
recentlyActiveGroupMember.get('e164') recentlyActiveGroupMember.get('e164')
); );
sinon.assert.calledWith( sinon.assert.calledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
inactiveGroupMember.get('uuid'), inactiveGroupMember.get('uuid'),
inactiveGroupMember.get('e164') inactiveGroupMember.get('e164')
); );
sinon.assert.neverCalledWith( sinon.assert.neverCalledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
memberWhoHasRecentlyRefreshed.get('uuid'), memberWhoHasRecentlyRefreshed.get('uuid'),
memberWhoHasRecentlyRefreshed.get('e164') memberWhoHasRecentlyRefreshed.get('e164')
); );
sinon.assert.neverCalledWith( sinon.assert.neverCalledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
groupConversation.get('uuid'), groupConversation.get('uuid'),
groupConversation.get('e164') groupConversation.get('e164')
); );
@ -288,11 +286,12 @@ describe('routineProfileRefresh', () => {
], ],
ourConversationId: me.id, ourConversationId: me.id,
storage: makeStorage(), storage: makeStorage(),
getProfileFn,
}); });
[...activeConversations, ...inactiveGroupMembers].forEach(conversation => { [...activeConversations, ...inactiveGroupMembers].forEach(conversation => {
sinon.assert.calledWith( sinon.assert.calledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
conversation.get('uuid'), conversation.get('uuid'),
conversation.get('e164') conversation.get('e164')
); );
@ -300,7 +299,7 @@ describe('routineProfileRefresh', () => {
[me, ...shouldNotBeIncluded].forEach(conversation => { [me, ...shouldNotBeIncluded].forEach(conversation => {
sinon.assert.neverCalledWith( sinon.assert.neverCalledWith(
getProfileStub.getProfile as sinon.SinonStub, getProfileFn,
conversation.get('uuid'), conversation.get('uuid'),
conversation.get('e164') conversation.get('e164')
); );

View file

@ -1,4 +1,4 @@
// Copyright 2020-2021 Signal Messenger, LLC // Copyright 2020-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai'; import { assert } from 'chai';
@ -31,7 +31,6 @@ import { ReadStatus } from '../../../messages/MessageReadStatus';
import { ContactSpoofingType } from '../../../util/contactSpoofing'; import { ContactSpoofingType } from '../../../util/contactSpoofing';
import { CallMode } from '../../../types/Calling'; import { CallMode } from '../../../types/Calling';
import { UUID } from '../../../types/UUID'; import { UUID } from '../../../types/UUID';
import * as groups from '../../../groups';
import { import {
getDefaultConversation, getDefaultConversation,
getDefaultConversationWithUuid, getDefaultConversationWithUuid,
@ -42,6 +41,7 @@ import {
defaultChooseGroupMembersComposerState, defaultChooseGroupMembersComposerState,
defaultSetGroupMetadataComposerState, defaultSetGroupMetadataComposerState,
} from '../../../test-both/helpers/defaultComposerStates'; } from '../../../test-both/helpers/defaultComposerStates';
import { updateRemoteConfig } from '../../../test-both/helpers/RemoteConfigStub';
const { const {
cantAddContactToGroup, cantAddContactToGroup,
@ -83,7 +83,7 @@ describe('both/state/ducks/conversations', () => {
sinonSandbox.stub(window.Whisper.events, 'trigger'); sinonSandbox.stub(window.Whisper.events, 'trigger');
createGroupStub = sinonSandbox.stub(groups, 'createGroupV2'); createGroupStub = sinon.stub();
}); });
afterEach(() => { afterEach(() => {
@ -686,7 +686,7 @@ describe('both/state/ducks/conversations', () => {
}); });
it('calls groups.createGroupV2', async () => { it('calls groups.createGroupV2', async () => {
await createGroup()( await createGroup(createGroupStub)(
sinon.spy(), sinon.spy(),
() => ({ () => ({
...getEmptyRootState(), ...getEmptyRootState(),
@ -706,7 +706,7 @@ describe('both/state/ducks/conversations', () => {
}); });
it("trims the group's title before calling groups.createGroupV2", async () => { it("trims the group's title before calling groups.createGroupV2", async () => {
await createGroup()( await createGroup(createGroupStub)(
sinon.spy(), sinon.spy(),
() => ({ () => ({
...getEmptyRootState(), ...getEmptyRootState(),
@ -732,7 +732,7 @@ describe('both/state/ducks/conversations', () => {
const dispatch = sinon.spy(); const dispatch = sinon.spy();
const createGroupPromise = createGroup()( const createGroupPromise = createGroup(createGroupStub)(
dispatch, dispatch,
() => ({ () => ({
...getEmptyRootState(), ...getEmptyRootState(),
@ -764,7 +764,7 @@ describe('both/state/ducks/conversations', () => {
const dispatch = sinon.spy(); const dispatch = sinon.spy();
const createGroupPromise = createGroup()( const createGroupPromise = createGroup(createGroupStub)(
dispatch, dispatch,
() => ({ () => ({
...getEmptyRootState(), ...getEmptyRootState(),
@ -796,7 +796,7 @@ describe('both/state/ducks/conversations', () => {
const dispatch = sinon.spy(); const dispatch = sinon.spy();
await createGroup()( await createGroup(createGroupStub)(
dispatch, dispatch,
() => ({ () => ({
...getEmptyRootState(), ...getEmptyRootState(),
@ -1572,15 +1572,15 @@ describe('both/state/ducks/conversations', () => {
return dispatch.getCall(0).args[0]; return dispatch.getCall(0).args[0];
} }
let remoteConfigGetValueStub: sinon.SinonStub; beforeEach(async () => {
await updateRemoteConfig([
beforeEach(() => { { name: 'global.groupsv2.maxGroupSize', value: '22', enabled: true },
remoteConfigGetValueStub = sinonSandbox {
.stub(window.Signal.RemoteConfig, 'getValue') name: 'global.groupsv2.groupSizeHardLimit',
.withArgs('global.groupsv2.maxGroupSize') value: '33',
.returns('22') enabled: true,
.withArgs('global.groupsv2.groupSizeHardLimit') },
.returns('33'); ]);
}); });
it('adds conversation IDs to the list', () => { it('adds conversation IDs to the list', () => {
@ -1657,11 +1657,21 @@ describe('both/state/ducks/conversations', () => {
}); });
}); });
it('defaults the maximum recommended size to 151', () => { it('defaults the maximum recommended size to 151', async () => {
[undefined, 'xyz'].forEach(value => { for (const value of [null, 'xyz']) {
remoteConfigGetValueStub // eslint-disable-next-line no-await-in-loop
.withArgs('global.groupsv2.maxGroupSize') await updateRemoteConfig([
.returns(value); {
name: 'global.groupsv2.maxGroupSize',
value,
enabled: true,
},
{
name: 'global.groupsv2.groupSizeHardLimit',
value: '33',
enabled: true,
},
]);
const state = { const state = {
...getEmptyState(), ...getEmptyState(),
@ -1670,7 +1680,7 @@ describe('both/state/ducks/conversations', () => {
const action = getAction(uuid(), state); const action = getAction(uuid(), state);
assert.strictEqual(action.payload.maxRecommendedGroupSize, 151); assert.strictEqual(action.payload.maxRecommendedGroupSize, 151);
}); }
}); });
it('shows the maximum group size modal when first reaching the maximum group size', () => { it('shows the maximum group size modal when first reaching the maximum group size', () => {
@ -1735,13 +1745,17 @@ describe('both/state/ducks/conversations', () => {
assert.deepEqual(result, state); assert.deepEqual(result, state);
}); });
it('defaults the maximum group size to 1001 if the recommended maximum is smaller', () => { it('defaults the maximum group size to 1001 if the recommended maximum is smaller', async () => {
[undefined, 'xyz'].forEach(value => { for (const value of [null, 'xyz']) {
remoteConfigGetValueStub // eslint-disable-next-line no-await-in-loop
.withArgs('global.groupsv2.maxGroupSize') await updateRemoteConfig([
.returns('2') { name: 'global.groupsv2.maxGroupSize', value: '2', enabled: true },
.withArgs('global.groupsv2.groupSizeHardLimit') {
.returns(value); name: 'global.groupsv2.groupSizeHardLimit',
value,
enabled: true,
},
]);
const state = { const state = {
...getEmptyState(), ...getEmptyState(),
@ -1750,15 +1764,22 @@ describe('both/state/ducks/conversations', () => {
const action = getAction(uuid(), state); const action = getAction(uuid(), state);
assert.strictEqual(action.payload.maxGroupSize, 1001); assert.strictEqual(action.payload.maxGroupSize, 1001);
}); }
}); });
it('defaults the maximum group size to (recommended maximum + 1) if the recommended maximum is more than 1001', () => { it('defaults the maximum group size to (recommended maximum + 1) if the recommended maximum is more than 1001', async () => {
remoteConfigGetValueStub await updateRemoteConfig([
.withArgs('global.groupsv2.maxGroupSize') {
.returns('1234') name: 'global.groupsv2.maxGroupSize',
.withArgs('global.groupsv2.groupSizeHardLimit') value: '1234',
.returns('2'); enabled: true,
},
{
name: 'global.groupsv2.groupSizeHardLimit',
value: '2',
enabled: true,
},
]);
const state = { const state = {
...getEmptyState(), ...getEmptyState(),

View file

@ -1,15 +1,15 @@
// Copyright 2021 Signal Messenger, LLC // Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai'; import { assert } from 'chai';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import { times } from 'lodash'; import { times } from 'lodash';
import { RowType } from '../../../components/ConversationList'; import { RowType } from '../../../components/ConversationList';
import * as remoteConfig from '../../../RemoteConfig';
import { ContactCheckboxDisabledReason } from '../../../components/conversationList/ContactCheckbox'; import { ContactCheckboxDisabledReason } from '../../../components/conversationList/ContactCheckbox';
import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation'; import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation';
import { LeftPaneChooseGroupMembersHelper } from '../../../components/leftPane/LeftPaneChooseGroupMembersHelper'; import { LeftPaneChooseGroupMembersHelper } from '../../../components/leftPane/LeftPaneChooseGroupMembersHelper';
import { updateRemoteConfig } from '../../../test-both/helpers/RemoteConfigStub';
describe('LeftPaneChooseGroupMembersHelper', () => { describe('LeftPaneChooseGroupMembersHelper', () => {
const defaults = { const defaults = {
@ -21,21 +21,15 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
selectedContacts: [], selectedContacts: [],
}; };
let sinonSandbox: sinon.SinonSandbox; beforeEach(async () => {
await updateRemoteConfig([
beforeEach(() => { { name: 'global.groupsv2.maxGroupSize', value: '22', enabled: true },
sinonSandbox = sinon.createSandbox(); {
name: 'global.groupsv2.groupSizeHardLimit',
sinonSandbox value: '33',
.stub(remoteConfig, 'getValue') enabled: true,
.withArgs('global.groupsv2.maxGroupSize') },
.returns('22') ]);
.withArgs('global.groupsv2.groupSizeHardLimit')
.returns('33');
});
afterEach(() => {
sinonSandbox.restore();
}); });
describe('getBackAction', () => { describe('getBackAction', () => {

View file

@ -1,4 +1,4 @@
// Copyright 2018-2021 Signal Messenger, LLC // Copyright 2018-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import is from '@sindresorhus/is'; import is from '@sindresorhus/is';
@ -323,7 +323,7 @@ export function removeSchemaVersion({
attachment: AttachmentType; attachment: AttachmentType;
logger: LoggerType; logger: LoggerType;
}): AttachmentType { }): AttachmentType {
if (!exports.isValid(attachment)) { if (!isValid(attachment)) {
logger.error( logger.error(
'Attachment.removeSchemaVersion: Invalid input attachment:', 'Attachment.removeSchemaVersion: Invalid input attachment:',
attachment attachment

View file

@ -6945,22 +6945,6 @@
"reasonCategory": "falseMatch", "reasonCategory": "falseMatch",
"updated": "2020-07-21T18:34:59.251Z" "updated": "2020-07-21T18:34:59.251Z"
}, },
{
"rule": "DOM-innerHTML",
"path": "ts/backbone/views/Lightbox.js",
"line": " container.innerHTML = '';",
"reasonCategory": "usageTrusted",
"updated": "2018-09-17T20:50:40.689Z",
"reasonDetail": "Hard-coded value"
},
{
"rule": "DOM-innerHTML",
"path": "ts/backbone/views/Lightbox.js",
"line": " container.innerHTML = '';",
"reasonCategory": "usageTrusted",
"updated": "2018-09-17T20:50:40.689Z",
"reasonDetail": "Hard-coded value"
},
{ {
"rule": "DOM-innerHTML", "rule": "DOM-innerHTML",
"path": "ts/backbone/views/Lightbox.ts", "path": "ts/backbone/views/Lightbox.ts",
@ -6977,14 +6961,6 @@
"updated": "2018-09-17T20:50:40.689Z", "updated": "2018-09-17T20:50:40.689Z",
"reasonDetail": "Hard-coded value" "reasonDetail": "Hard-coded value"
}, },
{
"rule": "jQuery-html(",
"path": "ts/backbone/views/whisper_view.js",
"line": " this.$el.html(window.Mustache.render(template, attrs));",
"reasonCategory": "usageTrusted",
"updated": "2021-02-26T18:44:56.450Z",
"reasonDetail": "Rendering provided template"
},
{ {
"rule": "jQuery-html(", "rule": "jQuery-html(",
"path": "ts/backbone/views/whisper_view.ts", "path": "ts/backbone/views/whisper_view.ts",
@ -7001,20 +6977,6 @@
"updated": "2021-12-10T23:24:03.829Z", "updated": "2021-12-10T23:24:03.829Z",
"reasonDetail": "Doesn't touch the DOM." "reasonDetail": "Doesn't touch the DOM."
}, },
{
"rule": "jQuery-load(",
"path": "ts/challenge.js",
"line": " async load() {",
"reasonCategory": "falseMatch",
"updated": "2021-05-05T23:11:22.692Z"
},
{
"rule": "jQuery-load(",
"path": "ts/challenge.js",
"line": " // 1. `.load()` when the `window.storage` is ready",
"reasonCategory": "falseMatch",
"updated": "2021-05-05T23:11:22.692Z"
},
{ {
"rule": "jQuery-load(", "rule": "jQuery-load(",
"path": "ts/challenge.ts", "path": "ts/challenge.ts",
@ -7100,14 +7062,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-12-01T01:31:12.757Z" "updated": "2021-12-01T01:31:12.757Z"
}, },
{
"rule": "React-useRef",
"path": "ts/components/CallingLobby.js",
"line": " const localVideoRef = react_1.default.useRef(null);",
"reasonCategory": "usageTrusted",
"updated": "2020-10-26T19:12:24.410Z",
"reasonDetail": "Used to get the local video element for rendering."
},
{ {
"rule": "React-useRef", "rule": "React-useRef",
"path": "ts/components/CallingLobby.tsx", "path": "ts/components/CallingLobby.tsx",
@ -7115,22 +7069,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-07-30T16:57:33.618Z" "updated": "2021-07-30T16:57:33.618Z"
}, },
{
"rule": "React-useRef",
"path": "ts/components/CallingPip.js",
"line": " const videoContainerRef = react_1.default.useRef(null);",
"reasonCategory": "usageTrusted",
"updated": "2020-10-26T19:12:24.410Z",
"reasonDetail": "Element is measured. Its HTML is not used."
},
{
"rule": "React-useRef",
"path": "ts/components/CallingPip.js",
"line": " const localVideoRef = react_1.default.useRef(null);",
"reasonCategory": "usageTrusted",
"updated": "2020-10-26T19:12:24.410Z",
"reasonDetail": "Used to get the local video element for rendering."
},
{ {
"rule": "React-useRef", "rule": "React-useRef",
"path": "ts/components/CallingPip.tsx", "path": "ts/components/CallingPip.tsx",
@ -7181,61 +7119,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-09-23T00:07:11.885Z" "updated": "2021-09-23T00:07:11.885Z"
}, },
{
"rule": "React-useRef",
"path": "ts/components/CompositionInput.js",
"line": " const emojiCompletionRef = React.useRef();",
"reasonCategory": "falseMatch",
"updated": "2020-10-26T19:12:24.410Z",
"reasonDetail": "Doesn't refer to a DOM element."
},
{
"rule": "React-useRef",
"path": "ts/components/CompositionInput.js",
"line": " const quillRef = React.useRef();",
"reasonCategory": "falseMatch",
"updated": "2020-10-26T19:12:24.410Z",
"reasonDetail": "Doesn't refer to a DOM element."
},
{
"rule": "React-useRef",
"path": "ts/components/CompositionInput.js",
"line": " const propsRef = React.useRef(props);",
"reasonCategory": "falseMatch",
"updated": "2020-10-26T19:12:24.410Z",
"reasonDetail": "Doesn't refer to a DOM element."
},
{
"rule": "React-useRef",
"path": "ts/components/CompositionInput.js",
"line": " const mentionCompletionRef = React.useRef();",
"reasonCategory": "falseMatch",
"updated": "2020-10-26T23:54:34.273Z",
"reasonDetail": "Doesn't refer to a DOM element."
},
{
"rule": "React-useRef",
"path": "ts/components/CompositionInput.js",
"line": " const memberRepositoryRef = React.useRef(new memberRepository_1.MemberRepository());",
"reasonCategory": "falseMatch",
"updated": "2020-10-26T23:56:13.482Z",
"reasonDetail": "Doesn't refer to a DOM element."
},
{
"rule": "React-useRef",
"path": "ts/components/CompositionInput.js",
"line": " const scrollerRef = React.useRef(null);",
"reasonCategory": "usageTrusted",
"updated": "2020-10-26T19:12:24.410Z",
"reasonDetail": "Used with Quill for scrolling."
},
{
"rule": "React-useRef",
"path": "ts/components/CompositionInput.js",
"line": " const callbacksRef = React.useRef(unstaleCallbacks);",
"reasonCategory": "usageTrusted",
"updated": "2021-04-21T21:35:38.757Z"
},
{ {
"rule": "React-useRef", "rule": "React-useRef",
"path": "ts/components/CompositionInput.tsx", "path": "ts/components/CompositionInput.tsx",
@ -7306,13 +7189,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-07-30T16:57:33.618Z" "updated": "2021-07-30T16:57:33.618Z"
}, },
{
"rule": "React-useRef",
"path": "ts/components/ForwardMessageModal.js",
"line": " const inputApiRef = react_1.default.useRef();",
"reasonCategory": "usageTrusted",
"updated": "2021-04-19T18:13:21.664Z"
},
{ {
"rule": "React-useRef", "rule": "React-useRef",
"path": "ts/components/ForwardMessageModal.tsx", "path": "ts/components/ForwardMessageModal.tsx",
@ -7414,13 +7290,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-07-30T16:57:33.618Z" "updated": "2021-07-30T16:57:33.618Z"
}, },
{
"rule": "jQuery-$(",
"path": "ts/components/Intl.js",
"line": " const FIND_REPLACEMENTS = /\\$([^$]+)\\$/g;",
"reasonCategory": "falseMatch",
"updated": "2020-07-21T18:34:59.251Z"
},
{ {
"rule": "jQuery-$(", "rule": "jQuery-$(",
"path": "ts/components/Intl.tsx", "path": "ts/components/Intl.tsx",
@ -7515,14 +7384,6 @@
"updated": "2022-01-04T21:43:17.517Z", "updated": "2022-01-04T21:43:17.517Z",
"reasonDetail": "Used to change the style in non-production builds." "reasonDetail": "Used to change the style in non-production builds."
}, },
{
"rule": "React-createRef",
"path": "ts/components/SafetyNumberChangeDialog.js",
"line": " const cancelButtonRef = React.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2020-06-23T06:48:06.829Z",
"reasonDetail": "Used to focus cancel button when dialog opens"
},
{ {
"rule": "React-useRef", "rule": "React-useRef",
"path": "ts/components/Slider.tsx", "path": "ts/components/Slider.tsx",
@ -7558,14 +7419,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-11-30T10:15:33.662Z" "updated": "2021-11-30T10:15:33.662Z"
}, },
{
"rule": "React-useRef",
"path": "ts/components/Tooltip.js",
"line": " const wrapperRef = react_1.default.useRef(null);",
"reasonCategory": "usageTrusted",
"updated": "2020-12-04T00:11:08.128Z",
"reasonDetail": "Used to add (and remove) event listeners."
},
{ {
"rule": "React-useRef", "rule": "React-useRef",
"path": "ts/components/Tooltip.tsx", "path": "ts/components/Tooltip.tsx",
@ -7573,22 +7426,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-07-30T16:57:33.618Z" "updated": "2021-07-30T16:57:33.618Z"
}, },
{
"rule": "React-createRef",
"path": "ts/components/conversation/ConversationHeader.js",
"line": " this.menuTriggerRef = react_1.default.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2020-08-28T16:12:19.904Z",
"reasonDetail": "Used to reference popup menu"
},
{
"rule": "React-createRef",
"path": "ts/components/conversation/ConversationHeader.js",
"line": " this.headerRef = react_1.default.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2021-01-18T22:24:05.937Z",
"reasonDetail": "Used to reference popup menu boundaries element"
},
{ {
"rule": "React-createRef", "rule": "React-createRef",
"path": "ts/components/conversation/ConversationHeader.tsx", "path": "ts/components/conversation/ConversationHeader.tsx",
@ -7627,14 +7464,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-07-30T16:57:33.618Z" "updated": "2021-07-30T16:57:33.618Z"
}, },
{
"rule": "React-createRef",
"path": "ts/components/conversation/InlineNotificationWrapper.js",
"line": " this.focusRef = react_1.default.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2019-11-06T19:56:38.557Z",
"reasonDetail": "Used to manage focus"
},
{ {
"rule": "React-createRef", "rule": "React-createRef",
"path": "ts/components/conversation/InlineNotificationWrapper.tsx", "path": "ts/components/conversation/InlineNotificationWrapper.tsx",
@ -7643,30 +7472,6 @@
"updated": "2019-11-06T19:56:38.557Z", "updated": "2019-11-06T19:56:38.557Z",
"reasonDetail": "Used to manage focus" "reasonDetail": "Used to manage focus"
}, },
{
"rule": "React-createRef",
"path": "ts/components/conversation/Message.js",
"line": " this.reactionsContainerRef = react_1.default.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2020-08-28T16:12:19.904Z",
"reasonDetail": "Used for detecting clicks outside reaction viewer"
},
{
"rule": "React-createRef",
"path": "ts/components/conversation/Message.js",
"line": " this.focusRef = react_1.default.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2021-03-05T20:05:07.474Z",
"reasonDetail": "Used for managing focus only"
},
{
"rule": "React-createRef",
"path": "ts/components/conversation/Message.js",
"line": " this.audioButtonRef = react_1.default.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2021-03-05T20:05:07.474Z",
"reasonDetail": "Used for propagating click from the Message to MessageAudio's button"
},
{ {
"rule": "React-createRef", "rule": "React-createRef",
"path": "ts/components/conversation/Message.tsx", "path": "ts/components/conversation/Message.tsx",
@ -7698,22 +7503,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-07-30T16:57:33.618Z" "updated": "2021-07-30T16:57:33.618Z"
}, },
{
"rule": "React-createRef",
"path": "ts/components/conversation/MessageDetail.js",
"line": " this.focusRef = react_1.default.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2019-11-01T22:46:33.013Z",
"reasonDetail": "Used for setting focus only"
},
{
"rule": "React-createRef",
"path": "ts/components/conversation/MessageDetail.js",
"line": " this.messageContainerRef = react_1.default.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2021-08-20T16:48:00.885Z",
"reasonDetail": "Needed to confine Poppers. We don't actually manipulate this DOM reference."
},
{ {
"rule": "React-useRef", "rule": "React-useRef",
"path": "ts/components/conversation/Quote.tsx", "path": "ts/components/conversation/Quote.tsx",
@ -7722,22 +7511,6 @@
"updated": "2021-01-20T21:30:08.430Z", "updated": "2021-01-20T21:30:08.430Z",
"reasonDetail": "Doesn't touch the DOM." "reasonDetail": "Doesn't touch the DOM."
}, },
{
"rule": "React-createRef",
"path": "ts/components/conversation/Timeline.js",
"line": " this.listRef = react_1.default.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2019-07-31T00:19:18.696Z",
"reasonDetail": "Timeline needs to interact with its child List directly"
},
{
"rule": "React-createRef",
"path": "ts/components/conversation/Timeline.js",
"line": " this.containerRef = react_1.default.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2021-08-20T16:48:00.885Z",
"reasonDetail": "Needed to confine Poppers. We don't actually manipulate this DOM reference."
},
{ {
"rule": "React-useRef", "rule": "React-useRef",
"path": "ts/components/conversation/conversation-details/AddGroupMembersModal/ChooseGroupMembersModal.tsx", "path": "ts/components/conversation/conversation-details/AddGroupMembersModal/ChooseGroupMembersModal.tsx",
@ -7766,14 +7539,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-07-30T16:57:33.618Z" "updated": "2021-07-30T16:57:33.618Z"
}, },
{
"rule": "React-createRef",
"path": "ts/components/conversation/media-gallery/MediaGallery.js",
"line": " this.focusRef = react_1.default.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2019-11-01T22:46:33.013Z",
"reasonDetail": "Used for setting focus only"
},
{ {
"rule": "React-createRef", "rule": "React-createRef",
"path": "ts/components/conversation/media-gallery/MediaGallery.tsx", "path": "ts/components/conversation/media-gallery/MediaGallery.tsx",
@ -7790,14 +7555,6 @@
"updated": "2021-12-06T23:07:28.947Z", "updated": "2021-12-06T23:07:28.947Z",
"reasonDetail": "Doesn't touch the DOM." "reasonDetail": "Doesn't touch the DOM."
}, },
{
"rule": "React-createRef",
"path": "ts/components/stickers/StickerManager.js",
"line": " const focusRef = React.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2019-11-21T06:13:49.384Z",
"reasonDetail": "Used for setting focus only"
},
{ {
"rule": "React-useRef", "rule": "React-useRef",
"path": "ts/hooks/useIntersectionObserver.ts", "path": "ts/hooks/useIntersectionObserver.ts",
@ -7812,35 +7569,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-09-17T20:16:37.959Z" "updated": "2021-09-17T20:16:37.959Z"
}, },
{
"rule": "React-useRef",
"path": "ts/hooks/useRestoreFocus.js",
"line": " const lastFocusedRef = React.useRef(null);",
"reasonCategory": "usageTrusted",
"updated": "2021-07-30T01:08:01.309Z",
"reasonDetail": "Used to store the previous-focused item, again to set focus"
},
{
"rule": "React-useRef",
"path": "ts/hooks/useRestoreFocus.js",
"line": " const toFocusRef = React.useRef(null);",
"reasonCategory": "usageTrusted",
"updated": "2021-09-17T17:37:46.279Z"
},
{
"rule": "React-useRef",
"path": "ts/hooks/useRestoreFocus.js",
"line": " const toFocusRef = React.useRef(null);",
"reasonCategory": "usageTrusted",
"updated": "2021-10-22T00:52:39.251Z"
},
{
"rule": "React-useRef",
"path": "ts/hooks/useRestoreFocus.js",
"line": " const lastFocusedRef = React.useRef(null);",
"reasonCategory": "usageTrusted",
"updated": "2021-10-22T00:52:39.251Z"
},
{ {
"rule": "React-useRef", "rule": "React-useRef",
"path": "ts/hooks/useRestoreFocus.ts", "path": "ts/hooks/useRestoreFocus.ts",
@ -7869,13 +7597,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-10-22T00:52:39.251Z" "updated": "2021-10-22T00:52:39.251Z"
}, },
{
"rule": "jQuery-load(",
"path": "ts/jobs/helpers/syncHelpers.js",
"line": " await window.ConversationController.load();",
"reasonCategory": "falseMatch",
"updated": "2021-12-15T19:58:28.089Z"
},
{ {
"rule": "jQuery-load(", "rule": "jQuery-load(",
"path": "ts/jobs/helpers/syncHelpers.ts", "path": "ts/jobs/helpers/syncHelpers.ts",
@ -7883,13 +7604,6 @@
"reasonCategory": "falseMatch", "reasonCategory": "falseMatch",
"updated": "2021-11-04T16:14:03.477Z" "updated": "2021-11-04T16:14:03.477Z"
}, },
{
"rule": "jQuery-load(",
"path": "ts/jobs/normalMessageSendJobQueue.js",
"line": " await window.ConversationController.load();",
"reasonCategory": "falseMatch",
"updated": "2021-11-04T16:14:03.477Z"
},
{ {
"rule": "jQuery-load(", "rule": "jQuery-load(",
"path": "ts/jobs/normalMessageSendJobQueue.ts", "path": "ts/jobs/normalMessageSendJobQueue.ts",
@ -7897,13 +7611,6 @@
"reasonCategory": "falseMatch", "reasonCategory": "falseMatch",
"updated": "2021-12-15T19:58:28.089Z" "updated": "2021-12-15T19:58:28.089Z"
}, },
{
"rule": "jQuery-load(",
"path": "ts/jobs/reactionJobQueue.js",
"line": " await window.ConversationController.load();",
"reasonCategory": "falseMatch",
"updated": "2021-11-04T16:14:03.477Z"
},
{ {
"rule": "jQuery-load(", "rule": "jQuery-load(",
"path": "ts/jobs/reactionJobQueue.ts", "path": "ts/jobs/reactionJobQueue.ts",
@ -7911,34 +7618,6 @@
"reasonCategory": "falseMatch", "reasonCategory": "falseMatch",
"updated": "2021-11-04T16:14:03.477Z" "updated": "2021-11-04T16:14:03.477Z"
}, },
{
"rule": "jQuery-append(",
"path": "ts/logging/uploadDebugLog.js",
"line": " form.append('key', uploadKey);",
"reasonCategory": "falseMatch",
"updated": "2020-12-17T18:08:07.752Z"
},
{
"rule": "jQuery-append(",
"path": "ts/logging/uploadDebugLog.js",
"line": " form.append(key, value);",
"reasonCategory": "falseMatch",
"updated": "2020-12-17T18:08:07.752Z"
},
{
"rule": "jQuery-append(",
"path": "ts/logging/uploadDebugLog.js",
"line": " form.append('Content-Type', contentType);",
"reasonCategory": "falseMatch",
"updated": "2020-12-17T18:08:07.752Z"
},
{
"rule": "jQuery-append(",
"path": "ts/logging/uploadDebugLog.js",
"line": " form.append('file', contentBuffer, {",
"reasonCategory": "falseMatch",
"updated": "2020-12-17T18:08:07.752Z"
},
{ {
"rule": "jQuery-append(", "rule": "jQuery-append(",
"path": "ts/logging/uploadDebugLog.ts", "path": "ts/logging/uploadDebugLog.ts",
@ -7967,22 +7646,6 @@
"reasonCategory": "falseMatch", "reasonCategory": "falseMatch",
"updated": "2020-12-17T18:08:07.752Z" "updated": "2020-12-17T18:08:07.752Z"
}, },
{
"rule": "jQuery-$(",
"path": "ts/manage_full_screen_class.js",
"line": "$(document).ready(() => {",
"reasonCategory": "usageTrusted",
"updated": "2021-01-21T23:06:13.270Z",
"reasonDetail": "Doesn't manipulate the DOM."
},
{
"rule": "jQuery-$(",
"path": "ts/manage_full_screen_class.js",
"line": " $(document.body).toggleClass('full-screen', isFullScreen);",
"reasonCategory": "usageTrusted",
"updated": "2021-01-21T23:06:13.270Z",
"reasonDetail": "Manipulates a trusted class."
},
{ {
"rule": "jQuery-$(", "rule": "jQuery-$(",
"path": "ts/manage_full_screen_class.ts", "path": "ts/manage_full_screen_class.ts",
@ -7999,21 +7662,6 @@
"updated": "2021-01-21T23:06:13.270Z", "updated": "2021-01-21T23:06:13.270Z",
"reasonDetail": "Manipulates a trusted class." "reasonDetail": "Manipulates a trusted class."
}, },
{
"rule": "React-createRef",
"path": "ts/quill/mentions/completion.js",
"line": " this.suggestionListRef = react_1.default.createRef();",
"reasonCategory": "usageTrusted",
"updated": "2020-10-30T23:03:08.319Z"
},
{
"rule": "DOM-innerHTML",
"path": "ts/quill/signal-clipboard/index.js",
"line": " return div.innerHTML;",
"reasonCategory": "usageTrusted",
"updated": "2020-11-06T17:43:07.381Z",
"reasonDetail": "used for figuring out clipboard contents"
},
{ {
"rule": "DOM-innerHTML", "rule": "DOM-innerHTML",
"path": "ts/quill/signal-clipboard/index.ts", "path": "ts/quill/signal-clipboard/index.ts",
@ -8022,22 +7670,6 @@
"updated": "2020-11-06T17:43:07.381Z", "updated": "2020-11-06T17:43:07.381Z",
"reasonDetail": "used for figuring out clipboard contents" "reasonDetail": "used for figuring out clipboard contents"
}, },
{
"rule": "jQuery-$(",
"path": "ts/set_os_class.js",
"line": " $(document.body).addClass(className);",
"reasonCategory": "usageTrusted",
"updated": "2021-01-21T23:06:13.270Z",
"reasonDetail": "Adds a trusted CSS class."
},
{
"rule": "jQuery-$(",
"path": "ts/set_os_class.js",
"line": "$(document).ready(() => {",
"reasonCategory": "usageTrusted",
"updated": "2021-01-21T23:06:13.270Z",
"reasonDetail": "Doesn't manipulate the DOM."
},
{ {
"rule": "jQuery-$(", "rule": "jQuery-$(",
"path": "ts/set_os_class.ts", "path": "ts/set_os_class.ts",
@ -8054,13 +7686,6 @@
"updated": "2021-01-21T23:06:13.270Z", "updated": "2021-01-21T23:06:13.270Z",
"reasonDetail": "Doesn't manipulate the DOM." "reasonDetail": "Doesn't manipulate the DOM."
}, },
{
"rule": "jQuery-load(",
"path": "ts/state/ducks/app.js",
"line": " await window.ConversationController.load();",
"reasonCategory": "falseMatch",
"updated": "2021-11-04T16:14:03.477Z"
},
{ {
"rule": "jQuery-load(", "rule": "jQuery-load(",
"path": "ts/state/ducks/app.ts", "path": "ts/state/ducks/app.ts",
@ -8076,13 +7701,6 @@
"updated": "2021-12-06T23:07:28.947Z", "updated": "2021-12-06T23:07:28.947Z",
"reasonDetail": "Doesn't touch the DOM." "reasonDetail": "Doesn't touch the DOM."
}, },
{
"rule": "jQuery-load(",
"path": "ts/types/Stickers.js",
"line": "async function load() {",
"reasonCategory": "falseMatch",
"updated": "2021-07-02T02:57:58.052Z"
},
{ {
"rule": "jQuery-load(", "rule": "jQuery-load(",
"path": "ts/types/Stickers.ts", "path": "ts/types/Stickers.ts",
@ -8090,13 +7708,6 @@
"reasonCategory": "falseMatch", "reasonCategory": "falseMatch",
"updated": "2019-04-26T17:48:30.675Z" "updated": "2019-04-26T17:48:30.675Z"
}, },
{
"rule": "jQuery-load(",
"path": "ts/util/avatarDataToBytes.js",
"line": " await font.load();",
"reasonCategory": "usageTrusted",
"updated": "2021-08-03T21:17:38.615Z"
},
{ {
"rule": "jQuery-load(", "rule": "jQuery-load(",
"path": "ts/util/avatarDataToBytes.ts", "path": "ts/util/avatarDataToBytes.ts",
@ -8104,46 +7715,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-08-03T21:17:38.615Z" "updated": "2021-08-03T21:17:38.615Z"
}, },
{
"rule": "jQuery-$(",
"path": "ts/util/createIPCEvents.js",
"line": " if ($('.dark-overlay').length) {",
"reasonCategory": "usageTrusted",
"updated": "2021-08-18T18:22:55.307Z",
"reasonDetail": "Legacy code"
},
{
"rule": "jQuery-$(",
"path": "ts/util/createIPCEvents.js",
"line": " $(document.body).prepend('<div class=\"dark-overlay\"></div>');",
"reasonCategory": "usageTrusted",
"updated": "2021-08-18T18:22:55.307Z",
"reasonDetail": "Legacy code"
},
{
"rule": "jQuery-$(",
"path": "ts/util/createIPCEvents.js",
"line": " $('.dark-overlay').on('click', () => $('.dark-overlay').remove());",
"reasonCategory": "usageTrusted",
"updated": "2021-08-18T18:22:55.307Z",
"reasonDetail": "Legacy code"
},
{
"rule": "jQuery-$(",
"path": "ts/util/createIPCEvents.js",
"line": " }, removeDarkOverlay: () => $('.dark-overlay').remove(), showKeyboardShortcuts: () => window.showKeyboardShortcuts(), deleteAllData: async () => {",
"reasonCategory": "usageTrusted",
"updated": "2021-08-18T18:22:55.307Z",
"reasonDetail": "Legacy code"
},
{
"rule": "jQuery-prepend(",
"path": "ts/util/createIPCEvents.js",
"line": " $(document.body).prepend('<div class=\"dark-overlay\"></div>');",
"reasonCategory": "usageTrusted",
"updated": "2021-08-18T18:22:55.307Z",
"reasonDetail": "Legacy code"
},
{ {
"rule": "jQuery-$(", "rule": "jQuery-$(",
"path": "ts/util/createIPCEvents.ts", "path": "ts/util/createIPCEvents.ts",
@ -8184,13 +7755,6 @@
"updated": "2021-08-18T18:22:55.307Z", "updated": "2021-08-18T18:22:55.307Z",
"reasonDetail": "Legacy code" "reasonDetail": "Legacy code"
}, },
{
"rule": "jQuery-load(",
"path": "ts/util/sendReceipts.js",
"line": " await window.ConversationController.load();",
"reasonCategory": "falseMatch",
"updated": "2021-12-15T19:58:28.089Z"
},
{ {
"rule": "jQuery-load(", "rule": "jQuery-load(",
"path": "ts/util/sendReceipts.ts", "path": "ts/util/sendReceipts.ts",
@ -8198,13 +7762,6 @@
"reasonCategory": "falseMatch", "reasonCategory": "falseMatch",
"updated": "2021-12-15T19:58:28.089Z" "updated": "2021-12-15T19:58:28.089Z"
}, },
{
"rule": "jQuery-$(",
"path": "ts/util/setupI18n.js",
"line": " const FIND_REPLACEMENTS = /\\$([^$]+)\\$/g;",
"reasonCategory": "falseMatch",
"updated": "2021-09-17T21:51:57.475Z"
},
{ {
"rule": "jQuery-$(", "rule": "jQuery-$(",
"path": "ts/util/setupI18n.ts", "path": "ts/util/setupI18n.ts",
@ -8212,90 +7769,6 @@
"reasonCategory": "falseMatch", "reasonCategory": "falseMatch",
"updated": "2021-09-17T21:51:57.475Z" "updated": "2021-09-17T21:51:57.475Z"
}, },
{
"rule": "jQuery-$(",
"path": "ts/views/inbox_view.js",
"line": " template: () => $('#app-loading-screen').html(),",
"reasonCategory": "usageTrusted",
"updated": "2021-09-15T21:07:50.995Z"
},
{
"rule": "jQuery-$(",
"path": "ts/views/inbox_view.js",
"line": " this.$('.message').text(message);",
"reasonCategory": "usageTrusted",
"updated": "2021-09-15T21:07:50.995Z"
},
{
"rule": "jQuery-$(",
"path": "ts/views/inbox_view.js",
"line": " template: () => $('#two-column').html(),",
"reasonCategory": "usageTrusted",
"updated": "2021-09-15T21:07:50.995Z"
},
{
"rule": "jQuery-$(",
"path": "ts/views/inbox_view.js",
"line": " el: this.$('.conversation-stack'),",
"reasonCategory": "usageTrusted",
"updated": "2021-09-15T21:07:50.995Z"
},
{
"rule": "jQuery-$(",
"path": "ts/views/inbox_view.js",
"line": " this.$('.left-pane-placeholder').replaceWith(this.leftPaneView.el);",
"reasonCategory": "usageTrusted",
"updated": "2021-10-08T17:39:41.541Z"
},
{
"rule": "jQuery-$(",
"path": "ts/views/inbox_view.js",
"line": " this.$('.no-conversation-open').toggle(!isAnyConversationOpen);",
"reasonCategory": "usageTrusted",
"updated": "2021-10-08T17:40:22.770Z"
},
{
"rule": "jQuery-$(",
"path": "ts/views/inbox_view.js",
"line": " this.$('.whats-new-placeholder').append(this.whatsNewLink.el);",
"reasonCategory": "usageTrusted",
"updated": "2021-10-22T20:58:48.103Z"
},
{
"rule": "jQuery-append(",
"path": "ts/views/inbox_view.js",
"line": " this.$('.whats-new-placeholder').append(this.whatsNewLink.el);",
"reasonCategory": "usageTrusted",
"updated": "2021-10-22T20:58:48.103Z"
},
{
"rule": "jQuery-appendTo(",
"path": "ts/views/inbox_view.js",
"line": " view.$el.appendTo(this.el);",
"reasonCategory": "usageTrusted",
"updated": "2021-09-20T22:27:31.785Z"
},
{
"rule": "jQuery-html(",
"path": "ts/views/inbox_view.js",
"line": " template: () => $('#app-loading-screen').html(),",
"reasonCategory": "usageTrusted",
"updated": "2021-09-15T21:07:50.995Z"
},
{
"rule": "jQuery-html(",
"path": "ts/views/inbox_view.js",
"line": " template: () => $('#two-column').html(),",
"reasonCategory": "usageTrusted",
"updated": "2021-09-15T21:07:50.995Z"
},
{
"rule": "jQuery-prependTo(",
"path": "ts/views/inbox_view.js",
"line": " this.appLoadingScreen.$el.prependTo(this.el);",
"reasonCategory": "usageTrusted",
"updated": "2021-09-15T21:07:50.995Z"
},
{ {
"rule": "jQuery-$(", "rule": "jQuery-$(",
"path": "ts/views/inbox_view.ts", "path": "ts/views/inbox_view.ts",
@ -8380,13 +7853,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-09-15T21:07:50.995Z" "updated": "2021-09-15T21:07:50.995Z"
}, },
{
"rule": "DOM-innerHTML",
"path": "ts/windows/loading/start.js",
"line": " message.innerHTML = window.SignalContext.i18n('optimizingApplication');",
"reasonCategory": "usageTrusted",
"updated": "2021-09-17T21:02:59.414Z"
},
{ {
"rule": "DOM-innerHTML", "rule": "DOM-innerHTML",
"path": "ts/windows/loading/start.ts", "path": "ts/windows/loading/start.ts",

View file

@ -31,6 +31,9 @@ const excludedFilesRegexp = RegExp(
'.+\\.stories\\.js', '.+\\.stories\\.js',
'.+\\.stories\\.tsx', '.+\\.stories\\.tsx',
// Compiled files
'^ts/.+\\.js',
// High-traffic files in our project // High-traffic files in our project
'^app/.+(ts|js)', '^app/.+(ts|js)',
'^ts/models/messages.js', '^ts/models/messages.js',
@ -74,6 +77,7 @@ const excludedFilesRegexp = RegExp(
'^.github/.+', '^.github/.+',
// Modules we trust // Modules we trust
'^node_modules/@signalapp/signal-client/.+',
'^node_modules/core-js-pure/.+', '^node_modules/core-js-pure/.+',
'^node_modules/core-js/.+', '^node_modules/core-js/.+',
'^node_modules/fbjs/.+', '^node_modules/fbjs/.+',
@ -104,6 +108,7 @@ const excludedFilesRegexp = RegExp(
'^node_modules/react-color/.+/(?:core-js|fbjs|lodash)/.+', '^node_modules/react-color/.+/(?:core-js|fbjs|lodash)/.+',
// Modules used only in test/development scenarios // Modules used only in test/development scenarios
'^node_modules/esbuild/.+',
'^node_modules/@babel/.+', '^node_modules/@babel/.+',
'^node_modules/@chanzuckerberg/axe-storybook-testing/.+', '^node_modules/@chanzuckerberg/axe-storybook-testing/.+',
'^node_modules/@svgr/.+', '^node_modules/@svgr/.+',

View file

@ -1,7 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
// Basic Options // Basic Options
"target": "es2017", // Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. "target": "es2020", // Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'.
"module": "commonjs", // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. "module": "commonjs", // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.
// Specify library files to be included in the compilation. // Specify library files to be included in the compilation.
"lib": [ "lib": [

View file

@ -1,23 +0,0 @@
// Copyright 2019-2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { resolve } from 'path';
// eslint-disable-next-line import/no-extraneous-dependencies
import { Configuration } from 'webpack';
const context = __dirname;
const workerConfig: Configuration = {
context,
mode: 'development',
devtool: false,
entry: ['./ts/workers/heicConverterWorker.js'],
target: 'node',
output: {
path: resolve(context, 'ts', 'workers'),
filename: 'heicConverter.bundle.js',
publicPath: './',
},
};
export default [workerConfig];

View file

@ -1,76 +0,0 @@
// Copyright 2019-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { resolve } from 'path';
// eslint-disable-next-line import/no-extraneous-dependencies
import { Configuration } from 'webpack';
import TerserPlugin = require('terser-webpack-plugin');
const context = __dirname;
const { NODE_ENV: mode = 'development' } = process.env;
const EXTERNAL_MODULE = new Set([
'@signalapp/signal-client',
'@signalapp/signal-client/zkgroup',
'backbone',
'better-sqlite3',
'fs-xattr',
'fsevents',
'got',
'jquery',
'mac-screen-capture-permissions',
'node-fetch',
'pino',
'proxy-agent',
'ringrtc',
'sharp',
'websocket',
// Uses fast-glob and dynamic requires
'./preload_test',
// Needs to exports `electronRequire`
'./ts/CI',
]);
const preloadConfig: Configuration = {
context,
mode: mode as Configuration['mode'],
devtool: mode === 'development' ? 'inline-source-map' : false,
entry: ['./preload.js'],
// Stack-traces have to be readable so don't mangle function names.
optimization: {
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
mangle: false,
keep_classnames: true,
keep_fnames: true,
},
}),
],
},
target: 'electron-preload',
output: {
path: resolve(context),
filename: 'preload.bundle.js',
publicPath: './',
},
resolve: {
extensions: ['.js'],
alias: {},
mainFields: ['browser', 'main'],
},
externals: [
({ request = '' }, callback) => {
if (EXTERNAL_MODULE.has(request)) {
return callback(undefined, `commonjs2 ${request}`);
}
callback();
},
],
};
export default [preloadConfig];

View file

@ -1,36 +0,0 @@
// Copyright 2019-2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { resolve, join } from 'path';
// eslint-disable-next-line import/no-extraneous-dependencies
import { Configuration } from 'webpack';
const context = __dirname;
// A path relative to `ts/sql/` in `asar.unpacked`
const libDir = join('..', '..', 'node_modules', 'better-sqlite3');
const bindingFile = join(libDir, 'build', 'Release', 'better_sqlite3.node');
const workerConfig: Configuration = {
context,
mode: 'development',
devtool: false,
entry: ['./ts/sql/mainWorker.js'],
target: 'node',
output: {
path: resolve(context, 'ts', 'sql'),
filename: 'mainWorker.bundle.js',
publicPath: './',
},
resolve: {
extensions: ['.js'],
alias: {
bindings: join(context, 'ts', 'sql', 'mainWorkerBindings.js'),
},
},
externals: {
'better_sqlite3.node': `commonjs2 ${bindingFile}`,
},
};
export default [workerConfig];

116
yarn.lock
View file

@ -1342,10 +1342,10 @@
"@react-spring/shared" "~9.4.0" "@react-spring/shared" "~9.4.0"
"@react-spring/types" "~9.4.0" "@react-spring/types" "~9.4.0"
"@signalapp/signal-client@0.11.1": "@signalapp/signal-client@0.12.4":
version "0.11.1" version "0.12.4"
resolved "https://registry.yarnpkg.com/@signalapp/signal-client/-/signal-client-0.11.1.tgz#f1f859453c2d187e5f47ab02707ae4580edaa6fc" resolved "https://registry.yarnpkg.com/@signalapp/signal-client/-/signal-client-0.12.4.tgz#19023456c9249db6afb01762b1841e18cc3614be"
integrity sha512-TXvspNNq5fRMMM7SDMjSzPd7lBPRt7oSb5tzJNoLVHNOwwSAwdpo+P6fzN5LszeNJYNjOXlXTSuBD4HB8v4TMg== integrity sha512-52XpJO2Xng4G+cV4ocV2uvzkSomVRodsyuILAx++o/A0jR4bup/thbvpJ/abi1oHOggdJJ0jn2nKgPl/2UAC2A==
dependencies: dependencies:
node-gyp-build "^4.2.3" node-gyp-build "^4.2.3"
uuid "^8.3.0" uuid "^8.3.0"
@ -6216,6 +6216,114 @@ es6-weak-map@^2.0.2:
es6-iterator "^2.0.1" es6-iterator "^2.0.1"
es6-symbol "^3.1.1" es6-symbol "^3.1.1"
esbuild-android-arm64@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.3.tgz#f0fc0a892dd6f2f42baf68f9ac24c9bfcfdaba20"
integrity sha512-v/vdnGJiSGWOAXzg422T9qb4S+P3tOaYtc5n3FDR27Bh3/xQDS7PdYz/yY7HhOlVp0eGwWNbPHEi8FcEhXjsuw==
esbuild-darwin-64@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.3.tgz#074268b97df08dc2ea60ddd3c29b05fd93ff63d3"
integrity sha512-swY5OtEg6cfWdgc/XEjkBP7wXSyXXeZHEsWMdh1bDiN1D6GmRphk9SgKFKTj+P3ZHhOGIcC1+UdIwHk5bUcOig==
esbuild-darwin-arm64@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.3.tgz#72a62c7e5c58a2321f0bb839f1368878d4a5a814"
integrity sha512-6i9dXPk8oT87wF6VHmwzSad76eMRU2Rt+GXrwF3Y4DCJgnPssJbabNQ9gurkuEX8M0YnEyJF0d1cR7rpTzcEiA==
esbuild-freebsd-64@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.3.tgz#63f507254f41ccbab97bb6dce655e7dbc127f351"
integrity sha512-WDY5ENsmyceeE+95U3eI+FM8yARY5akWkf21M/x/+v2P5OVsYqCYELglSeAI5Y7bhteCVV3g4i2fRqtkmprdSA==
esbuild-freebsd-arm64@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.3.tgz#6520f6c8339df943633586d0d597ac2ee1f1958d"
integrity sha512-4BEEGcP0wBzg04pCCWXlgaPuksQHHfwHvYgCIsi+7IsuB17ykt6MHhTkHR5b5pjI/jNtRhPfMsDODUyftQJgvw==
esbuild-linux-32@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.3.tgz#813d7baf2d33675c9264a07b09a26c39d588abb2"
integrity sha512-8yhsnjLG/GwCA1RAIndjmCHWViRB2Ol0XeOh2fCXS9qF8tlVrJB7qAiHZpm2vXx+yjOA/bFLTxzU+5pMKqkn5A==
esbuild-linux-64@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.3.tgz#6356ff2d2c6ec978eb6e794a8891cc5cfadab3f1"
integrity sha512-eNq4aixfbwXHIJq4bQDe+XaSNV1grxqpZYs/zHbp0HGHf6SBNlTI02uyTbYGpIzlXmCEPS9tpPCi7BTU45kcJQ==
esbuild-linux-arm64@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.3.tgz#a289bb67a5207e021d1ac8cae3532771eda473a6"
integrity sha512-wPLyRoqoV/tEMQ7M24DpAmCMyKqBmtgZY35w2tXM8X5O5b2Ohi7fkPSmd6ZgLIxZIApWt88toA8RT0S7qoxcOA==
esbuild-linux-arm@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.3.tgz#b193de64458d4829be18206e58d127296367c189"
integrity sha512-YcMvJHAQnWrWKb+eLxN9e/iWUC/3w01UF/RXuMknqOW3prX8UQ63QknWz9/RI8BY/sdrdgPEbSmsTU2jy2cayQ==
esbuild-linux-mips64le@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.3.tgz#d3c826fc746f1cbf3aea696017b001625ea28b59"
integrity sha512-DdmfM5rcuoqjQL3px5MbquAjZWnySB5LdTrg52SSapp0gXMnGcsM6GY2WVta02CMKn5qi7WPVG4WbqTWE++tJw==
esbuild-linux-ppc64le@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.3.tgz#483974c92555eefe86d623145ff5f328074b6c9b"
integrity sha512-ujdqryj0m135Ms9yaNDVFAcLeRtyftM/v2v7Osji5zElf2TivSMdFxdrYnYICuHfkm8c8gHg1ncwqitL0r+nnA==
esbuild-netbsd-64@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.3.tgz#76442f9d2d6e6dc796d18eb321256ccdc68ead53"
integrity sha512-Z/UB9OUdwo1KDJCSGnVueDuKowRZRkduLvRMegHtDBHC3lS5LfZ3RdM1i+4MMN9iafyk8Q9FNcqIXI178ZujvA==
esbuild-openbsd-64@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.3.tgz#13b0adfd39e165f0dfd30af3e629c601b1b5fa36"
integrity sha512-9I1uoMDeogq3zQuTe3qygmXYjImnvc6rBn51LLbLniQDlfvqHPBMnAZ/5KshwtXXIIMkCwByytDZdiuzRRlTvQ==
esbuild-sunos-64@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.3.tgz#f8ce1a0c6f165b82d589c7f3de01baf094587fd2"
integrity sha512-pldqx/Adxl4V4ymiyKxOOyJmHn6nUIo3wqk2xBx07iDgmL2XTcDDQd7N4U4QGu9LnYN4ZF+8IdOYa3oRRpbjtg==
esbuild-windows-32@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.3.tgz#f555cbf0fca5974c3c303d9d9ff0d39e08f26916"
integrity sha512-AqzvA/KbkC2m3kTXGpljLin3EttRbtoPTfBn6w6n2m9MWkTEbhQbE1ONoOBxhO5tExmyJdL/6B87TJJD5jEFBQ==
esbuild-windows-64@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.3.tgz#02c9804f9ca5e587ccb8b18e46a00f9237e54689"
integrity sha512-HGg3C6113zLGB5hN41PROTnBuoh/arG2lQdOird6xFl9giff1cAfMQOUJUfODKD57dDqHjQ1YGW8gOkg0/IrWw==
esbuild-windows-arm64@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.3.tgz#8bcf737feddde3ccf4d2d6d581b2422b45a9b6e2"
integrity sha512-qB2izYu4VpigGnOrAN2Yv7ICYLZWY/AojZtwFfteViDnHgW4jXPYkHQIXTISJbRz25H2cYiv+MfRQYK31RNjlw==
esbuild@0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.3.tgz#38db1d26aaeccc43f478225974538e2c4de9d6b1"
integrity sha512-zyEC5hkguW2oieXRXp8VJzQdcO/1FxCS5GjzqOHItRlojXnx/cTavsrkxdWvBH9li2lUq0bN+LeeVEmyCwiR/Q==
optionalDependencies:
esbuild-android-arm64 "0.14.3"
esbuild-darwin-64 "0.14.3"
esbuild-darwin-arm64 "0.14.3"
esbuild-freebsd-64 "0.14.3"
esbuild-freebsd-arm64 "0.14.3"
esbuild-linux-32 "0.14.3"
esbuild-linux-64 "0.14.3"
esbuild-linux-arm "0.14.3"
esbuild-linux-arm64 "0.14.3"
esbuild-linux-mips64le "0.14.3"
esbuild-linux-ppc64le "0.14.3"
esbuild-netbsd-64 "0.14.3"
esbuild-openbsd-64 "0.14.3"
esbuild-sunos-64 "0.14.3"
esbuild-windows-32 "0.14.3"
esbuild-windows-64 "0.14.3"
esbuild-windows-arm64 "0.14.3"
escalade@^3.1.1: escalade@^3.1.1:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"