diff --git a/src/api/Notifications/Notifications.tsx b/src/api/Notifications/Notifications.tsx index 1350e5bd..96a3425b 100644 --- a/src/api/Notifications/Notifications.tsx +++ b/src/api/Notifications/Notifications.tsx @@ -18,7 +18,7 @@ import { Settings } from "@api/Settings"; import { Queue } from "@utils/Queue"; -import { ReactDOM } from "@webpack/common"; +import { createRoot } from "@webpack/common"; import type { ReactNode } from "react"; import type { Root } from "react-dom/client"; @@ -35,7 +35,7 @@ function getRoot() { const container = document.createElement("div"); container.id = "vc-notification-container"; document.body.append(container); - reactRoot = ReactDOM.createRoot(container); + reactRoot = createRoot(container); } return reactRoot; } diff --git a/src/equicordplugins/findReply/index.tsx b/src/equicordplugins/findReply/index.tsx index 8f7e88c4..9ce27e2c 100644 --- a/src/equicordplugins/findReply/index.tsx +++ b/src/equicordplugins/findReply/index.tsx @@ -21,7 +21,7 @@ import { disableStyle, enableStyle } from "@api/Styles"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; -import { ChannelStore, MessageStore, ReactDOM, Toasts } from "@webpack/common"; +import { ChannelStore, createRoot, MessageStore, Toasts } from "@webpack/common"; import Message from "discord-types/general/Message"; import { Root } from "react-dom/client"; @@ -101,7 +101,7 @@ export default definePlugin({ madeComponent = true; element = document.createElement("div"); document.querySelector("[class^=base_]")!.appendChild(element); - root = ReactDOM.createRoot(element); + root = createRoot(element); } root!.render(); } diff --git a/src/equicordplugins/iconViewer/utils.tsx b/src/equicordplugins/iconViewer/utils.tsx index 56e21d9d..eb3f9cdd 100644 --- a/src/equicordplugins/iconViewer/utils.tsx +++ b/src/equicordplugins/iconViewer/utils.tsx @@ -6,7 +6,7 @@ import { saveFile } from "@utils/web"; import { filters, findAll, findByPropsLazy, waitFor } from "@webpack"; -import { React, ReactDOM } from "@webpack/common"; +import { createRoot, React, ReactDOM } from "@webpack/common"; import * as t from "@webpack/types"; export let _cssColors: string[] = []; export type IconsDef = { [k: string]: t.Icon; }; @@ -82,7 +82,7 @@ export function saveIcon(iconName: string, icon: EventTarget & SVGSVGElement | E export function convertComponentToHtml(component?: React.ReactElement): string { const container = document.createElement("div"); - const root = ReactDOM.createRoot(container); + const root = createRoot(container); ReactDOM.flushSync(() => root.render(component)); const content = container.innerHTML; diff --git a/src/equicordplugins/jumpscare/index.tsx b/src/equicordplugins/jumpscare/index.tsx index 8dec4fe2..67ddcf7c 100644 --- a/src/equicordplugins/jumpscare/index.tsx +++ b/src/equicordplugins/jumpscare/index.tsx @@ -9,7 +9,7 @@ import "./styles.css"; import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { FluxDispatcher, ReactDOM, useEffect, useState } from "@webpack/common"; +import { createRoot, FluxDispatcher, useEffect, useState } from "@webpack/common"; import { Root } from "react-dom/client"; let jumpscareRoot: Root | undefined; @@ -38,7 +38,7 @@ function getJumpscareRoot(): Root { element.id = "jumpscare-root"; element.classList.add("jumpscare-root"); document.body.append(element); - jumpscareRoot = ReactDOM.createRoot(element); + jumpscareRoot = createRoot(element); } return jumpscareRoot; diff --git a/src/equicordplugins/toastNotifications/components/Notifications.tsx b/src/equicordplugins/toastNotifications/components/Notifications.tsx index 204ac6e3..7e40ef2a 100644 --- a/src/equicordplugins/toastNotifications/components/Notifications.tsx +++ b/src/equicordplugins/toastNotifications/components/Notifications.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { React, ReactDOM } from "@webpack/common"; +import { createRoot, React } from "@webpack/common"; import type { JSX, ReactNode } from "react"; import type { Root } from "react-dom/client"; @@ -32,7 +32,7 @@ function getNotificationContainer() { const container = document.createElement("div"); container.id = "toastnotifications-container"; document.body.append(container); - RootContainer = ReactDOM.createRoot(container); + RootContainer = createRoot(container); } return RootContainer; diff --git a/src/plugins/consoleShortcuts/index.ts b/src/plugins/consoleShortcuts/index.ts index 57461555..813653a4 100644 --- a/src/plugins/consoleShortcuts/index.ts +++ b/src/plugins/consoleShortcuts/index.ts @@ -136,7 +136,7 @@ function makeShortcuts() { }); } - const root = Common.ReactDOM.createRoot(doc.body.appendChild(document.createElement("div"))); + const root = Common.createRoot(doc.body.appendChild(document.createElement("div"))); root.render(Common.React.createElement(component, props)); doc.addEventListener("close", () => root.unmount(), { once: true }); diff --git a/src/plugins/imageZoom/index.tsx b/src/plugins/imageZoom/index.tsx index d7e8d487..56e1d4a2 100644 --- a/src/plugins/imageZoom/index.tsx +++ b/src/plugins/imageZoom/index.tsx @@ -23,7 +23,7 @@ import { debounce } from "@shared/debounce"; import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; -import { Menu, ReactDOM } from "@webpack/common"; +import { createRoot, Menu } from "@webpack/common"; import { JSX } from "react"; import type { Root } from "react-dom/client"; @@ -242,7 +242,7 @@ export default definePlugin({ if (instance.props.id === ELEMENT_ID) { if (!this.currentMagnifierElement) { this.currentMagnifierElement = ; - this.root = ReactDOM.createRoot(this.element!); + this.root = createRoot(this.element!); this.root.render(this.currentMagnifierElement); } } diff --git a/src/plugins/reactErrorDecoder/index.ts b/src/plugins/reactErrorDecoder/index.ts index 9e2e5dc5..45ab297a 100644 --- a/src/plugins/reactErrorDecoder/index.ts +++ b/src/plugins/reactErrorDecoder/index.ts @@ -20,7 +20,7 @@ import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; import { React } from "@webpack/common"; -let ERROR_CODES: any; +let ERROR_CODES: Record | undefined; export default definePlugin({ name: "ReactErrorDecoder", @@ -28,13 +28,12 @@ export default definePlugin({ authors: [Devs.Cyn, Devs.maisymoe], patches: [ { - find: '"https://reactjs.org/docs/error-decoder.html?invariant="', + find: "React has blocked a javascript: URL as a security precaution.", replacement: { - match: /(function .\(.\)){(for\(var .="https:\/\/reactjs\.org\/docs\/error-decoder\.html\?invariant="\+.,.=1;. - `${func}{var decoded=$self.decodeError.apply(null, arguments);if(decoded)return decoded;${original}}`, - }, - }, + match: /"https:\/\/react.dev\/errors\/"\+\i;/, + replace: "$&const vcDecodedError=$self.decodeError(...arguments);if(vcDecodedError)return vcDecodedError;" + } + } ], async start() { @@ -56,5 +55,5 @@ export default definePlugin({ index++; return arg; }); - }, + } }); diff --git a/src/webpack/common/react.ts b/src/webpack/common/react.ts index bd5b1b53..b8b0e753 100644 --- a/src/webpack/common/react.ts +++ b/src/webpack/common/react.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { findByPropsLazy, waitFor } from "@webpack"; +import { findByCodeLazy, findByPropsLazy, waitFor } from "@webpack"; export let React: typeof import("react"); export let useState: typeof React.useState; @@ -27,7 +27,9 @@ export let useRef: typeof React.useRef; export let useReducer: typeof React.useReducer; export let useCallback: typeof React.useCallback; -export const ReactDOM: typeof import("react-dom") & typeof import("react-dom/client") = findByPropsLazy("createPortal"); +export const ReactDOM: typeof import("react-dom") = findByPropsLazy("createPortal"); +// 299 is an error code used in createRoot and createPortal +export const createRoot: typeof import("react-dom/client").createRoot = findByCodeLazy("(299));", ".onRecoverableError"); waitFor("useState", m => { React = m;