Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add missing await to floating promises #5813

Merged
merged 5 commits into from
Mar 22, 2021

Conversation

yury-s
Copy link
Member

@yury-s yury-s commented Mar 12, 2021

We have quite a few places where returned promises have no catch block. Some of them are valid and never expected to throw (this are now marked with void operator) others were missing await or catch block. Fixing some of them to give an idea of what it would look like. If we fix remaining occurrences we can enable no-floating-promises eslint check to prevent this problem in the future.

@yury-s yury-s force-pushed the no-floating-promises-1 branch from 45546e0 to 6bd870a Compare March 12, 2021 23:15
Copy link
Contributor

@dgozman dgozman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I think this adds more noise than solves problems. Some are good catches though. I'd advise against enabling the plugin.

src/client/android.ts Outdated Show resolved Hide resolved
@@ -100,7 +100,7 @@ export class CRConnection extends EventEmitter {
for (const session of this._sessions.values())
session._onClosed(browserDisconnectedLogs);
this._sessions.clear();
Promise.resolve().then(() => this.emit(ConnectionEvents.Disconnected));
void Promise.resolve().then(() => this.emit(ConnectionEvents.Disconnected));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite like these voids for no real reason 😄

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these void Promise.resolve().then( calls we can either introduce a helper function that will do .catch internally or can add .catch() inline which is silly. Which way you like better?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like neither 😄

requestId: event.requestId
});
}
if (!event.networkId) {
// Fetch without networkId means that request was not recongnized by inspector, and
// it will never receive Network.requestWillBeSent. Most likely, this is an internal request
// that we can safely fail.
this._client._sendMayFail('Fetch.failRequest', {
void this._client._sendMayFail('Fetch.failRequest', {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we should make _sendMayFail not return a promise?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are methods like InterceptableRequest.continue that wait on the returned promise.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, updated the code.

@@ -646,7 +646,7 @@ class FrameSession {
session.once('Runtime.executionContextCreated', async event => {
worker._createExecutionContext(new CRExecutionContext(session, event.context));
});
Promise.all([
void Promise.all([
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can just drop Promise.all.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but it would be even more verbose as it'd require void prefix for each statement.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed Promise.all and made replaced the methods with synchronous version.

@@ -969,7 +969,7 @@ class FrameSession {
});
const frameId = nodeInfo && typeof nodeInfo.node.frameId === 'string' ?
nodeInfo.node.frameId : null;
documentElement.dispose();
void documentElement.dispose();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, we can make handle.dispose() not return a Promise.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I think this adds more noise than solves problems. Some are good catches though. I'd advise against enabling the plugin.

Yeah, I'm not fond of this void prefixes all over the code. Without them there is a lot of noise in the linter output masking real issues but we can live with that for now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed dispose() to not return promise.

@@ -100,7 +100,7 @@ export class CRConnection extends EventEmitter {
for (const session of this._sessions.values())
session._onClosed(browserDisconnectedLogs);
this._sessions.clear();
Promise.resolve().then(() => this.emit(ConnectionEvents.Disconnected));
void Promise.resolve().then(() => this.emit(ConnectionEvents.Disconnected));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like neither 😄

@@ -90,7 +90,7 @@ export class FFExecutionContext implements js.ExecutionContextDelegate {
await this._session.send('Runtime.disposeObject', {
executionContextId: this._executionContextId,
objectId: handle._objectId,
}).catch(error => {});
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's caller's responsibility to catch exceptions if any and it does so now in .dispose().

@@ -210,7 +210,7 @@ export class Mouse {
async click(x: number, y: number, options: { delay?: number, button?: types.MouseButton, clickCount?: number } = {}) {
const { delay = null, clickCount = 1 } = options;
if (delay) {
this.move(x, y);
await this.move(x, y);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was not awaiting on purpose.

Copy link
Member Author

@yury-s yury-s Mar 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds sketchy and should be documented in that case.

src/server/snapshot/inMemorySnapshotter.ts Outdated Show resolved Hide resolved
_annotateFrameHierarchyAsync(frame).catch(e => {});
}

async function _annotateFrameHierarchyAsync(frame: Frame) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reminds me of C# 😄

@@ -45,15 +45,15 @@ export class InspectorController implements InstrumentationListener {
case 'log':
const originalMetadata = this._waitOperations.get(info.waitId)!;
originalMetadata.log.push(info.message);
this.onCallLog('api', info.message, sdkObject, originalMetadata);
await this.onCallLog('api', info.message, sdkObject, originalMetadata);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these were without await on purpose.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be .catch then?

}
}

async onBeforeCall(sdkObject: SdkObject, metadata: CallMetadata): Promise<void> {
if (this._mode === 'recording')
return;
this._captureSnapshot(sdkObject, metadata, 'before');
await this._captureSnapshot(sdkObject, metadata, 'before');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is important to no await here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, this should be commented then, maybe .catch too?

@@ -113,7 +113,7 @@ export class WKPage implements PageDelegate {
promises.push(this.updateHttpCredentials());
if (this._browserContext._permissions.size) {
for (const [key, value] of this._browserContext._permissions)
this._grantPermissions(key, value);
promises.push(this._grantPermissions(key, value));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

@yury-s yury-s force-pushed the no-floating-promises-1 branch from 3026c51 to c0c885d Compare March 20, 2021 00:51
@yury-s yury-s changed the title chore: add missing await annotate floating promises (1) chore: add missing await to floating promises Mar 20, 2021
@yury-s
Copy link
Member Author

yury-s commented Mar 20, 2021

Removed controversial parts, left only simple ones.

Copy link
Contributor

@dgozman dgozman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!

@yury-s yury-s merged commit 67c29e8 into microsoft:master Mar 22, 2021
@yury-s yury-s deleted the no-floating-promises-1 branch March 22, 2021 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants