diff --git a/lib/assets/src/index.ts b/lib/assets/src/index.ts index 1948f6d..80cace5 100644 --- a/lib/assets/src/index.ts +++ b/lib/assets/src/index.ts @@ -5,7 +5,7 @@ import { AssetRegistry } from './preinit' import type { Asset, AssetId, RegisterableAsset } from './types' -export * from './preinit' +export { AssetRegistry, AssetRegistryModuleId } from './preinit' // iOS cannot display SVGs let _preferredType: Asset['type'] = ReactNative.Platform.OS === 'ios' ? 'png' : 'svg' diff --git a/lib/assets/src/preinit.ts b/lib/assets/src/preinit.ts index a73b109..eda3ab7 100644 --- a/lib/assets/src/preinit.ts +++ b/lib/assets/src/preinit.ts @@ -1,7 +1,7 @@ -import { _mInitingId, _mUninited } from '@revenge-mod/modules/_/metro' -import { waitForModules } from '@revenge-mod/modules/finders' +import { _initing, _uninits } from '@revenge-mod/modules/_/metro' import { byName, byProps } from '@revenge-mod/modules/finders/filters' -import { getModuleDependencies } from '@revenge-mod/modules/metro' +import { waitForModules } from '@revenge-mod/modules/finders/wait' +import { getModuleDependencies } from '@revenge-mod/modules/metro/utils' import { _assets, _metas, _overrides } from './_internal' @@ -28,7 +28,7 @@ const unsubAR = waitForModules(byProps('registerAsse // More fragile way, but also more performant: // There is exactly one asset before the reexported asset registry :/ const firstAssetModuleId = id - 1 - for (const mId of _mUninited) { + for (const mId of _uninits) { if (mId < firstAssetModuleId) continue const deps = getModuleDependencies(mId)! @@ -53,7 +53,7 @@ const unsubAR = waitForModules(byProps('registerAsse // In-memory cache reg[1][type] = asset - _metas.set(asset, [result, _mInitingId]) + _metas.set(asset, [result, _initing]) return result } diff --git a/lib/externals/src/browserify.ts b/lib/externals/src/browserify.ts index 37de306..99fd557 100644 --- a/lib/externals/src/browserify.ts +++ b/lib/externals/src/browserify.ts @@ -1,11 +1,11 @@ -import { lookupModule } from '@revenge-mod/modules/finders' -import { byDependencies, byProps, moduleStateAware, relativeDep } from '@revenge-mod/modules/finders/filters' +import { byDependencies, byProps, preferExports, relativeDep } from '@revenge-mod/modules/finders/filters' +import { lookupModule } from '@revenge-mod/modules/finders/lookup' import { proxify } from '@revenge-mod/utils/proxy' export let nodeUtil: typeof import('node:util') = proxify( () => { const module = lookupModule( - moduleStateAware(byProps('inspect'), byDependencies([relativeDep(1), [], []])), + preferExports(byProps('inspect'), byDependencies([relativeDep(1), [], []])), { includeUninitialized: true, }, diff --git a/lib/externals/src/react-navigation.ts b/lib/externals/src/react-navigation.ts index a0b7b60..9151c53 100644 --- a/lib/externals/src/react-navigation.ts +++ b/lib/externals/src/react-navigation.ts @@ -1,6 +1,6 @@ +import { byDependencies, byName, byProps, looseDeps, preferExports } from '@revenge-mod/modules/finders/filters' +import { lookupModule, lookupModuleId } from '@revenge-mod/modules/finders/lookup' import { proxify } from '@revenge-mod/utils/proxy' -import { lookupModule, lookupModuleId } from '@revenge-mod/modules/finders' -import { byDependencies, byName, byProps, looseDeps, moduleStateAware } from '@revenge-mod/modules/finders/filters' const _createClassModuleId = lookupModuleId(byName('_createClass')) const _classCallCheckModuleId = lookupModuleId(byName('_classCallCheck')) @@ -8,7 +8,7 @@ const _classCallCheckModuleId = lookupModuleId(byName('_classCallCheck')) export let ReactNavigationNative: typeof import('@react-navigation/native') = proxify( () => { const module = lookupModule( - moduleStateAware( + preferExports( byProps('useLinkTo'), byDependencies(looseDeps([[], looseDeps([[_createClassModuleId, _classCallCheckModuleId]])])), ), @@ -27,7 +27,7 @@ export let ReactNavigationNative: typeof import('@react-navigation/native') = pr export let ReactNavigationStack: typeof import('@react-navigation/stack') = proxify( () => { const module = lookupModule( - moduleStateAware( + preferExports( byProps('createStackNavigator'), byDependencies(looseDeps([[], looseDeps([[_createClassModuleId, _classCallCheckModuleId]])])), ), diff --git a/lib/externals/src/shopify.ts b/lib/externals/src/shopify.ts index 0bce8a5..be46b2d 100644 --- a/lib/externals/src/shopify.ts +++ b/lib/externals/src/shopify.ts @@ -1,5 +1,5 @@ -import { byDependencies, byProps, moduleStateAware } from '@revenge-mod/modules/finders/filters' -import { lookupModule } from '@revenge-mod/modules/finders' +import { byDependencies, byProps, preferExports } from '@revenge-mod/modules/finders/filters' +import { lookupModule } from '@revenge-mod/modules/finders/lookup' import { proxify } from '@revenge-mod/utils/proxy' import { ReactJsxRuntimeModuleId, ReactModuleId, ReactNativeModuleId } from '@revenge-mod/react' @@ -7,7 +7,7 @@ import { ReactJsxRuntimeModuleId, ReactModuleId, ReactNativeModuleId } from '@re export let FlashList: typeof import('@shopify/flash-list') = proxify( () => { const module = lookupModule( - moduleStateAware( + preferExports( byProps('FlashList'), // biome-ignore lint/suspicious/noSparseArray: don't care byDependencies([ReactModuleId, ReactNativeModuleId, ReactJsxRuntimeModuleId, , , , 2, ,]), diff --git a/lib/modules/package.json b/lib/modules/package.json index 30d83ea..8f5047e 100644 --- a/lib/modules/package.json +++ b/lib/modules/package.json @@ -3,21 +3,24 @@ "private": true, "type": "module", "exports": { - ".": { - "default": "./src/index.ts" - }, - "./finders": { - "default": "./src/finders/index.ts" - }, "./finders/filters": { "default": "./src/finders/filters.ts" }, - "./metro": { - "default": "./src/metro/index.ts" + "./finders/find": { + "default": "./src/finders/find.ts" + }, + "./finders/lookup": { + "default": "./src/finders/lookup.ts" + }, + "./finders/wait": { + "default": "./src/finders/wait.ts" }, "./metro/subscriptions": { "default": "./src/metro/subscriptions/index.ts" }, + "./metro/utils": { + "default": "./src/metro/utils.ts" + }, "./native": { "default": "./src/native.ts" }, @@ -25,7 +28,7 @@ "default": "./src/preinit.ts" }, "./types": { - "default": "./types.ts" + "default": "./src/types.ts" }, "./_/metro": { "default": "./src/metro/_internal.ts" diff --git a/lib/modules/src/finders/_internal.ts b/lib/modules/src/finders/_internal.ts index f30576c..3dbeaa2 100644 --- a/lib/modules/src/finders/_internal.ts +++ b/lib/modules/src/finders/_internal.ts @@ -1,7 +1,7 @@ -import { isModuleExportBad } from '../metro' +import { isModuleExportBad } from '../metro/utils' import type { If } from '@revenge-mod/utils/types' -import type { Metro } from '../../types' +import type { Metro } from '../types' import type { Filter } from './filters' export interface RunFilterOptions { diff --git a/lib/modules/src/finders/filters.ts b/lib/modules/src/finders/filters.ts index 078d552..bb60543 100644 --- a/lib/modules/src/finders/filters.ts +++ b/lib/modules/src/finders/filters.ts @@ -1,9 +1,9 @@ -import { _mInited } from '../metro/_internal' +import { _inits } from '../metro/_internal' -import { getModuleDependencies, initializedModuleHasBadExports, isModuleInitialized } from '../metro' +import { getModuleDependencies, initializedModuleHasBadExports, isModuleInitialized } from '../metro/utils' import type { If, LogicalOr } from '@revenge-mod/utils/types' -import type { Metro } from '../../types' +import type { Metro } from '../types' export type FilterResult = F extends Filter ? R : never @@ -79,8 +79,18 @@ export type ByProps = = Record>( * ``` */ export const byProps = createFilterGenerator>( - (props, _, exports) => - (typeof exports === 'object' || typeof exports === 'function') && props.every(prop => prop in exports), + (props, _, exports) => { + if (typeof exports === 'object' || typeof exports === 'function') { + for (const prop of props) { + if (prop in exports) continue + return false + } + + return true + } + + return false + }, props => `revenge.props(${props.join(',')})`, ) as ByProps @@ -93,8 +103,12 @@ export type WithoutProps = >(prop: string, ...prop * @param props More properties to check for (optional). */ export const withoutProps = createFilterGenerator>( - (props, _, exports) => - (typeof exports === 'object' || typeof exports === 'function') && !props.some(prop => prop in exports), + (props, _, exports) => { + if (typeof exports === 'object' || typeof exports === 'function') + for (const prop of props) if (prop in exports) return false + + return true + }, props => `revenge.withoutProps(${props.join(',')})`, ) as WithoutProps @@ -173,7 +187,7 @@ type ByDependencies = (deps: ComparableDependencyMap) => Filter */ export const byDependencies = createFilterGenerator>( ([deps], id) => compareDeps(id, deps, deps.l), - deps => `revenge.deps(${depsToKey(deps)})`, + deps => `revenge.deps(${genDepsKey(deps)})`, ) as ByDependencies /** @@ -194,21 +208,11 @@ export function looseDeps(deps: ComparableDependencyMap) { * Marks this dependency to compare relatively to the module ID being compared. * * @param id The dependency ID to mark as relative. + * @param root Whether this dependency should be relatively to the root module ID. Useless for single-depth comparisons. */ -export function relativeDep(id: Metro.ModuleID): RelativeDependency { +export function relativeDep(id: Metro.ModuleID, root?: boolean): RelativeDependency { const o = Object(id) as RelativeDependency - return o -} - -/** - * 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): RelativeDependency { - const o = Object(id) as RelativeDependency - o.r = true + if (root) o.r = true return o } @@ -249,14 +253,14 @@ function compareDeps(rootOf: Metro.ModuleID, compare: ComparableDependencyMap, l return true } -function depsToKey(deps: ComparableDependencyMap): string { +function genDepsKey(deps: ComparableDependencyMap): string { let key = '' for (const dep of deps) if (dep === undefined) key += ',' else if (Array.isArray(dep)) { if (dep.l) key += '#' - key += `[${depsToKey(dep)}],` + key += `[${genDepsKey(dep)}],` } else key += `${(dep as RelativeDependency).r ? `r${dep.valueOf()}` : dep.valueOf()},` return key.substring(0, key.length - 1) @@ -408,7 +412,7 @@ export type PreferExports = ( */ export const preferExports = createFilterGenerator>( ([withExportsFilter, exportslessFilter], id, exports) => { - if (_mInited.has(id)) return withExportsFilter(id, exports) + if (_inits.has(id)) return withExportsFilter(id, exports) return exportslessFilter(id) }, ([f1, f2]) => `revenge.preferExports(${f1.key},${f2.key})`, diff --git a/lib/modules/src/finders/find.ts b/lib/modules/src/finders/find.ts index 9a13bb0..8a93753 100644 --- a/lib/modules/src/finders/find.ts +++ b/lib/modules/src/finders/find.ts @@ -3,10 +3,11 @@ import { type LookupModulesOptions, lookupModule, lookupModuleByImportedPath, lo import { type WaitForModulesOptions, waitForModuleByImportedPath, waitForModules } from './wait' import type { If } from '@revenge-mod/utils/types' -import type { LookupModuleIdsOptions, MaybeDefaultExportMatched } from '.' -import type { Metro } from '../../types' +import type { MaybeDefaultExportMatched } from '../types' +import type { Metro } from '../types' import type { RunFilterReturnExportsOptions } from './_internal' import type { Filter, FilterResult } from './filters' +import type { LookupModuleIdsOptions } from './lookup' export interface BaseFindModuleOptions { /** diff --git a/lib/modules/src/finders/index.ts b/lib/modules/src/finders/index.ts deleted file mode 100644 index ab4331d..0000000 --- a/lib/modules/src/finders/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './lookup' -export * from './wait' -export * from './find' - -/** - * Maybe the default export matched instead of the namespace, because you're using `options.returnNamespace`. - */ -export type MaybeDefaultExportMatched = T | { default: T } diff --git a/lib/modules/src/finders/lookup.ts b/lib/modules/src/finders/lookup.ts index 1750d4e..78bbe99 100644 --- a/lib/modules/src/finders/lookup.ts +++ b/lib/modules/src/finders/lookup.ts @@ -1,4 +1,4 @@ -import { _mInited, _mMd, _mPaths, _mUninited } from '../metro/_internal' +import { _inits, _metas, _paths, _uninits } from '../metro/_internal' import { type RunFilterOptions, type RunFilterReturnExportsOptions, @@ -6,11 +6,11 @@ import { runFilter, } from './_internal' -import { getInitializedModuleExports } from '../metro' +import { getInitializedModuleExports } from '../metro/utils' import type { If } from '@revenge-mod/utils/types' -import type { MaybeDefaultExportMatched } from '.' -import type { Metro } from '../../types' +import type { MaybeDefaultExportMatched } from '../types' +import type { Metro } from '../types' import type { Filter, FilterResult } from './filters' export interface BaseLookupModulesOptions extends RunFilterOptions { @@ -53,6 +53,9 @@ export type LookupModuleIdsOptions< | ({ /** * Whether to include all modules, including ones with bad exports. + * This option overrides `includeInitialized` and `includeUninitialized`. + * + * This will filter modules in order of how they're defined. * * @default false */ @@ -92,12 +95,12 @@ export function* lookupModuleIds( options?: O, ): Generator { if (options?.includeAll) { - for (const id of _mMd.keys()) if (runFilter(filter, id, getInitializedModuleExports(id), options)) yield id + for (const id of _metas.keys()) if (runFilter(filter, id, getInitializedModuleExports(id), options)) yield id } else { if (options?.includeInitialized ?? true) - for (const id of _mInited) if (runFilter(filter, id, getInitializedModuleExports(id), options)) yield id + for (const id of _inits) if (runFilter(filter, id, getInitializedModuleExports(id), options)) yield id - if (options?.includeUninitialized) for (const id of _mUninited) if (runFilter(filter, id)) yield id + if (options?.includeUninitialized) for (const id of _uninits) if (runFilter(filter, id)) yield id } } @@ -127,14 +130,14 @@ export function lookupModules< export function* lookupModules(filter: Filter, options?: LookupModulesOptions) { if (options?.includeInitialized ?? true) - for (const id of _mInited) { + for (const id of _inits) { const exports = getInitializedModuleExports(id) const flag = runFilter(filter, id, exports, options) if (flag) yield exportsFromFilterResultFlag(flag, exports, options) } if (options?.includeUninitialized) - for (const id of _mUninited) + for (const id of _uninits) if (runFilter(filter, id)) { // Run the filter again to ensure we have the correct exports const exports = __r(id) @@ -171,12 +174,12 @@ export function lookupModuleId( options?: O, ): Metro.ModuleID | undefined { if (options?.includeAll) { - for (const id of _mMd.keys()) if (runFilter(filter, id, getInitializedModuleExports(id), options)) return id + for (const id of _metas.keys()) if (runFilter(filter, id, getInitializedModuleExports(id), options)) return id } else { if (options?.includeInitialized ?? true) - for (const id of _mInited) if (runFilter(filter, id, getInitializedModuleExports(id), options)) return id + for (const id of _inits) if (runFilter(filter, id, getInitializedModuleExports(id), options)) return id - if (options?.includeUninitialized) for (const id of _mUninited) if (runFilter(filter, id)) return id + if (options?.includeUninitialized) for (const id of _uninits) if (runFilter(filter, id)) return id } } @@ -203,20 +206,20 @@ export function lookupModule( export function lookupModule(filter: Filter, options?: LookupModulesOptions) { if (options?.includeInitialized ?? true) - for (const id of _mInited) { + for (const id of _inits) { const exports = getInitializedModuleExports(id) const flag = runFilter(filter, id, exports, options) if (flag) return exportsFromFilterResultFlag(flag, exports, options) } if (options?.includeUninitialized) - for (const id of _mUninited) { + for (const id of _uninits) if (runFilter(filter, id)) { const exports = __r(id) + // Run the filter again to ensure we have the correct exports const flag = runFilter(filter, id, exports, options) if (flag) return exportsFromFilterResultFlag(flag, exports, options) } - } } /** @@ -231,7 +234,7 @@ export function lookupModule(filter: Filter, options?: LookupModulesOptions) { * ``` */ export function lookupModuleIdByImportedPath(path: string): Metro.ModuleID | undefined { - return _mPaths.get(path) + return _paths.get(path) } /** @@ -248,6 +251,6 @@ export function lookupModuleIdByImportedPath(path: string): Metro.ModuleID | und * ``` */ export function lookupModuleByImportedPath(path: string): T | undefined { - const id = lookupModuleIdByImportedPath(path) - return getInitializedModuleExports(id!) + // undefined will also return undefined either way, so we can just non-nullish assert it + return getInitializedModuleExports(lookupModuleIdByImportedPath(path)!) } diff --git a/lib/modules/src/finders/wait.ts b/lib/modules/src/finders/wait.ts index b9dc33d..78cf7de 100644 --- a/lib/modules/src/finders/wait.ts +++ b/lib/modules/src/finders/wait.ts @@ -1,13 +1,9 @@ -import { - getInitializedModuleExports, - initializedModuleHasBadExports, - onAnyModuleInitialized, - onModuleFinishedImporting, -} from '../metro' +import { onAnyModuleInitialized, onModuleFinishedImporting } from '../metro/subscriptions' +import { getInitializedModuleExports, initializedModuleHasBadExports } from '../metro/utils' import { type RunFilterReturnExportsOptions, exportsFromFilterResultFlag, runFilter } from './_internal' -import type { MaybeDefaultExportMatched } from '.' -import type { Metro } from '../../types' +import type { MaybeDefaultExportMatched } from '../types' +import type { Metro } from '../types' import type { Filter, FilterResult } from './filters' export interface BaseWaitForModulesOptions { @@ -64,16 +60,18 @@ export function waitForModules( callback: (id: Metro.ModuleID, exports: Metro.ModuleExports) => any, options?: WaitForModulesOptions, ) { - return options?.includeAll - ? onAnyModuleInitialized((id, exports) => { - const flag = runFilter(filter, id, exports, options) - if (flag) callback(id, exportsFromFilterResultFlag(flag, exports, options)) - }) - : onAnyModuleInitialized((id, exports) => { - if (initializedModuleHasBadExports(id)) return - const flag = runFilter(filter, id, exports, options) - if (flag) callback(id, exportsFromFilterResultFlag(flag, exports, options)) - }) + return onAnyModuleInitialized( + options?.includeAll + ? (id, exports) => { + const flag = runFilter(filter, id, exports, options) + if (flag) callback(id, exportsFromFilterResultFlag(flag, exports, options)) + } + : (id, exports) => { + if (initializedModuleHasBadExports(id)) return + const flag = runFilter(filter, id, exports, options) + if (flag) callback(id, exportsFromFilterResultFlag(flag, exports, options)) + }, + ) } /** @@ -103,13 +101,22 @@ export function waitForModuleByImportedPath( callback: (id: Metro.ModuleID, exports: T) => any, options?: BaseWaitForModulesOptions, ) { - const unsub = onModuleFinishedImporting((id, cmpPath) => { - if (path === cmpPath) { - unsub() - if (!options?.includeAll && initializedModuleHasBadExports(id)) return - callback(id, getInitializedModuleExports(id)) - } - }) + const unsub = onModuleFinishedImporting( + options?.includeAll + ? (id, cmpPath) => { + if (path === cmpPath) { + unsub() + callback(id, getInitializedModuleExports(id)) + } + } + : (id, cmpPath) => { + if (path === cmpPath) { + unsub() + if (initializedModuleHasBadExports(id)) return + callback(id, getInitializedModuleExports(id)) + } + }, + ) return unsub } diff --git a/lib/modules/src/index.ts b/lib/modules/src/index.ts deleted file mode 100644 index 4dbff8f..0000000 --- a/lib/modules/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * as finders from './finders' -export * as filters from './finders/filters' -export * as metro from './metro' -export * as native from './native' diff --git a/lib/modules/src/metro/_internal.ts b/lib/modules/src/metro/_internal.ts index b30744c..97b6b72 100644 --- a/lib/modules/src/metro/_internal.ts +++ b/lib/modules/src/metro/_internal.ts @@ -1,49 +1,49 @@ -import { _executeInitializedSubscription, _executeRequiredSubscription } from './subscriptions/_internal' +import { _execInitSubs, _execReqSubs } from './subscriptions/_internal' import { isModuleExportsBad } from './utils' -import type { Metro } from '../../types' +import type { Metro } from '../types' /** Initializing ID */ -export let _mInitingId = -1 -/** Known uninitialized IDs (not blacklisted) */ -export const _mUninited = new Set() +export let _initing = -1 +/** Known uninitialized IDs */ +export const _uninits = new Set() /** Known initialized IDs (not blacklisted) */ -export const _mInited = new Set() +export const _inits = new Set() -export const _mPaths = new Map() -export const _mMd = new Map() +export const _paths = new Map() +export const _metas = new Map< + Metro.ModuleID, + [deps: Metro.DependencyMap, initialized: boolean, module?: Metro.Module] +>() export function patchMetroDefine(metroDefine: Metro.DefineFn) { return ((origFactory, id, deps) => { // deps won't be undefined last time I checked - const metadata = [deps!, false] as typeof _mMd extends Map ? V : never - _mMd.set(id, metadata) - _mUninited.add(id) + const metadata = [deps!, false] as typeof _metas extends Map ? V : never + _metas.set(id, metadata) + _uninits.add(id) metroDefine( ((global, req, importDefault, importAll, module, exports, deps) => { - metadata[1] = true metadata[2] = module - const prevIId = _mInitingId - _mInitingId = id + const prevIId = _initing + _initing = id - _executeRequiredSubscription(id) + _execReqSubs(id) try { origFactory(global, req, importDefault, importAll, module, exports, deps) - // Don't use exports here, as modules can set module.exports to a different object - if (isModuleExportsBad(module.exports)) throw undefined + metadata[1] = true // Add the module to the initialized set only if the factory doesn't error or the exports aren't bad - _mInited.add(id) - } catch { - } finally { - _mInitingId = prevIId - _mUninited.delete(id) // Don't use exports here, as modules can set module.exports to a different object - _executeInitializedSubscription(id, module.exports) - } + if (!isModuleExportsBad(module.exports)) _inits.add(id) + _execInitSubs(id, module.exports) + } catch {} + + _initing = prevIId + _uninits.delete(id) }) satisfies Metro.FactoryFn, id, deps, diff --git a/lib/modules/src/metro/index.ts b/lib/modules/src/metro/index.ts deleted file mode 100644 index 7f39d7a..0000000 --- a/lib/modules/src/metro/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './subscriptions' -export * from './utils' - -// TODO(modules): caching diff --git a/lib/modules/src/metro/patches.ts b/lib/modules/src/metro/patches.ts index 62f7895..e7710ff 100644 --- a/lib/modules/src/metro/patches.ts +++ b/lib/modules/src/metro/patches.ts @@ -1,19 +1,18 @@ -import { _mInitingId, _mPaths } from './_internal' +import { _initing, _paths } from './_internal' -import { _executeImportedPathSubscription } from './subscriptions/_internal' +import { _execPathSubs } from './subscriptions/_internal' -import { waitForModules } from '../finders' import { byProps } from '../finders/filters' +import { waitForModules } from '../finders/wait' + +const unsubFFI = waitForModules(byProps('fileFinishedImporting'), (_, exports) => { + unsubFFI() -const unsubForImportTracker = waitForModules(byProps('fileFinishedImporting'), (_, exports) => { const orig = exports.fileFinishedImporting - if (orig) { - unsubForImportTracker() - exports.fileFinishedImporting = (path: string) => { - orig(path) - const id = _mInitingId - _mPaths.set(path, id) - _executeImportedPathSubscription(id, path) - } + exports.fileFinishedImporting = (path: string) => { + orig(path) + const id = _initing + _paths.set(path, id) + _execPathSubs(id, path) } }) diff --git a/lib/modules/src/metro/subscriptions/_internal.ts b/lib/modules/src/metro/subscriptions/_internal.ts index 294be14..cf130a9 100644 --- a/lib/modules/src/metro/subscriptions/_internal.ts +++ b/lib/modules/src/metro/subscriptions/_internal.ts @@ -1,30 +1,32 @@ -import { _mInitingId } from '../_internal' +import type { + ModuleFirstRequiredCallback, + ModuleInitializedCallback, + ModuleWithImportedPathInitializedCallback, +} from '.' +import type { Metro } from '../../types' -import type { ModuleInitializedCallback, ModuleRequiredCallback, ModuleWithImportedPathInitializedCallback } from '.' -import type { Metro } from '../../../types' - -export const _reqAll = new Set() -export const _reqSpecific = new Map>() +export const _reqAll = new Set() +export const _req = new Map>() export const _initAll = new Set() -export const _initSpecific = new Map>() -export const _importedPath = new Set() +export const _init = new Map>() +export const _path = new Set() -export function _executeRequiredSubscription(id: Metro.ModuleID) { +export function _execReqSubs(id: Metro.ModuleID) { for (const cb of _reqAll) cb(id) - if (_reqSpecific.has(id)) { - for (const cb of _reqSpecific.get(id)!) cb(id) - _reqSpecific.delete(id) + if (_req.has(id)) { + for (const cb of _req.get(id)!) cb(id) + _req.delete(id) } } -export function _executeInitializedSubscription(id: Metro.ModuleID, exports: Metro.ModuleExports) { +export function _execInitSubs(id: Metro.ModuleID, exports: Metro.ModuleExports) { for (const cb of _initAll) cb(id, exports) - if (_initSpecific.has(id)) { - for (const cb of _initSpecific.get(id)!) cb(id, exports) - _initSpecific.delete(id) + if (_init.has(id)) { + for (const cb of _init.get(id)!) cb(id, exports) + _init.delete(id) } } -export function _executeImportedPathSubscription(id: Metro.ModuleID, path: string) { - for (const cb of _importedPath) cb(id, path) +export function _execPathSubs(id: Metro.ModuleID, path: string) { + for (const cb of _path) cb(id, path) } diff --git a/lib/modules/src/metro/subscriptions/index.ts b/lib/modules/src/metro/subscriptions/index.ts index f9422ce..d7dda12 100644 --- a/lib/modules/src/metro/subscriptions/index.ts +++ b/lib/modules/src/metro/subscriptions/index.ts @@ -1,9 +1,9 @@ -import { _importedPath, _initAll, _initSpecific, _reqAll, _reqSpecific } from './_internal' +import { _init, _initAll, _path, _req, _reqAll } from './_internal' -import type { Metro } from '../../../types' +import type { Metro } from '../../types' import type { initializedModuleHasBadExports } from '../utils' -export type ModuleRequiredCallback = (id: Metro.ModuleID) => void +export type ModuleFirstRequiredCallback = (id: Metro.ModuleID) => void export type ModuleInitializedCallback = (id: Metro.ModuleID, exports: Metro.ModuleExports) => void export type ModuleWithImportedPathInitializedCallback = (id: Metro.ModuleID, path: string) => void @@ -30,8 +30,12 @@ export function onAnyModuleInitialized(callback: ModuleInitializedCallback) { * @returns A function that unregisters the callback. */ export function onModuleInitialized(id: Metro.ModuleID, callback: ModuleInitializedCallback) { - if (!_initSpecific.has(id)) _initSpecific.set(id, new Set()) - const set = _initSpecific.get(id)! + let set = _init.get(id) + if (!set) { + set = new Set() + _init.set(id, set) + } + set.add(callback) return () => set.delete(callback) } @@ -45,8 +49,8 @@ export function onModuleInitialized(id: Metro.ModuleID, callback: ModuleInitiali * @returns A function that unregisters the callback. */ export function onModuleFinishedImporting(callback: ModuleWithImportedPathInitializedCallback) { - _importedPath.add(callback) - return () => _importedPath.delete(callback) + _path.add(callback) + return () => _path.delete(callback) } /** @@ -57,9 +61,9 @@ export function onModuleFinishedImporting(callback: ModuleWithImportedPathInitia * @param callback The callback to be called. * @returns A function that unregisters the callback. */ -export function onAnyModuleFirstRequired(callback: ModuleRequiredCallback) { - _reqAll.add(id => callback(id)) - return () => _reqAll.delete(id => callback(id)) +export function onAnyModuleFirstRequired(callback: ModuleFirstRequiredCallback) { + _reqAll.add(callback) + return () => _reqAll.delete(callback) } /** @@ -71,9 +75,13 @@ export function onAnyModuleFirstRequired(callback: ModuleRequiredCallback) { * @param callback The callback to be called. * @returns A function that unregisters the callback. */ -export function onModuleFirstRequired(id: Metro.ModuleID, callback: ModuleRequiredCallback) { - if (!_reqSpecific.has(id)) _reqSpecific.set(id, new Set()) - const set = _reqSpecific.get(id)! +export function onModuleFirstRequired(id: Metro.ModuleID, callback: ModuleFirstRequiredCallback) { + let set = _req.get(id) + if (!set) { + set = new Set() + _req.set(id, set) + } + set.add(callback) return () => set.delete(callback) } diff --git a/lib/modules/src/metro/utils.ts b/lib/modules/src/metro/utils.ts index b393f99..e5efd98 100644 --- a/lib/modules/src/metro/utils.ts +++ b/lib/modules/src/metro/utils.ts @@ -1,7 +1,7 @@ import { isProxy } from '@revenge-mod/utils/proxy' -import { _mInited, _mMd, _mUninited } from './_internal' +import { _inits, _metas, _uninits } from './_internal' -import type { Metro } from '../../types' +import type { Metro } from '../types' /** * Returns whether an uninitialized module has bad exports. @@ -11,7 +11,7 @@ import type { Metro } from '../../types' * @param id The module ID. */ export function uninitializedModuleHasBadExports(id: Metro.ModuleID): boolean { - return !_mUninited.has(id) + return !_uninits.has(id) } /** @@ -22,7 +22,7 @@ export function uninitializedModuleHasBadExports(id: Metro.ModuleID): boolean { * @param id The module ID. */ export function initializedModuleHasBadExports(id: Metro.ModuleID): boolean { - return !_mInited.has(id) + return !_inits.has(id) } /** @@ -30,7 +30,7 @@ export function initializedModuleHasBadExports(id: Metro.ModuleID): boolean { * @param id The module ID. */ export function getModuleDependencies(id: Metro.ModuleID): Metro.DependencyMap | undefined { - return _mMd.get(id)?.[0] + return _metas.get(id)?.[0] } /** @@ -38,7 +38,7 @@ export function getModuleDependencies(id: Metro.ModuleID): Metro.DependencyMap | * @param id The module ID. */ export function isModuleInitialized(id: Metro.ModuleID): boolean { - return _mMd.get(id)?.[1]! + return _metas.get(id)?.[1]! } /** @@ -46,7 +46,7 @@ export function isModuleInitialized(id: Metro.ModuleID): boolean { * @param id The module ID. */ export function getInitializedModuleExports(id: Metro.ModuleID): Metro.ModuleExports | undefined { - return _mMd.get(id)?.[2]?.exports + return _metas.get(id)?.[2]?.exports } /** @@ -80,7 +80,7 @@ export function isModuleExportsBad(exports: Metro.ModuleExports): boolean { // Checking if the object is empty (exports.__proto__ === Object.prototype && !Reflect.ownKeys(exports).length) || // Can't run isProxy() on this because this isn't your typical proxy: - // https://github.com/discord/react-native/blob/master/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp + // https://github.com/facebook/react-native/blob/master/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp exports === nativeModuleProxy ) } diff --git a/lib/modules/types.ts b/lib/modules/src/types.ts similarity index 86% rename from lib/modules/types.ts rename to lib/modules/src/types.ts index bc717e7..14a2a1d 100644 --- a/lib/modules/types.ts +++ b/lib/modules/src/types.ts @@ -3,7 +3,7 @@ import type { If, Nullish } from '@revenge-mod/utils/types' /** * Metro is a bundler for React Native. * - * @see {@link https://github.com/facebook/metro/blob/1361405/packages/metro-runtime/src/polyfills/require.js} + * @see {@link https://github.com/facebook/metro/blob/main/packages/metro-runtime/src/polyfills/require.js} */ export namespace Metro { export type DependencyMap = Array @@ -68,3 +68,8 @@ export namespace Metro { export type ModuleExports = any } + +/** + * Maybe the default export matched instead of the namespace, because you're using `options.returnNamespace`. + */ +export type MaybeDefaultExportMatched = T | { default: T } diff --git a/lib/react/package.json b/lib/react/package.json index 72e2c7c..33c528f 100644 --- a/lib/react/package.json +++ b/lib/react/package.json @@ -13,7 +13,7 @@ "default": "./src/preinit.ts" }, "./types": { - "default": "./types.ts" + "default": "./src/types.ts" } } } diff --git a/lib/react/src/index.ts b/lib/react/src/index.ts index bfcc898..ad46fb2 100644 --- a/lib/react/src/index.ts +++ b/lib/react/src/index.ts @@ -1,10 +1,7 @@ -import { lookupModuleId, lookupModuleIds } from '@revenge-mod/modules/finders' import { byProps } from '@revenge-mod/modules/finders/filters' +import { lookupModuleId, lookupModuleIds } from '@revenge-mod/modules/finders/lookup' import { yielded } from '@revenge-mod/utils/generators' -export * as jsxRuntime from './jsx-runtime' -export * from '../types' - export const ReactModuleId = yielded(lookupModuleIds(byProps('useState')), 1)! export const ReactNativeModuleId = lookupModuleId(byProps('AppRegistry'))! export const ReactJsxRuntimeModuleId = yielded(lookupModuleIds(byProps('jsx'))!, 1) diff --git a/lib/react/types.ts b/lib/react/src/types.ts similarity index 100% rename from lib/react/types.ts rename to lib/react/src/types.ts diff --git a/lib/utils/package.json b/lib/utils/package.json index f6bf853..660c9d8 100644 --- a/lib/utils/package.json +++ b/lib/utils/package.json @@ -3,9 +3,6 @@ "private": true, "type": "module", "exports": { - ".": { - "default": "./src/index.ts" - }, "./callbacks": { "default": "./src/callbacks.ts" }, diff --git a/lib/utils/src/index.ts b/lib/utils/src/index.ts deleted file mode 100644 index e7a6bd9..0000000 --- a/lib/utils/src/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export * from './callbacks' -export * from './errors' -export * from './generators' -export * from './logger' -export * from './objects' -export * from './proxy' -export * from './react' -export * from './trees' -export * from './types'