Merge branch 'immediate-finds' into immediate-finds-modules-proxy

This commit is contained in:
Nuckyz 2024-05-26 00:29:49 -03:00
commit 3e6e399544
No known key found for this signature in database
GPG key ID: 440BF8296E1C4AD9
7 changed files with 55 additions and 41 deletions

View file

@ -1,6 +1,9 @@
{ {
"root": true, "root": true,
"parser": "@typescript-eslint/parser", "parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"ignorePatterns": ["dist", "browser"], "ignorePatterns": ["dist", "browser"],
"plugins": [ "plugins": [
"@typescript-eslint", "@typescript-eslint",
@ -62,7 +65,14 @@
"no-constant-condition": ["error", { "checkLoops": false }], "no-constant-condition": ["error", { "checkLoops": false }],
"no-duplicate-imports": "error", "no-duplicate-imports": "error",
"no-extra-semi": "error", "no-extra-semi": "error",
"dot-notation": "error", "dot-notation": "off",
"@typescript-eslint/dot-notation": [
"error",
{
"allowPrivateClassPropertyAccess": true,
"allowProtectedClassPropertyAccess": true
}
],
"no-useless-escape": [ "no-useless-escape": [
"error", "error",
{ {

View file

@ -289,10 +289,8 @@ async function runtime(token: string) {
}); });
// Monkey patch Logger to not log with custom css // Monkey patch Logger to not log with custom css
// @ts-ignore const originalLog = Vencord.Util.Logger.prototype["_log"];
const originalLog = Vencord.Util.Logger.prototype._log; Vencord.Util.Logger.prototype["_log"] = function (level, levelColor, args) {
// @ts-ignore
Vencord.Util.Logger.prototype._log = function (level, levelColor, args) {
if (level === "warn" || level === "error") if (level === "warn" || level === "error")
return console[level]("[Vencord]", this.name + ":", ...args); return console[level]("[Vencord]", this.name + ":", ...args);

View file

@ -212,10 +212,9 @@ function computeWidthAndHeight(width: number, height: number) {
function withEmbeddedBy(message: Message, embeddedBy: string[]) { function withEmbeddedBy(message: Message, embeddedBy: string[]) {
return new Proxy(message, { return new Proxy(message, {
get(_, prop) { get(target, prop, receiver) {
if (prop === "vencordEmbeddedBy") return embeddedBy; if (prop === "vencordEmbeddedBy") return embeddedBy;
// @ts-ignore ts so bad return Reflect.get(target, prop, receiver);
return Reflect.get(...arguments);
} }
}); });
} }

View file

@ -15,7 +15,11 @@ export type ProxyLazy<T = AnyObject> = T & {
export const proxyLazyGet = Symbol.for("vencord.lazy.get"); export const proxyLazyGet = Symbol.for("vencord.lazy.get");
export const proxyLazyCache = Symbol.for("vencord.lazy.cached"); export const proxyLazyCache = Symbol.for("vencord.lazy.cached");
export function makeLazy<T>(factory: () => T, attempts = 5, { isIndirect = false }: { isIndirect?: boolean; } = {}): () => T { export type LazyFunction<T> = (() => T) & {
$$vencordLazyFailed: () => boolean;
};
export function makeLazy<T>(factory: () => T, attempts = 5, { isIndirect = false }: { isIndirect?: boolean; } = {}): LazyFunction<T> {
let tries = 0; let tries = 0;
let cache: T; let cache: T;
@ -79,7 +83,6 @@ export function proxyLazy<T = AnyObject>(factory: () => T, attempts = 5, isChild
Object.assign(proxyDummy, { Object.assign(proxyDummy, {
[proxyLazyGet]() { [proxyLazyGet]() {
if (!proxyDummy[proxyLazyCache]) { if (!proxyDummy[proxyLazyCache]) {
// @ts-ignore
if (!get.$$vencordLazyFailed()) { if (!get.$$vencordLazyFailed()) {
proxyDummy[proxyLazyCache] = get(); proxyDummy[proxyLazyCache] = get();
} }
@ -110,7 +113,10 @@ export function proxyLazy<T = AnyObject>(factory: () => T, attempts = 5, isChild
// `const { meow } = proxyLazy(() => ({ meow: [] }));` // `const { meow } = proxyLazy(() => ({ meow: [] }));`
if (!isChild && isSameTick) { if (!isChild && isSameTick) {
return proxyLazy( return proxyLazy(
() => Reflect.get(target[proxyLazyGet](), p, target[proxyLazyGet]()), () => {
const lazyTarget = target[proxyLazyGet]();
return Reflect.get(lazyTarget, p, lazyTarget);
},
attempts, attempts,
true true
); );

View file

@ -27,7 +27,6 @@ export function LazyComponent<T extends object = any>(factory: () => React.Compo
let lazyFailedLogged = false; let lazyFailedLogged = false;
const LazyComponent = (props: T) => { const LazyComponent = (props: T) => {
// @ts-ignore
if (!get.$$vencordLazyFailed()) { if (!get.$$vencordLazyFailed()) {
const ResultComponent = get(); const ResultComponent = get();
if (ResultComponent != null) { if (ResultComponent != null) {
@ -36,7 +35,6 @@ export function LazyComponent<T extends object = any>(factory: () => React.Compo
} }
if (InnerComponent === null && !lazyFailedLogged) { if (InnerComponent === null && !lazyFailedLogged) {
// @ts-ignore
if (get.$$vencordLazyFailed()) { if (get.$$vencordLazyFailed()) {
lazyFailedLogged = true; lazyFailedLogged = true;
} }

View file

@ -27,21 +27,22 @@ export const onceReady = new Promise<void>(r => _resolveReady = r);
export let wreq: WebpackRequire; export let wreq: WebpackRequire;
export let cache: WebpackRequire["c"]; export let cache: WebpackRequire["c"];
export type FilterFn = (module: ModuleExports) => boolean; export type FilterFn = ((module: ModuleExports) => boolean) & {
$$vencordProps?: string[];
};
export const filters = { export const filters = {
byProps: (...props: string[]): FilterFn => { byProps: (...props: string[]): FilterFn => {
const filter = props.length === 1 const filter: FilterFn = props.length === 1
? m => m?.[props[0]] !== void 0 ? m => m?.[props[0]] !== void 0
: m => props.every(p => m?.[p] !== void 0); : m => props.every(p => m?.[p] !== void 0);
// @ts-ignore
filter.$$vencordProps = ["byProps", ...props]; filter.$$vencordProps = ["byProps", ...props];
return filter; return filter;
}, },
byCode: (...code: string[]): FilterFn => { byCode: (...code: string[]): FilterFn => {
const filter = m => { const filter: FilterFn = m => {
if (typeof m !== "function") return false; if (typeof m !== "function") return false;
const s = Function.prototype.toString.call(m); const s = Function.prototype.toString.call(m);
for (const c of code) { for (const c of code) {
@ -55,29 +56,36 @@ export const filters = {
}, },
byStoreName: (name: string): FilterFn => { byStoreName: (name: string): FilterFn => {
const filter = m => m?.constructor?.displayName === name; const filter: FilterFn = m => m?.constructor?.displayName === name;
filter.$$vencordProps = ["byStoreName", name]; filter.$$vencordProps = ["byStoreName", name];
return filter; return filter;
}, },
componentByCode: (...code: string[]): FilterFn => { componentByCode: (...code: string[]): FilterFn => {
const filter = filters.byCode(...code); const byCodeFilter = filters.byCode(...code);
const wrapper = m => { const filter: FilterFn = m => {
if (filter(m)) return true; let inner = m;
if (!m?.$$typeof) return false;
if (m?.type && m.type.render) return filter(m.type.render); // memo + forwardRef while (inner != null) {
if (m?.type) return filter(m.type); // memos if (byCodeFilter(inner)) return true;
if (m?.render) return filter(m.render); // forwardRefs else if (!inner.$$typeof) return false;
else if (inner.type) inner = inner.type; // memos
else if (inner.render) inner = inner.render; // forwardRefs
else return false;
}
return false; return false;
}; };
wrapper.$$vencordProps = ["componentByCode", ...code]; filter.$$vencordProps = ["componentByCode", ...code];
return wrapper; return filter;
} }
}; };
export type ModCallbackFn = (module: ModuleExports) => void; export type ModCallbackFn = ((module: ModuleExports) => void) & {
$$vencordCallbackCalled?: () => boolean;
};
export type ModCallbackFnWithId = (module: ModuleExports, id: PropertyKey) => void; export type ModCallbackFnWithId = (module: ModuleExports, id: PropertyKey) => void;
export const waitForSubscriptions = new Map<FilterFn, ModCallbackFn>(); export const waitForSubscriptions = new Map<FilterFn, ModCallbackFn>();
@ -99,15 +107,15 @@ let devToolsOpen = false;
if (IS_DEV && IS_DISCORD_DESKTOP) { if (IS_DEV && IS_DISCORD_DESKTOP) {
// At this point in time, DiscordNative has not been exposed yet, so setImmediate is needed // At this point in time, DiscordNative has not been exposed yet, so setImmediate is needed
setTimeout(() => { setTimeout(() => {
DiscordNative/* just to make sure */?.window.setDevtoolsCallbacks(() => devToolsOpen = true, () => devToolsOpen = false); DiscordNative?.window.setDevtoolsCallbacks(() => devToolsOpen = true, () => devToolsOpen = false);
}, 0); }, 0);
} }
export const webpackSearchHistory = [] as Array<["waitFor" | "find" | "findComponent" | "findExportedComponent" | "findComponentByCode" | "findByProps" | "findByCode" | "findStore" | "extractAndLoadChunks" | "webpackDependantLazy" | "webpackDependantLazyComponent", any[]]>; export const webpackSearchHistory = [] as Array<["waitFor" | "find" | "findComponent" | "findExportedComponent" | "findComponentByCode" | "findByProps" | "findByCode" | "findStore" | "extractAndLoadChunks" | "webpackDependantLazy" | "webpackDependantLazyComponent", any[]]>;
function printFilter(filter: FilterFn) { function printFilter(filter: FilterFn) {
if ("$$vencordProps" in filter) { if (filter.$$vencordProps != null) {
const props = filter.$$vencordProps as string[]; const props = filter.$$vencordProps;
return `${props[0]}(${props.slice(1).map(arg => `"${arg}"`).join(", ")})`; return `${props[0]}(${props.slice(1).map(arg => `"${arg}"`).join(", ")})`;
} }
@ -132,16 +140,13 @@ export function waitFor(filter: FilterFn, callback: ModCallbackFn, { isIndirect
const originalCallback = callback; const originalCallback = callback;
let callbackCalled = false; let callbackCalled = false;
callback = function () { callback = function (this: unknown) {
callbackCalled = true; callbackCalled = true;
// @ts-ignore Reflect.apply(originalCallback, this, arguments);
originalCallback(...arguments);
}; };
// @ts-ignore
callback.$$vencordCallbackCalled = () => callbackCalled; callback.$$vencordCallbackCalled = () => callbackCalled;
webpackSearchHistory.push(["waitFor", [callback, filter]]); webpackSearchHistory.push(["waitFor", [callback, filter]]);
} }
@ -282,7 +287,7 @@ export function findExportedComponent<T extends object = any>(...props: string[]
if (IS_DEV) { if (IS_DEV) {
WrapperComponent.$$vencordInner = () => InnerComponent; WrapperComponent.$$vencordInner = () => InnerComponent;
webpackSearchHistory.push(["findExportedComponent", [WrapperComponent, ...props]]); webpackSearchHistory.push(["findExportedComponent", [WrapperComponent, ...newProps]]);
} }
if (InnerComponent !== null) return InnerComponent; if (InnerComponent !== null) return InnerComponent;
@ -314,7 +319,7 @@ export function findComponentByCode<T extends object = any>(...code: string[] |
const ComponentResult = findComponent<T>(filters.componentByCode(...newCode), parse, { isIndirect: true }); const ComponentResult = findComponent<T>(filters.componentByCode(...newCode), parse, { isIndirect: true });
if (IS_DEV) { if (IS_DEV) {
webpackSearchHistory.push(["findComponentByCode", [ComponentResult, ...code]]); webpackSearchHistory.push(["findComponentByCode", [ComponentResult, ...newCode]]);
} }
return ComponentResult; return ComponentResult;
@ -480,7 +485,6 @@ export const cacheFindBulk = traceFunction("cacheFindBulk", function cacheFindBu
/** /**
* Find the id of the first module factory that includes all the given code. * Find the id of the first module factory that includes all the given code.
* @returns string or null
*/ */
export const findModuleId = traceFunction("findModuleId", function findModuleId(...code: string[]) { export const findModuleId = traceFunction("findModuleId", function findModuleId(...code: string[]) {
outer: outer:
@ -508,7 +512,6 @@ export const findModuleId = traceFunction("findModuleId", function findModuleId(
/** /**
* Find the first module factory that includes all the given code. * Find the first module factory that includes all the given code.
* @returns The module factory or null
*/ */
export function findModuleFactory(...code: string[]) { export function findModuleFactory(...code: string[]) {
const id = findModuleId(...code); const id = findModuleId(...code);

View file

@ -39,5 +39,5 @@
} }
] ]
}, },
"include": ["src/**/*", "browser/**/*", "scripts/**/*"] "include": ["src/**/*", "browser/**/*", "scripts/**/*", "packages/**/*"]
} }