2024-07-30 00:18:01 +08:00
|
|
|
import { getMetroCache, indexBlacklistFlag, indexExportsFlags } from "@metro/internals/caches";
|
2024-05-20 15:36:33 +08:00
|
|
|
import { Metro } from "@metro/types";
|
2024-07-08 19:22:01 +08:00
|
|
|
|
2024-07-20 10:46:45 +08:00
|
|
|
import { ModuleFlags, ModulesMapInternal } from "./enums";
|
|
|
|
|
|
2024-07-08 19:22:01 +08:00
|
|
|
const { before, instead } = require("spitroast");
|
2024-04-02 22:24:56 +08:00
|
|
|
|
2024-05-20 19:11:23 +08:00
|
|
|
export const metroModules: Metro.ModuleList = window.modules;
|
2024-05-20 15:36:33 +08:00
|
|
|
const metroRequire: Metro.Require = window.__r;
|
2024-02-23 15:11:35 +08:00
|
|
|
|
2024-05-22 03:02:13 +08:00
|
|
|
// eslint-disable-next-line func-call-spacing
|
|
|
|
|
const moduleSubscriptions = new Map<number, Set<() => void>>();
|
2024-05-23 00:59:09 +08:00
|
|
|
const blacklistedIds = new Set<number>();
|
2024-05-10 02:15:32 +08:00
|
|
|
const noopHandler = () => undefined;
|
|
|
|
|
const functionToString = Function.prototype.toString;
|
|
|
|
|
|
|
|
|
|
let patchedInspectSource = false;
|
2024-05-20 19:11:23 +08:00
|
|
|
let patchedImportTracker = false;
|
2024-09-04 16:55:54 +08:00
|
|
|
let patchedNativeComponentRegistry = false;
|
2024-05-23 00:59:09 +08:00
|
|
|
let _importingModuleId: number = -1;
|
2024-05-08 00:23:08 +08:00
|
|
|
|
2024-05-23 00:59:09 +08:00
|
|
|
for (const key in metroModules) {
|
|
|
|
|
const id = Number(key);
|
2024-05-20 19:11:23 +08:00
|
|
|
const metroModule = metroModules[id];
|
2024-04-02 19:53:23 +08:00
|
|
|
|
2024-12-27 02:01:12 +07:00
|
|
|
const cache = getMetroCache().flagsIndex[id];
|
2024-07-20 10:46:45 +08:00
|
|
|
if (cache & ModuleFlags.BLACKLISTED) {
|
2024-05-21 20:21:54 +08:00
|
|
|
blacklistModule(id);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-04 23:33:53 -04:00
|
|
|
if (metroModule!.factory) {
|
|
|
|
|
instead("factory", metroModule, ((args: Parameters<Metro.FactoryFn>, origFunc: Metro.FactoryFn) => {
|
2024-06-16 18:04:48 +08:00
|
|
|
const originalImportingId = _importingModuleId;
|
2024-05-10 02:15:32 +08:00
|
|
|
_importingModuleId = id;
|
2024-06-16 18:04:48 +08:00
|
|
|
|
2024-04-30 17:55:00 +08:00
|
|
|
const { 1: metroRequire, 4: moduleObject } = args;
|
|
|
|
|
|
2024-05-04 23:33:53 -04:00
|
|
|
args[2 /* metroImportDefault */] = id => {
|
|
|
|
|
const exps = metroRequire(id);
|
|
|
|
|
return exps && exps.__esModule ? exps.default : exps;
|
2024-04-30 17:55:00 +08:00
|
|
|
};
|
|
|
|
|
|
2024-05-04 23:33:53 -04:00
|
|
|
args[3 /* metroImportAll */] = id => {
|
|
|
|
|
const exps = metroRequire(id);
|
|
|
|
|
if (exps && exps.__esModule) return exps;
|
2024-04-30 17:55:00 +08:00
|
|
|
|
|
|
|
|
const importAll: Record<string, any> = {};
|
2024-05-04 23:33:53 -04:00
|
|
|
if (exps) Object.assign(importAll, exps);
|
|
|
|
|
importAll.default = exps;
|
|
|
|
|
return importAll;
|
2024-04-30 17:55:00 +08:00
|
|
|
};
|
|
|
|
|
|
2024-05-04 23:33:53 -04:00
|
|
|
origFunc(...args);
|
2024-05-10 00:20:37 +08:00
|
|
|
if (!isBadExports(moduleObject.exports)) {
|
|
|
|
|
onModuleRequire(moduleObject.exports, id);
|
|
|
|
|
} else {
|
|
|
|
|
blacklistModule(id);
|
|
|
|
|
}
|
2024-05-23 00:59:09 +08:00
|
|
|
|
2024-06-16 18:04:48 +08:00
|
|
|
_importingModuleId = originalImportingId;
|
2024-05-04 23:33:53 -04:00
|
|
|
}) as any); // If only spitroast had better types
|
2024-04-02 19:53:23 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-21 16:04:56 +08:00
|
|
|
/** Makes the module associated with the specified ID non-enumberable. */
|
2024-05-23 00:59:09 +08:00
|
|
|
function blacklistModule(id: number) {
|
2024-05-21 16:04:56 +08:00
|
|
|
Object.defineProperty(metroModules, id, { enumerable: false });
|
|
|
|
|
blacklistedIds.add(id);
|
2024-05-21 20:21:54 +08:00
|
|
|
indexBlacklistFlag(Number(id));
|
2024-05-21 16:04:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isBadExports(exports: any) {
|
2024-05-22 03:02:13 +08:00
|
|
|
return !exports
|
|
|
|
|
|| exports === window
|
|
|
|
|
|| exports["<!@ pylix was here :fuyusquish: !@>"] === null
|
|
|
|
|
|| (exports.__proto__ === Object.prototype && Reflect.ownKeys(exports).length === 0);
|
2024-05-21 16:04:56 +08:00
|
|
|
}
|
|
|
|
|
|
2024-05-08 00:23:08 +08:00
|
|
|
function onModuleRequire(moduleExports: any, id: Metro.ModuleID) {
|
2024-05-23 00:59:09 +08:00
|
|
|
indexExportsFlags(id, moduleExports);
|
2024-05-21 20:21:54 +08:00
|
|
|
|
2024-04-30 20:41:04 +08:00
|
|
|
// Temporary
|
2024-05-04 23:33:53 -04:00
|
|
|
moduleExports.initSentry &&= () => undefined;
|
|
|
|
|
if (moduleExports.default?.track && moduleExports.default.trackMaker)
|
|
|
|
|
moduleExports.default.track = () => Promise.resolve();
|
2024-04-30 20:41:04 +08:00
|
|
|
|
2024-05-10 02:15:32 +08:00
|
|
|
if (moduleExports.registerAsset) {
|
2024-12-27 02:01:12 +07:00
|
|
|
require("@lib/api/assets/patches").patchAssets(moduleExports);
|
2024-05-10 02:15:32 +08:00
|
|
|
}
|
|
|
|
|
|
2024-04-02 19:53:23 +08:00
|
|
|
// There are modules registering the same native component
|
2024-09-04 16:55:54 +08:00
|
|
|
if (!patchedNativeComponentRegistry && ["customBubblingEventTypes", "customDirectEventTypes", "register", "get"].every(x => moduleExports[x])) {
|
2024-12-27 02:01:12 +07:00
|
|
|
instead("register", moduleExports, ([name, cb]: any, origFunc: any) => {
|
2024-02-11 22:44:16 +08:00
|
|
|
try {
|
2024-12-27 02:01:12 +07:00
|
|
|
return origFunc(name, cb);
|
|
|
|
|
} catch {
|
|
|
|
|
return name;
|
|
|
|
|
}
|
2024-03-06 01:57:59 +08:00
|
|
|
});
|
2024-09-04 16:55:54 +08:00
|
|
|
|
|
|
|
|
patchedNativeComponentRegistry = true;
|
2024-02-11 22:44:16 +08:00
|
|
|
}
|
2024-03-26 17:15:42 +08:00
|
|
|
|
2024-12-27 02:01:12 +07:00
|
|
|
|
2024-04-02 19:53:23 +08:00
|
|
|
// Hook DeveloperExperimentStore
|
2024-05-04 23:33:53 -04:00
|
|
|
if (moduleExports?.default?.constructor?.displayName === "DeveloperExperimentStore") {
|
|
|
|
|
moduleExports.default = new Proxy(moduleExports.default, {
|
|
|
|
|
get(target, property, receiver) {
|
2024-03-26 17:15:42 +08:00
|
|
|
if (property === "isDeveloper") {
|
|
|
|
|
// Hopefully won't explode accessing it here :3
|
2024-07-30 00:18:01 +08:00
|
|
|
const { settings } = require("@lib/api/settings");
|
2024-03-26 17:15:42 +08:00
|
|
|
return settings.enableDiscordDeveloperSettings ?? false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Reflect.get(target, property, receiver);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-02-11 22:44:16 +08:00
|
|
|
|
2024-05-20 19:11:23 +08:00
|
|
|
if (!patchedImportTracker && moduleExports.fileFinishedImporting) {
|
2024-07-08 19:22:01 +08:00
|
|
|
before("fileFinishedImporting", moduleExports, ([filePath]: [string]) => {
|
2024-05-23 00:59:09 +08:00
|
|
|
if (_importingModuleId === -1 || !filePath) return;
|
2024-05-20 19:11:23 +08:00
|
|
|
metroModules[_importingModuleId]!.__filePath = filePath;
|
|
|
|
|
});
|
|
|
|
|
patchedImportTracker = true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-02 19:53:23 +08:00
|
|
|
// Funny infinity recursion caused by a race condition
|
|
|
|
|
if (!patchedInspectSource && window["__core-js_shared__"]) {
|
2024-05-04 23:33:53 -04:00
|
|
|
const inspect = (f: unknown) => typeof f === "function" && functionToString.apply(f, []);
|
2024-04-02 19:53:23 +08:00
|
|
|
window["__core-js_shared__"].inspectSource = inspect;
|
|
|
|
|
patchedInspectSource = true;
|
|
|
|
|
}
|
2024-03-09 05:27:55 +08:00
|
|
|
|
2024-12-27 02:01:12 +07:00
|
|
|
//
|
2024-05-08 00:23:08 +08:00
|
|
|
if (moduleExports.findHostInstance_DEPRECATED) {
|
2024-05-23 00:59:09 +08:00
|
|
|
const prevExports = metroModules[id - 1]?.publicModule.exports;
|
2024-05-08 00:23:08 +08:00
|
|
|
const inc = prevExports.default?.reactProfilingEnabled ? 1 : -1;
|
2024-05-23 00:59:09 +08:00
|
|
|
if (!metroModules[id + inc]?.isInitialized) {
|
|
|
|
|
blacklistModule(id + inc);
|
2024-05-08 00:23:08 +08:00
|
|
|
}
|
|
|
|
|
}
|
2024-05-10 00:20:37 +08:00
|
|
|
|
|
|
|
|
// Hindi timestamps moment
|
|
|
|
|
if (moduleExports.isMoment) {
|
2024-07-08 19:22:01 +08:00
|
|
|
instead("defineLocale", moduleExports, (args: [string], orig: (lcl: string) => string) => {
|
2024-05-10 00:20:37 +08:00
|
|
|
const origLocale = moduleExports.locale();
|
|
|
|
|
orig(...args);
|
|
|
|
|
moduleExports.locale(origLocale);
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-05-22 03:02:13 +08:00
|
|
|
|
2024-05-23 00:47:21 +08:00
|
|
|
const subs = moduleSubscriptions.get(Number(id));
|
|
|
|
|
if (subs) {
|
|
|
|
|
subs.forEach(s => s());
|
|
|
|
|
moduleSubscriptions.delete(Number(id));
|
|
|
|
|
}
|
2024-05-08 00:23:08 +08:00
|
|
|
}
|
2024-05-04 23:33:53 -04:00
|
|
|
|
2024-05-10 02:15:32 +08:00
|
|
|
export function getImportingModuleId() {
|
|
|
|
|
return _importingModuleId;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-22 03:02:13 +08:00
|
|
|
export function subscribeModule(id: number, cb: () => void): () => void {
|
|
|
|
|
const subs = moduleSubscriptions.get(id) ?? new Set();
|
|
|
|
|
|
2024-05-22 03:32:41 +08:00
|
|
|
subs.add(cb);
|
2024-05-22 03:02:13 +08:00
|
|
|
moduleSubscriptions.set(id, subs);
|
|
|
|
|
|
2024-05-22 03:32:41 +08:00
|
|
|
return () => subs.delete(cb);
|
2024-05-22 03:02:13 +08:00
|
|
|
}
|
|
|
|
|
|
2024-05-10 00:20:37 +08:00
|
|
|
export function requireModule(id: Metro.ModuleID) {
|
2024-05-20 19:11:23 +08:00
|
|
|
if (!metroModules[0]?.isInitialized) metroRequire(0);
|
2024-05-23 00:59:09 +08:00
|
|
|
if (blacklistedIds.has(id)) return undefined;
|
2024-05-10 00:20:37 +08:00
|
|
|
|
2024-05-29 09:26:27 +08:00
|
|
|
if (Number(id) === -1) return require("@metro/polyfills/redesign");
|
2024-05-21 16:04:56 +08:00
|
|
|
|
2024-05-20 19:11:23 +08:00
|
|
|
if (metroModules[id]?.isInitialized && !metroModules[id]?.hasError) {
|
2024-05-10 00:20:37 +08:00
|
|
|
return metroRequire(id);
|
|
|
|
|
}
|
2024-03-09 05:27:55 +08:00
|
|
|
|
2024-07-20 10:46:45 +08:00
|
|
|
// Disable Internal RN error reporting logic
|
2024-05-04 23:33:53 -04:00
|
|
|
const originalHandler = ErrorUtils.getGlobalHandler();
|
|
|
|
|
ErrorUtils.setGlobalHandler(noopHandler);
|
2024-03-09 05:27:55 +08:00
|
|
|
|
2024-05-04 23:33:53 -04:00
|
|
|
let moduleExports;
|
2024-04-02 19:53:23 +08:00
|
|
|
try {
|
2024-05-04 23:33:53 -04:00
|
|
|
moduleExports = metroRequire(id);
|
2024-04-02 19:53:23 +08:00
|
|
|
} catch {
|
2024-05-23 00:59:09 +08:00
|
|
|
blacklistModule(id);
|
2024-05-04 23:33:53 -04:00
|
|
|
moduleExports = undefined;
|
2024-04-02 19:53:23 +08:00
|
|
|
}
|
2024-03-09 05:27:55 +08:00
|
|
|
|
2024-04-02 19:53:23 +08:00
|
|
|
// Done initializing! Now, revert our hacks
|
2024-05-04 23:33:53 -04:00
|
|
|
ErrorUtils.setGlobalHandler(originalHandler);
|
2024-03-09 05:27:55 +08:00
|
|
|
|
2024-05-04 23:33:53 -04:00
|
|
|
return moduleExports;
|
2024-03-09 05:27:55 +08:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 20:20:55 +08:00
|
|
|
export function* getModules(uniq: string, all = false) {
|
2024-05-29 09:26:27 +08:00
|
|
|
yield [-1, require("@metro/polyfills/redesign")];
|
2024-05-10 00:20:37 +08:00
|
|
|
|
2024-05-20 20:20:55 +08:00
|
|
|
let cache = getMetroCache().findIndex[uniq];
|
2024-05-29 09:26:27 +08:00
|
|
|
if (all && !cache?.[`_${ModulesMapInternal.FULL_LOOKUP}`]) cache = undefined;
|
|
|
|
|
if (cache?.[`_${ModulesMapInternal.NOT_FOUND}`]) return;
|
2024-04-02 22:24:56 +08:00
|
|
|
|
2024-05-29 09:26:27 +08:00
|
|
|
for (const id in cache) {
|
|
|
|
|
if (id[0] === "_") continue;
|
|
|
|
|
const exports = requireModule(Number(id));
|
|
|
|
|
if (isBadExports(exports)) continue;
|
|
|
|
|
yield [id, exports];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const id in metroModules) {
|
2024-05-23 00:59:09 +08:00
|
|
|
const exports = requireModule(Number(id));
|
2024-05-10 00:20:37 +08:00
|
|
|
if (isBadExports(exports)) continue;
|
|
|
|
|
yield [id, exports];
|
2024-04-02 22:24:56 +08:00
|
|
|
}
|
|
|
|
|
}
|
2024-05-20 16:39:51 +08:00
|
|
|
|
|
|
|
|
export function* getCachedPolyfillModules(name: string) {
|
2024-06-02 00:09:16 +08:00
|
|
|
const cache = getMetroCache().polyfillIndex[name]!;
|
2024-05-29 09:26:27 +08:00
|
|
|
|
|
|
|
|
for (const id in cache) {
|
|
|
|
|
const exports = requireModule(Number(id));
|
|
|
|
|
if (isBadExports(exports)) continue;
|
|
|
|
|
yield [id, exports];
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-02 00:09:16 +08:00
|
|
|
if (!cache[`_${ModulesMapInternal.FULL_LOOKUP}`]) {
|
|
|
|
|
for (const id in metroModules) {
|
|
|
|
|
const exports = requireModule(Number(id));
|
|
|
|
|
if (isBadExports(exports)) continue;
|
|
|
|
|
yield [id, exports];
|
|
|
|
|
}
|
2024-05-20 16:39:51 +08:00
|
|
|
}
|
|
|
|
|
}
|