Browse Source

fix: interceptWindowEvent crash on FireMonkey

Sv443 5 months ago
parent
commit
390110e
3 changed files with 13 additions and 2 deletions
  1. 5 0
      .changeset/purple-hats-argue.md
  2. 3 1
      README.md
  3. 5 1
      lib/dom.ts

+ 5 - 0
.changeset/purple-hats-argue.md

@@ -0,0 +1,5 @@
+---
+"@sv443-network/userutils": patch
+---
+
+Throw an error when calling `interceptEvent()` on `window` or `unsafeWindow` on FireMonkey instead of crashing the entire page

+ 3 - 1
README.md

@@ -622,6 +622,7 @@ If no predicate is specified, all events will be discarded.
 Calling this function will set the `Error.stackTraceLimit` to 100 (if it's not already higher) to ensure the stack trace is preserved.  
   
 ⚠️ This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are *attached* after this function is called.  
+⚠️ Due to this function modifying the `addEventListener` prototype, it might break execution of the page's main script if the userscript is running in an isolated context (like it does in FireMonkey). In that case, calling this function will throw an error.  
   
 <details><summary><b>Example - click to view</b></summary>
 
@@ -655,7 +656,8 @@ If no predicate is specified, all events will be discarded.
 This is essentially the same as [`interceptEvent()`](#interceptevent), but automatically uses the `unsafeWindow` (or falls back to regular `window`).  
   
 ⚠️ This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are *attached* after this function is called.  
-⚠️ In order for all events to be interceptable, the directive `@grant unsafeWindow` should be set.  
+⚠️ In order to have the best chance at intercepting events, the directive `@grant unsafeWindow` should be set.  
+⚠️ Due to this function modifying the `addEventListener` prototype, it might break execution of the page's main script if the userscript is running in an isolated context (like it does in FireMonkey). In that case, calling this function will throw an error.  
   
 <details><summary><b>Example - click to view</b></summary>
 

+ 5 - 1
lib/dom.ts

@@ -97,6 +97,10 @@ export function interceptEvent<
   eventName: Parameters<TEvtObj["addEventListener"]>[0],
   predicate: (event: TPredicateEvt) => boolean = () => true,
 ): void {
+  // @ts-ignore
+  if((eventObject === window || eventObject === getUnsafeWindow()) && GM?.info?.scriptHandler && GM.info.scriptHandler === "FireMonkey")
+    throw new Error("Intercepting window events is not supported on FireMonkey due to the isolated context the userscript runs in.");
+
   // default is 25 on FF so this should hopefully be more than enough
   // @ts-ignore
   Error.stackTraceLimit = Math.max(Error.stackTraceLimit, 100);
@@ -128,7 +132,7 @@ export function interceptEvent<
 export function interceptWindowEvent<TEvtKey extends keyof WindowEventMap>(
   eventName: TEvtKey,
   predicate: (event: WindowEventMap[TEvtKey]) => boolean = () => true,
-): void {  
+): void {
   return interceptEvent(getUnsafeWindow(), eventName, predicate);
 }