From 729ff59fd9a0ced8e250f1fb0f842c5f9525cb32 Mon Sep 17 00:00:00 2001 From: PalmDevs Date: Wed, 30 Apr 2025 23:44:00 +0700 Subject: [PATCH] feat(lib/modules/finders/filters): add relative dependency comparisons --- lib/modules/src/finders/filters.ts | 47 ++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/lib/modules/src/finders/filters.ts b/lib/modules/src/finders/filters.ts index 01aec06..dd00e8f 100644 --- a/lib/modules/src/finders/filters.ts +++ b/lib/modules/src/finders/filters.ts @@ -135,6 +135,12 @@ export type ComparableDependencyMap = Array( @@ -156,24 +162,47 @@ export function looseDeps(deps: ComparableDependencyMap) { return deps } -function compareDeps(of: Metro.ModuleID, compare: ComparableDependencyMap, loose = false): boolean { - const stack: Array<[of: Metro.ModuleID[], compare: ComparableDependencyMap, loose: boolean]> = [] - stack.push([getModuleDependencies(of)!, compare, loose]) +const RootRelativeDepBit = 1 << 31 + +/** + * Marks this dependency to compare relatively to the root module ID, instead of the module ID of the module being compared. + * 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 +} + +function compareDeps(rootOf: Metro.ModuleID, compare: ComparableDependencyMap, loose = false): 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, compare, loose] = stack.pop()! - if (loose ? of.length < compare.length : of.length !== compare.length) return false + const [of, deps, compare, loose] = stack.pop()! + if (loose ? deps.length < compare.length : deps.length !== compare.length) return false for (let i = 0; i < compare.length; i++) { - const orig = of[i] + const orig = deps[i] const cmp = compare[i] if (cmp === undefined) continue if (Array.isArray(cmp)) { const dependencies = getModuleDependencies(orig) if (!dependencies) return false - stack.push([dependencies, cmp, cmp.loose ?? false]) - } else if (orig !== cmp) 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 } } @@ -188,7 +217,7 @@ function depsToKey(deps: ComparableDependencyMap): string { else if (Array.isArray(dep)) { if (dep.loose) key += '#' key += `[${depsToKey(dep)}],` - } else key += `${dep},` + } else key += `${-dep & RootRelativeDepBit ? `r${dep}` : dep},` return key.substring(0, key.length - 1) }