mapMangledModule: Properly support component finds

This commit is contained in:
Nuckyz 2024-07-20 19:17:05 -03:00
parent cd3534f6fc
commit 42353373db
No known key found for this signature in database
GPG key ID: 440BF8296E1C4AD9
6 changed files with 79 additions and 57 deletions

View file

@ -276,7 +276,7 @@ function ThemesTab() {
/> />
))} ))}
</div> </div>
</Forms.FormSection > </Forms.FormSection>
</> </>
); );
} }

View file

@ -84,6 +84,8 @@ async function runReporter() {
for (const innerMap in result) { for (const innerMap in result) {
if (result[innerMap][SYM_PROXY_INNER_GET] != null && result[innerMap][SYM_PROXY_INNER_VALUE] == null) { if (result[innerMap][SYM_PROXY_INNER_GET] != null && result[innerMap][SYM_PROXY_INNER_VALUE] == null) {
throw new Error("Webpack Find Fail"); throw new Error("Webpack Find Fail");
} else if (result[innerMap][SYM_LAZY_COMPONENT_INNER] != null && result[innerMap][SYM_LAZY_COMPONENT_INNER]() == null) {
throw new Error("Webpack Find Fail");
} }
} }
} }
@ -148,7 +150,11 @@ async function runReporter() {
const [code, mappers] = parsedArgs; const [code, mappers] = parsedArgs;
const parsedFailedMappers = Object.entries<any>(mappers) const parsedFailedMappers = Object.entries<any>(mappers)
.filter(([key]) => result == null || (result[key][SYM_PROXY_INNER_GET] != null && result[key][SYM_PROXY_INNER_VALUE] == null)) .filter(([key]) =>
result == null ||
(result[key][SYM_PROXY_INNER_GET] != null && result[key][SYM_PROXY_INNER_VALUE] == null) ||
(result[key][SYM_LAZY_COMPONENT_INNER] != null && result[key][SYM_LAZY_COMPONENT_INNER]() == null)
)
.map(([key, filter]) => { .map(([key, filter]) => {
let parsedFilter: string; let parsedFilter: string;

View file

@ -19,6 +19,7 @@
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import { getCurrentChannel, getCurrentGuild } from "@utils/discord"; import { getCurrentChannel, getCurrentGuild } from "@utils/discord";
import { SYM_LAZY_CACHED, SYM_LAZY_GET } from "@utils/lazy"; import { SYM_LAZY_CACHED, SYM_LAZY_GET } from "@utils/lazy";
import { SYM_LAZY_COMPONENT_INNER } from "@utils/lazyReact";
import { relaunch } from "@utils/native"; import { relaunch } from "@utils/native";
import { canonicalizeMatch, canonicalizeReplace, canonicalizeReplacement } from "@utils/patches"; import { canonicalizeMatch, canonicalizeReplace, canonicalizeReplacement } from "@utils/patches";
import { SYM_PROXY_INNER_GET, SYM_PROXY_INNER_VALUE } from "@utils/proxyInner"; import { SYM_PROXY_INNER_GET, SYM_PROXY_INNER_VALUE } from "@utils/proxyInner";
@ -166,25 +167,30 @@ function loadAndCacheShortcut(key: string, val: any, forceLoad: boolean) {
return forceLoad ? value[SYM_LAZY_GET]() : value[SYM_LAZY_CACHED]; return forceLoad ? value[SYM_LAZY_GET]() : value[SYM_LAZY_CACHED];
} else if (value[SYM_PROXY_INNER_GET]) { } else if (value[SYM_PROXY_INNER_GET]) {
return forceLoad ? value[SYM_PROXY_INNER_GET]() : value[SYM_PROXY_INNER_VALUE]; return forceLoad ? value[SYM_PROXY_INNER_GET]() : value[SYM_PROXY_INNER_VALUE];
} else if (value[SYM_LAZY_COMPONENT_INNER]) {
return value[SYM_LAZY_COMPONENT_INNER]() != null ? value[SYM_LAZY_COMPONENT_INNER]() : value;
} }
return value; return value;
} }
const value = unwrapProxy(currentVal); const value = unwrapProxy(currentVal);
if (typeof value === "object") { if (value != null && typeof value === "object") {
const descriptors = Object.getOwnPropertyDescriptors(value); const descriptors = Object.getOwnPropertyDescriptors(value);
for (const propKey in descriptors) { for (const propKey in descriptors) {
const descriptor = descriptors[propKey]; const descriptor = descriptors[propKey];
if (descriptor.writable === true || descriptor.set != null) { if (descriptor.writable === true || descriptor.set != null) {
value[propKey] = unwrapProxy(value[propKey]); const newValue = unwrapProxy(value[propKey]);
if (newValue != null) {
value[propKey] = newValue;
}
} }
} }
} }
if (value) { if (value != null) {
define(window.shortcutList, key, { value }); define(window.shortcutList, key, { value });
} }

View file

@ -18,9 +18,9 @@ import { cl, DecorationModalStyles, requireAvatarDecorationModal, requireCreateS
import { AvatarDecorationModalPreview } from "../components"; import { AvatarDecorationModalPreview } from "../components";
const FileUpload = findComponentByCode("fileUploadInput,"); const FileUpload = findComponentByCode("fileUploadInput,");
const HelpMessage = findComponentByCode(".iconDiv,", "messageType");
const { HelpMessageTypes } = mapMangledModule('POSITIVE=3]="POSITIVE', { const { HelpMessage, HelpMessageTypes } = mapMangledModule('POSITIVE=3]="POSITIVE', {
HelpMessage: filters.byComponentCode(".iconDiv,", "messageType"),
HelpMessageTypes: filters.byProps("POSITIVE", "WARNING"), HelpMessageTypes: filters.byProps("POSITIVE", "WARNING"),
}); });

View file

@ -49,13 +49,13 @@ const handler: ProxyHandler<any> = {
* @returns A proxy which will act like the inner value when accessed * @returns A proxy which will act like the inner value when accessed
*/ */
export function proxyInner<T = any>( export function proxyInner<T = any>(
errMsg = "Proxy inner value is undefined, setInnerValue was never called.", errMsg: string | (() => string) = "Proxy inner value is undefined, setInnerValue was never called.",
primitiveErrMsg = "proxyInner called on a primitive value." primitiveErrMsg = "proxyInner called on a primitive value."
): [proxy: T, setInnerValue: (innerValue: T) => void] { ): [proxy: T, setInnerValue: (innerValue: T) => void] {
const proxyDummy = Object.assign(function () { }, { const proxyDummy = Object.assign(function () { }, {
[SYM_PROXY_INNER_GET]: function () { [SYM_PROXY_INNER_GET]: function () {
if (proxyDummy[SYM_PROXY_INNER_VALUE] == null) { if (proxyDummy[SYM_PROXY_INNER_VALUE] == null) {
throw new Error(errMsg); throw new Error(typeof errMsg === "string" ? errMsg : errMsg());
} }
return proxyDummy[SYM_PROXY_INNER_VALUE]; return proxyDummy[SYM_PROXY_INNER_VALUE];

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
*/ */
import { lazyString, makeLazy, proxyLazy } from "@utils/lazy"; import { makeLazy, proxyLazy } from "@utils/lazy";
import { LazyComponent, LazyComponentType, SYM_LAZY_COMPONENT_INNER } from "@utils/lazyReact"; import { LazyComponent, LazyComponentType, SYM_LAZY_COMPONENT_INNER } from "@utils/lazyReact";
import { Logger } from "@utils/Logger"; import { Logger } from "@utils/Logger";
import { canonicalizeMatch } from "@utils/patches"; import { canonicalizeMatch } from "@utils/patches";
@ -68,6 +68,7 @@ export type StoreNameFilter = string;
export type FilterFn = ((module: any) => boolean) & { export type FilterFn = ((module: any) => boolean) & {
$$vencordProps?: Array<string | RegExp>; $$vencordProps?: Array<string | RegExp>;
$$vencordIsComponentFilter?: boolean;
$$vencordIsFactoryFilter?: boolean; $$vencordIsFactoryFilter?: boolean;
}; };
@ -123,6 +124,7 @@ export const filters = {
}; };
filter.$$vencordProps = ["componentByCode", ...code]; filter.$$vencordProps = ["componentByCode", ...code];
filter.$$vencordIsComponentFilter = true;
return filter; return filter;
}, },
@ -147,6 +149,29 @@ function printFilter(filter: FilterFn) {
return String(filter); return String(filter);
} }
function wrapWebpackComponent<T extends object = any>(errMsg: string | (() => string)): [WrapperComponent: LazyComponentType<T>, setInnerComponent: (rawComponent: any, parsedComponent: LazyComponentType<T>) => void] {
let InnerComponent = null as LazyComponentType<T> | null;
let findFailedLogged = false;
const WrapperComponent = (props: T) => {
if (InnerComponent === null && !findFailedLogged) {
findFailedLogged = true;
logger.error(typeof errMsg === "string" ? errMsg : errMsg());
}
return InnerComponent && <InnerComponent {...props} />;
};
WrapperComponent[SYM_LAZY_COMPONENT_INNER] = () => InnerComponent;
function setInnerComponent(rawComponent: any, parsedComponent: LazyComponentType<T>) {
InnerComponent = parsedComponent;
Object.assign(WrapperComponent, rawComponent);
}
return [WrapperComponent, setInnerComponent];
}
/** /**
* Wait for the first export or module exports that matches the provided filter to be required, * Wait for the first export or module exports that matches the provided filter to be required,
* then call the callback with the export or module exports as the first argument. * then call the callback with the export or module exports as the first argument.
@ -232,33 +257,18 @@ export function findComponent<T extends object = any>(filter: FilterFn, parse: (
if (typeof parse !== "function") if (typeof parse !== "function")
throw new Error("Invalid component parse. Expected a function got " + typeof parse); throw new Error("Invalid component parse. Expected a function got " + typeof parse);
let InnerComponent = null as LazyComponentType<T> | null; const [WrapperComponent, setInnerComponent] = wrapWebpackComponent<T>(`Webpack find matched no module. Filter: ${printFilter(filter)}`);
waitFor(filter, m => {
let findFailedLogged = false; setInnerComponent(m, parse(m));
const WrapperComponent = (props: T) => {
if (InnerComponent === null && !findFailedLogged) {
findFailedLogged = true;
logger.error(`Webpack find matched no module. Filter: ${printFilter(filter)}`);
}
return InnerComponent && <InnerComponent {...props} />;
};
WrapperComponent[SYM_LAZY_COMPONENT_INNER] = () => InnerComponent;
waitFor(filter, (v: any) => {
const parsedComponent = parse(v);
InnerComponent = parsedComponent;
Object.assign(WrapperComponent, parsedComponent);
}, { isIndirect: true }); }, { isIndirect: true });
if (IS_REPORTER && !isIndirect) { if (IS_REPORTER && !isIndirect) {
webpackSearchHistory.push(["findComponent", [WrapperComponent, filter]]); webpackSearchHistory.push(["findComponent", [WrapperComponent, filter]]);
} }
if (InnerComponent !== null) return InnerComponent; if (WrapperComponent[SYM_LAZY_COMPONENT_INNER]() != null) return WrapperComponent[SYM_LAZY_COMPONENT_INNER]() as LazyComponentType<T>;
return WrapperComponent as LazyComponentType<T>; return WrapperComponent;
} }
/** /**
@ -277,33 +287,18 @@ export function findExportedComponent<T extends object = any>(...props: PropsFil
const filter = filters.byProps(...newProps); const filter = filters.byProps(...newProps);
let InnerComponent = null as LazyComponentType<T> | null; const [WrapperComponent, setInnerComponent] = wrapWebpackComponent<T>(`Webpack find matched no module. Filter: ${printFilter(filter)}`);
waitFor(filter, m => {
let findFailedLogged = false; setInnerComponent(m[newProps[0]], parse(m[newProps[0]]));
const WrapperComponent = (props: T) => {
if (InnerComponent === null && !findFailedLogged) {
findFailedLogged = true;
logger.error(`Webpack find matched no module. Filter: ${printFilter(filter)}`);
}
return InnerComponent && <InnerComponent {...props} />;
};
WrapperComponent[SYM_LAZY_COMPONENT_INNER] = () => InnerComponent;
waitFor(filter, (v: any) => {
const parsedComponent = parse(v[newProps[0]]);
InnerComponent = parsedComponent;
Object.assign(WrapperComponent, parsedComponent);
}, { isIndirect: true }); }, { isIndirect: true });
if (IS_REPORTER) { if (IS_REPORTER) {
webpackSearchHistory.push(["findExportedComponent", [WrapperComponent, ...newProps]]); webpackSearchHistory.push(["findExportedComponent", [WrapperComponent, ...newProps]]);
} }
if (InnerComponent !== null) return InnerComponent; if (WrapperComponent[SYM_LAZY_COMPONENT_INNER]() != null) return WrapperComponent[SYM_LAZY_COMPONENT_INNER]() as LazyComponentType<T>;
return WrapperComponent as LazyComponentType<T>; return WrapperComponent;
} }
/** /**
@ -440,15 +435,24 @@ export function findByFactoryCode<T = any>(...code: CodeFilter | [...CodeFilter,
*/ */
export function mapMangledModule<S extends PropertyKey>(code: string | RegExp | CodeFilter, mappers: Record<S, FilterFn>) { export function mapMangledModule<S extends PropertyKey>(code: string | RegExp | CodeFilter, mappers: Record<S, FilterFn>) {
const mapping = {} as Record<S, any>; const mapping = {} as Record<S, any>;
const setters = {} as Record<S, (innerValue: any) => void>; const proxyInnerSetters = {} as Record<S, ReturnType<typeof proxyInner>[1]>;
const wrapperComponentSetters = {} as Record<S, ReturnType<typeof wrapWebpackComponent>[1]>;
for (const newName in mappers) { for (const newName in mappers) {
// Wrapper to select whether the parent factory filter or child mapper filter failed when the error is thrown const mapperFilter = mappers[newName];
const errorMsgWrapper = lazyString(() => `Webpack mapMangledModule ${callbackCalled ? "mapper" : "factory"} filter matched no module. Filter: ${printFilter(callbackCalled ? mappers[newName] : factoryFilter)}`);
// Wrapper to select whether the parent factory filter or child mapper filter failed when the error is thrown
const errorMsgWrapper = () => `Webpack mapMangledModule ${callbackCalled ? "mapper" : "factory"} filter matched no module. Filter: ${printFilter(callbackCalled ? mapperFilter : factoryFilter)}`;
if (mapperFilter.$$vencordIsComponentFilter) {
const [WrapperComponent, setInnerComponent] = wrapWebpackComponent(errorMsgWrapper);
mapping[newName] = WrapperComponent;
wrapperComponentSetters[newName] = setInnerComponent;
} else {
const [proxy, setInnerValue] = proxyInner(errorMsgWrapper, "Webpack find with proxy called on a primitive value. This may happen if you are trying to destructure a mapMangledModule primitive value on top level."); const [proxy, setInnerValue] = proxyInner(errorMsgWrapper, "Webpack find with proxy called on a primitive value. This may happen if you are trying to destructure a mapMangledModule primitive value on top level.");
mapping[newName] = proxy; mapping[newName] = proxy;
setters[newName] = setInnerValue; proxyInnerSetters[newName] = setInnerValue;
}
} }
const factoryFilter = filters.byFactoryCode(...Array.isArray(code) ? code : [code]); const factoryFilter = filters.byFactoryCode(...Array.isArray(code) ? code : [code]);
@ -469,7 +473,11 @@ export function mapMangledModule<S extends PropertyKey>(code: string | RegExp |
mapping[newName] = exportValue; mapping[newName] = exportValue;
} }
setters[newName](exportValue); if (filter.$$vencordIsComponentFilter) {
wrapperComponentSetters[newName](exportValue, exportValue);
} else {
proxyInnerSetters[newName](exportValue);
}
} }
} }
} }
@ -485,6 +493,8 @@ export function mapMangledModule<S extends PropertyKey>(code: string | RegExp |
if (innerValue[SYM_PROXY_INNER_VALUE] != null) { if (innerValue[SYM_PROXY_INNER_VALUE] != null) {
mapping[innerMap] = innerValue[SYM_PROXY_INNER_VALUE]; mapping[innerMap] = innerValue[SYM_PROXY_INNER_VALUE];
} else if (innerValue[SYM_LAZY_COMPONENT_INNER] != null && innerValue[SYM_LAZY_COMPONENT_INNER]() != null) {
mapping[innerMap] = innerValue[SYM_LAZY_COMPONENT_INNER]();
} }
} }
} }