From 7645bfdf617de672e157f7a3a776c8daade0a989 Mon Sep 17 00:00:00 2001 From: PalmDevs Date: Tue, 8 Jul 2025 11:24:48 +0700 Subject: [PATCH] chore: new `DEBUG_WAITS` build flag, improve `DBEUG_LOOKUPS` build flag logs, other dev env fixes --- lib/modules/src/finders/_internal.ts | 13 +++-- lib/modules/src/finders/lookup.ts | 75 ++++++++++++++++++++++------ lib/modules/src/finders/wait.ts | 43 ++++++++++++++-- lib/modules/src/metro/_internal.ts | 2 +- lib/utils/src/proxy.ts | 7 ++- scripts/build.ts | 1 + shims/shims.d.ts | 8 +++ shims/tsconfig.json | 7 +++ src/preinit.ts | 9 ++++ tsconfig.json | 2 +- types.d.ts | 13 +++-- 11 files changed, 149 insertions(+), 31 deletions(-) create mode 100644 shims/shims.d.ts create mode 100644 shims/tsconfig.json diff --git a/lib/modules/src/finders/_internal.ts b/lib/modules/src/finders/_internal.ts index 406dea9..e9078ab 100644 --- a/lib/modules/src/finders/_internal.ts +++ b/lib/modules/src/finders/_internal.ts @@ -56,6 +56,13 @@ export const FilterResultFlags = { export type FilterResultFlag = (typeof FilterResultFlags)[keyof typeof FilterResultFlags] +export const FilterResultFlagToHumanReadable: Record = + { + [FilterResultFlags.Default]: '\u001b[94mdefault\u001b[0m', + [FilterResultFlags.Namespace]: '\u001b[35mnamespace\u001b[0m', + [FilterResultFlags.Found]: '\u001b[96mexportsless\u001b[0m', + } + // The reason this returns a flag is because flags are never falsy, while exports may be falsy when using ID-only filters (eg. `byDependencies`). // Currently, we only have options that are relevant for checking exports @@ -84,8 +91,7 @@ export function runFilter( if (options?.initialize ?? true) { if (__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__) { const flag = runFilter(filter, id, __r(id), options) - if (!flag) - warnDeveloperAboutPartialFilterMatch(id, filter.key) + if (!flag) DEBUG_warnPartialFilterMatch(id, filter.key) return flag } else return runFilter(filter, id, __r(id), options) } @@ -119,9 +125,8 @@ export function exportsFromFilterResultFlag( /** * Warns the developer that the filter matched during exportsless comparison, but not during the full comparison. * This will cause modules to be initialized unnecessarily, and may cause issues. - * @internal */ -function warnDeveloperAboutPartialFilterMatch(id: Metro.ModuleID, key: string) { +function DEBUG_warnPartialFilterMatch(id: Metro.ModuleID, key: string) { nativeLoggingHook( `\u001b[33m${key} matched module ${id} partially.\n${getCurrentStack()}\u001b[0m`, 2, diff --git a/lib/modules/src/finders/lookup.ts b/lib/modules/src/finders/lookup.ts index 70e8529..89ee23c 100644 --- a/lib/modules/src/finders/lookup.ts +++ b/lib/modules/src/finders/lookup.ts @@ -11,10 +11,17 @@ import { getInitializedModuleExports, isModuleInitialized, } from '../metro/utils' -import { exportsFromFilterResultFlag, runFilter } from './_internal' +import { + exportsFromFilterResultFlag, + FilterResultFlagToHumanReadable, + runFilter, +} from './_internal' import type { If, Nullish } from '@revenge-mod/utils/types' import type { MaybeDefaultExportMatched, Metro } from '../types' -import type { RunFilterReturnExportsOptions } from './_internal' +import type { + FilterResultFlag, + RunFilterReturnExportsOptions, +} from './_internal' import type { Filter, FilterResult } from './filters' type LookupModulesOptionsWithAll = If< @@ -177,6 +184,9 @@ export function* lookupModules(filter: Filter, options?: LookupModulesOptions) { cached.add(id) + if (__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__) + DEBUG_logLookupMatched(filter.key, flag, id, true) + yield [exportsFromFilterResultFlag(flag, exports, options), id] } } @@ -191,6 +201,10 @@ export function* lookupModules(filter: Filter, options?: LookupModulesOptions) { const flag = runFilter(filter, id, exports, options) if (flag) { notFound = false + + if (__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__) + DEBUG_logLookupMatched(filter.key, flag, id) + yield [exportsFromFilterResultFlag(flag, exports, options), id] } } @@ -207,6 +221,10 @@ export function* lookupModules(filter: Filter, options?: LookupModulesOptions) { const flag = runFilter(filter, id, exports, options) if (flag) { notFound = false + + if (__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__) + DEBUG_logLookupMatched(filter.key, flag, id) + yield [ exportsFromFilterResultFlag(flag, exports, options), id, @@ -222,6 +240,9 @@ export function* lookupModules(filter: Filter, options?: LookupModulesOptions) { if (flag) { notFound = false + if (__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__) + DEBUG_logLookupMatched(filter.key, flag, id) + yield [ exportsFromFilterResultFlag( flag, @@ -235,7 +256,7 @@ export function* lookupModules(filter: Filter, options?: LookupModulesOptions) { } if (__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__) - if (notFound) warnDeveloperAboutNoFilterMatch(filter) + if (notFound) DEBUG_warnLookupNoMatch(filter.key) } /** @@ -288,6 +309,9 @@ export function lookupModule(filter: Filter, options?: LookupModulesOptions) { exports = __r(id) } + if (__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__) + DEBUG_logLookupMatched(filter.key, flag, id, true) + return [exportsFromFilterResultFlag(flag, exports, options), id] } } @@ -297,12 +321,16 @@ export function lookupModule(filter: Filter, options?: LookupModulesOptions) { for (let id = 0; id < mDeps.length; id++) { const exports = getInitializedModuleExports(id) const flag = runFilter(filter, id, exports, options) - if (flag) + if (flag) { + if (__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__) + DEBUG_logLookupMatched(filter.key, flag, id) + return [exportsFromFilterResultFlag(flag, exports, options), id] + } } if (__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__) - warnDeveloperAboutNoFilterMatch(filter) + DEBUG_warnLookupNoMatch(filter.key) cache[filter.key] = null // Full lookup, and still not found! @@ -314,17 +342,24 @@ export function lookupModule(filter: Filter, options?: LookupModulesOptions) { for (const id of mInitialized) { const exports = getInitializedModuleExports(id) const flag = runFilter(filter, id, exports, options) - if (flag) + if (flag) { + if (__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__) + DEBUG_logLookupMatched(filter.key, flag, id) + return [ exportsFromFilterResultFlag(flag, exports, options), id, ] + } } if (options?.uninitialized) for (const id of mUninitialized) { const flag = runFilter(filter, id, undefined, options) - if (flag) + if (flag) { + if (__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__) + DEBUG_logLookupMatched(filter.key, flag, id) + return [ exportsFromFilterResultFlag( flag, @@ -333,11 +368,11 @@ export function lookupModule(filter: Filter, options?: LookupModulesOptions) { ), id, ] + } } } - if (__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__) - warnDeveloperAboutNoFilterMatch(filter) + if (__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__) DEBUG_warnLookupNoMatch(filter.key) return NotFoundResult } @@ -376,17 +411,29 @@ const __DEBUG_TRACER_IGNORE_LIST__ = __BUILD_FLAG_DEBUG_MODULE_LOOKUPS__ ) : [] +/** + * Logs to the developer that a module was found, how it is found, and whether it was a cached result. + */ +function DEBUG_logLookupMatched( + key: string, + flag: FilterResultFlag, + id: Metro.ModuleID, + cached?: boolean, +) { + nativeLoggingHook( + `\u001b[32mSuccessful lookup: \u001b[33m${key}\u001b[0m (matched ${id}, ${FilterResultFlagToHumanReadable[flag]}${cached ? ', \u001b[92mcached\u001b[0m' : ''})`, + 1, + ) +} + /** * Warns the developer that no module was found for the given filter. * This is useful for debugging purposes, especially when using filters that are expected to match a module. */ -function warnDeveloperAboutNoFilterMatch(filter: Filter) { +function DEBUG_warnLookupNoMatch(key: string) { const stack = getCurrentStack() for (const func of __DEBUG_TRACER_IGNORE_LIST__) if (stack.includes(func.name)) return - nativeLoggingHook( - `\u001b[31mNo module found for filter: ${filter.key}\n${stack}\u001b[0m`, - 2, - ) + nativeLoggingHook(`\u001b[31mFailed lookup: ${key}\n${stack}\u001b[0m`, 2) } diff --git a/lib/modules/src/finders/wait.ts b/lib/modules/src/finders/wait.ts index 2d400c1..e3f8be2 100644 --- a/lib/modules/src/finders/wait.ts +++ b/lib/modules/src/finders/wait.ts @@ -4,9 +4,16 @@ import { onModuleFinishedImporting, } from '../metro/subscriptions' import { getInitializedModuleExports } from '../metro/utils' -import { exportsFromFilterResultFlag, runFilter } from './_internal' +import { + exportsFromFilterResultFlag, + FilterResultFlagToHumanReadable, + runFilter, +} from './_internal' import type { MaybeDefaultExportMatched, Metro } from '../types' -import type { RunFilterReturnExportsOptions } from './_internal' +import type { + FilterResultFlag, + RunFilterReturnExportsOptions, +} from './_internal' import type { Filter, FilterResult } from './filters' export interface BaseWaitForModulesOptions { @@ -76,20 +83,33 @@ export function waitForModules( callback: WaitForModulesCallback, options?: WaitForModulesOptions, ) { + if (__BUILD_FLAG_DEBUG_MODULE_WAITS__) + nativeLoggingHook( + `\u001b[94mWaiting for module matching: \u001b[93m${filter.key}\u001b[0m`, + 1, + ) + return onAnyModuleInitialized( options?.all ? (id, exports) => { const flag = runFilter(filter, id, exports, options) - if (flag) + if (flag) { + if (__BUILD_FLAG_DEBUG_MODULE_WAITS__) + DEBUG_logWaitMatched(filter.key, id, flag) + callback( exportsFromFilterResultFlag(flag, exports, options), id, ) + } } : (id, exports) => { if (mInitialized.has(id)) { const flag = runFilter(filter, id, exports, options) - if (flag) + if (flag) { + if (__BUILD_FLAG_DEBUG_MODULE_WAITS__) + DEBUG_logWaitMatched(filter.key, id, flag) + callback( exportsFromFilterResultFlag( flag, @@ -98,6 +118,7 @@ export function waitForModules( ), id, ) + } } }, ) @@ -148,3 +169,17 @@ export function waitForModuleByImportedPath( return unsub } + +/** + * Logs to the developer that a module wait has matched. + */ +function DEBUG_logWaitMatched( + key: string, + id: Metro.ModuleID, + flag: FilterResultFlag, +) { + nativeLoggingHook( + `\u001b[32mWait matched: \u001b[33m${key}\u001b[0m (matched ${id}, ${FilterResultFlagToHumanReadable[flag]})`, + 1, + ) +} diff --git a/lib/modules/src/metro/_internal.ts b/lib/modules/src/metro/_internal.ts index 37a42c9..98c1886 100644 --- a/lib/modules/src/metro/_internal.ts +++ b/lib/modules/src/metro/_internal.ts @@ -22,7 +22,7 @@ export let mList: Metro.ModuleList * Here's how Metro sets itself up: * 1. `__METRO_GLOBAL_PREFIX__ = ""` * 2. `${__METRO_GLOBAL_PREFIX__}__d = function define(...) {}` - * - Why don't we patch it here? Because we need to know the value of __METRO_GLOBAL_PREFIX__ first + * - Why don't we patch it here? Because we need to know the value of `__METRO_GLOBAL_PREFIX__` first * - And since Revenge runs before everything else, we need to patch in the next steps: * - We chose to patch it in 4. because we can access all the global functions at that point. * 3. `__r = function metroRequire(...) {}` diff --git a/lib/utils/src/proxy.ts b/lib/utils/src/proxy.ts index 31e806c..b02cb97 100644 --- a/lib/utils/src/proxy.ts +++ b/lib/utils/src/proxy.ts @@ -147,7 +147,7 @@ export function proxify(signal: () => T, options?: ProxifyOptions): T { if (__BUILD_FLAG_DEBUG_PROXIFIED_VALUES__) { const v = unproxifyFromHint(hint) - if (v == null) warnDeveloperAboutNullishProxifiedValue() + if (v == null) DEBUG_warnNullishProxifiedValue() } return new Proxy(hint, _handler) @@ -242,7 +242,10 @@ export function destructure( }) } -function warnDeveloperAboutNullishProxifiedValue() { +/** + * Warns the developer that the proxified value is nullish. + */ +function DEBUG_warnNullishProxifiedValue() { nativeLoggingHook( `\u001b[33mProxified value is nullish! The signal is may be invalid.\n${getCurrentStack()}\u001b[0m`, 3, diff --git a/scripts/build.ts b/scripts/build.ts index effa7a3..fb5725f 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -59,6 +59,7 @@ export default async function build(dev = Dev, log = true) { // See types.d.ts for what these flags do __BUILD_FLAG_DEBUG_MODULE_LOOKUPS__: String(dev), + __BUILD_FLAG_DEBUG_MODULE_WAITS__: String(dev), __BUILD_FLAG_DEBUG_PROXIFIED_VALUES__: 'false', __BUILD_FLAG_LOG_PROMISE_REJECTIONS__: String(dev), }, diff --git a/shims/shims.d.ts b/shims/shims.d.ts new file mode 100644 index 0000000..78356b1 --- /dev/null +++ b/shims/shims.d.ts @@ -0,0 +1,8 @@ +declare global { + // CommonJS modules, we don't want to depend on @types/node + const module: { + exports: any + } +} + +export {} diff --git a/shims/tsconfig.json b/shims/tsconfig.json new file mode 100644 index 0000000..a36549e --- /dev/null +++ b/shims/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": ["../tsconfig.json"], + "compilerOptions": { + "types": ["./shims.d.ts"] + }, + "include": ["./**/*.ts"] +} diff --git a/src/preinit.ts b/src/preinit.ts index 136ea65..24a7b26 100644 --- a/src/preinit.ts +++ b/src/preinit.ts @@ -14,6 +14,9 @@ onModuleFirstRequired(IndexModuleId, function onIndexRequired() { if (__BUILD_FLAG_LOG_PROMISE_REJECTIONS__) require('./patches/log-promise-rejections') + if (__BUILD_ENV__ === 'development') + nativeLoggingHook(`\u001b[31m--- PREINIT STAGE ---\u001b[0m`, 1) + // Initialize preinit libraries require('@revenge-mod/modules/preinit') require('@revenge-mod/react/preinit') @@ -27,6 +30,12 @@ onModuleFirstRequired(IndexModuleId, function onIndexRequired() { onModuleInitialized(IndexModuleId, function onIndexInitialized() { try { + if (__BUILD_ENV__ === 'development') + nativeLoggingHook( + `\u001b[31m--- INIT STAGE ---\u001b[0m`, + 1, + ) + // Initialize init libraries require('@revenge-mod/storage/init') require('@revenge-mod/externals/init') diff --git a/tsconfig.json b/tsconfig.json index 75a652e..dc6009c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,5 +14,5 @@ "~assets/*": ["./dist/assets/generated/*"] } }, - "include": ["lib", "src", "shims"] + "include": ["lib", "src"] } diff --git a/types.d.ts b/types.d.ts index 4d021ba..198baeb 100644 --- a/types.d.ts +++ b/types.d.ts @@ -13,6 +13,7 @@ declare global { /** * Whether to debug module lookups. * + * - Logs successful lookups. * - Logs failed lookups with stack traces. * - Logs partial matches (matches exportless, but not with-exports). */ @@ -24,11 +25,13 @@ declare global { * - Warns if the proxified value is nullish. */ const __BUILD_FLAG_DEBUG_PROXIFIED_VALUES__: boolean - - // CommonJS modules, we don't want to depend on @types/node - const module: { - exports: any - } + /** + * Whether to debug module waits. + * + * - Logs when a module is waited for. + * - Logs when a module is found. + */ + const __BUILD_FLAG_DEBUG_MODULE_WAITS__: boolean export interface ImportMeta { glob(