minor cleanup
This commit is contained in:
parent
b1ad0a0d58
commit
26a71caced
|
@ -22,7 +22,7 @@ import { Margins } from "@utils/margins";
|
|||
import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches";
|
||||
import { makeCodeblock } from "@utils/text";
|
||||
import { Patch, ReplaceFn } from "@utils/types";
|
||||
import { search } from "@webpack";
|
||||
import { searchFactories } from "@webpack";
|
||||
import { Button, Clipboard, Forms, Parser, React, Switch, TextArea, TextInput } from "@webpack/common";
|
||||
|
||||
import { SettingsTab, wrapTab } from "./shared";
|
||||
|
@ -33,7 +33,7 @@ if (IS_DEV) {
|
|||
}
|
||||
|
||||
const findCandidates = debounce(function ({ find, setModule, setError }) {
|
||||
const candidates = search(find);
|
||||
const candidates = searchFactories(find);
|
||||
const keys = Object.keys(candidates);
|
||||
const len = keys.length;
|
||||
if (len === 0)
|
||||
|
|
|
@ -25,7 +25,7 @@ import { canonicalizeMatch, canonicalizeReplace, canonicalizeReplacement } from
|
|||
import { SYM_PROXY_INNER_GET, SYM_PROXY_INNER_VALUE } from "@utils/proxyInner";
|
||||
import definePlugin, { PluginNative, StartAt } from "@utils/types";
|
||||
import * as Webpack from "@webpack";
|
||||
import { cacheFindAll, cacheFindModuleId, extract, filters, search } from "@webpack";
|
||||
import { _cacheFindAll, cacheFindAll, cacheFindModuleId, extract, filters, searchFactories } from "@webpack";
|
||||
import * as Common from "@webpack/common";
|
||||
import { loadLazyChunks } from "debug/loadLazyChunks";
|
||||
import type { ComponentType } from "react";
|
||||
|
@ -34,85 +34,101 @@ const DESKTOP_ONLY = (f: string) => () => {
|
|||
throw new Error(`'${f}' is Discord Desktop only.`);
|
||||
};
|
||||
|
||||
const define: typeof Object.defineProperty =
|
||||
(obj, prop, desc) => {
|
||||
if (Object.hasOwn(desc, "value"))
|
||||
desc.writable = true;
|
||||
|
||||
return Object.defineProperty(obj, prop, {
|
||||
type Define = typeof Object.defineProperty;
|
||||
const define: Define = (target, p, attributes) => {
|
||||
if (Object.hasOwn(attributes, "value")) {
|
||||
attributes.writable = true;
|
||||
}
|
||||
|
||||
return Object.defineProperty(target, p, {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
...desc
|
||||
...attributes
|
||||
});
|
||||
};
|
||||
|
||||
function makeShortcuts() {
|
||||
function newFindWrapper(filterFactory: (...props: any[]) => Webpack.FilterFn) {
|
||||
function newFindWrapper(filterFactory: (...props: any[]) => Webpack.FilterFn, shouldReturnFactory = false) {
|
||||
const cache = new Map<string, unknown>();
|
||||
|
||||
return function (...filterProps: unknown[]) {
|
||||
const cacheKey = String(filterProps);
|
||||
if (cache.has(cacheKey)) return cache.get(cacheKey);
|
||||
|
||||
const matches = cacheFindAll(filterFactory(...filterProps));
|
||||
const matches = _cacheFindAll(filterFactory(...filterProps));
|
||||
|
||||
const result = (() => {
|
||||
switch (matches.length) {
|
||||
case 0: return null;
|
||||
case 1: return matches[0];
|
||||
case 1: return shouldReturnFactory ? matches[0].factory : matches[0].result;
|
||||
default:
|
||||
const uniqueMatches = [...new Set(matches)];
|
||||
if (uniqueMatches.length > 1)
|
||||
const uniqueMatches = [...new Set(shouldReturnFactory ? matches.map(m => m.factory) : matches.map(m => m.result))];
|
||||
if (uniqueMatches.length > 1) {
|
||||
console.warn(`Warning: This filter matches ${matches.length} modules. Make it more specific!\n`, uniqueMatches);
|
||||
}
|
||||
|
||||
return matches[0];
|
||||
return uniqueMatches[0];
|
||||
}
|
||||
})();
|
||||
|
||||
if (result && cacheKey) cache.set(cacheKey, result);
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
let fakeRenderWin: WeakRef<Window> | undefined;
|
||||
|
||||
const find = newFindWrapper(f => f);
|
||||
const findByProps = newFindWrapper(filters.byProps);
|
||||
|
||||
return {
|
||||
...Object.fromEntries(Object.keys(Common).map(key => [key, { getter: () => Common[key] }])),
|
||||
wp: Webpack,
|
||||
wpc: { getter: () => Webpack.cache },
|
||||
wreq: { getter: () => Webpack.wreq },
|
||||
|
||||
WebpackInstances: { getter: () => Vencord.WebpackPatcher.allWebpackInstances },
|
||||
wpsearch: search,
|
||||
wpex: extract,
|
||||
wpexs: (code: string) => extract(cacheFindModuleId(code)!),
|
||||
loadLazyChunks: IS_DEV ? loadLazyChunks : () => { throw new Error("loadLazyChunks is dev only."); },
|
||||
|
||||
wpsearch: searchFactories,
|
||||
wpex: extract,
|
||||
wpexs: (...code: Webpack.CodeFilter) => extract(cacheFindModuleId(...code)!),
|
||||
|
||||
filters,
|
||||
find,
|
||||
findAll: cacheFindAll,
|
||||
findByProps,
|
||||
findAllByProps: (...props: string[]) => cacheFindAll(filters.byProps(...props)),
|
||||
findProp: (...props: string[]) => findByProps(...props)[props[0]],
|
||||
findByCode: newFindWrapper(filters.byCode),
|
||||
findAllByCode: (code: string) => cacheFindAll(filters.byCode(code)),
|
||||
findComponent: find,
|
||||
findAllComponents: cacheFindAll,
|
||||
findExportedComponent: (...props: Webpack.PropsFilter) => findByProps(...props)[props[0]],
|
||||
findComponentByCode: newFindWrapper(filters.componentByCode),
|
||||
findAllComponentsByCode: (...code: string[]) => cacheFindAll(filters.componentByCode(...code)),
|
||||
findAllComponentsByCode: (...code: Webpack.PropsFilter) => cacheFindAll(filters.componentByCode(...code)),
|
||||
findComponentByFields: newFindWrapper(filters.componentByFields),
|
||||
findAllComponentsByFields: (...fields: string[]) => cacheFindAll(filters.componentByFields(...fields)),
|
||||
findExportedComponent: (...props: string[]) => findByProps(...props)[props[0]],
|
||||
findAllComponentsByFields: (...fields: Webpack.PropsFilter) => cacheFindAll(filters.componentByFields(...fields)),
|
||||
findByProps,
|
||||
findAllByProps: (...props: Webpack.PropsFilter) => cacheFindAll(filters.byProps(...props)),
|
||||
findProp: (...props: Webpack.PropsFilter) => findByProps(...props)[props[0]],
|
||||
findByCode: newFindWrapper(filters.byCode),
|
||||
findAllByCode: (code: Webpack.CodeFilter) => cacheFindAll(filters.byCode(...code)),
|
||||
findStore: newFindWrapper(filters.byStoreName),
|
||||
findByFactoryCode: newFindWrapper(filters.byFactoryCode),
|
||||
findAllByFactoryCode: (...code: string[]) => cacheFindAll(filters.byFactoryCode(...code)),
|
||||
PluginsApi: { getter: () => Vencord.Plugins },
|
||||
findAllByFactoryCode: (...code: Webpack.CodeFilter) => cacheFindAll(filters.byFactoryCode(...code)),
|
||||
findModuleFactory: newFindWrapper(filters.byFactoryCode, true),
|
||||
findAllModuleFactories: (...code: Webpack.CodeFilter) => _cacheFindAll(filters.byFactoryCode(...code)).map(m => m.factory),
|
||||
|
||||
plugins: { getter: () => Vencord.Plugins.plugins },
|
||||
PluginsApi: { getter: () => Vencord.Plugins },
|
||||
Settings: { getter: () => Vencord.Settings },
|
||||
Api: { getter: () => Vencord.Api },
|
||||
Util: { getter: () => Vencord.Util },
|
||||
|
||||
reload: () => location.reload(),
|
||||
restart: IS_WEB ? DESKTOP_ONLY("restart") : relaunch,
|
||||
|
||||
canonicalizeMatch,
|
||||
canonicalizeReplace,
|
||||
canonicalizeReplacement,
|
||||
|
||||
preEnable: (plugin: string) => (Vencord.Settings.plugins[plugin] ??= { enabled: true }).enabled = true,
|
||||
fakeRender: (component: ComponentType, props: any) => {
|
||||
const prevWin = fakeRenderWin?.deref();
|
||||
const win = prevWin?.closed === false
|
||||
|
@ -142,8 +158,6 @@ function makeShortcuts() {
|
|||
Common.ReactDOM.render(Common.React.createElement(component, props), doc.body.appendChild(document.createElement("div")));
|
||||
},
|
||||
|
||||
preEnable: (plugin: string) => (Vencord.Settings.plugins[plugin] ??= { enabled: true }).enabled = true,
|
||||
|
||||
channel: { getter: () => getCurrentChannel(), preload: false },
|
||||
channelId: { getter: () => Common.SelectedChannelStore.getChannelId(), preload: false },
|
||||
guild: { getter: () => getCurrentGuild(), preload: false },
|
||||
|
@ -152,6 +166,7 @@ function makeShortcuts() {
|
|||
meId: { getter: () => Common.UserStore.getCurrentUser().id, preload: false },
|
||||
messages: { getter: () => Common.MessageStore.getMessages(Common.SelectedChannelStore.getChannelId()), preload: false },
|
||||
|
||||
...Object.fromEntries(Object.keys(Common).map(key => [key, { getter: () => Common[key] }])),
|
||||
Stores: {
|
||||
getter: () => Object.fromEntries(
|
||||
Common.Flux.Store.getAll()
|
||||
|
@ -213,8 +228,10 @@ export default definePlugin({
|
|||
const shortcuts = makeShortcuts();
|
||||
window.shortcutList = {};
|
||||
|
||||
for (const [key, val] of Object.entries(shortcuts)) {
|
||||
if ("getter" in val) {
|
||||
for (const key in shortcuts) {
|
||||
const val = shortcuts[key];
|
||||
|
||||
if (Object.hasOwn(val, "getter")) {
|
||||
define(window.shortcutList, key, {
|
||||
get: () => loadAndCacheShortcut(key, val, true)
|
||||
});
|
||||
|
@ -228,7 +245,7 @@ export default definePlugin({
|
|||
}
|
||||
}
|
||||
|
||||
// unproxy loaded modules
|
||||
// Unproxy loaded modules
|
||||
Webpack.onceDiscordLoaded.then(() => {
|
||||
setTimeout(() => this.eagerLoad(false), 1000);
|
||||
|
||||
|
@ -243,10 +260,10 @@ export default definePlugin({
|
|||
await Webpack.onceDiscordLoaded;
|
||||
|
||||
const shortcuts = makeShortcuts();
|
||||
for (const key in shortcuts) {
|
||||
const val = shortcuts[key];
|
||||
|
||||
for (const [key, val] of Object.entries(shortcuts)) {
|
||||
if (!Object.hasOwn(val, "getter") || (val as any).preload === false) continue;
|
||||
|
||||
if (!Object.hasOwn(val, "getter") || val.preload === false) continue;
|
||||
try {
|
||||
loadAndCacheShortcut(key, val, forceLoad);
|
||||
} catch { } // swallow not found errors in DEV
|
||||
|
|
|
@ -22,7 +22,7 @@ import { Devs } from "@utils/constants";
|
|||
import { Logger } from "@utils/Logger";
|
||||
import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches";
|
||||
import definePlugin, { OptionType, ReporterTestable } from "@utils/types";
|
||||
import { cacheFindAll, filters, search } from "@webpack";
|
||||
import { cacheFindAll, filters, searchFactories } from "@webpack";
|
||||
|
||||
const PORT = 8485;
|
||||
const NAV_ID = "dev-companion-reconnect";
|
||||
|
@ -154,7 +154,7 @@ function initWs(isManual = false) {
|
|||
case "testPatch": {
|
||||
const { find, replacement } = data as PatchData;
|
||||
|
||||
const candidates = search(find);
|
||||
const candidates = searchFactories(find);
|
||||
const keys = Object.keys(candidates);
|
||||
if (keys.length !== 1)
|
||||
return reply("Expected exactly one 'find' matches, found " + keys.length);
|
||||
|
@ -213,7 +213,7 @@ function initWs(isManual = false) {
|
|||
results = cacheFindAll(filters.byCode(...parsedArgs));
|
||||
break;
|
||||
case "ModuleId":
|
||||
results = Object.keys(search(parsedArgs[0]));
|
||||
results = Object.keys(searchFactories(parsedArgs[0]));
|
||||
break;
|
||||
case "ComponentByCode":
|
||||
results = cacheFindAll(filters.componentByCode(...parsedArgs));
|
||||
|
|
|
@ -678,16 +678,18 @@ export const _cacheFind = traceFunction("cacheFind", function _cacheFind(filter:
|
|||
const mod = cache[key];
|
||||
if (!mod?.loaded || mod?.exports == null) continue;
|
||||
|
||||
const factory = wreq.m[key] as AnyModuleFactory;
|
||||
|
||||
if (filter.$$vencordIsFactoryFilter) {
|
||||
if (filter(wreq.m[key])) {
|
||||
return { result: mod.exports, id: key, exportKey: null, factory: wreq.m[key] as AnyModuleFactory };
|
||||
return { result: mod.exports, id: key, exportKey: null, factory };
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (filter(mod.exports)) {
|
||||
return { result: mod.exports, id: key, exportKey: null, factory: wreq.m[key] as AnyModuleFactory };
|
||||
return { result: mod.exports, id: key, exportKey: null, factory };
|
||||
}
|
||||
|
||||
if (typeof mod.exports !== "object") {
|
||||
|
@ -695,14 +697,14 @@ export const _cacheFind = traceFunction("cacheFind", function _cacheFind(filter:
|
|||
}
|
||||
|
||||
if (mod.exports.default != null && filter(mod.exports.default)) {
|
||||
return { result: mod.exports.default, id: key, exportKey: "default ", factory: wreq.m[key] as AnyModuleFactory };
|
||||
return { result: mod.exports.default, id: key, exportKey: "default ", factory };
|
||||
}
|
||||
|
||||
for (const exportKey in mod.exports) if (exportKey.length <= 3) {
|
||||
const exportValue = mod.exports[exportKey];
|
||||
|
||||
if (exportValue != null && filter(exportValue)) {
|
||||
return { result: exportValue, id: key, exportKey, factory: wreq.m[key] as AnyModuleFactory };
|
||||
return { result: exportValue, id: key, exportKey, factory };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -717,37 +719,37 @@ export const _cacheFind = traceFunction("cacheFind", function _cacheFind(filter:
|
|||
* @returns The found export or module exports, or undefined
|
||||
*/
|
||||
export function cacheFind(filter: FilterFn) {
|
||||
const cacheFindResult = _cacheFind(filter);
|
||||
|
||||
return cacheFindResult.result;
|
||||
return _cacheFind(filter).result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the the export or module exports from an all the required modules that match the filter.
|
||||
*
|
||||
* @param filter A function that takes an export or module exports and returns a boolean
|
||||
* @returns An array of all the found export or module exports
|
||||
*/
|
||||
export function cacheFindAll(filter: FilterFn) {
|
||||
export function _cacheFindAll(filter: FilterFn): Required<CacheFindResult>[] {
|
||||
if (typeof filter !== "function") {
|
||||
throw new Error("Invalid filter. Expected a function got " + typeof filter);
|
||||
}
|
||||
|
||||
const ret: ModuleExports[] = [];
|
||||
const results: Required<CacheFindResult>[] = [];
|
||||
|
||||
for (const key in cache) {
|
||||
const mod = cache[key];
|
||||
if (!mod?.loaded || mod?.exports == null) continue;
|
||||
|
||||
const factory = wreq.m[key] as AnyModuleFactory;
|
||||
|
||||
if (filter.$$vencordIsFactoryFilter) {
|
||||
if (filter(wreq.m[key])) {
|
||||
ret.push(mod.exports);
|
||||
results.push({ result: mod.exports, id: key, exportKey: null, factory });
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (filter(mod.exports)) {
|
||||
ret.push(mod.exports);
|
||||
results.push({ result: mod.exports, id: key, exportKey: null, factory });
|
||||
}
|
||||
|
||||
if (typeof mod.exports !== "object") {
|
||||
|
@ -755,57 +757,54 @@ export function cacheFindAll(filter: FilterFn) {
|
|||
}
|
||||
|
||||
if (mod.exports.default != null && filter(mod.exports.default)) {
|
||||
ret.push(mod.exports.default);
|
||||
results.push({ result: mod.exports.default, id: key, exportKey: "default ", factory });
|
||||
}
|
||||
|
||||
for (const exportKey in mod.exports) if (exportKey.length <= 3) {
|
||||
const exportValue = mod.exports[exportKey];
|
||||
|
||||
if (exportValue != null && filter(exportValue)) {
|
||||
ret.push(exportValue);
|
||||
results.push({ result: exportValue, id: key, exportKey, factory });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the the export or module exports from an all the required modules that match the filter.
|
||||
*
|
||||
* @param filter A function that takes an export or module exports and returns a boolean
|
||||
* @returns An array of found exports or module exports
|
||||
*/
|
||||
export function cacheFindAll(filter: FilterFn) {
|
||||
return _cacheFindAll(filter).map(({ result }) => result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the id of the first already loaded module factory that includes all the given code.
|
||||
*/
|
||||
export const cacheFindModuleId = traceFunction("cacheFindModuleId", function cacheFindModuleId(...code: CodeFilter) {
|
||||
const parsedCode = code.map(canonicalizeMatch);
|
||||
|
||||
for (const id in wreq.m) {
|
||||
if (stringMatches(String(wreq.m[id]), parsedCode)) {
|
||||
return id;
|
||||
export function cacheFindModuleId(...code: CodeFilter) {
|
||||
return _cacheFind(filters.byFactoryCode(...code)).id;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Search modules by keyword. This searches the factory methods,
|
||||
* Search factories by keyword. This searches the source code of the module factories,
|
||||
* meaning you can search all sorts of things, methodName, strings somewhere in the code, etc.
|
||||
*
|
||||
* @param code One or more strings or regexes
|
||||
* @returns Mapping of found modules
|
||||
* @returns Mapping of found factories by their module id
|
||||
*/
|
||||
export function search(...code: CodeFilter) {
|
||||
code = code.map(canonicalizeMatch);
|
||||
export function searchFactories(...code: CodeFilter) {
|
||||
const filter = filters.byFactoryCode(...code);
|
||||
|
||||
const results: WebpackRequire["m"] = {};
|
||||
const factories = wreq.m;
|
||||
|
||||
for (const id in factories) {
|
||||
const factory = factories[id];
|
||||
|
||||
if (stringMatches(String(factory), code)) {
|
||||
return _cacheFindAll(filter).reduce((results, { factory, id }) => {
|
||||
results[id] = factory;
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}, {} as Record<PropertyKey, AnyModuleFactory>);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -819,7 +818,7 @@ export function search(...code: CodeFilter) {
|
|||
*/
|
||||
export function extract(id: PropertyKey) {
|
||||
const factory = wreq.m[id];
|
||||
if (!factory) return null;
|
||||
if (factory == null) return null;
|
||||
|
||||
const code = `
|
||||
// [EXTRACTED] WebpackModule${String(id)}
|
||||
|
@ -833,6 +832,8 @@ export function extract(id: PropertyKey) {
|
|||
return extracted;
|
||||
}
|
||||
|
||||
/* ------------------------------- Deprecations ------------------------------- */
|
||||
|
||||
/**
|
||||
* @deprecated Use separate finds instead
|
||||
* Same as {@link cacheFind} but in bulk.
|
||||
|
@ -1040,7 +1041,7 @@ export const mapMangledModuleLazy = deprecatedRedirect("mapMangledModuleLazy", "
|
|||
export const findAll = deprecatedRedirect("findAll", "cacheFindAll", cacheFindAll);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link cacheFindBulk} instead
|
||||
* @deprecated Use separate finds instead
|
||||
*
|
||||
* Same as {@link cacheFind} but in bulk
|
||||
*
|
||||
|
@ -1057,3 +1058,14 @@ export const findBulk = deprecatedRedirect("findBulk", "cacheFindBulk", cacheFin
|
|||
* @returns string or null
|
||||
*/
|
||||
export const findModuleId = deprecatedRedirect("findModuleId", "cacheFindModuleId", cacheFindModuleId);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link searchFactories} instead
|
||||
*
|
||||
* Search modules by keyword. This searches the factory methods,
|
||||
* meaning you can search all sorts of things, methodName, strings somewhere in the code, etc.
|
||||
*
|
||||
* @param code One or more strings or regexes
|
||||
* @returns Mapping of found modules
|
||||
*/
|
||||
export const search = deprecatedRedirect("search", "searchFactories", searchFactories);
|
||||
|
|
|
@ -481,7 +481,7 @@ function patchFactory(id: PropertyKey, factory: AnyModuleFactory) {
|
|||
// inline require to avoid including it in !IS_DEV builds
|
||||
const diff = (require("diff") as typeof import("diff")).diffWordsWithSpace(context, patchedContext);
|
||||
let fmt = "%c %s ";
|
||||
const elements = [] as string[];
|
||||
const elements: string[] = [];
|
||||
for (const d of diff) {
|
||||
const color = d.removed
|
||||
? "red"
|
||||
|
|
Loading…
Reference in a new issue