Skip to content

Commit 7ace093

Browse files
authored
meta(eslint-config): Don't allow voiding Promises (#9814)
1 parent bf32ea4 commit 7ace093

File tree

40 files changed

+179
-82
lines changed

40 files changed

+179
-82
lines changed

packages/browser-integration-tests/utils/replayHelpers.ts

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -105,40 +105,35 @@ export function waitForReplayRequest(
105105
* Wait until a callback returns true, collecting all replay responses along the way.
106106
* This can be useful when you don't know if stuff will be in one or multiple replay requests.
107107
*/
108-
export function waitForReplayRequests(
108+
export async function waitForReplayRequests(
109109
page: Page,
110110
callback: (event: ReplayEvent, res: Response) => boolean,
111111
timeout?: number,
112112
): Promise<Response[]> {
113113
const responses: Response[] = [];
114114

115-
return new Promise<Response[]>(resolve => {
116-
void page.waitForResponse(
117-
res => {
118-
const req = res.request();
115+
await page.waitForResponse(
116+
res => {
117+
const req = res.request();
119118

120-
const event = getReplayEventFromRequest(req);
119+
const event = getReplayEventFromRequest(req);
121120

122-
if (!event) {
123-
return false;
124-
}
121+
if (!event) {
122+
return false;
123+
}
125124

126-
responses.push(res);
125+
responses.push(res);
127126

128-
try {
129-
if (callback(event, res)) {
130-
resolve(responses);
131-
return true;
132-
}
127+
try {
128+
return callback(event, res);
129+
} catch {
130+
return false;
131+
}
132+
},
133+
timeout ? { timeout } : undefined,
134+
);
133135

134-
return false;
135-
} catch {
136-
return false;
137-
}
138-
},
139-
timeout ? { timeout } : undefined,
140-
);
141-
});
136+
return responses;
142137
}
143138

144139
export function isReplayEvent(event: Event): event is ReplayEvent {

packages/browser/src/client.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@ export class BrowserClient extends BaseClient<BrowserClientOptions> {
106106
dsn: this.getDsn(),
107107
tunnel: this.getOptions().tunnel,
108108
});
109-
void this._sendEnvelope(envelope);
109+
110+
// _sendEnvelope should not throw
111+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
112+
this._sendEnvelope(envelope);
110113
}
111114

112115
/**
@@ -137,6 +140,9 @@ export class BrowserClient extends BaseClient<BrowserClientOptions> {
137140
DEBUG_BUILD && logger.log('Sending outcomes:', outcomes);
138141

139142
const envelope = createClientReportEnvelope(outcomes, this._options.tunnel && dsnToString(this._dsn));
140-
void this._sendEnvelope(envelope);
143+
144+
// _sendEnvelope should not throw
145+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
146+
this._sendEnvelope(envelope);
141147
}
142148
}

packages/browser/src/profiling/hubextensions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ export function startProfileForTransaction(transaction: Transaction): Transactio
139139
);
140140
}
141141
// If the timeout exceeds, we want to stop profiling, but not finish the transaction
142-
void onProfileHandler();
142+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
143+
onProfileHandler();
143144
}, MAX_PROFILE_DURATION_MS);
144145

145146
// We need to reference the original finish call to avoid creating an infinite loop

packages/core/src/baseclient.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,10 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
375375
*/
376376
public sendSession(session: Session | SessionAggregates): void {
377377
const env = createSessionEnvelope(session, this._dsn, this._options._metadata, this._options.tunnel);
378-
void this._sendEnvelope(env);
378+
379+
// _sendEnvelope should not throw
380+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
381+
this._sendEnvelope(env);
379382
}
380383

381384
/**
@@ -409,7 +412,10 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
409412
this._options._metadata,
410413
this._options.tunnel,
411414
);
412-
void this._sendEnvelope(metricsEnvelope);
415+
416+
// _sendEnvelope should not throw
417+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
418+
this._sendEnvelope(metricsEnvelope);
413419
}
414420

415421
// Keep on() & emit() signatures in sync with types' client.ts interface

packages/core/src/server-runtime-client.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,11 @@ export class ServerRuntimeClient<
193193
);
194194

195195
DEBUG_BUILD && logger.info('Sending checkin:', checkIn.monitorSlug, checkIn.status);
196-
void this._sendEnvelope(envelope);
196+
197+
// _sendEnvelope should not throw
198+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
199+
this._sendEnvelope(envelope);
200+
197201
return id;
198202
}
199203

packages/deno/src/integrations/globalhandlers.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,16 @@ function installGlobalErrorHandler(client: Client): void {
7979
data.preventDefault();
8080
isExiting = true;
8181

82-
void flush().then(() => {
83-
// rethrow to replicate Deno default behavior
84-
throw error;
85-
});
82+
flush().then(
83+
() => {
84+
// rethrow to replicate Deno default behavior
85+
throw error;
86+
},
87+
() => {
88+
// rethrow to replicate Deno default behavior
89+
throw error;
90+
},
91+
);
8692
});
8793
}
8894

@@ -122,10 +128,16 @@ function installGlobalUnhandledRejectionHandler(client: Client): void {
122128
e.preventDefault();
123129
isExiting = true;
124130

125-
void flush().then(() => {
126-
// rethrow to replicate Deno default behavior
127-
throw error;
128-
});
131+
flush().then(
132+
() => {
133+
// rethrow to replicate Deno default behavior
134+
throw error;
135+
},
136+
() => {
137+
// rethrow to replicate Deno default behavior
138+
throw error;
139+
},
140+
);
129141
});
130142
}
131143

packages/e2e-tests/prepare.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ async function run(): Promise<void> {
2121
}
2222
}
2323

24-
void run();
24+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
25+
run();

packages/e2e-tests/run.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,5 @@ async function run(): Promise<void> {
8080
}
8181
}
8282

83-
void run();
83+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
84+
run();

packages/eslint-config-sdk/src/base.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ module.exports = {
8484
'@typescript-eslint/no-unused-expressions': ['error', { allowShortCircuit: true }],
8585

8686
// Make sure Promises are handled appropriately
87-
'@typescript-eslint/no-floating-promises': 'error',
87+
'@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: false }],
8888

8989
// Disallow delete operator. We should make this operation opt in (by disabling this rule).
9090
'@typescript-eslint/no-dynamic-delete': 'error',
@@ -158,7 +158,17 @@ module.exports = {
158158
env: {
159159
jest: true,
160160
},
161-
files: ['test.ts', '*.test.ts', '*.test.tsx', '*.test.js', '*.test.jsx', 'test/**/*.ts', 'test/**/*.js'],
161+
files: [
162+
'test.ts',
163+
'*.test.ts',
164+
'*.test.tsx',
165+
'*.test.js',
166+
'*.test.jsx',
167+
'test/**/*.ts',
168+
'test/**/*.js',
169+
'tests/**/*.ts',
170+
'tests/**/*.js',
171+
],
162172
rules: {
163173
'max-lines': 'off',
164174
'@typescript-eslint/explicit-function-return-type': 'off',
@@ -171,6 +181,7 @@ module.exports = {
171181
'@typescript-eslint/no-empty-function': 'off',
172182
'@sentry-internal/sdk/no-optional-chaining': 'off',
173183
'@sentry-internal/sdk/no-nullish-coalescing': 'off',
184+
'@typescript-eslint/no-floating-promises': 'off',
174185
},
175186
},
176187
{

packages/integrations/scripts/buildBundles.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ if (runParallel) {
4747
process.exit(1);
4848
});
4949
} else {
50-
void (async () => {
50+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
51+
(async () => {
5152
for (const integration of getIntegrations()) {
5253
await buildBundle(integration, 'es5');
5354
await buildBundle(integration, 'es6');

packages/nextjs/src/common/utils/responseEnd.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import type { ResponseEndMethod, WrappedResponseEndMethod } from '../types';
2626
export function autoEndTransactionOnResponseEnd(transaction: Transaction, res: ServerResponse): void {
2727
const wrapEndMethod = (origEnd: ResponseEndMethod): WrappedResponseEndMethod => {
2828
return function sentryWrappedEnd(this: ServerResponse, ...args: unknown[]) {
29-
void finishTransaction(transaction, this);
29+
finishTransaction(transaction, this);
3030
return origEnd.call(this, ...args);
3131
};
3232
};
@@ -39,7 +39,7 @@ export function autoEndTransactionOnResponseEnd(transaction: Transaction, res: S
3939
}
4040

4141
/** Finish the given response's transaction and set HTTP status data */
42-
export async function finishTransaction(transaction: Transaction | undefined, res: ServerResponse): Promise<void> {
42+
export function finishTransaction(transaction: Transaction | undefined, res: ServerResponse): void {
4343
if (transaction) {
4444
transaction.setHttpStatus(res.statusCode);
4545
transaction.finish();

packages/nextjs/src/common/withServerActionInstrumentation.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ async function withServerActionInstrumentationImplementation<A extends (...args:
129129
}
130130

131131
if (process.env.NEXT_RUNTIME === 'edge') {
132-
void flushQueue();
132+
// flushQueue should not throw
133+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
134+
flushQueue();
133135
}
134136
}
135137

packages/nextjs/src/common/wrapApiHandlerWithSentry.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ export function withSentry(apiHandler: NextApiHandler, parameterizedRoute?: stri
153153
const origResEnd = res.end;
154154
res.end = async function (this: unknown, ...args: unknown[]) {
155155
if (transaction) {
156-
await finishTransaction(transaction, res);
156+
finishTransaction(transaction, res);
157157
await flushQueue();
158158
}
159159

@@ -207,15 +207,14 @@ export function withSentry(apiHandler: NextApiHandler, parameterizedRoute?: stri
207207
res.statusCode = 500;
208208
res.statusMessage = 'Internal Server Error';
209209

210+
finishTransaction(transaction, res);
211+
210212
// Make sure we have a chance to finish the transaction and flush events to Sentry before the handler errors
211213
// out. (Apps which are deployed on Vercel run their API routes in lambdas, and those lambdas will shut down the
212214
// moment they detect an error, so it's important to get this done before rethrowing the error. Apps not
213215
// deployed serverlessly will run into this cleanup code again in `res.end(), but the transaction will already
214216
// be finished and the queue will already be empty, so effectively it'll just no-op.)
215217
if (platformSupportsStreaming() && !wrappingTarget.__sentry_test_doesnt_support_streaming__) {
216-
void finishTransaction(transaction, res);
217-
} else {
218-
await finishTransaction(transaction, res);
219218
await flushQueue();
220219
}
221220

packages/nextjs/src/common/wrapServerComponentWithSentry.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ export function wrapServerComponentWithSentry<F extends (...args: any[]) => any>
8888
}
8989
},
9090
() => {
91-
void flushQueue();
91+
// flushQueue should not throw
92+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
93+
flushQueue();
9294
},
9395
);
9496

packages/node-integration-tests/suites/tracing-new/apollo-graphql/scenario.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ const transaction = Sentry.startTransaction({ name: 'test_transaction', op: 'tra
3131

3232
Sentry.getCurrentScope().setSpan(transaction);
3333

34-
void (async () => {
34+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
35+
(async () => {
3536
// Ref: https://www.apollographql.com/docs/apollo-server/testing/testing/#testing-using-executeoperation
3637
await server.executeOperation({
3738
query: '{hello}',

packages/node-integration-tests/suites/tracing-new/auto-instrument/mongodb/scenario.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,5 @@ async function run(): Promise<void> {
4141
}
4242
}
4343

44-
void run();
44+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
45+
run();

packages/node-integration-tests/suites/tracing-new/prisma-orm/scenario.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ async function run(): Promise<void> {
4242
}
4343
}
4444

45-
void run();
45+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
46+
run();

packages/node-integration-tests/suites/tracing/apollo-graphql/scenario.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ const transaction = Sentry.startTransaction({ name: 'test_transaction', op: 'tra
3333

3434
Sentry.getCurrentScope().setSpan(transaction);
3535

36-
void (async () => {
36+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
37+
(async () => {
3738
// Ref: https://www.apollographql.com/docs/apollo-server/testing/testing/#testing-using-executeoperation
3839
await server.executeOperation({
3940
query: '{hello}',

packages/node-integration-tests/suites/tracing/auto-instrument/mongodb/scenario.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ async function run(): Promise<void> {
4242
}
4343
}
4444

45-
void run();
45+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
46+
run();

packages/node-integration-tests/suites/tracing/prisma-orm/scenario.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,5 @@ async function run(): Promise<void> {
4444
}
4545
}
4646

47-
void run();
47+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
48+
run();

packages/node-integration-tests/utils/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ export class TestEnv {
184184
envelopeTypeArray,
185185
);
186186

187-
void makeRequest(options.method, options.url || this.url, this._axiosConfig);
187+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
188+
makeRequest(options.method, options.url || this.url, this._axiosConfig);
188189
return resProm;
189190
}
190191

@@ -305,7 +306,8 @@ export class TestEnv {
305306

306307
nock.cleanAll();
307308

308-
void this._closeServer().then(() => {
309+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
310+
this._closeServer().then(() => {
309311
resolve(reqCount);
310312
});
311313
},

packages/node-integration-tests/utils/run-tests.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ const workers = os.cpus().map(async (_, i) => {
7070
}
7171
});
7272

73-
void Promise.all(workers).then(() => {
73+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
74+
Promise.all(workers).then(() => {
7475
console.log('-------------------');
7576
console.log(`Successfully ran ${numTests} tests.`);
7677
if (fails.length > 0) {

packages/node/src/integrations/anr/worker.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,9 @@ if (options.captureStackTrace) {
152152
session.post('Debugger.disable');
153153

154154
const context = trace_id?.length && span_id?.length ? { trace_id, span_id, parent_span_id } : undefined;
155-
void sendAnrEvent(stackFrames, context);
155+
sendAnrEvent(stackFrames, context).then(null, () => {
156+
log('Sending ANR event failed.');
157+
});
156158
},
157159
);
158160
} catch (e) {
@@ -196,7 +198,9 @@ function watchdogTimeout(): void {
196198
debuggerPause();
197199
} else {
198200
log('Capturing event without a stack trace');
199-
void sendAnrEvent();
201+
sendAnrEvent().then(null, () => {
202+
log('Sending ANR event failed on watchdog timeout.');
203+
});
200204
}
201205
}
202206

0 commit comments

Comments
 (0)