From bf967de9022413afd8dea0249cb2ea44d69797f8 Mon Sep 17 00:00:00 2001 From: PalmDevs Date: Wed, 1 Apr 2026 13:35:05 +0700 Subject: [PATCH] fix(lib/modules/finders/get): only lookup initialized modules --- lib/modules/src/finders/get.ts | 36 ++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/lib/modules/src/finders/get.ts b/lib/modules/src/finders/get.ts index a5a7573..6710422 100644 --- a/lib/modules/src/finders/get.ts +++ b/lib/modules/src/finders/get.ts @@ -1,4 +1,7 @@ +import { onModuleInitialized } from '@revenge-mod/modules/metro/subscriptions' +import { isModuleInitialized } from '@revenge-mod/modules/metro/utils' import { asap, noop } from '@revenge-mod/utils/callback' +import { FilterScopes } from './filters' import { lookupModule, lookupModules } from './lookup' import { waitForModules } from './wait' import type { Metro } from '../types' @@ -28,12 +31,12 @@ export type GetModulesUnsubscribeFunction = () => void /** * Get modules matching the filter. - * - * This is a combination of {@link lookupModule} and {@link waitForModules}. + * If the matching modules are already initialized, the callback will be called immediately. + * Otherwise, it will be called when the matching modules are initialized. * * @param filter The filter to use to find the module. * @param options The options to use for the find. - * @returns A promise that resolves to the module's exports or rejects if the find is aborted before a module is found. + * @returns A function to unsubscribe. * * @example * ```ts @@ -69,19 +72,36 @@ export function getModules( ) { let max = options?.max ?? 1 - if (max === 1) { - const [exports, id] = lookupModule(filter, options!) - if (id !== undefined) { + // Only lookup modules that are already initialized + const lookupFilter = filter.scope(FilterScopes.Initialized) + + function handleModule( + exports: Metro.ModuleExports | undefined, + id: Metro.ModuleID, + ) { + if (isModuleInitialized(id)) { // Run callback at the end of the event loop. This ensures that the noop is returned first. // Module is already initialized, there is likely no harm calling the callback late. asap(() => { callback(exports, id) }) + } else { + // Module is not initialized, wait for it to be initialized before calling the callback. + onModuleInitialized(id, (_, exports) => { + callback(exports, id) + }) + } + } + + if (max === 1) { + const [exports, id] = lookupModule(lookupFilter, options!) + if (id !== undefined) { + handleModule(exports, id) return noop } } else - for (const [exports, id] of lookupModules(filter, options!)) { - callback(exports, id) + for (const [exports, id] of lookupModules(lookupFilter, options!)) { + handleModule(exports, id) if (!--max) return noop }