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

View file

@ -360,7 +360,7 @@ export default definePlugin({
{
// Render editHistory in the deepest div for message content
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/>.
*/
import ErrorBoundary from "@components/ErrorBoundary";
import { classes } from "@utils/misc";
import { findByPropsLazy } from "@webpack";
import { UserStore } from "@webpack/common";
@ -39,17 +40,17 @@ function shouldShow(message: Message): boolean {
return true;
}
export function PronounsChatComponentWrapper({ message }: { message: Message; }) {
export const PronounsChatComponentWrapper = ErrorBoundary.wrap(({ message }: { message: Message; }) => {
return shouldShow(message)
? <PronounsChatComponent message={message} />
: null;
}
}, { noop: true });
export function CompactPronounsChatComponentWrapper({ message }: { message: Message; }) {
export const CompactPronounsChatComponentWrapper = ErrorBoundary.wrap(({ message }: { message: Message; }) => {
return shouldShow(message)
? <CompactPronounsChatComponent message={message} />
: null;
}
}, { noop: true });
function PronounsChatComponent({ message }: { message: Message; }) {
const [result] = useFormattedPronouns(message.author.id);
@ -63,7 +64,7 @@ function PronounsChatComponent({ message }: { message: Message; }) {
: null;
}
export function CompactPronounsChatComponent({ message }: { message: Message; }) {
export const CompactPronounsChatComponent = ErrorBoundary.wrap(({ message }: { message: Message; }) => {
const [result] = useFormattedPronouns(message.author.id);
return result
@ -73,4 +74,4 @@ export function CompactPronounsChatComponent({ message }: { message: Message; })
> {result}</span>
)
: null;
}
}, { noop: true });

View file

@ -41,7 +41,7 @@ export default definePlugin({
find: "showCommunicationDisabledStyles",
replacement: {
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)
@ -49,7 +49,7 @@ export default definePlugin({
find: "showCommunicationDisabledStyles",
replacement: {
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

View file

@ -16,7 +16,7 @@
* 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 { LazyComponent } from "./react";
@ -132,12 +132,7 @@ export const ModalContent = LazyComponent(() => Modals.ModalContent);
export const ModalFooter = LazyComponent(() => Modals.ModalFooter);
export const ModalCloseButton = LazyComponent(() => Modals.ModalCloseButton);
const ModalAPI = mapMangledModuleLazy("onCloseRequest:null!=", {
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,")
});
const ModalAPI = findByPropsLazy("openModalLazy");
/**
* 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/>.
*/
import { proxyLazy } from "@utils/lazy";
import type * as Stores from "discord-types/stores";
// 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 * as t from "./types/stores";
@ -83,7 +84,14 @@ export const useStateFromStores: <T>(
idk?: any,
isEqual?: (old: T, newer: T) => boolean
) => 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("UserStore", s => UserStore = s);

View file

@ -16,10 +16,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { proxyLazy } from "@utils/lazy";
import type { User } from "discord-types/general";
// 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";
export let FluxDispatcher: t.FluxDispatcher;
@ -126,4 +127,11 @@ waitFor("parseTopic", m => Parser = m);
export let SettingsRouter: any;
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, {
get: () => webpackChunk,
set: v => {
if (v?.push !== Array.prototype.push) {
if (v?.push !== Array.prototype.push && _initWebpack(v)) {
logger.info(`Patching ${WEBPACK_CHUNK}.push`);
_initWebpack(v);
patchPush();
// @ts-ignore
delete window[WEBPACK_CHUNK];
@ -85,10 +84,9 @@ function patchPush() {
logger.error("Error in patched chunk", err);
return void originalMod(module, exports, require);
}
// There are (at the time of writing) 11 modules exporting the window
// Make these non enumerable to improve webpack search performance
if (module.exports === window) {
if (exports === window) {
Object.defineProperty(require.c, id, {
value: require.c[id],
enumerable: false,

View file

@ -62,9 +62,50 @@ export type CallbackFn = (mod: any, id: number) => void;
export function _initWebpack(instance: typeof window.webpackChunkdiscord_app) {
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;
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) {