diff --git a/lib/discord/src/preinit.ts b/lib/discord/src/preinit.ts index 6fe18a7..240b43a 100644 --- a/lib/discord/src/preinit.ts +++ b/lib/discord/src/preinit.ts @@ -1,4 +1,4 @@ -import { byDependencies, byProps, moduleStateAware } from '@revenge-mod/modules/finders/filters' +import { byDependencies, byProps, moduleStateAware, relativeDep } from '@revenge-mod/modules/finders/filters' import { lookupModule } from '@revenge-mod/modules/finders' import type { DiscordModules } from '../types' @@ -8,7 +8,7 @@ export const AppStartPerformance = lookupModule( moduleStateAware( byProps('markAndLog'), // biome-ignore lint/suspicious/noSparseArray: Nah - byDependencies([-1, , , 2]), + byDependencies([relativeDep(-1), , , 2]), ), { includeUninitialized: true, diff --git a/lib/modules/src/finders/filters.ts b/lib/modules/src/finders/filters.ts index ea8a6a7..00bd7d3 100644 --- a/lib/modules/src/finders/filters.ts +++ b/lib/modules/src/finders/filters.ts @@ -120,10 +120,19 @@ export const byName = createFilterGenerator>( ([name]) => `revenge.name(${name})`, ) as ByName -export type ComparableDependencyMap = Array & { - loose?: boolean +export type RelativeDependency = object & { + valueOf(): Metro.ModuleID + r?: boolean } +export type ComparableDependencyMap = Array< + Metro.ModuleID | RelativeDependency | undefined | ComparableDependencyMap +> & { + l?: boolean +} + +type ComputedComparableDependencyMap = Exclude> + /** * Filter modules by their dependency map. * @@ -137,14 +146,17 @@ export type ComparableDependencyMap = Array( - ([deps], id) => compareDeps(id, deps, deps.loose), + ([deps], id) => compareDeps(id, deps, deps.l), deps => `revenge.deps(${depsToKey(deps)})`, ) @@ -158,51 +170,63 @@ export const byDependencies = createFilterGenerator<[deps: ComparableDependencyM * @returns The modified dependency map. */ export function looseDeps(deps: ComparableDependencyMap) { - deps.loose = true + deps.l = true return deps } -const RootRelativeDepBit = 1 << 31 +/** + * Marks this dependency to compare relatively to the module ID being compared. + * + * @param id The dependency ID to mark as relative. + */ +export function relativeDep(id: Metro.ModuleID): RelativeDependency { + const o = Object(id) as RelativeDependency + return o +} /** - * Marks this dependency to compare relatively to the root module ID, instead of the module ID of the module being compared. + * Marks this dependency to compare relatively to the module ID that the filter is given. * Useless for single-depth comparisons, but useful for nested comparisons. * * @param id The dependency ID to mark as root relative. */ -export function rootRelativeDep(id: Metro.ModuleID) { - return id | RootRelativeDepBit +export function rootRelativeDep(id: Metro.ModuleID): RelativeDependency { + const o = Object(id) as RelativeDependency + o.r = true + return o } function compareDeps(rootOf: Metro.ModuleID, compare: ComparableDependencyMap, loose = false): boolean { - const stack: Array<[of: Metro.ModuleID, deps: Metro.ModuleID[], compare: ComparableDependencyMap, loose: boolean]> = - [] + const stack: Array< + [of: Metro.ModuleID, deps: Metro.ModuleID[], compare: ComparableDependencyMap, loose?: boolean] + > = [] + stack.push([rootOf, getModuleDependencies(rootOf)!, compare, loose]) while (stack.length) { const [of, deps, compare, loose] = stack.pop()! if (loose ? deps.length < compare.length : deps.length !== compare.length) return false + const ccmp: ComputedComparableDependencyMap = [] for (let i = 0; i < compare.length; i++) { - const orig = deps[i] const cmp = compare[i] if (cmp === undefined) continue + if (Array.isArray(cmp)) ccmp[i] = cmp + else if (typeof cmp === 'object') ccmp[i] = cmp.r ? rootOf + cmp.valueOf() : of + cmp.valueOf() + else ccmp[i] = cmp + } + + for (let i = 0; i < ccmp.length; i++) { + const orig = deps[i] + const cmp = ccmp[i] + if (cmp === undefined) continue + if (Array.isArray(cmp)) { const dependencies = getModuleDependencies(orig) if (!dependencies) return false - stack.push([orig, dependencies, cmp, cmp.loose ?? false]) - } else if ( - cmp < 0 - ? -cmp & RootRelativeDepBit - ? // Root relative dependency - rootOf + (-cmp & ~RootRelativeDepBit) !== orig - : // Relative dependency - of + cmp !== orig - : // Absolute dependency - cmp !== orig - ) - return false + stack.push([orig, dependencies, cmp, cmp.l]) + } else if (cmp !== orig) return false } } @@ -215,7 +239,7 @@ function depsToKey(deps: ComparableDependencyMap): string { for (const dep of deps) if (dep === undefined) key += ',' else if (Array.isArray(dep)) { - if (dep.loose) key += '#' + if (dep.l) key += '#' key += `[${depsToKey(dep)}],` } else key += `${dep},`