Skip to content

refactor: Create and use generic portal traversal utility#1935

Merged
marcustyphoon merged 4 commits into
masterfrom
marcustyphoon/traverse-portals
Jan 29, 2026
Merged

refactor: Create and use generic portal traversal utility#1935
marcustyphoon merged 4 commits into
masterfrom
marcustyphoon/traverse-portals

Conversation

@marcustyphoon

@marcustyphoon marcustyphoon commented Oct 23, 2025

Copy link
Copy Markdown
Collaborator

Description

A little messy, but it works? Maybe helpful for #1931? I dunno. Possibly not worth it otherwise?

This:

  • Places both xkit-injection-request and xkit-injection-response handlers on document.documentElement (yes, this could mean a few extra handlers firing once in a blue moon; one could make xkit-injection-element-response and 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.

@marcustyphoon

This comment was marked as resolved.

@marcustyphoon marcustyphoon changed the title refactor: Create generic portal traversal utility refactor: Create and use generic portal traversal utility Oct 23, 2025
@marcustyphoon marcustyphoon force-pushed the marcustyphoon/traverse-portals branch from 25a034f to 51c3253 Compare October 25, 2025 04:21

@AprilSylph AprilSylph left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Yeah, separate event names would be better. As it is, the code diff for src/main_world/index.js just looks like it's trying to avoid setting { bubbles: true } when dispatching events to document.documentElement, which... there's nowhere for it to bubble anyway... so it doesn't make sense until you realise it's just being used as a signal for responseHandler to resolve to something different. Best to just be explicit instead.

Comment thread src/utils/inject.js
@marcustyphoon

Copy link
Copy Markdown
Collaborator Author

The remaining parts of the above diff:

diff --git a/src/main_world/index.js b/src/main_world/index.js
index 08508f7e..0e0a5858 100644
--- a/src/main_world/index.js
+++ b/src/main_world/index.js
@@ -22,7 +22,7 @@ document.documentElement.addEventListener('xkit-injection-request', async event
         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 b29e2953..1591935a 100644
--- a/src/utils/inject.js
+++ b/src/utils/inject.js
@@ -17,7 +17,7 @@ export const inject = (path, args = [], target = document.documentElement) =>
       const { id, result, exception } = JSON.parse(detail);
       if (id !== requestId) return;
 
-      document.documentElement.removeEventListener('xkit-injection-response', responseHandler);
+      target.removeEventListener('xkit-injection-response', responseHandler);
       document.documentElement.removeEventListener('xkit-injection-element-response', responseHandler);
 
       if (exception) {
@@ -28,7 +28,7 @@ export const inject = (path, args = [], target = document.documentElement) =>
         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(

Comment thread src/utils/inject.js Outdated
Co-authored-by: April Sylph <28949509+AprilSylph@users.noreply.github.com>
@marcustyphoon marcustyphoon merged commit 272f67b into master Jan 29, 2026
5 checks passed
@marcustyphoon marcustyphoon deleted the marcustyphoon/traverse-portals branch January 29, 2026 17:27
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