Fix canary crashing (#1833)

This commit is contained in:
V 2023-10-25 00:17:11 +02:00 committed by GitHub
parent 4a2def03e7
commit 1a1d9b07e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 87 additions and 36 deletions

View file

@ -63,26 +63,26 @@ export default definePlugin({
replacement: { replacement: {
get match() { get match() {
switch (Settings.plugins.Settings.settingsLocation) { switch (Settings.plugins.Settings.settingsLocation) {
case "top": return /\{section:(\i)\.ID\.HEADER,\s*label:(\i)\.\i\.Messages\.USER_SETTINGS\}/; case "top": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.USER_SETTINGS\}/;
case "aboveNitro": return /\{section:(\i)\.ID\.HEADER,\s*label:(\i)\.\i\.Messages\.BILLING_SETTINGS\}/; case "aboveNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.BILLING_SETTINGS\}/;
case "belowNitro": return /\{section:(\i)\.ID\.HEADER,\s*label:(\i)\.\i\.Messages\.APP_SETTINGS\}/; case "belowNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.APP_SETTINGS\}/;
case "belowActivity": return /(?<=\{section:(\i)\.ID\.DIVIDER},)\{section:"changelog"/; case "belowActivity": return /(?<=\{section:(\i\.\i)\.DIVIDER},)\{section:"changelog"/;
case "bottom": return /\{section:(\i)\.ID\.CUSTOM,\s*element:.+?}/; case "bottom": return /\{section:(\i\.\i)\.CUSTOM,\s*element:.+?}/;
case "aboveActivity": case "aboveActivity":
default: default:
return /\{section:(\i)\.ID\.HEADER,\s*label:(\i)\.\i\.Messages\.ACTIVITY_SETTINGS\}/; return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.ACTIVITY_SETTINGS\}/;
} }
}, },
replace: "...$self.makeSettingsCategories($1),$&" replace: "...$self.makeSettingsCategories($1),$&"
} }
}], }],
customSections: [] as ((ID: Record<string, unknown>) => any)[], customSections: [] as ((SectionTypes: Record<string, unknown>) => any)[],
makeSettingsCategories({ ID }: { ID: Record<string, unknown>; }) { makeSettingsCategories(SectionTypes: Record<string, unknown>) {
return [ return [
{ {
section: ID.HEADER, section: SectionTypes.HEADER,
label: "Vencord", label: "Vencord",
className: "vc-settings-header" className: "vc-settings-header"
}, },
@ -128,9 +128,9 @@ export default definePlugin({
element: require("@components/VencordSettings/PatchHelperTab").default, element: require("@components/VencordSettings/PatchHelperTab").default,
className: "vc-patch-helper" className: "vc-patch-helper"
}, },
...this.customSections.map(func => func(ID)), ...this.customSections.map(func => func(SectionTypes)),
{ {
section: ID.DIVIDER section: SectionTypes.DIVIDER
} }
].filter(Boolean); ].filter(Boolean);
}, },

View file

@ -360,7 +360,7 @@ export default definePlugin({
{ {
// Render editHistory in the deepest div for message content // Render editHistory in the deepest div for message content
match: /(\)\("div",\{id:.+?children:\[)/, match: /(\)\("div",\{id:.+?children:\[)/,
replace: "$1 (arguments[0].message.editHistory.length > 0 ? arguments[0].message.editHistory.map(edit => $self.renderEdit(edit)) : null), " replace: "$1 (arguments[0].message.editHistory?.length > 0 ? arguments[0].message.editHistory.map(edit => $self.renderEdit(edit)) : null), "
} }
] ]
}, },

View file

@ -16,6 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import ErrorBoundary from "@components/ErrorBoundary";
import { classes } from "@utils/misc"; import { classes } from "@utils/misc";
import { findByPropsLazy } from "@webpack"; import { findByPropsLazy } from "@webpack";
import { UserStore } from "@webpack/common"; import { UserStore } from "@webpack/common";
@ -39,17 +40,17 @@ function shouldShow(message: Message): boolean {
return true; return true;
} }
export function PronounsChatComponentWrapper({ message }: { message: Message; }) { export const PronounsChatComponentWrapper = ErrorBoundary.wrap(({ message }: { message: Message; }) => {
return shouldShow(message) return shouldShow(message)
? <PronounsChatComponent message={message} /> ? <PronounsChatComponent message={message} />
: null; : null;
} }, { noop: true });
export function CompactPronounsChatComponentWrapper({ message }: { message: Message; }) { export const CompactPronounsChatComponentWrapper = ErrorBoundary.wrap(({ message }: { message: Message; }) => {
return shouldShow(message) return shouldShow(message)
? <CompactPronounsChatComponent message={message} /> ? <CompactPronounsChatComponent message={message} />
: null; : null;
} }, { noop: true });
function PronounsChatComponent({ message }: { message: Message; }) { function PronounsChatComponent({ message }: { message: Message; }) {
const [result] = useFormattedPronouns(message.author.id); const [result] = useFormattedPronouns(message.author.id);
@ -63,7 +64,7 @@ function PronounsChatComponent({ message }: { message: Message; }) {
: null; : null;
} }
export function CompactPronounsChatComponent({ message }: { message: Message; }) { export const CompactPronounsChatComponent = ErrorBoundary.wrap(({ message }: { message: Message; }) => {
const [result] = useFormattedPronouns(message.author.id); const [result] = useFormattedPronouns(message.author.id);
return result return result
@ -73,4 +74,4 @@ export function CompactPronounsChatComponent({ message }: { message: Message; })
> {result}</span> > {result}</span>
) )
: null; : null;
} }, { noop: true });

View file

@ -41,7 +41,7 @@ export default definePlugin({
find: "showCommunicationDisabledStyles", find: "showCommunicationDisabledStyles",
replacement: { replacement: {
match: /("span",{id:\i,className:\i,children:\i}\))/, match: /("span",{id:\i,className:\i,children:\i}\))/,
replace: "$1, $self.CompactPronounsChatComponentWrapper(e)" replace: "$1, $self.CompactPronounsChatComponentWrapper(arguments[0])"
} }
}, },
// Patch the chat timestamp element (normal mode) // Patch the chat timestamp element (normal mode)
@ -49,7 +49,7 @@ export default definePlugin({
find: "showCommunicationDisabledStyles", find: "showCommunicationDisabledStyles",
replacement: { replacement: {
match: /(?<=return\s*\(0,\i\.jsxs?\)\(.+!\i&&)(\(0,\i.jsxs?\)\(.+?\{.+?\}\))/, match: /(?<=return\s*\(0,\i\.jsxs?\)\(.+!\i&&)(\(0,\i.jsxs?\)\(.+?\{.+?\}\))/,
replace: "[$1, $self.PronounsChatComponentWrapper(e)]" replace: "[$1, $self.PronounsChatComponentWrapper(arguments[0])]"
} }
}, },
// Patch the profile popout username header to use our pronoun hook instead of Discord's pronouns // Patch the profile popout username header to use our pronoun hook instead of Discord's pronouns

View file

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { filters, findByCode, mapMangledModuleLazy } from "@webpack"; import { filters, findByCode, findByPropsLazy, mapMangledModuleLazy } from "@webpack";
import type { ComponentType, PropsWithChildren, ReactNode, Ref } from "react"; import type { ComponentType, PropsWithChildren, ReactNode, Ref } from "react";
import { LazyComponent } from "./react"; import { LazyComponent } from "./react";
@ -132,12 +132,7 @@ export const ModalContent = LazyComponent(() => Modals.ModalContent);
export const ModalFooter = LazyComponent(() => Modals.ModalFooter); export const ModalFooter = LazyComponent(() => Modals.ModalFooter);
export const ModalCloseButton = LazyComponent(() => Modals.ModalCloseButton); export const ModalCloseButton = LazyComponent(() => Modals.ModalCloseButton);
const ModalAPI = mapMangledModuleLazy("onCloseRequest:null!=", { const ModalAPI = findByPropsLazy("openModalLazy");
openModal: filters.byCode("onCloseRequest:null!="),
closeModal: filters.byCode("onCloseCallback&&"),
openModalLazy: m => m?.length === 1 && filters.byCode(".apply(this,arguments)")(m),
closeAllModals: filters.byCode(".value.key,")
});
/** /**
* Wait for the render promise to resolve, then open a modal with it. * Wait for the render promise to resolve, then open a modal with it.

View file

@ -16,10 +16,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { proxyLazy } from "@utils/lazy";
import type * as Stores from "discord-types/stores"; import type * as Stores from "discord-types/stores";
// eslint-disable-next-line path-alias/no-relative // eslint-disable-next-line path-alias/no-relative
import { filters, findByCodeLazy, findByPropsLazy, mapMangledModuleLazy } from "../webpack"; import { filters, findByCode, findByProps, findByPropsLazy, mapMangledModuleLazy } from "../webpack";
import { waitForStore } from "./internal"; import { waitForStore } from "./internal";
import * as t from "./types/stores"; import * as t from "./types/stores";
@ -83,7 +84,14 @@ export const useStateFromStores: <T>(
idk?: any, idk?: any,
isEqual?: (old: T, newer: T) => boolean isEqual?: (old: T, newer: T) => boolean
) => T ) => T
= findByCodeLazy("useStateFromStores"); // FIXME: hack to support old stable and new canary
= proxyLazy(() => {
try {
return findByProps("useStateFromStores").useStateFromStores;
} catch {
return findByCode('("useStateFromStores")');
}
});
waitForStore("DraftStore", s => DraftStore = s); waitForStore("DraftStore", s => DraftStore = s);
waitForStore("UserStore", s => UserStore = s); waitForStore("UserStore", s => UserStore = s);

View file

@ -16,10 +16,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { proxyLazy } from "@utils/lazy";
import type { User } from "discord-types/general"; import type { User } from "discord-types/general";
// eslint-disable-next-line path-alias/no-relative // eslint-disable-next-line path-alias/no-relative
import { _resolveReady, filters, findByCodeLazy, findByPropsLazy, findLazy, mapMangledModuleLazy, waitFor } from "../webpack"; import { _resolveReady, filters, find, findByCodeLazy, findByPropsLazy, findLazy, mapMangledModuleLazy, waitFor } from "../webpack";
import type * as t from "./types/utils"; import type * as t from "./types/utils";
export let FluxDispatcher: t.FluxDispatcher; export let FluxDispatcher: t.FluxDispatcher;
@ -126,4 +127,11 @@ waitFor("parseTopic", m => Parser = m);
export let SettingsRouter: any; export let SettingsRouter: any;
waitFor(["open", "saveAccountChanges"], m => SettingsRouter = m); waitFor(["open", "saveAccountChanges"], m => SettingsRouter = m);
export const PermissionsBits: t.PermissionsBits = findLazy(m => typeof m.ADMINISTRATOR === "bigint"); // FIXME: hack to support old stable and new canary
export const PermissionsBits: t.PermissionsBits = proxyLazy(() => {
try {
return find(m => m.Permissions?.ADMINISTRATOR).Permissions;
} catch {
return find(m => typeof m.ADMINISTRATOR === "bigint");
}
});

View file

@ -36,9 +36,8 @@ if (window[WEBPACK_CHUNK]) {
Object.defineProperty(window, WEBPACK_CHUNK, { Object.defineProperty(window, WEBPACK_CHUNK, {
get: () => webpackChunk, get: () => webpackChunk,
set: v => { set: v => {
if (v?.push !== Array.prototype.push) { if (v?.push !== Array.prototype.push && _initWebpack(v)) {
logger.info(`Patching ${WEBPACK_CHUNK}.push`); logger.info(`Patching ${WEBPACK_CHUNK}.push`);
_initWebpack(v);
patchPush(); patchPush();
// @ts-ignore // @ts-ignore
delete window[WEBPACK_CHUNK]; delete window[WEBPACK_CHUNK];
@ -85,10 +84,9 @@ function patchPush() {
logger.error("Error in patched chunk", err); logger.error("Error in patched chunk", err);
return void originalMod(module, exports, require); return void originalMod(module, exports, require);
} }
// 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 (module.exports === window) { if (exports === window) {
Object.defineProperty(require.c, id, { Object.defineProperty(require.c, id, {
value: require.c[id], value: require.c[id],
enumerable: false, enumerable: false,

View file

@ -62,9 +62,50 @@ export type CallbackFn = (mod: any, id: number) => void;
export function _initWebpack(instance: typeof window.webpackChunkdiscord_app) { export function _initWebpack(instance: typeof window.webpackChunkdiscord_app) {
if (cache !== void 0) throw "no."; if (cache !== void 0) throw "no.";
wreq = instance.push([[Symbol("Vencord")], {}, r => r]); instance.push([[Symbol("Vencord")], {}, r => wreq = r]);
if (!wreq) return false;
cache = wreq.c; cache = wreq.c;
instance.pop(); instance.pop();
for (const id in cache) {
const { exports } = cache[id];
if (!exports) continue;
const numberId = Number(id);
for (const callback of listeners) {
try {
callback(exports, numberId);
} catch (err) {
logger.error("Error in webpack listener", err);
}
}
for (const [filter, callback] of subscriptions) {
try {
if (filter(exports)) {
subscriptions.delete(filter);
callback(exports, numberId);
} else if (typeof exports === "object") {
if (exports.default && filter(exports.default)) {
subscriptions.delete(filter);
callback(exports.default, numberId);
}
for (const nested in exports) if (nested.length <= 3) {
if (exports[nested] && filter(exports[nested])) {
subscriptions.delete(filter);
callback(exports[nested], numberId);
}
}
}
} catch (err) {
logger.error("Error while firing callback for webpack chunk", err);
}
}
}
return true;
} }
if (IS_DEV && IS_DISCORD_DESKTOP) { if (IS_DEV && IS_DISCORD_DESKTOP) {