11import type { Metro } from "@metro/types" ;
22import { version } from "bunny-build-info" ;
3+ const { instead } = require ( "spitroast" ) ;
34
45// @ts -ignore - window is defined later in the bundle, so we assign it early
56globalThis . window = globalThis ;
@@ -33,29 +34,44 @@ if (typeof window.__r === "undefined") {
3334 // Revenge delays the execution of index.ts(x) because Revenge's initialization is asynchronous
3435 interface DeferredQueue {
3536 object : any ;
36- original : any ;
3737 method : string ;
38+ resume ?: ( queue : DeferredQueue ) => void ;
3839 args : any [ ] ;
3940 }
4041
4142 const deferredCalls : Array < DeferredQueue > = [ ] ;
42-
43- const deferMethodExecution = ( object : any , method : string , condition ?: ( ...args : any [ ] ) => boolean ) => {
44- const originalMethod = object [ method ] ;
45- object [ method ] = ( ...args : any [ ] ) => {
46- if ( condition && ! condition ( ...args ) ) {
47- originalMethod ( ...args ) ;
48- return ;
43+ const unpatches : Array < ( ) => void > = [ ] ;
44+
45+ const deferMethodExecution = (
46+ object : any ,
47+ method : string ,
48+ condition ?: ( ...args : any [ ] ) => boolean ,
49+ resume ?: ( queue : DeferredQueue ) => void ,
50+ returnWith ?: ( queue : DeferredQueue ) => any
51+ ) => {
52+ const restore = instead ( method , object , function ( this : any , args : any [ ] , original : any ) {
53+ if ( ! condition || condition ( ...args ) ) {
54+ const queue : DeferredQueue = { object, method, args, resume } ;
55+ deferredCalls . push ( queue ) ;
56+ return returnWith ? returnWith ( queue ) : undefined ;
4957 }
5058
51- deferredCalls . push ( { object, original : originalMethod , method, args } ) ;
52- } ;
59+ // If the condition is not met, we execute the original method immediately
60+ return original . apply ( this , args ) ;
61+ } ) ;
62+
63+ unpatches . push ( restore ) ;
5364 }
5465
55- const resumeDeferredAndRestore = ( ) => {
56- for ( const { object, method, args, original } of deferredCalls ) {
57- object [ method ] = original ;
58- object [ method ] ( ...args ) ;
66+ const resumeDeferred = ( ) => {
67+ for ( const queue of deferredCalls ) {
68+ const { object, method, args, resume } = queue ;
69+
70+ if ( resume ) {
71+ resume ( queue ) ;
72+ } else {
73+ object [ method ] ( ...args ) ;
74+ }
5975 }
6076
6177 deferredCalls . length = 0 ;
@@ -64,11 +80,20 @@ if (typeof window.__r === "undefined") {
6480 const onceIndexRequired = ( originalRequire : Metro . RequireFn ) => {
6581 // We hold calls from the native side
6682 if ( window . __fbBatchedBridge ) {
67- deferMethodExecution ( window . __fbBatchedBridge , "callFunctionReturnFlushedQueue" , args => {
83+ const batchedBridge = window . __fbBatchedBridge ;
84+ deferMethodExecution (
85+ batchedBridge ,
86+ "callFunctionReturnFlushedQueue" ,
6887 // If the call is to AppRegistry, we want to defer it because it is not yet registered (Revenge delays it)
6988 // Same goes to the non-callable modules, which are not registered yet, so we ensure that only registered ones can get through
70- return args [ 0 ] !== "AppRegistry" && window . __fbBatchedBridge . getCallableModule ( args [ 0 ] ) ;
71- } ) ;
89+ ( ...args ) => args [ 0 ] === "AppRegistry" || ! batchedBridge . getCallableModule ( args [ 0 ] ) ,
90+ ( { args } ) => {
91+ if ( batchedBridge . getCallableModule ( args [ 0 ] ) ) {
92+ batchedBridge . __callFunction ( ...args ) ;
93+ }
94+ } ,
95+ ( ) => batchedBridge . flushedQueue ( )
96+ ) ;
7297 }
7398
7499 // Introduced since RN New Architecture
@@ -78,9 +103,12 @@ if (typeof window.__r === "undefined") {
78103
79104 const startDiscord = async ( ) => {
80105 await initializeRevenge ( ) ;
81- originalRequire ( 0 ) ;
106+
107+ for ( const unpatch of unpatches ) unpatch ( ) ;
108+ unpatches . length = 0 ;
82109
83- resumeDeferredAndRestore ( ) ;
110+ originalRequire ( 0 ) ;
111+ resumeDeferred ( ) ;
84112 } ;
85113
86114 startDiscord ( ) ;
0 commit comments