diff --git a/lib/init/src/index.ts b/lib/init/src/index.ts index 239ffc0..8cb170a 100644 --- a/lib/init/src/index.ts +++ b/lib/init/src/index.ts @@ -1,13 +1,14 @@ -import './preinit' +// Note that both Object.freeze and Proxy patches are implicitly run by requiring the two libraries below. +import { patchMetroDefine } from '@revenge-mod/modules/_/metro' +import { interceptProperty } from '@revenge-mod/utils/objects' -import './patches/prevent-freeze' -import './patches/proxy' +// By doing this, we are assuming __METRO_GLOBAL_PREFIX__ is an empty string and globalThis.__d isn't already set. +// But both should be true either way. +const unintercept = interceptProperty('__d', (_, mDefine) => (unintercept(), patchMetroDefine(mDefine))) import { onModuleFirstRequired, onModuleInitialized } from '@revenge-mod/modules/metro/subscriptions' import { getErrorStack } from '@revenge-mod/utils/errors' -import { logger } from './shared' - onModuleFirstRequired(0, function onceIndexRequired() { runCatching(() => { if (__BUILD_FLAG_LOG_PROMISE_REJECTIONS__) require('./patches/log-promise-rejections') @@ -25,8 +26,6 @@ onModuleFirstRequired(0, function onceIndexRequired() { // Initialize init libraries require('@revenge-mod/plugins/init') - - logger.log('Revenge loaded!') }) }) }) @@ -36,11 +35,12 @@ function runCatching(fn: () => void) { try { fn() } catch (e) { + // TODO(init): Move to use native provided alert function, which will accept a string stack trace + // Above will reduce the need for runCatching() to exist, as the code won't be able to be deduped any further const { ClientInfoModule, DeviceModule } = require('@revenge-mod/discord/native') as // biome-ignore format: Don't format this please typeof import('@revenge-mod/discord/native') - // TODO(init): Move to use native module alert( // biome-ignore lint/style/useTemplate: I want this to be readable, thank you `Failed to load Revenge (${__BUILD_VERSION__}-${__BUILD_COMMIT__}-${__BUILD_BRANCH__} (${__BUILD_ENV__}))\n` + diff --git a/lib/init/src/patches/log-promise-rejections.ts b/lib/init/src/patches/log-promise-rejections.ts index 625f36b..a259c18 100644 --- a/lib/init/src/patches/log-promise-rejections.ts +++ b/lib/init/src/patches/log-promise-rejections.ts @@ -6,8 +6,9 @@ */ import { getErrorStack } from '@revenge-mod/utils/errors' +import { createLogger } from '@revenge-mod/utils/logger' -import { logger } from '../shared' +const logger = createLogger('revenge.init.promise-rejections') const ErrorTypeWhitelist = [ReferenceError, TypeError, RangeError] diff --git a/lib/init/src/patches/prevent-freeze.ts b/lib/init/src/patches/prevent-freeze.ts deleted file mode 100644 index 1250a72..0000000 --- a/lib/init/src/patches/prevent-freeze.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * This patch prevents objects from being made immutable. - */ - -// Retain reference to the functions so the actual functions can be used later -import '@revenge-mod/utils/functions' - -// Discord only uses Object.freeze -Object.freeze = (o: any) => o diff --git a/lib/init/src/patches/proxy.ts b/lib/init/src/patches/proxy.ts deleted file mode 100644 index 0470d1a..0000000 --- a/lib/init/src/patches/proxy.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * This patch allows us to store instances of Proxy, so we can check whether a value is created using Proxy or not. - * This is especially useful for blacklisting discord-intl modules exports, and exports that cannot be patched. - */ - -export const _targets = new WeakMap() - -const OriginalProxy = globalThis.Proxy -globalThis.Proxy = new Proxy(OriginalProxy, { - construct(_target, args) { - const prox = new OriginalProxy(args[0], args[1]) - _targets.set(prox, args[0]) - return prox - }, -}) diff --git a/lib/init/src/preinit.ts b/lib/init/src/preinit.ts deleted file mode 100644 index c6de6f0..0000000 --- a/lib/init/src/preinit.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { patchMetroDefine } from '@revenge-mod/modules/_/metro' -import { interceptProperty } from '@revenge-mod/utils/objects' - -// By doing this, we are assuming __METRO_GLOBAL_PREFIX__ is an empty string -// and globalThis.__d isn't already set (which should be the case anyways) -const unintercept = interceptProperty('__d', (_, mDefine) => (unintercept(), patchMetroDefine(mDefine))) diff --git a/lib/init/src/shared.ts b/lib/init/src/shared.ts deleted file mode 100644 index 7ee49d6..0000000 --- a/lib/init/src/shared.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createLogger } from '@revenge-mod/utils/logger' - -export const logger = createLogger('revenge.init') diff --git a/lib/utils/package.json b/lib/utils/package.json index 675aa57..f6bf853 100644 --- a/lib/utils/package.json +++ b/lib/utils/package.json @@ -12,9 +12,6 @@ "./errors": { "default": "./src/errors.ts" }, - "./functions": { - "default": "./src/functions.ts" - }, "./generators": { "default": "./src/generators.ts" }, diff --git a/lib/utils/src/functions.ts b/lib/utils/src/functions.ts deleted file mode 100644 index 0ef8e30..0000000 --- a/lib/utils/src/functions.ts +++ /dev/null @@ -1,4 +0,0 @@ -// This file is imported before the functions are modified - -export const objectFreeze = Object.freeze -export const objectDefineProperty = Object.defineProperty diff --git a/lib/utils/src/index.ts b/lib/utils/src/index.ts index faaf1ac..e7a6bd9 100644 --- a/lib/utils/src/index.ts +++ b/lib/utils/src/index.ts @@ -1,6 +1,5 @@ export * from './callbacks' export * from './errors' -export * from './functions' export * from './generators' export * from './logger' export * from './objects' diff --git a/lib/utils/src/objects.ts b/lib/utils/src/objects.ts index 93b55fd..c2f54b9 100644 --- a/lib/utils/src/objects.ts +++ b/lib/utils/src/objects.ts @@ -1,10 +1,13 @@ // Retain reference to original functions -import './functions' +export const objectFreeze = Object.freeze +export const objectDefineProperty = Object.defineProperty + +// Patch to prevent the use of Object.freeze +Object.freeze = (o: any) => o // Heavily inspired by uwu/shelter // https://github.com/uwu/shelter/blob/main/packages/shelter/src/exfiltrate.ts -const defineProperty = Object.defineProperty // Patch to fix intercepting properties on Object.prototype Object.defineProperty = (target, p, d) => { if (target === Object.prototype && _intercepting.has(p)) { @@ -12,7 +15,7 @@ Object.defineProperty = (target, p, d) => { return target } - return defineProperty(target, p, d) + return objectDefineProperty(target, p, d) } const _intercepting = new Map() @@ -32,7 +35,7 @@ export function interceptProperty(prop: PropertyKey, callback: (target: object, const proto = Object.prototype _intercepting.set(prop, Object.getOwnPropertyDescriptor(proto, prop)) - defineProperty(proto, prop, { + objectDefineProperty(proto, prop, { configurable: true, set(value) { if (this === proto) { @@ -40,7 +43,7 @@ export function interceptProperty(prop: PropertyKey, callback: (target: object, return } - defineProperty(this, prop, { + objectDefineProperty(this, prop, { configurable: true, writable: true, enumerable: true, @@ -57,7 +60,7 @@ export function interceptProperty(prop: PropertyKey, callback: (target: object, // @ts-expect-error delete proto[prop] const desc = _intercepting.get(prop) - if (desc) defineProperty(proto, prop, desc) + if (desc) objectDefineProperty(proto, prop, desc) _intercepting.delete(prop) } } diff --git a/lib/utils/src/proxy.ts b/lib/utils/src/proxy.ts index 6366cd8..3e92c19 100644 --- a/lib/utils/src/proxy.ts +++ b/lib/utils/src/proxy.ts @@ -1,4 +1,18 @@ -import { _targets } from '../../init/src/patches/proxy' +/** + * This patch allows us to store instances of Proxy, so we can check whether a value is created using Proxy or not. + * This is especially useful for blacklisting exports that cannot be patched. + */ + +const _targets = new WeakMap() + +const OriginalProxy = globalThis.Proxy +globalThis.Proxy = new Proxy(OriginalProxy, { + construct(_target, args) { + const prox = new OriginalProxy(args[0], args[1]) + _targets.set(prox, args[0]) + return prox + }, +}) /** * Returns whether the object is a proxy @@ -20,9 +34,9 @@ export function getProxyTarget(obj: object) { // Heavily inspired by Wintry's lazy utils, but more optimized and stripped down, with a few fixes. // https://github.com/pylixonly/wintry/blob/main/src/utils/lazy.ts -const _proxifyMetadatas = new WeakMap unknown, cacheable: boolean, cache?: unknown]>() +const _metas = new WeakMap unknown, cacheable: boolean, cache?: unknown]>() -const _proxifyHandler = { +const _handler = { ...Object.fromEntries( Object.getOwnPropertyNames(Reflect).map(k => [ k, @@ -31,7 +45,7 @@ const _proxifyHandler = { Reflect[k](unproxifyFromHint(hint), ...args), ]), ), - // Workaround to fix functions that the correct `this` + // Workaround to fix functions that need the correct `this` get: (hint, p, recv) => { const target = unproxifyFromHint(hint) const val = Reflect.get(target!, p, recv) @@ -91,8 +105,8 @@ export interface ProxifyOptions { export function proxify(signal: () => T, options?: ProxifyOptions): T { // biome-ignore lint/complexity/useArrowFunction: We need a function with a constructor const hint = (options?.hint === 'object' ? {} : function () {}) as any - _proxifyMetadatas.set(hint, [signal, options?.cache ?? false]) - return new Proxy(hint, _proxifyHandler) + _metas.set(hint, [signal, options?.cache ?? false]) + return new Proxy(hint, _handler) } /** @@ -130,7 +144,7 @@ export function unproxify(proxified: T): T { } function unproxifyFromHint(hint: object) { - const meta = _proxifyMetadatas.get(hint)! + const meta = _metas.get(hint)! if (meta[1]) return meta[2] ?? ((meta[2] = meta[0]()) as any) return meta[0]() as any } diff --git a/lib/utils/src/react.ts b/lib/utils/src/react.ts index abd332f..1810e1b 100644 --- a/lib/utils/src/react.ts +++ b/lib/utils/src/react.ts @@ -15,11 +15,8 @@ export function useIsFirstRender() { } export function useReRender() { - const [_, forceUpdate] = React.useReducer(x => ~x, 0) - - return React.useCallback(() => { - forceUpdate() - }, []) + const [, forceUpdate] = React.useReducer(x => ~x, 0) + return forceUpdate } const ReactFiberWalkable = new Set(['props', 'children', 'child', 'sibling'])