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

Start using webext-messenger (for background functions and messages) #1258

Merged
merged 17 commits into from
Sep 12, 2021

Conversation

fregante
Copy link
Contributor

@fregante fregante commented Sep 9, 2021

Related:

NB: By necessity and by design, this pattern is more verbose than the lift pattern since we intentionally keep the implementation separate from the caller. More context in:

This PR:

  • I redesigned the messenger’s API several times looking for the pattern that offered the most constraints and was less error prone, but some rules just can't be enforced (unless I write a lint rule, maybe)
  • I ported a few background functions to this new pattern, including some that were plain sendMessage calls
  • API and registration always happens in 2 files (per context)
  • Implementations (the code that is actually executed in the background) are currently either in their previous location or in "executor". They don't need to be there, I just kept them there for diff clarity.
  • No functionality was changed (with 2 exceptions I mention in my review), so large diffs are just due to indentation changes
  • I tested most of the methods, except uninstallContextMenu and activateTab, which I'm not sure how to trigger exactly since tab is already active

Future work:

@fregante fregante changed the title Start using webext-messenger Start using webext-messenger (for background functions and messages) Sep 9, 2021
return sender;
}

export async function notifyReady(): Promise<void> {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I moved the contents of this function to the only place where it was called, to avoid too much redirection. This readiness part can likely be further simplified over time

Comment on lines -113 to -121
if (sender == null) {
// If you see this error, it means the wrong message handler responded to the message.
// The most likely cause of this is that background listener function was accidentally marked
// with the "async" keyword as that prevents the method from returning "undefined" to indicate
// that it did not handle the message
throw new ConnectionError(
`Internal error: received null response for ${MESSAGE_CONTENT_SCRIPT_ECHO_SENDER}. Check use of async in message listeners`
);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This applies to every single message and it's now being automatically checked by webext-messenger itself:

https://github.com/pixiebrix/webext-messenger/blob/c98e5d1714032662574970ad485e5922cae9e561/index.ts#L49


declare global {
interface MessengerMethods {
CONTAINS_PERMISSIONS: typeof browser.permissions.contains;
Copy link
Contributor

@twschiller twschiller Sep 9, 2021

Choose a reason for hiding this comment

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

If you define a literal of what you passed to registerMethods, shouldn't you be able to have typescript generate the type from the literal instead of having to retype it all?

Updated: I wrote a comment in slack after I looked over the library code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's exactly what we're trying to avoid in #669

If you specify the object:

const handlers = {
  UNARY: unary
}

registerMethods(handlers);

With the intent of using the type in the caller context, webpack will definitely include the unary function in both contexts.

payload: {},
});
export async function whoAmI(
this: MessengerMeta
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm really not a fan of "overloading" this to mean the messenger. this has a special meaning in OO languages

@twschiller
Copy link
Contributor

twschiller commented Sep 9, 2021

Thoughts on toErrorResponse, isErrorResponse, etc? Are they unnecessary serialization?

Re-reading the code, it looks like they're self contained within the handlers, so if we don't need the serialization they should be safe to drop if we don't think serialization is necessary

@fregante
Copy link
Contributor Author

The sendMessage API indeed already serializes errors but:

So I think in order to maintain stacktraces of errors that happened in the background I'll have to implement the error serialization now

}

// Chrome offers this API in more contexts than Firefox, so it skips the messenger entirely
export const containsPermissions = browser.permissions
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure there's much benefit in having different code paths for the browser here

Copy link
Contributor Author

@fregante fregante Sep 12, 2021

Choose a reason for hiding this comment

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

Sure, I just preserved the existing logic:

if (browser.permissions) {
return browser.permissions.contains(permissions);
}
return containsPermissionsInBackground(permissions);

However I think it's still worth doing because:

  • it's a simple API wrap
  • Chrome users (the majority) win in perf
  • we still need a comment to explain why we're using a background call
  • it reminds us we will probably be able to drop this background call at some point

@twschiller twschiller merged commit 6815bc0 into main Sep 12, 2021
@twschiller twschiller deleted the F/feature/messenger branch September 12, 2021 00:52
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