fix(lib): refactor init and utils
This commit is contained in:
parent
9e857d7751
commit
c51e5e6a13
12 changed files with 42 additions and 68 deletions
|
|
@ -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` +
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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<object, object>()
|
||||
|
||||
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
|
||||
},
|
||||
})
|
||||
|
|
@ -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)))
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
import { createLogger } from '@revenge-mod/utils/logger'
|
||||
|
||||
export const logger = createLogger('revenge.init')
|
||||
|
|
@ -12,9 +12,6 @@
|
|||
"./errors": {
|
||||
"default": "./src/errors.ts"
|
||||
},
|
||||
"./functions": {
|
||||
"default": "./src/functions.ts"
|
||||
},
|
||||
"./generators": {
|
||||
"default": "./src/generators.ts"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
// This file is imported before the functions are modified
|
||||
|
||||
export const objectFreeze = Object.freeze
|
||||
export const objectDefineProperty = Object.defineProperty
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
export * from './callbacks'
|
||||
export * from './errors'
|
||||
export * from './functions'
|
||||
export * from './generators'
|
||||
export * from './logger'
|
||||
export * from './objects'
|
||||
|
|
|
|||
|
|
@ -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<PropertyKey, PropertyDescriptor | undefined>()
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<object, object>()
|
||||
|
||||
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<object, [() => unknown, cacheable: boolean, cache?: unknown]>()
|
||||
const _metas = new WeakMap<object, [factory: () => 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<T>(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<T extends object>(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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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'])
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue