diff --git a/src/components/VencordSettings/ThemesTab.tsx b/src/components/VencordSettings/ThemesTab.tsx index 12ff57306..4aa2809da 100644 --- a/src/components/VencordSettings/ThemesTab.tsx +++ b/src/components/VencordSettings/ThemesTab.tsx @@ -276,7 +276,7 @@ function ThemesTab() { /> ))} - + ); } diff --git a/src/debug/runReporter.ts b/src/debug/runReporter.ts index 9c2684d19..b33ae9f68 100644 --- a/src/debug/runReporter.ts +++ b/src/debug/runReporter.ts @@ -84,6 +84,8 @@ async function runReporter() { for (const innerMap in result) { if (result[innerMap][SYM_PROXY_INNER_GET] != null && result[innerMap][SYM_PROXY_INNER_VALUE] == null) { 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 parsedFailedMappers = Object.entries(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]) => { let parsedFilter: string; diff --git a/src/plugins/consoleShortcuts/index.ts b/src/plugins/consoleShortcuts/index.ts index 74243d9cd..114900508 100644 --- a/src/plugins/consoleShortcuts/index.ts +++ b/src/plugins/consoleShortcuts/index.ts @@ -19,6 +19,7 @@ import { Devs } from "@utils/constants"; import { getCurrentChannel, getCurrentGuild } from "@utils/discord"; import { SYM_LAZY_CACHED, SYM_LAZY_GET } from "@utils/lazy"; +import { SYM_LAZY_COMPONENT_INNER } from "@utils/lazyReact"; import { relaunch } from "@utils/native"; import { canonicalizeMatch, canonicalizeReplace, canonicalizeReplacement } from "@utils/patches"; 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]; } else if (value[SYM_PROXY_INNER_GET]) { 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; } const value = unwrapProxy(currentVal); - if (typeof value === "object") { + if (value != null && typeof value === "object") { const descriptors = Object.getOwnPropertyDescriptors(value); for (const propKey in descriptors) { const descriptor = descriptors[propKey]; 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 }); } diff --git a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx index b130bee46..05c601257 100644 --- a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx @@ -18,9 +18,9 @@ import { cl, DecorationModalStyles, requireAvatarDecorationModal, requireCreateS import { AvatarDecorationModalPreview } from "../components"; 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"), }); diff --git a/src/utils/proxyInner.ts b/src/utils/proxyInner.ts index 0840f397b..8a74766c4 100644 --- a/src/utils/proxyInner.ts +++ b/src/utils/proxyInner.ts @@ -49,13 +49,13 @@ const handler: ProxyHandler = { * @returns A proxy which will act like the inner value when accessed */ export function proxyInner( - 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." ): [proxy: T, setInnerValue: (innerValue: T) => void] { const proxyDummy = Object.assign(function () { }, { [SYM_PROXY_INNER_GET]: function () { 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]; diff --git a/src/webpack/api.tsx b/src/webpack/api.tsx index a4c708748..7a7f63a5c 100644 --- a/src/webpack/api.tsx +++ b/src/webpack/api.tsx @@ -4,7 +4,7 @@ * 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 { Logger } from "@utils/Logger"; import { canonicalizeMatch } from "@utils/patches"; @@ -68,6 +68,7 @@ export type StoreNameFilter = string; export type FilterFn = ((module: any) => boolean) & { $$vencordProps?: Array; + $$vencordIsComponentFilter?: boolean; $$vencordIsFactoryFilter?: boolean; }; @@ -123,6 +124,7 @@ export const filters = { }; filter.$$vencordProps = ["componentByCode", ...code]; + filter.$$vencordIsComponentFilter = true; return filter; }, @@ -147,6 +149,29 @@ function printFilter(filter: FilterFn) { return String(filter); } +function wrapWebpackComponent(errMsg: string | (() => string)): [WrapperComponent: LazyComponentType, setInnerComponent: (rawComponent: any, parsedComponent: LazyComponentType) => void] { + let InnerComponent = null as LazyComponentType | null; + + let findFailedLogged = false; + const WrapperComponent = (props: T) => { + if (InnerComponent === null && !findFailedLogged) { + findFailedLogged = true; + logger.error(typeof errMsg === "string" ? errMsg : errMsg()); + } + + return InnerComponent && ; + }; + + WrapperComponent[SYM_LAZY_COMPONENT_INNER] = () => InnerComponent; + + function setInnerComponent(rawComponent: any, parsedComponent: LazyComponentType) { + 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, * then call the callback with the export or module exports as the first argument. @@ -232,33 +257,18 @@ export function findComponent(filter: FilterFn, parse: ( if (typeof parse !== "function") throw new Error("Invalid component parse. Expected a function got " + typeof parse); - let InnerComponent = null as LazyComponentType | null; - - let findFailedLogged = false; - const WrapperComponent = (props: T) => { - if (InnerComponent === null && !findFailedLogged) { - findFailedLogged = true; - logger.error(`Webpack find matched no module. Filter: ${printFilter(filter)}`); - } - - return InnerComponent && ; - }; - - WrapperComponent[SYM_LAZY_COMPONENT_INNER] = () => InnerComponent; - - waitFor(filter, (v: any) => { - const parsedComponent = parse(v); - InnerComponent = parsedComponent; - Object.assign(WrapperComponent, parsedComponent); + const [WrapperComponent, setInnerComponent] = wrapWebpackComponent(`Webpack find matched no module. Filter: ${printFilter(filter)}`); + waitFor(filter, m => { + setInnerComponent(m, parse(m)); }, { isIndirect: true }); if (IS_REPORTER && !isIndirect) { 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; - return WrapperComponent as LazyComponentType; + return WrapperComponent; } /** @@ -277,33 +287,18 @@ export function findExportedComponent(...props: PropsFil const filter = filters.byProps(...newProps); - let InnerComponent = null as LazyComponentType | null; - - let findFailedLogged = false; - const WrapperComponent = (props: T) => { - if (InnerComponent === null && !findFailedLogged) { - findFailedLogged = true; - logger.error(`Webpack find matched no module. Filter: ${printFilter(filter)}`); - } - - return InnerComponent && ; - }; - - WrapperComponent[SYM_LAZY_COMPONENT_INNER] = () => InnerComponent; - - waitFor(filter, (v: any) => { - const parsedComponent = parse(v[newProps[0]]); - InnerComponent = parsedComponent; - Object.assign(WrapperComponent, parsedComponent); + const [WrapperComponent, setInnerComponent] = wrapWebpackComponent(`Webpack find matched no module. Filter: ${printFilter(filter)}`); + waitFor(filter, m => { + setInnerComponent(m[newProps[0]], parse(m[newProps[0]])); }, { isIndirect: true }); if (IS_REPORTER) { 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; - return WrapperComponent as LazyComponentType; + return WrapperComponent; } /** @@ -440,15 +435,24 @@ export function findByFactoryCode(...code: CodeFilter | [...CodeFilter, */ export function mapMangledModule(code: string | RegExp | CodeFilter, mappers: Record) { const mapping = {} as Record; - const setters = {} as Record void>; + const proxyInnerSetters = {} as Record[1]>; + const wrapperComponentSetters = {} as Record[1]>; for (const newName in mappers) { - // Wrapper to select whether the parent factory filter or child mapper filter failed when the error is thrown - const errorMsgWrapper = lazyString(() => `Webpack mapMangledModule ${callbackCalled ? "mapper" : "factory"} filter matched no module. Filter: ${printFilter(callbackCalled ? mappers[newName] : factoryFilter)}`); + const mapperFilter = mappers[newName]; - 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; - setters[newName] = setInnerValue; + // 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."); + mapping[newName] = proxy; + proxyInnerSetters[newName] = setInnerValue; + } } const factoryFilter = filters.byFactoryCode(...Array.isArray(code) ? code : [code]); @@ -469,7 +473,11 @@ export function mapMangledModule(code: string | RegExp | mapping[newName] = exportValue; } - setters[newName](exportValue); + if (filter.$$vencordIsComponentFilter) { + wrapperComponentSetters[newName](exportValue, exportValue); + } else { + proxyInnerSetters[newName](exportValue); + } } } } @@ -485,6 +493,8 @@ export function mapMangledModule(code: string | RegExp | if (innerValue[SYM_PROXY_INNER_VALUE] != null) { 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](); } } }