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

This commit is contained in:
Nuckyz 2024-06-21 04:58:43 -03:00
commit cd79150a84
No known key found for this signature in database
GPG key ID: 440BF8296E1C4AD9
4 changed files with 39 additions and 36 deletions

View file

@ -86,6 +86,7 @@ function makeShortcuts() {
wpex: extract, wpex: extract,
wpexs: (code: string) => extract(Webpack.cacheFindModuleId(code)!), wpexs: (code: string) => extract(Webpack.cacheFindModuleId(code)!),
loadLazyChunks: IS_DEV ? loadLazyChunks : () => { throw new Error("loadLazyChunks is dev only."); }, loadLazyChunks: IS_DEV ? loadLazyChunks : () => { throw new Error("loadLazyChunks is dev only."); },
filters,
find, find,
findAll: cacheFindAll, findAll: cacheFindAll,
findByProps, findByProps,

View file

@ -283,7 +283,7 @@ function wrapAndPatchFactory(id: PropertyKey, originalFactory: AnyModuleFactory)
// There are (at the time of writing) 11 modules exporting the window // There are (at the time of writing) 11 modules exporting the window
// Make these non enumerable to improve webpack search performance // Make these non enumerable to improve webpack search performance
if (require.c) { if (typeof require === "function" && require.c != null) {
let foundWindow = false; let foundWindow = false;
if (exports === window) { if (exports === window) {
@ -308,13 +308,13 @@ function wrapAndPatchFactory(id: PropertyKey, originalFactory: AnyModuleFactory)
writable: true writable: true
}); });
return; return factoryReturn;
} }
} }
for (const callback of moduleListeners) { for (const callback of moduleListeners) {
try { try {
callback(exports, { id, factory: originalMod }); callback(exports, { id, factory: wrappedFactory.$$vencordOriginal! });
} catch (err) { } catch (err) {
logger.error("Error in Webpack module listener:\n", err, callback); logger.error("Error in Webpack module listener:\n", err, callback);
} }
@ -322,15 +322,15 @@ function wrapAndPatchFactory(id: PropertyKey, originalFactory: AnyModuleFactory)
for (const [filter, callback] of waitForSubscriptions) { for (const [filter, callback] of waitForSubscriptions) {
try { try {
if (filter.$$vencordIsFactoryFilter && filter(originalMod)) { if (filter.$$vencordIsFactoryFilter && filter(wrappedFactory.$$vencordOriginal!)) {
waitForSubscriptions.delete(filter); waitForSubscriptions.delete(filter);
callback(exports, { id, exportKey: null, factory: originalMod }); callback(exports, { id, exportKey: null, factory: wrappedFactory.$$vencordOriginal! });
continue; continue;
} }
if (filter(exports)) { if (filter(exports)) {
waitForSubscriptions.delete(filter); waitForSubscriptions.delete(filter);
callback(exports, { id, exportKey: null, factory: originalMod }); callback(exports, { id, exportKey: null, factory: wrappedFactory.$$vencordOriginal! });
continue; continue;
} }
@ -340,7 +340,7 @@ function wrapAndPatchFactory(id: PropertyKey, originalFactory: AnyModuleFactory)
if (exports.default != null && filter(exports.default)) { if (exports.default != null && filter(exports.default)) {
waitForSubscriptions.delete(filter); waitForSubscriptions.delete(filter);
callback(exports.default, { id, exportKey: "default", factory: originalMod }); callback(exports.default, { id, exportKey: "default", factory: wrappedFactory.$$vencordOriginal! });
continue; continue;
} }
@ -349,7 +349,7 @@ function wrapAndPatchFactory(id: PropertyKey, originalFactory: AnyModuleFactory)
if (exportValue != null && filter(exportValue)) { if (exportValue != null && filter(exportValue)) {
waitForSubscriptions.delete(filter); waitForSubscriptions.delete(filter);
callback(exportValue, { id, exportKey, factory: originalMod }); callback(exportValue, { id, exportKey, factory: wrappedFactory.$$vencordOriginal! });
break; break;
} }
} }

View file

@ -13,7 +13,7 @@ import { AnyObject } from "@utils/types";
import { traceFunction } from "../debug/Tracer"; import { traceFunction } from "../debug/Tracer";
import { GenericStore } from "./common"; import { GenericStore } from "./common";
import { ModuleExports, ModuleFactory, WebpackRequire } from "./wreq"; import { AnyModuleFactory, ModuleExports, ModuleFactory, WebpackRequire } from "./wreq";
const logger = new Logger("Webpack"); const logger = new Logger("Webpack");
@ -95,13 +95,13 @@ export const filters = {
export type ModListenerInfo = { export type ModListenerInfo = {
id: PropertyKey; id: PropertyKey;
factory: ModuleFactory; factory: AnyModuleFactory;
}; };
export type ModCallbackInfo = { export type ModCallbackInfo = {
id: PropertyKey; id: PropertyKey;
exportKey: PropertyKey | null; exportKey: PropertyKey | null;
factory: ModuleFactory; factory: AnyModuleFactory;
}; };
export type ModListenerFn = (module: ModuleExports, info: ModListenerInfo) => void; export type ModListenerFn = (module: ModuleExports, info: ModListenerInfo) => void;
@ -109,7 +109,7 @@ export type ModCallbackFn = ((module: ModuleExports, info: ModCallbackInfo) => v
$$vencordCallbackCalled?: () => boolean; $$vencordCallbackCalled?: () => boolean;
}; };
export const factoryListeners = new Set<(factory: ModuleFactory) => void>(); export const factoryListeners = new Set<(factory: AnyModuleFactory) => void>();
export const moduleListeners = new Set<ModListenerFn>(); export const moduleListeners = new Set<ModListenerFn>();
export const waitForSubscriptions = new Map<FilterFn, ModCallbackFn>(); export const waitForSubscriptions = new Map<FilterFn, ModCallbackFn>();
export const beforeInitListeners = new Set<(wreq: WebpackRequire) => void>(); export const beforeInitListeners = new Set<(wreq: WebpackRequire) => void>();
@ -395,10 +395,10 @@ export function findByFactoryCode<T = AnyObject>(...code: string[]) {
export function findModuleFactory(...code: string[]) { export function findModuleFactory(...code: string[]) {
const filter = filters.byFactoryCode(...code); const filter = filters.byFactoryCode(...code);
const [proxy, setInnerValue] = proxyInner<ModuleFactory>(`Webpack module factory find matched no module. Filter: ${printFilter(filter)}`, "Webpack find with proxy called on a primitive value. This can happen if you try to destructure a primitive in the top level definition of the find."); const [proxy, setInnerValue] = proxyInner<AnyModuleFactory>(`Webpack module factory find matched no module. Filter: ${printFilter(filter)}`, "Webpack find with proxy called on a primitive value. This can happen if you try to destructure a primitive in the top level definition of the find.");
waitFor(filter, (_, { factory }) => setInnerValue(factory)); waitFor(filter, (_, { factory }) => setInnerValue(factory));
if (proxy[SYM_PROXY_INNER_VALUE] != null) return proxy[SYM_PROXY_INNER_VALUE] as ProxyInner<ModuleFactory>; if (proxy[SYM_PROXY_INNER_VALUE] != null) return proxy[SYM_PROXY_INNER_VALUE] as ProxyInner<AnyModuleFactory>;
return proxy; return proxy;
} }
@ -418,8 +418,8 @@ export function findModuleFactory(...code: string[]) {
* @returns Unmangled exports as specified in mappers * @returns Unmangled exports as specified in mappers
*/ */
export function mapMangledModule<S extends PropertyKey>(code: string | string[], mappers: Record<S, FilterFn>) { export function mapMangledModule<S extends PropertyKey>(code: string | string[], mappers: Record<S, FilterFn>) {
const result = find<Record<S, any>>(filters.byFactoryCode(...Array.isArray(code) ? code : [code]), exports => { const result = find<Record<S, ModuleExports>>(filters.byFactoryCode(...Array.isArray(code) ? code : [code]), exports => {
const mapping = {} as Record<S, any>; const mapping = {} as Record<S, ModuleExports>;
outer: outer:
for (const newName in mappers) { for (const newName in mappers) {
@ -459,7 +459,7 @@ type CacheFindResult = {
/** The key exporting the result. `null` if the find result was all the module exports, `undefined` if nothing was found */ /** The key exporting the result. `null` if the find result was all the module exports, `undefined` if nothing was found */
exportKey?: PropertyKey | null; exportKey?: PropertyKey | null;
/** The factory of the module exporting the result. `undefined` if nothing was found */ /** The factory of the module exporting the result. `undefined` if nothing was found */
factory?: ModuleFactory; factory?: AnyModuleFactory;
}; };
/** /**
@ -476,11 +476,11 @@ export const _cacheFind = traceFunction("cacheFind", function _cacheFind(filter:
if (!mod?.loaded || mod?.exports == null) continue; if (!mod?.loaded || mod?.exports == null) continue;
if (filter.$$vencordIsFactoryFilter && filter(wreq.m[key])) { if (filter.$$vencordIsFactoryFilter && filter(wreq.m[key])) {
return { result: exports, id: key, exportKey: null, factory: wreq.m[key] }; return { result: exports, id: key, exportKey: null, factory: wreq.m[key] as AnyModuleFactory };
} }
if (filter(mod.exports)) { if (filter(mod.exports)) {
return { result: exports, id: key, exportKey: null, factory: wreq.m[key] }; return { result: exports, id: key, exportKey: null, factory: wreq.m[key] as AnyModuleFactory };
} }
if (typeof mod.exports !== "object") { if (typeof mod.exports !== "object") {
@ -488,14 +488,14 @@ export const _cacheFind = traceFunction("cacheFind", function _cacheFind(filter:
} }
if (mod.exports.default != null && filter(mod.exports.default)) { if (mod.exports.default != null && filter(mod.exports.default)) {
return { result: exports.default, id: key, exportKey: "default ", factory: wreq.m[key] }; return { result: exports.default, id: key, exportKey: "default ", factory: wreq.m[key] as AnyModuleFactory };
} }
for (const exportKey in mod.exports) if (exportKey.length <= 3) { for (const exportKey in mod.exports) if (exportKey.length <= 3) {
const exportValue = mod.exports[exportKey]; const exportValue = mod.exports[exportKey];
if (exportValue != null && filter(exportValue)) { if (exportValue != null && filter(exportValue)) {
return { result: exportValue, id: key, exportKey, factory: wreq.m[key] }; return { result: exportValue, id: key, exportKey, factory: wreq.m[key] as AnyModuleFactory };
} }
} }
} }

32
src/webpack/wreq.d.ts vendored
View file

@ -58,21 +58,21 @@ export type WebpackRequire = ((moduleId: PropertyKey) => ModuleExports) & {
m: Record<PropertyKey, ModuleFactory>; m: Record<PropertyKey, ModuleFactory>;
/** The module cache, where all modules which have been WebpackRequire'd are stored */ /** The module cache, where all modules which have been WebpackRequire'd are stored */
c: Record<PropertyKey, Module>; c: Record<PropertyKey, Module>;
/** // /**
* Export star. Sets properties of "fromObject" to "toObject" as getters that return the value from "fromObject", like this: // * Export star. Sets properties of "fromObject" to "toObject" as getters that return the value from "fromObject", like this:
* @example // * @example
* const fromObject = { a: 1 }; // * const fromObject = { a: 1 };
* Object.keys(fromObject).forEach(key => { // * Object.keys(fromObject).forEach(key => {
* if (key !== "default" && !Object.hasOwn(toObject, key)) { // * if (key !== "default" && !Object.hasOwn(toObject, key)) {
* Object.defineProperty(toObject, key, { // * Object.defineProperty(toObject, key, {
* get: () => fromObject[key], // * get: () => fromObject[key],
* enumerable: true // * enumerable: true
* }); // * });
* } // * }
* }); // * });
* @returns fromObject // * @returns fromObject
*/ // */
es: (this: WebpackRequire, fromObject: Record<PropertyKey, any>, toObject: Record<PropertyKey, any>) => Record<PropertyKey, any>; // es: (this: WebpackRequire, fromObject: Record<PropertyKey, any>, toObject: Record<PropertyKey, any>) => Record<PropertyKey, any>;
/** /**
* Creates an async module. A module that exports something that is a Promise, or requires an export from an async module. * Creates an async module. A module that exports something that is a Promise, or requires an export from an async module.
* *
@ -179,6 +179,8 @@ export type WebpackRequire = ((moduleId: PropertyKey) => ModuleExports) & {
v: (this: WebpackRequire, exports: ModuleExports, wasmModuleId: any, wasmModuleHash: string, importsObj?: WebAssembly.Imports) => Promise<any>; v: (this: WebpackRequire, exports: ModuleExports, wasmModuleId: any, wasmModuleHash: string, importsObj?: WebAssembly.Imports) => Promise<any>;
/** Bundle public path, where chunk files are stored. Used by other methods which load chunks to obtain the full asset url */ /** Bundle public path, where chunk files are stored. Used by other methods which load chunks to obtain the full asset url */
p: string; p: string;
/** The runtime id of the current runtime */
j: string;
/** Document baseURI or WebWorker location.href */ /** Document baseURI or WebWorker location.href */
b: string; b: string;
}; };