Skip to content

Commit

Permalink
mapMangledModule: Properly support component finds
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuckyz committed Jul 20, 2024
1 parent cd3534f commit 4235337
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 56 deletions.
2 changes: 1 addition & 1 deletion src/components/VencordSettings/ThemesTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ function ThemesTab() {
/>
))}
</div>
</Forms.FormSection >
</Forms.FormSection>
</>
);
}
Expand Down
8 changes: 7 additions & 1 deletion src/debug/runReporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}
}
Expand Down Expand Up @@ -148,7 +150,11 @@ async function runReporter() {
const [code, mappers] = parsedArgs;

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]) => {
let parsedFilter: string;

Expand Down
12 changes: 9 additions & 3 deletions src/plugins/consoleShortcuts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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 });
}

Expand Down
4 changes: 2 additions & 2 deletions src/plugins/decor/ui/modals/CreateDecorationModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
});

Expand Down
4 changes: 2 additions & 2 deletions src/utils/proxyInner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ const handler: ProxyHandler<any> = {
* @returns A proxy which will act like the inner value when accessed
*/
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."
): [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];
Expand Down
104 changes: 57 additions & 47 deletions src/webpack/api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -68,6 +68,7 @@ export type StoreNameFilter = string;

export type FilterFn = ((module: any) => boolean) & {
$$vencordProps?: Array<string | RegExp>;
$$vencordIsComponentFilter?: boolean;
$$vencordIsFactoryFilter?: boolean;
};

Expand Down Expand Up @@ -123,6 +124,7 @@ export const filters = {
};

filter.$$vencordProps = ["componentByCode", ...code];
filter.$$vencordIsComponentFilter = true;
return filter;
},

Expand All @@ -147,6 +149,29 @@ function printFilter(filter: FilterFn) {
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,
* then call the callback with the export or module exports as the first argument.
Expand Down Expand Up @@ -232,33 +257,18 @@ export function findComponent<T extends object = any>(filter: FilterFn, parse: (
if (typeof parse !== "function")
throw new Error("Invalid component parse. Expected a function got " + typeof parse);

let InnerComponent = null as LazyComponentType<T> | 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 && <InnerComponent {...props} />;
};

WrapperComponent[SYM_LAZY_COMPONENT_INNER] = () => InnerComponent;

waitFor(filter, (v: any) => {
const parsedComponent = parse(v);
InnerComponent = parsedComponent;
Object.assign(WrapperComponent, parsedComponent);
const [WrapperComponent, setInnerComponent] = wrapWebpackComponent<T>(`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<T>;

return WrapperComponent as LazyComponentType<T>;
return WrapperComponent;
}

/**
Expand All @@ -277,33 +287,18 @@ export function findExportedComponent<T extends object = any>(...props: PropsFil

const filter = filters.byProps(...newProps);

let InnerComponent = null as LazyComponentType<T> | 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 && <InnerComponent {...props} />;
};

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<T>(`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<T>;

return WrapperComponent as LazyComponentType<T>;
return WrapperComponent;
}

/**
Expand Down Expand Up @@ -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>) {
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) {
const mapperFilter = mappers[newName];

// 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 errorMsgWrapper = () => `Webpack mapMangledModule ${callbackCalled ? "mapper" : "factory"} filter matched no module. Filter: ${printFilter(callbackCalled ? mapperFilter : factoryFilter)}`;

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;
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]);
Expand All @@ -469,7 +473,11 @@ export function mapMangledModule<S extends PropertyKey>(code: string | RegExp |
mapping[newName] = exportValue;
}

setters[newName](exportValue);
if (filter.$$vencordIsComponentFilter) {
wrapperComponentSetters[newName](exportValue, exportValue);
} else {
proxyInnerSetters[newName](exportValue);
}
}
}
}
Expand All @@ -485,6 +493,8 @@ export function mapMangledModule<S extends PropertyKey>(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]();
}
}
}
Expand Down

0 comments on commit 4235337

Please sign in to comment.