XKit-Rewritten
XKit-Rewritten copied to clipboard
refactor: Create and use generic portal traversal utility
Description
A little messy, but it works? Maybe helpful for #1931? I dunno. Possibly not worth it otherwise?
This:
- Places both
xkit-injection-requestandxkit-injection-responsehandlers ondocument.documentElement(yes, this could mean a few extra handlers firing once in a blue moon; one could makexkit-injection-element-responseand add the event listener twice to prevent this I guess but I don't think that would save any cycles edit: see comment) - Allows injected functions to return DOM elements by passing them from the main world to the isolated world in the same way we pass the target DOM element from the isolated to the main world: event bubbling.
- Uses this ability to replace the overly-specific injected function in the meatballs menu util with, essentially a version of
.closest()that traverses portals.
Testing steps
- Confirm that meatballs menu items are still added to post meatball menus.
More tests could be run with #677/#1662, I guess.
Eh, you know, maybe this actually is more elegant. Leave the normal path's listeners where they are so calls don't trigger each other's listeners.
diff --git a/src/main_world/index.js b/src/main_world/index.js
index 329566b6..0e0a5858 100644
--- a/src/main_world/index.js
+++ b/src/main_world/index.js
@@ -19,10 +19,10 @@ document.documentElement.addEventListener('xkit-injection-request', async event
if (result instanceof Element) {
result.dispatchEvent(
- new CustomEvent('xkit-injection-response', { detail: JSON.stringify({ id }), bubbles: true })
+ new CustomEvent('xkit-injection-element-response', { detail: JSON.stringify({ id }), bubbles: true })
);
} else {
- document.documentElement.dispatchEvent(
+ target.dispatchEvent(
new CustomEvent('xkit-injection-response', { detail: JSON.stringify({ id, result }) })
);
}
diff --git a/src/utils/inject.js b/src/utils/inject.js
index b0d49079..1591935a 100644
--- a/src/utils/inject.js
+++ b/src/utils/inject.js
@@ -13,20 +13,23 @@ export const inject = (path, args = [], target = document.documentElement) =>
const requestId = String(Math.random());
const data = { path: browser.runtime.getURL(path), args, id: requestId };
- const responseHandler = ({ detail, bubbles, target }) => {
+ const responseHandler = ({ detail, type, target }) => {
const { id, result, exception } = JSON.parse(detail);
if (id !== requestId) return;
target.removeEventListener('xkit-injection-response', responseHandler);
+ document.documentElement.removeEventListener('xkit-injection-element-response', responseHandler);
+
if (exception) {
reject(exception);
- } else if (bubbles) {
+ } else if (type === 'xkit-injection-element-response') {
resolve(target);
} else if (result) {
resolve(result);
}
};
- document.documentElement.addEventListener('xkit-injection-response', responseHandler);
+ target.addEventListener('xkit-injection-response', responseHandler);
+ document.documentElement.addEventListener('xkit-injection-element-response', responseHandler);
target.dispatchEvent(
new CustomEvent('xkit-injection-request', { detail: JSON.stringify(data), bubbles: true })