Speed up UI loading, and usage of the app
Start enabled Vendetta plugins in small staggered batches and defer network fetches to the background. Register core plugins at init so they appear in the UI immediately. Remove BUNNY_PROXY_PREFIX usage and the unproxied-install confirmation. Restore Updater settings entry and bump build version to 1.1.6-2. Apply various Metro internals cleanup and robustness fixes (import tracking, export/blacklist handling, error guards)
This commit is contained in:
parent
9f6f62093d
commit
6745ca2514
8 changed files with 311 additions and 209 deletions
|
|
@ -77,7 +77,7 @@ const config = {
|
|||
constModules: {
|
||||
globals: {
|
||||
"bunny-build-info": {
|
||||
version: `"1.1.6-1"`,
|
||||
version: `"1.1.6-2"`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,13 +20,6 @@ export default function initSettings() {
|
|||
render: () => import("@core/ui/settings/pages/General"),
|
||||
useTrailing: () => `(${version})`,
|
||||
},
|
||||
{
|
||||
key: "SHIGGYCORD_UPDATER",
|
||||
title: () => "Updater",
|
||||
icon: findAssetId("BellIcon"),
|
||||
render: () => import("@core/ui/settings/pages/Updater"),
|
||||
},
|
||||
|
||||
{
|
||||
key: "CORE_PLUGINS",
|
||||
title: () => Strings.PLUGINS,
|
||||
|
|
@ -56,7 +49,12 @@ export default function initSettings() {
|
|||
render: () => import("@core/ui/settings/pages/Fonts"),
|
||||
usePredicate: () => isFontSupported(),
|
||||
},
|
||||
|
||||
{
|
||||
key: "SHIGGYCORD_UPDATER",
|
||||
title: () => "Updater",
|
||||
icon: findAssetId("BellIcon"),
|
||||
render: () => import("@core/ui/settings/pages/Updater"),
|
||||
},
|
||||
{
|
||||
key: "BUNNY_DEVELOPER",
|
||||
title: () => Strings.DEVELOPER,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import { findAssetId } from "@lib/api/assets";
|
|||
import { settings } from "@lib/api/settings";
|
||||
import { useObservable } from "@lib/api/storage";
|
||||
import { showToast } from "@lib/ui/toasts";
|
||||
import { BUNNY_PROXY_PREFIX, VD_PROXY_PREFIX } from "@lib/utils/constants";
|
||||
import { VD_PROXY_PREFIX } from "@lib/utils/constants";
|
||||
import { lazyDestructure } from "@lib/utils/lazy";
|
||||
import { findByProps } from "@metro";
|
||||
import { ComponentProps } from "react";
|
||||
|
|
@ -186,39 +186,6 @@ function InstallButton({
|
|||
}
|
||||
};
|
||||
|
||||
const continueInstallation = async () => {
|
||||
if (
|
||||
!addon.installUrl.startsWith(VD_PROXY_PREFIX) &&
|
||||
!addon.installUrl.startsWith(BUNNY_PROXY_PREFIX) &&
|
||||
!settings.developerSettings
|
||||
) {
|
||||
openAlert(
|
||||
"bunny-plugin-unproxied-confirmation",
|
||||
<AlertModalComponent
|
||||
title="Hold On!"
|
||||
content="You're trying to install a plugin from an unproxied external source. This means you're trusting the creator to run their code in this app without your knowledge. Are you sure you want to continue?"
|
||||
extraContent={
|
||||
<Card>
|
||||
<Text variant="text-md/bold">{addon.installUrl}</Text>
|
||||
</Card>
|
||||
}
|
||||
actions={
|
||||
<AlertActionsComponent>
|
||||
<AlertActionButton
|
||||
text="Continue"
|
||||
variant="primary"
|
||||
onPress={performInstall}
|
||||
/>
|
||||
<AlertActionButton text="Cancel" variant="secondary" />
|
||||
</AlertActionsComponent>
|
||||
}
|
||||
/>,
|
||||
);
|
||||
} else {
|
||||
performInstall();
|
||||
}
|
||||
};
|
||||
|
||||
const handleUninstall = () => {
|
||||
VdPluginManager.removePlugin(pluginId);
|
||||
setRefreshTick((prev: number) => prev + 1);
|
||||
|
|
@ -628,12 +595,13 @@ export default function Plugins() {
|
|||
|
||||
// Keep core plugins registration available if needed elsewhere
|
||||
const corePlugins = [...corePluginInstances.keys()]
|
||||
.map((id) => registeredPlugins.get(id)!)
|
||||
.map((id) => registeredPlugins.get(id))
|
||||
.filter((m): m is NonNullable<typeof m> => Boolean(m))
|
||||
.map(unifyBunnyPlugin);
|
||||
|
||||
// Merge lists: show Vendetta-managed plugins first (recent first),
|
||||
// then Bunny-installed externals (recent first).
|
||||
return [...vdPlugins, ...bnPlugins];
|
||||
// include core plugins, then Bunny-installed externals (recent first).
|
||||
return [...vdPlugins, ...corePlugins, ...bnPlugins];
|
||||
}}
|
||||
ListHeaderComponent={() => null}
|
||||
installAction={{
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
import { Author } from "@lib/addons/types";
|
||||
import { settings } from "@lib/api/settings";
|
||||
import { safeFetch } from "@lib/utils";
|
||||
import { BUNNY_PROXY_PREFIX, VD_PROXY_PREFIX } from "@lib/utils/constants";
|
||||
import { VD_PROXY_PREFIX } from "@lib/utils/constants";
|
||||
import { logger, LoggerClass } from "@lib/utils/logger";
|
||||
|
||||
type EvaledPlugin = {
|
||||
|
|
@ -192,24 +192,65 @@ export const VdPluginManager = {
|
|||
const allIds = Object.keys(plugins);
|
||||
|
||||
if (!settings.safeMode?.enabled) {
|
||||
// Loop over any plugin that is enabled, update it if allowed, then start it.
|
||||
await Promise.allSettled(
|
||||
allIds
|
||||
.filter((pl) => plugins[pl].enabled)
|
||||
.map(
|
||||
async (pl) => (
|
||||
plugins[pl].update &&
|
||||
(await this.fetchPlugin(pl).catch((e: Error) =>
|
||||
logger.error(e.message),
|
||||
)),
|
||||
await this.startPlugin(pl)
|
||||
),
|
||||
),
|
||||
);
|
||||
// Wait for the above to finish, then update all disabled plugins that are allowed to.
|
||||
allIds
|
||||
.filter((pl) => !plugins[pl].enabled && plugins[pl].update)
|
||||
.forEach((pl) => this.fetchPlugin(pl));
|
||||
// Staggered startup: start enabled plugins in small batches to avoid
|
||||
// CPU / I/O spikes during app launch. Network fetches (which may be slow)
|
||||
// are deferred to background so the UI can become interactive faster.
|
||||
const enabledIds = allIds.filter((pl) => plugins[pl].enabled);
|
||||
const batchSize = 2;
|
||||
const staggerInterval = 500;
|
||||
|
||||
if (enabledIds.length > 0) {
|
||||
const sleep = (ms: number) =>
|
||||
new Promise<void>((res) => setTimeout(res, ms));
|
||||
|
||||
for (let i = 0; i < enabledIds.length; i += batchSize) {
|
||||
const batch = enabledIds.slice(i, i + batchSize);
|
||||
|
||||
// Start the batch in parallel but avoid letting a single failing plugin
|
||||
// abort the whole process.
|
||||
await Promise.allSettled(
|
||||
batch.map(async (id) => {
|
||||
try {
|
||||
if (!plugins[id]) return;
|
||||
await this.startPlugin(id).catch((e) =>
|
||||
logger.error(`Vendetta plugin ${id} failed to start:`, e),
|
||||
);
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
`Unexpected error while starting vendetta plugin ${id}:`,
|
||||
err,
|
||||
);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
if (i + batchSize < enabledIds.length) {
|
||||
await sleep(staggerInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Defer network fetches to the background so startup isn't delayed.
|
||||
// We fetch updates for plugins (both enabled and disabled) but do this
|
||||
// asynchronously and with a small delay between requests to reduce contention.
|
||||
(async () => {
|
||||
const toFetch = allIds.filter((pl) => plugins[pl]?.update);
|
||||
for (const pl of toFetch) {
|
||||
try {
|
||||
// Fire fetch; fetchPlugin may update plugin JS/manifest. Errors are logged.
|
||||
await this.fetchPlugin(pl).catch((e: Error) => {
|
||||
logger.error(e.message);
|
||||
});
|
||||
} catch (e) {
|
||||
logger.error(
|
||||
`Failed background fetch for vendetta plugin ${pl}:`,
|
||||
e,
|
||||
);
|
||||
}
|
||||
// Small pause between network requests to avoid spikes
|
||||
await new Promise((res) => setTimeout(res, 200));
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
return () => this.stopAllPlugins();
|
||||
|
|
|
|||
11
src/index.ts
11
src/index.ts
|
|
@ -119,17 +119,6 @@ export default async () => {
|
|||
setTimeout(runDeferred, 200);
|
||||
}
|
||||
|
||||
// Schedule a delayed plugin repository refresh (5 minutes) if the earlier deferred schedule didn't run.
|
||||
// This ensures we refresh plugin metadata after the app is fully launched but avoid startup contention.
|
||||
setTimeout(
|
||||
() => {
|
||||
updatePlugins().catch((e) =>
|
||||
logger.log("Scheduled updatePlugins (5min) failed:", e),
|
||||
);
|
||||
},
|
||||
5 * 60 * 1000,
|
||||
);
|
||||
|
||||
// Periodic bundle check: every 3 hours, check GitHub releases (ignore prereleases).
|
||||
// We use the GitHub Releases API to find the latest non-prerelease release and compare its tag.
|
||||
const checkBundle = async () => {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,53 @@ export const apiObjects = new Map<
|
|||
ReturnType<typeof createBunnyPluginApi>
|
||||
>();
|
||||
|
||||
/**
|
||||
* Register core plugins into the runtime registries so they appear in the UI
|
||||
* as soon as this module is imported. This function is intentionally synchronous
|
||||
* and idempotent so it is safe to call at module-load time or from initialization
|
||||
* code.
|
||||
*/
|
||||
export function registerCorePlugins() {
|
||||
try {
|
||||
const core = getCorePlugins();
|
||||
for (const id in core) {
|
||||
try {
|
||||
const { default: instance, preenabled } = core[id];
|
||||
|
||||
// Ensure manifest is registered for UI listing
|
||||
registeredPlugins.set(id, instance.manifest);
|
||||
|
||||
// Keep a reference to the core plugin instance so isCorePlugin checks work
|
||||
corePluginInstances.set(id, instance);
|
||||
|
||||
// Ensure pluginSettings has an entry for the core plugin so the UI can
|
||||
// reflect enabled/disabled state. Do not overwrite existing user settings.
|
||||
try {
|
||||
// `pluginSettings` is a storage wrapper; ensure we only set a default if absent.
|
||||
if (pluginSettings[id] == null) {
|
||||
pluginSettings[id] = { enabled: preenabled ?? true };
|
||||
}
|
||||
} catch (e) {
|
||||
// Best-effort: if storage isn't available yet, ignore and continue.
|
||||
console.error(
|
||||
"Failed to set default pluginSettings for core plugin",
|
||||
id,
|
||||
e,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to register core plugin", id, e);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("registerCorePlugins: unexpected error", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Eager core plugin registration removed to avoid circular require / timing issues.
|
||||
// Call `registerCorePlugins()` explicitly from initialization code when appropriate,
|
||||
// for example during a safe deferred startup step.
|
||||
|
||||
export const pluginRepositories = createStorage<t.PluginRepoStorage>(
|
||||
"plugins/repositories.json",
|
||||
);
|
||||
|
|
@ -628,6 +675,16 @@ export async function initPlugins(
|
|||
) {
|
||||
const { staggerInterval = 100, batchSize = 3 } = options;
|
||||
|
||||
// Ensure core plugins are registered prior to any plugin startup logic so
|
||||
// settings pages and UI that read registered/core plugins show them.
|
||||
// registerCorePlugins is synchronous and idempotent, but call it here as a
|
||||
// safety-net in case module-load registration didn't run earlier.
|
||||
try {
|
||||
registerCorePlugins();
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
|
||||
await awaitStorage(pluginRepositories, pluginSettings);
|
||||
|
||||
// Collect enabled plugin ids
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ export const HTTP_REGEX =
|
|||
export const HTTP_REGEX_MULTI =
|
||||
/https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&\/=]*)/g;
|
||||
|
||||
export const BUNNY_PROXY_PREFIX = "https://bn-plugins.github.io/vd-proxy";
|
||||
|
||||
export const NEXPID_PLUGINS_REPO_URL = "https://revenge.nexpid.xyz";
|
||||
//export const OFFICIAL_PLUGINS_REPO_URL = "https://bn-plugins.github.io/dist/repo.json";
|
||||
export const OFFICIAL_PLUGINS_REPO_URL =
|
||||
"https://raw.githubusercontent.com/Purple-EyeZ/Plugins-List/refs/heads/main/src/plugins-data.json";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
import { getMetroCache, indexBlacklistFlag, indexExportsFlags } from "@metro/internals/caches";
|
||||
import {
|
||||
getMetroCache,
|
||||
indexBlacklistFlag,
|
||||
indexExportsFlags,
|
||||
} from "@metro/internals/caches";
|
||||
import { Metro } from "@metro/types";
|
||||
|
||||
import { ModuleFlags, ModulesMapInternal } from "./enums";
|
||||
|
|
@ -20,88 +24,103 @@ let patchedNativeComponentRegistry = false;
|
|||
let _importingModuleId: number = -1;
|
||||
|
||||
for (const key in metroModules) {
|
||||
const id = Number(key);
|
||||
const metroModule = metroModules[id];
|
||||
const id = Number(key);
|
||||
const metroModule = metroModules[id];
|
||||
|
||||
const cache = getMetroCache().flagsIndex[id];
|
||||
if (cache & ModuleFlags.BLACKLISTED) {
|
||||
const cache = getMetroCache().flagsIndex[id];
|
||||
if (cache & ModuleFlags.BLACKLISTED) {
|
||||
blacklistModule(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (metroModule!.factory) {
|
||||
instead("factory", metroModule, ((
|
||||
args: Parameters<Metro.FactoryFn>,
|
||||
origFunc: Metro.FactoryFn,
|
||||
) => {
|
||||
const originalImportingId = _importingModuleId;
|
||||
_importingModuleId = id;
|
||||
|
||||
const { 1: metroRequire, 4: moduleObject } = args;
|
||||
|
||||
args[2 /* metroImportDefault */] = (id) => {
|
||||
const exps = metroRequire(id);
|
||||
return exps && exps.__esModule ? exps.default : exps;
|
||||
};
|
||||
|
||||
args[3 /* metroImportAll */] = (id) => {
|
||||
const exps = metroRequire(id);
|
||||
if (exps && exps.__esModule) return exps;
|
||||
|
||||
const importAll: Record<string, any> = {};
|
||||
if (exps) Object.assign(importAll, exps);
|
||||
importAll.default = exps;
|
||||
return importAll;
|
||||
};
|
||||
|
||||
origFunc(...args);
|
||||
if (!isBadExports(moduleObject.exports)) {
|
||||
onModuleRequire(moduleObject.exports, id);
|
||||
} else {
|
||||
blacklistModule(id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (metroModule!.factory) {
|
||||
instead("factory", metroModule, ((args: Parameters<Metro.FactoryFn>, origFunc: Metro.FactoryFn) => {
|
||||
const originalImportingId = _importingModuleId;
|
||||
_importingModuleId = id;
|
||||
|
||||
const { 1: metroRequire, 4: moduleObject } = args;
|
||||
|
||||
args[2 /* metroImportDefault */] = id => {
|
||||
const exps = metroRequire(id);
|
||||
return exps && exps.__esModule ? exps.default : exps;
|
||||
};
|
||||
|
||||
args[3 /* metroImportAll */] = id => {
|
||||
const exps = metroRequire(id);
|
||||
if (exps && exps.__esModule) return exps;
|
||||
|
||||
const importAll: Record<string, any> = {};
|
||||
if (exps) Object.assign(importAll, exps);
|
||||
importAll.default = exps;
|
||||
return importAll;
|
||||
};
|
||||
|
||||
origFunc(...args);
|
||||
if (!isBadExports(moduleObject.exports)) {
|
||||
onModuleRequire(moduleObject.exports, id);
|
||||
} else {
|
||||
blacklistModule(id);
|
||||
}
|
||||
|
||||
_importingModuleId = originalImportingId;
|
||||
}) as any); // If only spitroast had better types
|
||||
}
|
||||
_importingModuleId = originalImportingId;
|
||||
}) as any); // If only spitroast had better types
|
||||
}
|
||||
}
|
||||
|
||||
/** Makes the module associated with the specified ID non-enumberable. */
|
||||
function blacklistModule(id: number) {
|
||||
Object.defineProperty(metroModules, id, { enumerable: false });
|
||||
blacklistedIds.add(id);
|
||||
indexBlacklistFlag(Number(id));
|
||||
Object.defineProperty(metroModules, id, { enumerable: false });
|
||||
blacklistedIds.add(id);
|
||||
indexBlacklistFlag(Number(id));
|
||||
}
|
||||
|
||||
function isBadExports(exports: any) {
|
||||
return !exports
|
||||
|| exports === window
|
||||
|| exports["<!@ pylix was here :fuyusquish: \n Hi pylix! -cocobo1!@>"] === null
|
||||
|| (exports.__proto__ === Object.prototype && Reflect.ownKeys(exports).length === 0)
|
||||
|| (exports.default?.[Symbol.toStringTag] === "IntlMessagesProxy");
|
||||
return (
|
||||
!exports ||
|
||||
exports === window ||
|
||||
exports["<!@ pylix was here :fuyusquish: \n Hi pylix! -cocobo1!@>"] ===
|
||||
null ||
|
||||
(exports.__proto__ === Object.prototype &&
|
||||
Reflect.ownKeys(exports).length === 0) ||
|
||||
exports.default?.[Symbol.toStringTag] === "IntlMessagesProxy"
|
||||
);
|
||||
}
|
||||
|
||||
function onModuleRequire(moduleExports: any, id: Metro.ModuleID) {
|
||||
indexExportsFlags(id, moduleExports);
|
||||
indexExportsFlags(id, moduleExports);
|
||||
|
||||
// Temporary
|
||||
moduleExports.initSentry &&= () => undefined;
|
||||
if (moduleExports.default?.track && moduleExports.default.trackMaker)
|
||||
moduleExports.default.track = () => Promise.resolve();
|
||||
// Temporary
|
||||
moduleExports.initSentry &&= () => undefined;
|
||||
if (moduleExports.default?.track && moduleExports.default.trackMaker)
|
||||
moduleExports.default.track = () => Promise.resolve();
|
||||
|
||||
if (moduleExports.registerAsset) {
|
||||
require("@lib/api/assets/patches").patchAssets(moduleExports);
|
||||
}
|
||||
if (moduleExports.registerAsset) {
|
||||
require("@lib/api/assets/patches").patchAssets(moduleExports);
|
||||
}
|
||||
|
||||
// There are modules registering the same native component
|
||||
if (!patchedNativeComponentRegistry && ["customBubblingEventTypes", "customDirectEventTypes", "register", "get"].every(x => moduleExports[x])) {
|
||||
instead("register", moduleExports, ([name, cb]: any, origFunc: any) => {
|
||||
try {
|
||||
return origFunc(name, cb);
|
||||
} catch {
|
||||
return name;
|
||||
}
|
||||
});
|
||||
// There are modules registering the same native component
|
||||
if (
|
||||
!patchedNativeComponentRegistry &&
|
||||
[
|
||||
"customBubblingEventTypes",
|
||||
"customDirectEventTypes",
|
||||
"register",
|
||||
"get",
|
||||
].every((x) => moduleExports[x])
|
||||
) {
|
||||
instead("register", moduleExports, ([name, cb]: any, origFunc: any) => {
|
||||
try {
|
||||
return origFunc(name, cb);
|
||||
} catch {
|
||||
return name;
|
||||
}
|
||||
});
|
||||
|
||||
patchedNativeComponentRegistry = true;
|
||||
}
|
||||
patchedNativeComponentRegistry = true;
|
||||
}
|
||||
|
||||
|
||||
// Hook DeveloperExperimentStore
|
||||
|
|
@ -141,100 +160,133 @@ function onModuleRequire(moduleExports: any, id: Metro.ModuleID) {
|
|||
if (!metroModules[id + inc]?.isInitialized) {
|
||||
blacklistModule(id + inc);
|
||||
}
|
||||
}
|
||||
|
||||
// Hindi timestamps moment
|
||||
if (moduleExports.isMoment) {
|
||||
instead("defineLocale", moduleExports, (args: [string], orig: (lcl: string) => string) => {
|
||||
const origLocale = moduleExports.locale();
|
||||
orig(...args);
|
||||
moduleExports.locale(origLocale);
|
||||
});
|
||||
}
|
||||
return Reflect.get(target, property, receiver);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const subs = moduleSubscriptions.get(Number(id));
|
||||
if (subs) {
|
||||
subs.forEach(s => s());
|
||||
moduleSubscriptions.delete(Number(id));
|
||||
if (!patchedImportTracker && moduleExports.fileFinishedImporting) {
|
||||
before("fileFinishedImporting", moduleExports, ([filePath]: [string]) => {
|
||||
if (_importingModuleId === -1 || !filePath) return;
|
||||
metroModules[_importingModuleId]!.__filePath = filePath;
|
||||
});
|
||||
patchedImportTracker = true;
|
||||
}
|
||||
|
||||
// Funny infinity recursion caused by a race condition
|
||||
if (!patchedInspectSource && window["__core-js_shared__"]) {
|
||||
const inspect = (f: unknown) =>
|
||||
typeof f === "function" && functionToString.apply(f, []);
|
||||
window["__core-js_shared__"].inspectSource = inspect;
|
||||
patchedInspectSource = true;
|
||||
}
|
||||
|
||||
//
|
||||
if (moduleExports.findHostInstance_DEPRECATED) {
|
||||
const prevExports = metroModules[id - 1]?.publicModule.exports;
|
||||
const inc = prevExports.default?.reactProfilingEnabled ? 1 : -1;
|
||||
if (!metroModules[id + inc]?.isInitialized) {
|
||||
blacklistModule(id + inc);
|
||||
}
|
||||
}
|
||||
|
||||
// Hindi timestamps moment
|
||||
if (moduleExports.isMoment) {
|
||||
instead(
|
||||
"defineLocale",
|
||||
moduleExports,
|
||||
(args: [string], orig: (lcl: string) => string) => {
|
||||
const origLocale = moduleExports.locale();
|
||||
orig(...args);
|
||||
moduleExports.locale(origLocale);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const subs = moduleSubscriptions.get(Number(id));
|
||||
if (subs) {
|
||||
subs.forEach((s) => s());
|
||||
moduleSubscriptions.delete(Number(id));
|
||||
}
|
||||
}
|
||||
|
||||
export function getImportingModuleId() {
|
||||
return _importingModuleId;
|
||||
return _importingModuleId;
|
||||
}
|
||||
|
||||
export function subscribeModule(id: number, cb: () => void): () => void {
|
||||
const subs = moduleSubscriptions.get(id) ?? new Set();
|
||||
const subs = moduleSubscriptions.get(id) ?? new Set();
|
||||
|
||||
subs.add(cb);
|
||||
moduleSubscriptions.set(id, subs);
|
||||
subs.add(cb);
|
||||
moduleSubscriptions.set(id, subs);
|
||||
|
||||
return () => subs.delete(cb);
|
||||
return () => subs.delete(cb);
|
||||
}
|
||||
|
||||
export function requireModule(id: Metro.ModuleID) {
|
||||
if (!metroModules[0]?.isInitialized) metroRequire(0);
|
||||
if (blacklistedIds.has(id)) return undefined;
|
||||
if (!metroModules[0]?.isInitialized) metroRequire(0);
|
||||
if (blacklistedIds.has(id)) return undefined;
|
||||
|
||||
if (Number(id) === -1) return require("@metro/polyfills/redesign");
|
||||
if (Number(id) === -1) return require("@metro/polyfills/redesign");
|
||||
|
||||
if (metroModules[id]?.isInitialized && !metroModules[id]?.hasError) {
|
||||
return metroRequire(id);
|
||||
}
|
||||
if (metroModules[id]?.isInitialized && !metroModules[id]?.hasError) {
|
||||
return metroRequire(id);
|
||||
}
|
||||
|
||||
// Disable Internal RN error reporting logic
|
||||
const originalHandler = ErrorUtils.getGlobalHandler();
|
||||
ErrorUtils.setGlobalHandler(noopHandler);
|
||||
// Disable Internal RN error reporting logic
|
||||
const originalHandler = ErrorUtils.getGlobalHandler();
|
||||
ErrorUtils.setGlobalHandler(noopHandler);
|
||||
|
||||
let moduleExports;
|
||||
try {
|
||||
moduleExports = metroRequire(id);
|
||||
} catch {
|
||||
blacklistModule(id);
|
||||
moduleExports = undefined;
|
||||
}
|
||||
let moduleExports;
|
||||
try {
|
||||
moduleExports = metroRequire(id);
|
||||
} catch {
|
||||
blacklistModule(id);
|
||||
moduleExports = undefined;
|
||||
}
|
||||
|
||||
// Done initializing! Now, revert our hacks
|
||||
ErrorUtils.setGlobalHandler(originalHandler);
|
||||
// Done initializing! Now, revert our hacks
|
||||
ErrorUtils.setGlobalHandler(originalHandler);
|
||||
|
||||
return moduleExports;
|
||||
return moduleExports;
|
||||
}
|
||||
|
||||
export function* getModules(uniq: string, all = false) {
|
||||
yield [-1, require("@metro/polyfills/redesign")];
|
||||
yield [-1, require("@metro/polyfills/redesign")];
|
||||
|
||||
let cache = getMetroCache().findIndex[uniq];
|
||||
if (all && !cache?.[`_${ModulesMapInternal.FULL_LOOKUP}`]) cache = undefined;
|
||||
if (cache?.[`_${ModulesMapInternal.NOT_FOUND}`]) return;
|
||||
let cache = getMetroCache().findIndex[uniq];
|
||||
if (all && !cache?.[`_${ModulesMapInternal.FULL_LOOKUP}`]) cache = undefined;
|
||||
if (cache?.[`_${ModulesMapInternal.NOT_FOUND}`]) return;
|
||||
|
||||
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 cache) {
|
||||
if (id[0] === "_") continue;
|
||||
const exports = requireModule(Number(id));
|
||||
if (isBadExports(exports)) continue;
|
||||
yield [id, exports];
|
||||
}
|
||||
|
||||
for (const id in metroModules) {
|
||||
const exports = requireModule(Number(id));
|
||||
if (isBadExports(exports)) continue;
|
||||
yield [id, exports];
|
||||
}
|
||||
for (const id in metroModules) {
|
||||
const exports = requireModule(Number(id));
|
||||
if (isBadExports(exports)) continue;
|
||||
yield [id, exports];
|
||||
}
|
||||
}
|
||||
|
||||
export function* getCachedPolyfillModules(name: string) {
|
||||
const cache = getMetroCache().polyfillIndex[name]!;
|
||||
const cache = getMetroCache().polyfillIndex[name]!;
|
||||
|
||||
for (const id in cache) {
|
||||
const exports = requireModule(Number(id));
|
||||
if (isBadExports(exports)) continue;
|
||||
yield [id, exports];
|
||||
}
|
||||
for (const id in cache) {
|
||||
const exports = requireModule(Number(id));
|
||||
if (isBadExports(exports)) continue;
|
||||
yield [id, exports];
|
||||
}
|
||||
|
||||
if (!cache[`_${ModulesMapInternal.FULL_LOOKUP}`]) {
|
||||
for (const id in metroModules) {
|
||||
const exports = requireModule(Number(id));
|
||||
if (isBadExports(exports)) continue;
|
||||
yield [id, exports];
|
||||
}
|
||||
if (!cache[`_${ModulesMapInternal.FULL_LOOKUP}`]) {
|
||||
for (const id in metroModules) {
|
||||
const exports = requireModule(Number(id));
|
||||
if (isBadExports(exports)) continue;
|
||||
yield [id, exports];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue