From 306890aa139995947f5cb02f92ca40aa966e7fbf Mon Sep 17 00:00:00 2001
From: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Date: Wed, 12 Feb 2025 14:03:18 -0300
Subject: [PATCH 1/2] WebpackPatcher: Use way less closures (#3217)
---
eslint.config.mjs | 2 +-
scripts/generateReport.ts | 4 -
src/debug/loadLazyChunks.ts | 6 +-
src/debug/runReporter.ts | 6 +-
src/plugins/_core/noTrack.ts | 2 +-
src/plugins/index.ts | 3 +-
src/webpack/patchWebpack.ts | 445 +++++++++++++++++------------------
src/webpack/webpack.ts | 2 +-
src/webpack/wreq.d.ts | 6 +-
tsconfig.json | 4 +-
10 files changed, 236 insertions(+), 244 deletions(-)
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 67327b938..d59c37532 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -134,7 +134,7 @@ export default tseslint.config(
"no-unsafe-optional-chaining": "error",
"no-useless-backreference": "error",
"use-isnan": "error",
- "prefer-const": "error",
+ "prefer-const": ["error", { destructuring: "all" }],
"prefer-spread": "error",
// Plugin Rules
diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts
index 5cab1b46e..7bfda763b 100644
--- a/scripts/generateReport.ts
+++ b/scripts/generateReport.ts
@@ -16,11 +16,7 @@
* along with this program. If not, see .
*/
-/* eslint-disable no-fallthrough */
-
-// eslint-disable-next-line spaced-comment
///
-// eslint-disable-next-line spaced-comment
///
import { createHmac } from "crypto";
diff --git a/src/debug/loadLazyChunks.ts b/src/debug/loadLazyChunks.ts
index 212078553..427acd11a 100644
--- a/src/debug/loadLazyChunks.ts
+++ b/src/debug/loadLazyChunks.ts
@@ -8,7 +8,7 @@ import { Logger } from "@utils/Logger";
import { canonicalizeMatch } from "@utils/patches";
import * as Webpack from "@webpack";
import { wreq } from "@webpack";
-import { AnyModuleFactory, ModuleFactory } from "webpack";
+import { AnyModuleFactory, ModuleFactory } from "@webpack/wreq.d";
export async function loadLazyChunks() {
const LazyChunkLoaderLogger = new Logger("LazyChunkLoader");
@@ -140,8 +140,8 @@ export async function loadLazyChunks() {
}
Webpack.factoryListeners.add(factoryListener);
- for (const factoryId in wreq.m) {
- factoryListener(wreq.m[factoryId]);
+ for (const moduleId in wreq.m) {
+ factoryListener(wreq.m[moduleId]);
}
await chunksSearchingDone;
diff --git a/src/debug/runReporter.ts b/src/debug/runReporter.ts
index 8d4194bc4..7a14609e1 100644
--- a/src/debug/runReporter.ts
+++ b/src/debug/runReporter.ts
@@ -6,9 +6,9 @@
import { Logger } from "@utils/Logger";
import * as Webpack from "@webpack";
-import { addPatch, patches } from "plugins";
-import { getBuildNumber } from "webpack/patchWebpack";
+import { getBuildNumber, patchTimings } from "@webpack/patcher";
+import { addPatch, patches } from "../plugins";
import { loadLazyChunks } from "./loadLazyChunks";
async function runReporter() {
@@ -51,7 +51,7 @@ async function runReporter() {
}
}
- for (const [plugin, moduleId, match, totalTime] of Vencord.WebpackPatcher.patchTimings) {
+ for (const [plugin, moduleId, match, totalTime] of patchTimings) {
if (totalTime > 5) {
new Logger("WebpackInterceptor").warn(`Patch by ${plugin} took ${Math.round(totalTime * 100) / 100}ms (Module id is ${String(moduleId)}): ${match}`);
}
diff --git a/src/plugins/_core/noTrack.ts b/src/plugins/_core/noTrack.ts
index 58d8d42a3..30920a067 100644
--- a/src/plugins/_core/noTrack.ts
+++ b/src/plugins/_core/noTrack.ts
@@ -20,7 +20,7 @@ import { definePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants";
import { Logger } from "@utils/Logger";
import definePlugin, { OptionType, StartAt } from "@utils/types";
-import { WebpackRequire } from "webpack";
+import { WebpackRequire } from "@webpack/wreq.d";
const settings = definePluginSettings({
disableAnalytics: {
diff --git a/src/plugins/index.ts b/src/plugins/index.ts
index e1899b743..4a2688681 100644
--- a/src/plugins/index.ts
+++ b/src/plugins/index.ts
@@ -31,6 +31,7 @@ import { Logger } from "@utils/Logger";
import { canonicalizeFind, canonicalizeReplacement } from "@utils/patches";
import { Patch, Plugin, PluginDef, ReporterTestable, StartAt } from "@utils/types";
import { FluxDispatcher } from "@webpack/common";
+import { patches } from "@webpack/patcher";
import { FluxEvents } from "@webpack/types";
import Plugins from "~plugins";
@@ -41,7 +42,7 @@ const logger = new Logger("PluginManager", "#a6d189");
export const PMLogger = logger;
export const plugins = Plugins;
-export const patches = [] as Patch[];
+export { patches };
/** Whether we have subscribed to flux events of all the enabled plugins when FluxDispatcher was ready */
let enabledPluginsSubscribedFlux = false;
diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts
index 870362373..14c1888c9 100644
--- a/src/webpack/patchWebpack.ts
+++ b/src/webpack/patchWebpack.ts
@@ -9,32 +9,23 @@ import { makeLazy } from "@utils/lazy";
import { Logger } from "@utils/Logger";
import { interpolateIfDefined } from "@utils/misc";
import { canonicalizeReplacement } from "@utils/patches";
-import { PatchReplacement } from "@utils/types";
+import { Patch, PatchReplacement } from "@utils/types";
import { traceFunctionWithResults } from "../debug/Tracer";
-import { patches } from "../plugins";
-import { _initWebpack, _shouldIgnoreModule, AnyModuleFactory, AnyWebpackRequire, factoryListeners, findModuleId, MaybeWrappedModuleFactory, ModuleExports, moduleListeners, waitForSubscriptions, WebpackRequire, WrappedModuleFactory, wreq } from ".";
+import { _initWebpack, _shouldIgnoreModule, factoryListeners, findModuleId, moduleListeners, waitForSubscriptions, wreq } from "./webpack";
+import { AnyModuleFactory, AnyWebpackRequire, MaybePatchedModuleFactory, ModuleExports, PatchedModuleFactory, WebpackRequire } from "./wreq.d";
+
+export const patches = [] as Patch[];
export const SYM_ORIGINAL_FACTORY = Symbol("WebpackPatcher.originalFactory");
export const SYM_PATCHED_SOURCE = Symbol("WebpackPatcher.patchedSource");
export const SYM_PATCHED_BY = Symbol("WebpackPatcher.patchedBy");
-/** A set with all the Webpack instances */
export const allWebpackInstances = new Set();
-export const patchTimings = [] as Array<[plugin: string, moduleId: PropertyKey, match: string | RegExp, totalTime: number]>;
-const logger = new Logger("WebpackInterceptor", "#8caaee");
-/** Whether we tried to fallback to factory WebpackRequire, or disabled patches */
-let wreqFallbackApplied = false;
-/** Whether we should be patching factories.
- *
- * This should be disabled if we start searching for the module to get the build number, and then resumed once it's done.
- * */
-let shouldPatchFactories = true;
+export const patchTimings = [] as Array<[plugin: string, moduleId: PropertyKey, match: PatchReplacement["match"], totalTime: number]>;
export const getBuildNumber = makeLazy(() => {
try {
- shouldPatchFactories = false;
-
try {
if (wreq.m[128014]?.toString().includes("Trying to open a changelog for an invalid build number")) {
const hardcodedGetBuildNumber = wreq(128014).b as () => number;
@@ -59,13 +50,23 @@ export const getBuildNumber = makeLazy(() => {
return typeof buildNumber === "number" ? buildNumber : -1;
} catch {
return -1;
- } finally {
- shouldPatchFactories = true;
}
});
-type Define = typeof Reflect.defineProperty;
-const define: Define = (target, p, attributes) => {
+export function getFactoryPatchedSource(moduleId: PropertyKey, webpackRequire = wreq as AnyWebpackRequire) {
+ return webpackRequire.m[moduleId]?.[SYM_PATCHED_SOURCE];
+}
+
+export function getFactoryPatchedBy(moduleId: PropertyKey, webpackRequire = wreq as AnyWebpackRequire) {
+ return webpackRequire.m[moduleId]?.[SYM_PATCHED_BY];
+}
+
+const logger = new Logger("WebpackInterceptor", "#8caaee");
+
+/** Whether we tried to fallback to the WebpackRequire of the factory, or disabled patches */
+let wreqFallbackApplied = false;
+
+const define: typeof Reflect.defineProperty = (target, p, attributes) => {
if (Object.hasOwn(attributes, "value")) {
attributes.writable = true;
}
@@ -77,22 +78,17 @@ const define: Define = (target, p, attributes) => {
});
};
-export function getOriginalFactory(id: PropertyKey, webpackRequire = wreq as AnyWebpackRequire) {
- const moduleFactory = webpackRequire.m[id];
- return (moduleFactory?.[SYM_ORIGINAL_FACTORY] ?? moduleFactory) as AnyModuleFactory | undefined;
-}
+// wreq.m is the Webpack object containing module factories. It is pre-populated with factories, and is also populated via webpackGlobal.push
+// We use this setter to intercept when wreq.m is defined and apply patching to its factories.
-export function getFactoryPatchedSource(id: PropertyKey, webpackRequire = wreq as AnyWebpackRequire) {
- return webpackRequire.m[id]?.[SYM_PATCHED_SOURCE];
-}
+// Factories can be patched in two ways. Eagerly or lazily.
+// If we are patching eagerly, pre-populated factories are patched immediately and new factories are patched when set.
+// Else, we only patch them when called.
-export function getFactoryPatchedBy(id: PropertyKey, webpackRequire = wreq as AnyWebpackRequire) {
- return webpackRequire.m[id]?.[SYM_PATCHED_BY];
-}
+// Factories are always wrapped in a proxy, which allows us to intercept the call to them, patch if they werent eagerly patched,
+// and call them with our wrapper which notifies our listeners.
-// wreq.m is the Webpack object containing module factories. It is pre-populated with module factories, and is also populated via webpackGlobal.push
-// We use this setter to intercept when wreq.m is defined and apply the patching in its module factories.
-// We wrap wreq.m with our proxy, which is responsible for patching the module factories when they are set, or defining getters for the patched versions.
+// wreq.m is also wrapped in a proxy to intercept when new factories are set, patch them eargely, if enabled, and wrap them in the factory proxy.
// If this is the main Webpack, we also set up the internal references to WebpackRequire.
define(Function.prototype, "m", {
@@ -131,13 +127,17 @@ define(Function.prototype, "m", {
const setterTimeout = setTimeout(() => Reflect.deleteProperty(this, "e"), 0);
// Patch the pre-populated factories
- for (const id in originalModules) {
- if (updateExistingFactory(originalModules, id, originalModules[id], true)) {
+ for (const moduleId in originalModules) {
+ const originalFactory = originalModules[moduleId];
+
+ if (updateExistingFactory(originalModules, moduleId, originalFactory, originalModules, true)) {
continue;
}
- notifyFactoryListeners(originalModules[id]);
- defineModulesFactoryGetter(id, Settings.eagerPatches && shouldPatchFactories ? wrapAndPatchFactory(id, originalModules[id]) : originalModules[id]);
+ notifyFactoryListeners(moduleId, originalFactory);
+
+ const proxiedFactory = new Proxy(Settings.eagerPatches ? patchFactory(moduleId, originalFactory) : originalFactory, moduleFactoryHandler);
+ define(originalModules, moduleId, { value: proxiedFactory });
}
define(originalModules, Symbol.toStringTag, {
@@ -145,7 +145,6 @@ define(Function.prototype, "m", {
enumerable: false
});
- // The proxy responsible for patching the module factories when they are set, or defining getters for the patched versions
const proxiedModuleFactories = new Proxy(originalModules, moduleFactoriesHandler);
/*
If Webpack ever decides to set module factories using the variable of the modules object directly, instead of wreq.m, switch the proxy to the prototype
@@ -156,6 +155,7 @@ define(Function.prototype, "m", {
}
});
+// The proxy for patching eagerly and/or wrapping factories in their proxy.
const moduleFactoriesHandler: ProxyHandler = {
/*
If Webpack ever decides to set module factories using the variable of the modules object directly instead of wreq.m, we need to switch the proxy to the prototype
@@ -172,57 +172,96 @@ const moduleFactoriesHandler: ProxyHandler = {
},
*/
- // The set trap for patching or defining getters for the module factories when new module factories are loaded
set(target, p, newValue, receiver) {
- if (updateExistingFactory(target, p, newValue)) {
+ if (updateExistingFactory(target, p, newValue, receiver)) {
return true;
}
- notifyFactoryListeners(newValue);
- defineModulesFactoryGetter(p, Settings.eagerPatches && shouldPatchFactories ? wrapAndPatchFactory(p, newValue) : newValue);
+ notifyFactoryListeners(p, newValue);
- return true;
+ const proxiedFactory = new Proxy(Settings.eagerPatches ? patchFactory(p, newValue) : newValue, moduleFactoryHandler);
+ return Reflect.set(target, p, proxiedFactory, receiver);
+ }
+};
+
+// The proxy for patching lazily and/or running factories with our wrapper.
+const moduleFactoryHandler: ProxyHandler = {
+ apply(target, thisArg: unknown, argArray: Parameters) {
+ // SAFETY: Factories have `name` as their key in the module factories object, and that is always their module id
+ const moduleId = target.name;
+
+ // SYM_ORIGINAL_FACTORY means the factory has already been patched
+ if (target[SYM_ORIGINAL_FACTORY] != null) {
+ return runFactoryWithWrap(moduleId, target as PatchedModuleFactory, thisArg, argArray);
+ }
+
+ const patchedFactory = patchFactory(moduleId, target);
+ return runFactoryWithWrap(moduleId, patchedFactory, thisArg, argArray);
+ },
+
+ get(target, p, receiver) {
+ if (target[SYM_ORIGINAL_FACTORY] != null && (p === SYM_PATCHED_SOURCE || p === SYM_PATCHED_BY)) {
+ return Reflect.get(target[SYM_ORIGINAL_FACTORY], p, target[SYM_ORIGINAL_FACTORY]);
+ }
+
+ const v = Reflect.get(target, p, receiver);
+
+ // Make proxied factories `toString` return their original factory `toString`
+ if (p === "toString") {
+ return v.bind(target[SYM_ORIGINAL_FACTORY] ?? target);
+ }
+
+ return v;
}
};
/**
* Update a factory that exists in any Webpack instance with a new original factory.
*
- * @target The module factories where this new original factory is being set
- * @param id The id of the module
+ * @param moduleFactoriesTarget The module factories where this new original factory is being set
+ * @param moduleId The id of the module
* @param newFactory The new original factory
+ * @param receiver The receiver of the new factory
* @param ignoreExistingInTarget Whether to ignore checking if the factory already exists in the moduleFactoriesTarget
* @returns Whether the original factory was updated, or false if it doesn't exist in any Webpack instance
*/
-function updateExistingFactory(moduleFactoriesTarget: AnyWebpackRequire["m"], id: PropertyKey, newFactory: AnyModuleFactory, ignoreExistingInTarget: boolean = false) {
+function updateExistingFactory(moduleFactoriesTarget: AnyWebpackRequire["m"], moduleId: PropertyKey, newFactory: AnyModuleFactory, receiver: any, ignoreExistingInTarget: boolean = false) {
let existingFactory: TypedPropertyDescriptor | undefined;
let moduleFactoriesWithFactory: AnyWebpackRequire["m"] | undefined;
for (const wreq of allWebpackInstances) {
- if (ignoreExistingInTarget && wreq.m === moduleFactoriesTarget) continue;
+ if (ignoreExistingInTarget && wreq.m === moduleFactoriesTarget) {
+ continue;
+ }
- if (Object.hasOwn(wreq.m, id)) {
- existingFactory = Reflect.getOwnPropertyDescriptor(wreq.m, id);
+ if (Object.hasOwn(wreq.m, moduleId)) {
+ existingFactory = Reflect.getOwnPropertyDescriptor(wreq.m, moduleId);
moduleFactoriesWithFactory = wreq.m;
break;
}
}
if (existingFactory != null) {
- // If existingFactory exists in any Webpack instance, it's either wrapped in defineModuleFactoryGetter, or it has already been required.
- // So define the descriptor of it on this current Webpack instance (if it doesn't exist already), call Reflect.set with the new original,
- // and let the correct logic apply (normal set, or defineModuleFactoryGetter setter)
-
+ // If existingFactory exists in any Webpack instance, it's either wrapped in our proxy, or it has already been required.
+ // In the case it is wrapped in our proxy, we need the Webpack instance with this new original factory to also have our proxy.
+ // So, define the descriptor of the existing factory on it.
if (moduleFactoriesWithFactory !== moduleFactoriesTarget) {
- Reflect.defineProperty(moduleFactoriesTarget, id, existingFactory);
+ Reflect.defineProperty(receiver, moduleId, existingFactory);
}
- // Persist patched source and patched by in the new original factory, if the patched one has already been required
- if (IS_DEV && existingFactory.value != null) {
- newFactory[SYM_PATCHED_SOURCE] = existingFactory.value[SYM_PATCHED_SOURCE];
- newFactory[SYM_PATCHED_BY] = existingFactory.value[SYM_PATCHED_BY];
+ const existingFactoryValue = moduleFactoriesWithFactory![moduleId];
+
+ // Update with the new original factory, if it does have a current original factory
+ if (existingFactoryValue[SYM_ORIGINAL_FACTORY] != null) {
+ existingFactoryValue[SYM_ORIGINAL_FACTORY] = newFactory;
}
- return Reflect.set(moduleFactoriesTarget, id, newFactory, moduleFactoriesTarget);
+ // Persist patched source and patched by in the new original factory
+ if (IS_DEV) {
+ newFactory[SYM_PATCHED_SOURCE] = existingFactoryValue[SYM_PATCHED_SOURCE];
+ newFactory[SYM_PATCHED_BY] = existingFactoryValue[SYM_PATCHED_BY];
+ }
+
+ return true;
}
return false;
@@ -231,12 +270,13 @@ function updateExistingFactory(moduleFactoriesTarget: AnyWebpackRequire["m"], id
/**
* Notify all factory listeners.
*
+ * @param moduleId The id of the module
* @param factory The original factory to notify for
*/
-function notifyFactoryListeners(factory: AnyModuleFactory) {
+function notifyFactoryListeners(moduleId: PropertyKey, factory: AnyModuleFactory) {
for (const factoryListener of factoryListeners) {
try {
- factoryListener(factory);
+ factoryListener(factory, moduleId);
} catch (err) {
logger.error("Error in Webpack factory listener:\n", err, factoryListener);
}
@@ -244,190 +284,138 @@ function notifyFactoryListeners(factory: AnyModuleFactory) {
}
/**
- * Define the getter for returning the patched version of the module factory.
+ * Run a (possibly) patched module factory with a wrapper which notifies our listeners.
*
- * If eagerPatches is enabled, the factory argument should already be the patched version, else it will be the original
- * and only be patched when accessed for the first time.
- *
- * @param id The id of the module
- * @param factory The original or patched module factory
+ * @param moduleId The id of the module
+ * @param patchedFactory The (possibly) patched module factory
+ * @param thisArg The `value` of the call to the factory
+ * @param argArray The arguments of the call to the factory
*/
-function defineModulesFactoryGetter(id: PropertyKey, factory: MaybeWrappedModuleFactory) {
- const descriptor: PropertyDescriptor = {
- get() {
- // SYM_ORIGINAL_FACTORY means the factory is already patched
- if (!shouldPatchFactories || factory[SYM_ORIGINAL_FACTORY] != null) {
- return factory;
- }
+function runFactoryWithWrap(moduleId: PropertyKey, patchedFactory: PatchedModuleFactory, thisArg: unknown, argArray: Parameters) {
+ const originalFactory = patchedFactory[SYM_ORIGINAL_FACTORY];
- return (factory = wrapAndPatchFactory(id, factory));
- },
- set(newFactory: MaybeWrappedModuleFactory) {
- if (IS_DEV) {
- newFactory[SYM_PATCHED_SOURCE] = factory[SYM_PATCHED_SOURCE];
- newFactory[SYM_PATCHED_BY] = factory[SYM_PATCHED_BY];
- }
-
- if (factory[SYM_ORIGINAL_FACTORY] != null) {
- factory.toString = newFactory.toString.bind(newFactory);
- factory[SYM_ORIGINAL_FACTORY] = newFactory;
- } else {
- factory = newFactory;
- }
- }
- };
-
- // Define the getter in all the module factories objects. Patches are only executed once, so make sure all module factories object
- // have the patched version
- for (const wreq of allWebpackInstances) {
- define(wreq.m, id, descriptor);
+ if (patchedFactory === originalFactory) {
+ // @ts-expect-error Clear up ORIGINAL_FACTORY if the factory did not have any patch applied
+ delete patchedFactory[SYM_ORIGINAL_FACTORY];
}
-}
-/**
- * Wraps and patches a module factory.
- *
- * @param id The id of the module
- * @param factory The original or patched module factory
- * @returns The wrapper for the patched module factory
- */
-function wrapAndPatchFactory(id: PropertyKey, originalFactory: AnyModuleFactory) {
- const [patchedFactory, patchedSource, patchedBy] = patchFactory(id, originalFactory);
+ // Restore the original factory in all the module factories objects, discarding our proxy and allowing it to be garbage collected
+ for (const wreq of allWebpackInstances) {
+ define(wreq.m, moduleId, { value: originalFactory });
+ }
- const wrappedFactory: WrappedModuleFactory = function (...args) {
- // Restore the original factory in all the module factories objects. We want to make sure the original factory is restored properly, no matter what is the Webpack instance
- for (const wreq of allWebpackInstances) {
- define(wreq.m, id, { value: wrappedFactory[SYM_ORIGINAL_FACTORY] });
- }
+ let [module, exports, require] = argArray;
- // eslint-disable-next-line prefer-const
- let [module, exports, require] = args;
+ if (wreq == null) {
+ if (!wreqFallbackApplied) {
+ wreqFallbackApplied = true;
- if (wreq == null) {
- if (!wreqFallbackApplied) {
- wreqFallbackApplied = true;
+ // Make sure the require argument is actually the WebpackRequire function
+ if (typeof require === "function" && require.m != null) {
+ const { stack } = new Error();
+ const webpackInstanceFileName = stack?.match(/\/assets\/(.+?\.js)/)?.[1];
- // Make sure the require argument is actually the WebpackRequire function
- if (typeof require === "function" && require.m != null) {
- const { stack } = new Error();
- const webpackInstanceFileName = stack?.match(/\/assets\/(.+?\.js)/)?.[1];
+ logger.warn(
+ "WebpackRequire was not initialized, falling back to WebpackRequire passed to the first called wrapped module factory (" +
+ `id: ${String(moduleId)}` + interpolateIfDefined`, WebpackInstance origin: ${webpackInstanceFileName}` +
+ ")"
+ );
- logger.warn(
- "WebpackRequire was not initialized, falling back to WebpackRequire passed to the first called patched module factory (" +
- `id: ${String(id)}` + interpolateIfDefined`, WebpackInstance origin: ${webpackInstanceFileName}` +
- ")"
- );
-
- _initWebpack(require as WebpackRequire);
- } else if (IS_DEV) {
- logger.error("WebpackRequire was not initialized, running modules without patches instead.");
- return wrappedFactory[SYM_ORIGINAL_FACTORY].apply(this, args);
- }
+ // Could technically be wrong, but it's better than nothing
+ _initWebpack(require as WebpackRequire);
} else if (IS_DEV) {
- return wrappedFactory[SYM_ORIGINAL_FACTORY].apply(this, args);
+ logger.error("WebpackRequire was not initialized, running modules without patches instead.");
+ return originalFactory.apply(thisArg, argArray);
}
+ } else if (IS_DEV) {
+ return originalFactory.apply(thisArg, argArray);
+ }
+ }
+
+ let factoryReturn: unknown;
+ try {
+ factoryReturn = patchedFactory.apply(thisArg, argArray);
+ } catch (err) {
+ // Just re-throw Discord errors
+ if (patchedFactory === originalFactory) {
+ throw err;
}
- let factoryReturn: unknown;
- try {
- // Call the patched factory
- factoryReturn = patchedFactory.apply(this, args);
- } catch (err) {
- // Just re-throw Discord errors
- if (patchedFactory === wrappedFactory[SYM_ORIGINAL_FACTORY]) {
- throw err;
+ logger.error("Error in patched module factory:\n", err);
+ return originalFactory.apply(thisArg, argArray);
+ }
+
+ exports = module.exports;
+ if (exports == null) {
+ return factoryReturn;
+ }
+
+ if (typeof require === "function") {
+ const shouldIgnoreModule = _shouldIgnoreModule(exports);
+
+ if (shouldIgnoreModule) {
+ if (require.c != null) {
+ Object.defineProperty(require.c, moduleId, {
+ value: require.c[moduleId],
+ enumerable: false,
+ configurable: true,
+ writable: true
+ });
}
- logger.error("Error in patched module factory:\n", err);
- return wrappedFactory[SYM_ORIGINAL_FACTORY].apply(this, args);
- }
-
- exports = module.exports;
- if (exports == null) {
return factoryReturn;
}
-
- if (typeof require === "function") {
- const shouldIgnoreModule = _shouldIgnoreModule(exports);
-
- if (shouldIgnoreModule) {
- if (require.c != null) {
- Object.defineProperty(require.c, id, {
- value: require.c[id],
- enumerable: false,
- configurable: true,
- writable: true
- });
- }
-
- return factoryReturn;
- }
- }
-
- for (const callback of moduleListeners) {
- try {
- callback(exports, id);
- } catch (err) {
- logger.error("Error in Webpack module listener:\n", err, callback);
- }
- }
-
- for (const [filter, callback] of waitForSubscriptions) {
- try {
- if (filter(exports)) {
- waitForSubscriptions.delete(filter);
- callback(exports, id);
- continue;
- }
-
- if (typeof exports !== "object") {
- continue;
- }
-
- for (const exportKey in exports) {
- const exportValue = exports[exportKey];
-
- if (exportValue != null && filter(exportValue)) {
- waitForSubscriptions.delete(filter);
- callback(exportValue, id);
- break;
- }
- }
- } catch (err) {
- logger.error("Error while firing callback for Webpack waitFor subscription:\n", err, filter, callback);
- }
- }
-
- return factoryReturn;
- };
-
- wrappedFactory.toString = originalFactory.toString.bind(originalFactory);
- wrappedFactory[SYM_ORIGINAL_FACTORY] = originalFactory;
-
- if (IS_DEV && patchedFactory !== originalFactory) {
- wrappedFactory[SYM_PATCHED_SOURCE] = patchedSource;
- wrappedFactory[SYM_PATCHED_BY] = patchedBy;
- originalFactory[SYM_PATCHED_SOURCE] = patchedSource;
- originalFactory[SYM_PATCHED_BY] = patchedBy;
}
- // @ts-expect-error Allow GC to get into action, if possible
- originalFactory = undefined;
- return wrappedFactory;
+ for (const callback of moduleListeners) {
+ try {
+ callback(exports, moduleId);
+ } catch (err) {
+ logger.error("Error in Webpack module listener:\n", err, callback);
+ }
+ }
+
+ for (const [filter, callback] of waitForSubscriptions) {
+ try {
+ if (filter(exports)) {
+ waitForSubscriptions.delete(filter);
+ callback(exports, moduleId);
+ continue;
+ }
+
+ if (typeof exports !== "object") {
+ continue;
+ }
+
+ for (const exportKey in exports) {
+ const exportValue = exports[exportKey];
+
+ if (exportValue != null && filter(exportValue)) {
+ waitForSubscriptions.delete(filter);
+ callback(exportValue, moduleId);
+ break;
+ }
+ }
+ } catch (err) {
+ logger.error("Error while firing callback for Webpack waitFor subscription:\n", err, filter, callback);
+ }
+ }
+
+ return factoryReturn;
}
/**
* Patches a module factory.
*
- * @param id The id of the module
- * @param factory The original module factory
- * @returns The patched module factory, the patched source of it, and the plugins that patched it
+ * @param moduleId The id of the module
+ * @param originalFactory The original module factory
+ * @returns The patched module factory
*/
-function patchFactory(id: PropertyKey, factory: AnyModuleFactory): [patchedFactory: AnyModuleFactory, patchedSource: string, patchedBy: Set] {
+function patchFactory(moduleId: PropertyKey, originalFactory: AnyModuleFactory): PatchedModuleFactory {
// 0, prefix to turn it into an expression: 0,function(){} would be invalid syntax without the 0,
- let code: string = "0," + String(factory);
+ let code: string = "0," + String(originalFactory);
let patchedSource = code;
- let patchedFactory = factory;
+ let patchedFactory = originalFactory;
const patchedBy = new Set();
@@ -442,8 +430,8 @@ function patchFactory(id: PropertyKey, factory: AnyModuleFactory): [patchedFacto
continue;
}
- // Reporter eagerly patches and cannot retrieve the build number because this code runs before the module for it is loaded
- const buildNumber = IS_REPORTER ? -1 : getBuildNumber();
+ // Eager patches cannot retrieve the build number because this code runs before the module for it is loaded
+ const buildNumber = Settings.eagerPatches ? -1 : getBuildNumber();
const shouldCheckBuildNumber = !Settings.eagerPatches && buildNumber !== -1;
if (
@@ -463,7 +451,7 @@ function patchFactory(id: PropertyKey, factory: AnyModuleFactory): [patchedFacto
});
const previousCode = code;
- const previousFactory = factory;
+ const previousFactory = originalFactory;
let markedAsPatched = false;
// We change all patch.replacement to array in plugins/index
@@ -482,18 +470,18 @@ function patchFactory(id: PropertyKey, factory: AnyModuleFactory): [patchedFacto
}
const lastCode = code;
- const lastFactory = factory;
+ const lastFactory = originalFactory;
try {
const [newCode, totalTime] = executePatch(replacement.match, replacement.replace as string);
if (IS_REPORTER) {
- patchTimings.push([patch.plugin, id, replacement.match, totalTime]);
+ patchTimings.push([patch.plugin, moduleId, replacement.match, totalTime]);
}
if (newCode === code) {
if (!patch.noWarn) {
- logger.warn(`Patch by ${patch.plugin} had no effect (Module id is ${String(id)}): ${replacement.match}`);
+ logger.warn(`Patch by ${patch.plugin} had no effect (Module id is ${String(moduleId)}): ${replacement.match}`);
if (IS_DEV) {
logger.debug("Function Source:\n", code);
}
@@ -515,7 +503,7 @@ function patchFactory(id: PropertyKey, factory: AnyModuleFactory): [patchedFacto
}
code = newCode;
- patchedSource = `// Webpack Module ${String(id)} - Patched by ${[...patchedBy, patch.plugin].join(", ")}\n${newCode}\n//# sourceURL=WebpackModule${String(id)}`;
+ patchedSource = `// Webpack Module ${String(moduleId)} - Patched by ${[...patchedBy, patch.plugin].join(", ")}\n${newCode}\n//# sourceURL=WebpackModule${String(moduleId)}`;
patchedFactory = (0, eval)(patchedSource);
if (!patchedBy.has(patch.plugin)) {
@@ -523,7 +511,7 @@ function patchFactory(id: PropertyKey, factory: AnyModuleFactory): [patchedFacto
markedAsPatched = true;
}
} catch (err) {
- logger.error(`Patch by ${patch.plugin} errored (Module id is ${String(id)}): ${replacement.match}\n`, err);
+ logger.error(`Patch by ${patch.plugin} errored (Module id is ${String(moduleId)}): ${replacement.match}\n`, err);
if (IS_DEV) {
diffErroredPatch(code, lastCode, lastCode.match(replacement.match)!);
@@ -550,7 +538,14 @@ function patchFactory(id: PropertyKey, factory: AnyModuleFactory): [patchedFacto
}
}
- return [patchedFactory, patchedSource, patchedBy];
+ patchedFactory[SYM_ORIGINAL_FACTORY] = originalFactory;
+
+ if (IS_DEV && patchedFactory !== originalFactory) {
+ originalFactory[SYM_PATCHED_SOURCE] = patchedSource;
+ originalFactory[SYM_PATCHED_BY] = patchedBy;
+ }
+
+ return patchedFactory as PatchedModuleFactory;
}
function diffErroredPatch(code: string, lastCode: string, match: RegExpMatchArray) {
diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts
index 8d5b3c688..09c04a2a1 100644
--- a/src/webpack/webpack.ts
+++ b/src/webpack/webpack.ts
@@ -90,7 +90,7 @@ export const filters = {
};
export type CallbackFn = (module: ModuleExports, id: PropertyKey) => void;
-export type FactoryListernFn = (factory: AnyModuleFactory) => void;
+export type FactoryListernFn = (factory: AnyModuleFactory, moduleId: PropertyKey) => void;
export const waitForSubscriptions = new Map();
export const moduleListeners = new Set();
diff --git a/src/webpack/wreq.d.ts b/src/webpack/wreq.d.ts
index dbc451054..b9f5353f3 100644
--- a/src/webpack/wreq.d.ts
+++ b/src/webpack/wreq.d.ts
@@ -200,12 +200,10 @@ export type AnyModuleFactory = ((this: ModuleExports, module: Module, exports: M
[SYM_PATCHED_BY]?: Set;
};
-export type WrappedModuleFactory = AnyModuleFactory & {
+export type PatchedModuleFactory = AnyModuleFactory & {
[SYM_ORIGINAL_FACTORY]: AnyModuleFactory;
[SYM_PATCHED_SOURCE]?: string;
[SYM_PATCHED_BY]?: Set;
};
-export type MaybeWrappedModuleFactory = AnyModuleFactory | WrappedModuleFactory;
-
-export type WrappedModuleFactories = Record;
+export type MaybePatchedModuleFactory = PatchedModuleFactory | AnyModuleFactory;
diff --git a/tsconfig.json b/tsconfig.json
index db6d0918d..d2a42bd57 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -29,7 +29,9 @@
"@shared/*": ["./shared/*"],
"@webpack/types": ["./webpack/common/types"],
"@webpack/common": ["./webpack/common"],
- "@webpack": ["./webpack/webpack"]
+ "@webpack": ["./webpack/webpack"],
+ "@webpack/patcher": ["./webpack/patchWebpack"],
+ "@webpack/wreq.d": ["./webpack/wreq.d"],
},
"plugins": [
From 5196c2adc0fe348d66dacde7e04d3247f58dc073 Mon Sep 17 00:00:00 2001
From: v
Date: Wed, 12 Feb 2025 18:09:14 +0100
Subject: [PATCH 2/2] Update esbuild to latest version (#3218)
---
browser/manifest.json | 2 +-
browser/monaco.ts | 2 +-
browser/monacoWin.html | 4 +-
package.json | 5 +-
pnpm-lock.yaml | 482 +++++++++++++++-------------
scripts/build/build.mjs | 99 +++---
scripts/build/buildWeb.mjs | 138 ++++----
scripts/build/common.mjs | 43 ++-
scripts/build/tsconfig.esbuild.json | 7 -
9 files changed, 406 insertions(+), 376 deletions(-)
delete mode 100644 scripts/build/tsconfig.esbuild.json
diff --git a/browser/manifest.json b/browser/manifest.json
index 357312b09..3463e46cf 100644
--- a/browser/manifest.json
+++ b/browser/manifest.json
@@ -36,7 +36,7 @@
"web_accessible_resources": [
{
- "resources": ["dist/*", "third-party/*"],
+ "resources": ["dist/*", "vendor/*"],
"matches": ["*://*.discord.com/*"]
}
],
diff --git a/browser/monaco.ts b/browser/monaco.ts
index ead061d65..dc243df7d 100644
--- a/browser/monaco.ts
+++ b/browser/monaco.ts
@@ -15,7 +15,7 @@ declare global {
const getTheme: () => string;
}
-const BASE = "/dist/monaco/vs";
+const BASE = "/vendor/monaco/vs";
self.MonacoEnvironment = {
getWorkerUrl(_moduleId: unknown, label: string) {
diff --git a/browser/monacoWin.html b/browser/monacoWin.html
index a55b0e547..12523d455 100644
--- a/browser/monacoWin.html
+++ b/browser/monacoWin.html
@@ -24,12 +24,12 @@
diff --git a/package.json b/package.json
index dca52a16f..872d7ce03 100644
--- a/package.json
+++ b/package.json
@@ -30,13 +30,12 @@
"lint": "eslint",
"lint-styles": "stylelint \"src/**/*.css\" --ignore-pattern src/userplugins",
"lint:fix": "pnpm lint --fix",
- "test": "pnpm buildStandalone && pnpm lint && pnpm lint-styles && pnpm testTsc && pnpm generatePluginJson",
+ "test": "pnpm buildStandalone && pnpm testTsc && pnpm lint && pnpm lint-styles && pnpm generatePluginJson",
"testWeb": "pnpm lint && pnpm buildWeb && pnpm testTsc",
"testTsc": "tsc --noEmit"
},
"dependencies": {
"@intrnl/xxhash64": "^0.1.2",
- "@sapphi-red/web-noise-suppressor": "0.3.5",
"@vap/core": "0.0.12",
"@vap/shiki": "0.10.5",
"fflate": "^0.8.2",
@@ -56,7 +55,7 @@
"@types/yazl": "^2.4.5",
"diff": "^7.0.0",
"discord-types": "^1.3.26",
- "esbuild": "^0.15.18",
+ "esbuild": "^0.25.0",
"eslint": "^9.17.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-path-alias": "2.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a49df467b..169d76fcf 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -19,9 +19,6 @@ importers:
'@intrnl/xxhash64':
specifier: ^0.1.2
version: 0.1.2
- '@sapphi-red/web-noise-suppressor':
- specifier: 0.3.5
- version: 0.3.5
'@vap/core':
specifier: 0.0.12
version: 0.0.12
@@ -75,8 +72,8 @@ importers:
specifier: ^1.3.26
version: 1.3.26
esbuild:
- specifier: ^0.15.18
- version: 0.15.18
+ specifier: ^0.25.0
+ version: 0.25.0
eslint:
specifier: ^9.17.0
version: 9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4)
@@ -229,6 +226,12 @@ packages:
cpu: [ppc64]
os: [aix]
+ '@esbuild/aix-ppc64@0.25.0':
+ resolution: {integrity: sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
'@esbuild/android-arm64@0.17.19':
resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
engines: {node: '>=12'}
@@ -241,10 +244,10 @@ packages:
cpu: [arm64]
os: [android]
- '@esbuild/android-arm@0.15.18':
- resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==}
- engines: {node: '>=12'}
- cpu: [arm]
+ '@esbuild/android-arm64@0.25.0':
+ resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.17.19':
@@ -259,6 +262,12 @@ packages:
cpu: [arm]
os: [android]
+ '@esbuild/android-arm@0.25.0':
+ resolution: {integrity: sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
'@esbuild/android-x64@0.17.19':
resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==}
engines: {node: '>=12'}
@@ -271,6 +280,12 @@ packages:
cpu: [x64]
os: [android]
+ '@esbuild/android-x64@0.25.0':
+ resolution: {integrity: sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
'@esbuild/darwin-arm64@0.17.19':
resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==}
engines: {node: '>=12'}
@@ -283,6 +298,12 @@ packages:
cpu: [arm64]
os: [darwin]
+ '@esbuild/darwin-arm64@0.25.0':
+ resolution: {integrity: sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
'@esbuild/darwin-x64@0.17.19':
resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==}
engines: {node: '>=12'}
@@ -295,6 +316,12 @@ packages:
cpu: [x64]
os: [darwin]
+ '@esbuild/darwin-x64@0.25.0':
+ resolution: {integrity: sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
'@esbuild/freebsd-arm64@0.17.19':
resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==}
engines: {node: '>=12'}
@@ -307,6 +334,12 @@ packages:
cpu: [arm64]
os: [freebsd]
+ '@esbuild/freebsd-arm64@0.25.0':
+ resolution: {integrity: sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
'@esbuild/freebsd-x64@0.17.19':
resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==}
engines: {node: '>=12'}
@@ -319,6 +352,12 @@ packages:
cpu: [x64]
os: [freebsd]
+ '@esbuild/freebsd-x64@0.25.0':
+ resolution: {integrity: sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
'@esbuild/linux-arm64@0.17.19':
resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==}
engines: {node: '>=12'}
@@ -331,6 +370,12 @@ packages:
cpu: [arm64]
os: [linux]
+ '@esbuild/linux-arm64@0.25.0':
+ resolution: {integrity: sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
'@esbuild/linux-arm@0.17.19':
resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==}
engines: {node: '>=12'}
@@ -343,6 +388,12 @@ packages:
cpu: [arm]
os: [linux]
+ '@esbuild/linux-arm@0.25.0':
+ resolution: {integrity: sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
'@esbuild/linux-ia32@0.17.19':
resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==}
engines: {node: '>=12'}
@@ -355,10 +406,10 @@ packages:
cpu: [ia32]
os: [linux]
- '@esbuild/linux-loong64@0.15.18':
- resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==}
- engines: {node: '>=12'}
- cpu: [loong64]
+ '@esbuild/linux-ia32@0.25.0':
+ resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.17.19':
@@ -373,6 +424,12 @@ packages:
cpu: [loong64]
os: [linux]
+ '@esbuild/linux-loong64@0.25.0':
+ resolution: {integrity: sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
'@esbuild/linux-mips64el@0.17.19':
resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==}
engines: {node: '>=12'}
@@ -385,6 +442,12 @@ packages:
cpu: [mips64el]
os: [linux]
+ '@esbuild/linux-mips64el@0.25.0':
+ resolution: {integrity: sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
'@esbuild/linux-ppc64@0.17.19':
resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==}
engines: {node: '>=12'}
@@ -397,6 +460,12 @@ packages:
cpu: [ppc64]
os: [linux]
+ '@esbuild/linux-ppc64@0.25.0':
+ resolution: {integrity: sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
'@esbuild/linux-riscv64@0.17.19':
resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==}
engines: {node: '>=12'}
@@ -409,6 +478,12 @@ packages:
cpu: [riscv64]
os: [linux]
+ '@esbuild/linux-riscv64@0.25.0':
+ resolution: {integrity: sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
'@esbuild/linux-s390x@0.17.19':
resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==}
engines: {node: '>=12'}
@@ -421,6 +496,12 @@ packages:
cpu: [s390x]
os: [linux]
+ '@esbuild/linux-s390x@0.25.0':
+ resolution: {integrity: sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
'@esbuild/linux-x64@0.17.19':
resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==}
engines: {node: '>=12'}
@@ -433,6 +514,18 @@ packages:
cpu: [x64]
os: [linux]
+ '@esbuild/linux-x64@0.25.0':
+ resolution: {integrity: sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-arm64@0.25.0':
+ resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
'@esbuild/netbsd-x64@0.17.19':
resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==}
engines: {node: '>=12'}
@@ -445,12 +538,24 @@ packages:
cpu: [x64]
os: [netbsd]
+ '@esbuild/netbsd-x64@0.25.0':
+ resolution: {integrity: sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
'@esbuild/openbsd-arm64@0.23.1':
resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
+ '@esbuild/openbsd-arm64@0.25.0':
+ resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
'@esbuild/openbsd-x64@0.17.19':
resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==}
engines: {node: '>=12'}
@@ -463,6 +568,12 @@ packages:
cpu: [x64]
os: [openbsd]
+ '@esbuild/openbsd-x64@0.25.0':
+ resolution: {integrity: sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
'@esbuild/sunos-x64@0.17.19':
resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==}
engines: {node: '>=12'}
@@ -475,6 +586,12 @@ packages:
cpu: [x64]
os: [sunos]
+ '@esbuild/sunos-x64@0.25.0':
+ resolution: {integrity: sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
'@esbuild/win32-arm64@0.17.19':
resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==}
engines: {node: '>=12'}
@@ -487,6 +604,12 @@ packages:
cpu: [arm64]
os: [win32]
+ '@esbuild/win32-arm64@0.25.0':
+ resolution: {integrity: sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
'@esbuild/win32-ia32@0.17.19':
resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==}
engines: {node: '>=12'}
@@ -499,6 +622,12 @@ packages:
cpu: [ia32]
os: [win32]
+ '@esbuild/win32-ia32@0.25.0':
+ resolution: {integrity: sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
'@esbuild/win32-x64@0.17.19':
resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==}
engines: {node: '>=12'}
@@ -511,6 +640,12 @@ packages:
cpu: [x64]
os: [win32]
+ '@esbuild/win32-x64@0.25.0':
+ resolution: {integrity: sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
'@eslint-community/eslint-utils@4.4.1':
resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -609,9 +744,6 @@ packages:
'@rtsao/scc@1.1.0':
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
- '@sapphi-red/web-noise-suppressor@0.3.5':
- resolution: {integrity: sha512-jh3+V9yM+zxLriQexoGm0GatoPaJWjs6ypFIbFYwQp+AoUb55eUXrjKtKQyuC5zShzzeAQUl0M5JzqB7SSrsRA==}
-
'@stylistic/eslint-plugin@2.12.1':
resolution: {integrity: sha512-fubZKIHSPuo07FgRTn6S4Nl0uXPRPYVNpyZzIDGfp7Fny6JjNus6kReLD7NI380JXi4HtUTSOZ34LBuNPO1XLQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -1205,131 +1337,6 @@ packages:
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
engines: {node: '>= 0.4'}
- esbuild-android-64@0.15.18:
- resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [android]
-
- esbuild-android-arm64@0.15.18:
- resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [android]
-
- esbuild-darwin-64@0.15.18:
- resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [darwin]
-
- esbuild-darwin-arm64@0.15.18:
- resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [darwin]
-
- esbuild-freebsd-64@0.15.18:
- resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [freebsd]
-
- esbuild-freebsd-arm64@0.15.18:
- resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [freebsd]
-
- esbuild-linux-32@0.15.18:
- resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==}
- engines: {node: '>=12'}
- cpu: [ia32]
- os: [linux]
-
- esbuild-linux-64@0.15.18:
- resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [linux]
-
- esbuild-linux-arm64@0.15.18:
- resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [linux]
-
- esbuild-linux-arm@0.15.18:
- resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==}
- engines: {node: '>=12'}
- cpu: [arm]
- os: [linux]
-
- esbuild-linux-mips64le@0.15.18:
- resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==}
- engines: {node: '>=12'}
- cpu: [mips64el]
- os: [linux]
-
- esbuild-linux-ppc64le@0.15.18:
- resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==}
- engines: {node: '>=12'}
- cpu: [ppc64]
- os: [linux]
-
- esbuild-linux-riscv64@0.15.18:
- resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==}
- engines: {node: '>=12'}
- cpu: [riscv64]
- os: [linux]
-
- esbuild-linux-s390x@0.15.18:
- resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==}
- engines: {node: '>=12'}
- cpu: [s390x]
- os: [linux]
-
- esbuild-netbsd-64@0.15.18:
- resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [netbsd]
-
- esbuild-openbsd-64@0.15.18:
- resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [openbsd]
-
- esbuild-sunos-64@0.15.18:
- resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [sunos]
-
- esbuild-windows-32@0.15.18:
- resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==}
- engines: {node: '>=12'}
- cpu: [ia32]
- os: [win32]
-
- esbuild-windows-64@0.15.18:
- resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [win32]
-
- esbuild-windows-arm64@0.15.18:
- resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [win32]
-
- esbuild@0.15.18:
- resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==}
- engines: {node: '>=12'}
- hasBin: true
-
esbuild@0.17.19:
resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==}
engines: {node: '>=12'}
@@ -1340,6 +1347,11 @@ packages:
engines: {node: '>=18'}
hasBin: true
+ esbuild@0.25.0:
+ resolution: {integrity: sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==}
+ engines: {node: '>=18'}
+ hasBin: true
+
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
@@ -2889,13 +2901,16 @@ snapshots:
'@esbuild/aix-ppc64@0.23.1':
optional: true
+ '@esbuild/aix-ppc64@0.25.0':
+ optional: true
+
'@esbuild/android-arm64@0.17.19':
optional: true
'@esbuild/android-arm64@0.23.1':
optional: true
- '@esbuild/android-arm@0.15.18':
+ '@esbuild/android-arm64@0.25.0':
optional: true
'@esbuild/android-arm@0.17.19':
@@ -2904,55 +2919,79 @@ snapshots:
'@esbuild/android-arm@0.23.1':
optional: true
+ '@esbuild/android-arm@0.25.0':
+ optional: true
+
'@esbuild/android-x64@0.17.19':
optional: true
'@esbuild/android-x64@0.23.1':
optional: true
+ '@esbuild/android-x64@0.25.0':
+ optional: true
+
'@esbuild/darwin-arm64@0.17.19':
optional: true
'@esbuild/darwin-arm64@0.23.1':
optional: true
+ '@esbuild/darwin-arm64@0.25.0':
+ optional: true
+
'@esbuild/darwin-x64@0.17.19':
optional: true
'@esbuild/darwin-x64@0.23.1':
optional: true
+ '@esbuild/darwin-x64@0.25.0':
+ optional: true
+
'@esbuild/freebsd-arm64@0.17.19':
optional: true
'@esbuild/freebsd-arm64@0.23.1':
optional: true
+ '@esbuild/freebsd-arm64@0.25.0':
+ optional: true
+
'@esbuild/freebsd-x64@0.17.19':
optional: true
'@esbuild/freebsd-x64@0.23.1':
optional: true
+ '@esbuild/freebsd-x64@0.25.0':
+ optional: true
+
'@esbuild/linux-arm64@0.17.19':
optional: true
'@esbuild/linux-arm64@0.23.1':
optional: true
+ '@esbuild/linux-arm64@0.25.0':
+ optional: true
+
'@esbuild/linux-arm@0.17.19':
optional: true
'@esbuild/linux-arm@0.23.1':
optional: true
+ '@esbuild/linux-arm@0.25.0':
+ optional: true
+
'@esbuild/linux-ia32@0.17.19':
optional: true
'@esbuild/linux-ia32@0.23.1':
optional: true
- '@esbuild/linux-loong64@0.15.18':
+ '@esbuild/linux-ia32@0.25.0':
optional: true
'@esbuild/linux-loong64@0.17.19':
@@ -2961,75 +3000,117 @@ snapshots:
'@esbuild/linux-loong64@0.23.1':
optional: true
+ '@esbuild/linux-loong64@0.25.0':
+ optional: true
+
'@esbuild/linux-mips64el@0.17.19':
optional: true
'@esbuild/linux-mips64el@0.23.1':
optional: true
+ '@esbuild/linux-mips64el@0.25.0':
+ optional: true
+
'@esbuild/linux-ppc64@0.17.19':
optional: true
'@esbuild/linux-ppc64@0.23.1':
optional: true
+ '@esbuild/linux-ppc64@0.25.0':
+ optional: true
+
'@esbuild/linux-riscv64@0.17.19':
optional: true
'@esbuild/linux-riscv64@0.23.1':
optional: true
+ '@esbuild/linux-riscv64@0.25.0':
+ optional: true
+
'@esbuild/linux-s390x@0.17.19':
optional: true
'@esbuild/linux-s390x@0.23.1':
optional: true
+ '@esbuild/linux-s390x@0.25.0':
+ optional: true
+
'@esbuild/linux-x64@0.17.19':
optional: true
'@esbuild/linux-x64@0.23.1':
optional: true
+ '@esbuild/linux-x64@0.25.0':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.25.0':
+ optional: true
+
'@esbuild/netbsd-x64@0.17.19':
optional: true
'@esbuild/netbsd-x64@0.23.1':
optional: true
+ '@esbuild/netbsd-x64@0.25.0':
+ optional: true
+
'@esbuild/openbsd-arm64@0.23.1':
optional: true
+ '@esbuild/openbsd-arm64@0.25.0':
+ optional: true
+
'@esbuild/openbsd-x64@0.17.19':
optional: true
'@esbuild/openbsd-x64@0.23.1':
optional: true
+ '@esbuild/openbsd-x64@0.25.0':
+ optional: true
+
'@esbuild/sunos-x64@0.17.19':
optional: true
'@esbuild/sunos-x64@0.23.1':
optional: true
+ '@esbuild/sunos-x64@0.25.0':
+ optional: true
+
'@esbuild/win32-arm64@0.17.19':
optional: true
'@esbuild/win32-arm64@0.23.1':
optional: true
+ '@esbuild/win32-arm64@0.25.0':
+ optional: true
+
'@esbuild/win32-ia32@0.17.19':
optional: true
'@esbuild/win32-ia32@0.23.1':
optional: true
+ '@esbuild/win32-ia32@0.25.0':
+ optional: true
+
'@esbuild/win32-x64@0.17.19':
optional: true
'@esbuild/win32-x64@0.23.1':
optional: true
+ '@esbuild/win32-x64@0.25.0':
+ optional: true
+
'@eslint-community/eslint-utils@4.4.1(eslint@9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4))':
dependencies:
eslint: 9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4)
@@ -3135,8 +3216,6 @@ snapshots:
'@rtsao/scc@1.1.0': {}
- '@sapphi-red/web-noise-suppressor@0.3.5': {}
-
'@stylistic/eslint-plugin@2.12.1(eslint@9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4))(typescript@5.7.2)':
dependencies:
'@typescript-eslint/utils': 8.18.1(eslint@9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4))(typescript@5.7.2)
@@ -3936,91 +4015,6 @@ snapshots:
is-date-object: 1.1.0
is-symbol: 1.1.1
- esbuild-android-64@0.15.18:
- optional: true
-
- esbuild-android-arm64@0.15.18:
- optional: true
-
- esbuild-darwin-64@0.15.18:
- optional: true
-
- esbuild-darwin-arm64@0.15.18:
- optional: true
-
- esbuild-freebsd-64@0.15.18:
- optional: true
-
- esbuild-freebsd-arm64@0.15.18:
- optional: true
-
- esbuild-linux-32@0.15.18:
- optional: true
-
- esbuild-linux-64@0.15.18:
- optional: true
-
- esbuild-linux-arm64@0.15.18:
- optional: true
-
- esbuild-linux-arm@0.15.18:
- optional: true
-
- esbuild-linux-mips64le@0.15.18:
- optional: true
-
- esbuild-linux-ppc64le@0.15.18:
- optional: true
-
- esbuild-linux-riscv64@0.15.18:
- optional: true
-
- esbuild-linux-s390x@0.15.18:
- optional: true
-
- esbuild-netbsd-64@0.15.18:
- optional: true
-
- esbuild-openbsd-64@0.15.18:
- optional: true
-
- esbuild-sunos-64@0.15.18:
- optional: true
-
- esbuild-windows-32@0.15.18:
- optional: true
-
- esbuild-windows-64@0.15.18:
- optional: true
-
- esbuild-windows-arm64@0.15.18:
- optional: true
-
- esbuild@0.15.18:
- optionalDependencies:
- '@esbuild/android-arm': 0.15.18
- '@esbuild/linux-loong64': 0.15.18
- esbuild-android-64: 0.15.18
- esbuild-android-arm64: 0.15.18
- esbuild-darwin-64: 0.15.18
- esbuild-darwin-arm64: 0.15.18
- esbuild-freebsd-64: 0.15.18
- esbuild-freebsd-arm64: 0.15.18
- esbuild-linux-32: 0.15.18
- esbuild-linux-64: 0.15.18
- esbuild-linux-arm: 0.15.18
- esbuild-linux-arm64: 0.15.18
- esbuild-linux-mips64le: 0.15.18
- esbuild-linux-ppc64le: 0.15.18
- esbuild-linux-riscv64: 0.15.18
- esbuild-linux-s390x: 0.15.18
- esbuild-netbsd-64: 0.15.18
- esbuild-openbsd-64: 0.15.18
- esbuild-sunos-64: 0.15.18
- esbuild-windows-32: 0.15.18
- esbuild-windows-64: 0.15.18
- esbuild-windows-arm64: 0.15.18
-
esbuild@0.17.19:
optionalDependencies:
'@esbuild/android-arm': 0.17.19
@@ -4073,6 +4067,34 @@ snapshots:
'@esbuild/win32-ia32': 0.23.1
'@esbuild/win32-x64': 0.23.1
+ esbuild@0.25.0:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.25.0
+ '@esbuild/android-arm': 0.25.0
+ '@esbuild/android-arm64': 0.25.0
+ '@esbuild/android-x64': 0.25.0
+ '@esbuild/darwin-arm64': 0.25.0
+ '@esbuild/darwin-x64': 0.25.0
+ '@esbuild/freebsd-arm64': 0.25.0
+ '@esbuild/freebsd-x64': 0.25.0
+ '@esbuild/linux-arm': 0.25.0
+ '@esbuild/linux-arm64': 0.25.0
+ '@esbuild/linux-ia32': 0.25.0
+ '@esbuild/linux-loong64': 0.25.0
+ '@esbuild/linux-mips64el': 0.25.0
+ '@esbuild/linux-ppc64': 0.25.0
+ '@esbuild/linux-riscv64': 0.25.0
+ '@esbuild/linux-s390x': 0.25.0
+ '@esbuild/linux-x64': 0.25.0
+ '@esbuild/netbsd-arm64': 0.25.0
+ '@esbuild/netbsd-x64': 0.25.0
+ '@esbuild/openbsd-arm64': 0.25.0
+ '@esbuild/openbsd-x64': 0.25.0
+ '@esbuild/sunos-x64': 0.25.0
+ '@esbuild/win32-arm64': 0.25.0
+ '@esbuild/win32-ia32': 0.25.0
+ '@esbuild/win32-x64': 0.25.0
+
escalade@3.2.0: {}
escape-string-regexp@4.0.0: {}
diff --git a/scripts/build/build.mjs b/scripts/build/build.mjs
index 623f9f940..9c2b49708 100755
--- a/scripts/build/build.mjs
+++ b/scripts/build/build.mjs
@@ -17,38 +17,41 @@
* along with this program. If not, see .
*/
-import esbuild from "esbuild";
+// @ts-check
+
import { readdir } from "fs/promises";
import { join } from "path";
-import { BUILD_TIMESTAMP, commonOpts, exists, globPlugins, IS_DEV, IS_REPORTER, IS_STANDALONE, IS_UPDATER_DISABLED, resolvePluginName, VERSION, commonRendererPlugins, watch } from "./common.mjs";
+import { BUILD_TIMESTAMP, commonOpts, exists, globPlugins, IS_DEV, IS_REPORTER, IS_STANDALONE, IS_UPDATER_DISABLED, resolvePluginName, VERSION, commonRendererPlugins, watch, buildOrWatchAll, stringifyValues } from "./common.mjs";
-const defines = {
+const defines = stringifyValues({
IS_STANDALONE,
IS_DEV,
IS_REPORTER,
IS_UPDATER_DISABLED,
IS_WEB: false,
IS_EXTENSION: false,
- VERSION: JSON.stringify(VERSION),
+ VERSION,
BUILD_TIMESTAMP
-};
+});
-if (defines.IS_STANDALONE === false)
+if (defines.IS_STANDALONE === "false") {
// If this is a local build (not standalone), optimize
// for the specific platform we're on
defines["process.platform"] = JSON.stringify(process.platform);
+}
/**
- * @type {esbuild.BuildOptions}
+ * @type {import("esbuild").BuildOptions}
*/
const nodeCommonOpts = {
...commonOpts,
+ define: defines,
format: "cjs",
platform: "node",
target: ["esnext"],
- external: ["electron", "original-fs", "~pluginNatives", ...commonOpts.external],
- define: defines
+ // @ts-ignore this is never undefined
+ external: ["electron", "original-fs", "~pluginNatives", ...commonOpts.external]
};
const sourceMapFooter = s => watch ? "" : `//# sourceMappingURL=vencord://${s}.js.map`;
@@ -102,25 +105,27 @@ const globNativesPlugin = {
}
};
-await Promise.all([
+/** @type {import("esbuild").BuildOptions[]} */
+const buildConfigs = ([
// Discord Desktop main & renderer & preload
- esbuild.build({
+ {
...nodeCommonOpts,
entryPoints: ["src/main/index.ts"],
outfile: "dist/patcher.js",
footer: { js: "//# sourceURL=VencordPatcher\n" + sourceMapFooter("patcher") },
sourcemap,
- define: {
- ...defines,
- IS_DISCORD_DESKTOP: true,
- IS_VESKTOP: false
- },
plugins: [
+ // @ts-ignore this is never undefined
...nodeCommonOpts.plugins,
globNativesPlugin
- ]
- }),
- esbuild.build({
+ ],
+ define: {
+ ...defines,
+ IS_DISCORD_DESKTOP: "true",
+ IS_VESKTOP: "false"
+ }
+ },
+ {
...commonOpts,
entryPoints: ["src/Vencord.ts"],
outfile: "dist/renderer.js",
@@ -135,11 +140,11 @@ await Promise.all([
],
define: {
...defines,
- IS_DISCORD_DESKTOP: true,
- IS_VESKTOP: false
+ IS_DISCORD_DESKTOP: "true",
+ IS_VESKTOP: "false"
}
- }),
- esbuild.build({
+ },
+ {
...nodeCommonOpts,
entryPoints: ["src/preload.ts"],
outfile: "dist/preload.js",
@@ -147,29 +152,29 @@ await Promise.all([
sourcemap,
define: {
...defines,
- IS_DISCORD_DESKTOP: true,
- IS_VESKTOP: false
+ IS_DISCORD_DESKTOP: "true",
+ IS_VESKTOP: "false"
}
- }),
+ },
// Vencord Desktop main & renderer & preload
- esbuild.build({
+ {
...nodeCommonOpts,
entryPoints: ["src/main/index.ts"],
outfile: "dist/vencordDesktopMain.js",
footer: { js: "//# sourceURL=VencordDesktopMain\n" + sourceMapFooter("vencordDesktopMain") },
sourcemap,
- define: {
- ...defines,
- IS_DISCORD_DESKTOP: false,
- IS_VESKTOP: true
- },
plugins: [
...nodeCommonOpts.plugins,
globNativesPlugin
- ]
- }),
- esbuild.build({
+ ],
+ define: {
+ ...defines,
+ IS_DISCORD_DESKTOP: "false",
+ IS_VESKTOP: "true"
+ }
+ },
+ {
...commonOpts,
entryPoints: ["src/Vencord.ts"],
outfile: "dist/vencordDesktopRenderer.js",
@@ -184,11 +189,11 @@ await Promise.all([
],
define: {
...defines,
- IS_DISCORD_DESKTOP: false,
- IS_VESKTOP: true
+ IS_DISCORD_DESKTOP: "false",
+ IS_VESKTOP: "true"
}
- }),
- esbuild.build({
+ },
+ {
...nodeCommonOpts,
entryPoints: ["src/preload.ts"],
outfile: "dist/vencordDesktopPreload.js",
@@ -196,14 +201,10 @@ await Promise.all([
sourcemap,
define: {
...defines,
- IS_DISCORD_DESKTOP: false,
- IS_VESKTOP: true
+ IS_DISCORD_DESKTOP: "false",
+ IS_VESKTOP: "true"
}
- }),
-]).catch(err => {
- console.error("Build failed");
- console.error(err.message);
- // make ci fail
- if (!commonOpts.watch)
- process.exitCode = 1;
-});
+ }
+]);
+
+await buildOrWatchAll(buildConfigs);
diff --git a/scripts/build/buildWeb.mjs b/scripts/build/buildWeb.mjs
index deab86610..33168ff97 100644
--- a/scripts/build/buildWeb.mjs
+++ b/scripts/build/buildWeb.mjs
@@ -17,29 +17,30 @@
* along with this program. If not, see .
*/
-import esbuild from "esbuild";
+// @ts-check
+
import { readFileSync } from "fs";
import { appendFile, mkdir, readdir, readFile, rm, writeFile } from "fs/promises";
import { join } from "path";
import Zip from "zip-local";
-import { BUILD_TIMESTAMP, commonOpts, globPlugins, IS_DEV, IS_REPORTER, VERSION, commonRendererPlugins } from "./common.mjs";
+import { BUILD_TIMESTAMP, commonOpts, globPlugins, IS_DEV, IS_REPORTER, VERSION, commonRendererPlugins, buildOrWatchAll, stringifyValues } from "./common.mjs";
/**
- * @type {esbuild.BuildOptions}
+ * @type {import("esbuild").BuildOptions}
*/
const commonOptions = {
...commonOpts,
entryPoints: ["browser/Vencord.ts"],
- globalName: "Vencord",
format: "iife",
+ globalName: "Vencord",
external: ["~plugins", "~git-hash", "/assets/*"],
+ target: ["esnext"],
plugins: [
globPlugins("web"),
...commonRendererPlugins
],
- target: ["esnext"],
- define: {
+ define: stringifyValues({
IS_WEB: true,
IS_EXTENSION: false,
IS_STANDALONE: true,
@@ -48,9 +49,9 @@ const commonOptions = {
IS_DISCORD_DESKTOP: false,
IS_VESKTOP: false,
IS_UPDATER_DISABLED: true,
- VERSION: JSON.stringify(VERSION),
+ VERSION,
BUILD_TIMESTAMP
- }
+ })
};
const MonacoWorkerEntryPoints = [
@@ -58,70 +59,59 @@ const MonacoWorkerEntryPoints = [
"vs/editor/editor.worker.js"
];
-const RnNoiseFiles = [
- "dist/rnnoise.wasm",
- "dist/rnnoise_simd.wasm",
- "dist/rnnoise/workletProcessor.js",
- "LICENSE"
+/** @type {import("esbuild").BuildOptions[]} */
+const buildConfigs = [
+ {
+ entryPoints: MonacoWorkerEntryPoints.map(entry => `node_modules/monaco-editor/esm/${entry}`),
+ bundle: true,
+ minify: true,
+ format: "iife",
+ outbase: "node_modules/monaco-editor/esm/",
+ outdir: "dist/vendor/monaco"
+ },
+ {
+ entryPoints: ["browser/monaco.ts"],
+ bundle: true,
+ minify: true,
+ format: "iife",
+ outfile: "dist/vendor/monaco/index.js",
+ loader: {
+ ".ttf": "file"
+ }
+ },
+ {
+ ...commonOptions,
+ outfile: "dist/browser.js",
+ footer: { js: "//# sourceURL=VencordWeb" }
+ },
+ {
+ ...commonOptions,
+ outfile: "dist/extension.js",
+ define: {
+ ...commonOptions.define,
+ IS_EXTENSION: "true"
+ },
+ footer: { js: "//# sourceURL=VencordWeb" }
+ },
+ {
+ ...commonOptions,
+ inject: ["browser/GMPolyfill.js", ...(commonOptions?.inject || [])],
+ define: {
+ ...commonOptions.define,
+ window: "unsafeWindow",
+ },
+ outfile: "dist/Vencord.user.js",
+ banner: {
+ js: readFileSync("browser/userscript.meta.js", "utf-8").replace("%version%", `${VERSION}.${new Date().getTime()}`)
+ },
+ footer: {
+ // UserScripts get wrapped in an iife, so define Vencord prop on window that returns our local
+ js: "Object.defineProperty(unsafeWindow,'Vencord',{get:()=>Vencord});"
+ }
+ }
];
-await Promise.all(
- [
- esbuild.build({
- entryPoints: MonacoWorkerEntryPoints.map(entry => `node_modules/monaco-editor/esm/${entry}`),
- bundle: true,
- minify: true,
- format: "iife",
- outbase: "node_modules/monaco-editor/esm/",
- outdir: "dist/monaco"
- }),
- esbuild.build({
- entryPoints: ["browser/monaco.ts"],
- bundle: true,
- minify: true,
- format: "iife",
- outfile: "dist/monaco/index.js",
- loader: {
- ".ttf": "file"
- }
- }),
- esbuild.build({
- ...commonOptions,
- outfile: "dist/browser.js",
- footer: { js: "//# sourceURL=VencordWeb" }
- }),
- esbuild.build({
- ...commonOptions,
- outfile: "dist/extension.js",
- define: {
- ...commonOptions?.define,
- IS_EXTENSION: true,
- },
- footer: { js: "//# sourceURL=VencordWeb" }
- }),
- esbuild.build({
- ...commonOptions,
- inject: ["browser/GMPolyfill.js", ...(commonOptions?.inject || [])],
- define: {
- ...(commonOptions?.define),
- window: "unsafeWindow",
- },
- outfile: "dist/Vencord.user.js",
- banner: {
- js: readFileSync("browser/userscript.meta.js", "utf-8").replace("%version%", `${VERSION}.${new Date().getTime()}`)
- },
- footer: {
- // UserScripts get wrapped in an iife, so define Vencord prop on window that returns our local
- js: "Object.defineProperty(unsafeWindow,'Vencord',{get:()=>Vencord});"
- }
- })
- ]
-).catch(err => {
- console.error("Build failed");
- console.error(err.message);
- if (!commonOpts.watch)
- process.exit(1);
-});;
+await buildOrWatchAll(buildConfigs);
/**
* @type {(dir: string) => Promise}
@@ -155,16 +145,13 @@ async function buildExtension(target, files) {
const entries = {
"dist/Vencord.js": await readFile("dist/extension.js"),
"dist/Vencord.css": await readFile("dist/extension.css"),
- ...await loadDir("dist/monaco"),
- ...Object.fromEntries(await Promise.all(RnNoiseFiles.map(async file =>
- [`third-party/rnnoise/${file.replace(/^dist\//, "")}`, await readFile(`node_modules/@sapphi-red/web-noise-suppressor/${file}`)]
- ))),
+ ...await loadDir("dist/vendor/monaco", "dist/"),
...Object.fromEntries(await Promise.all(files.map(async f => {
let content = await readFile(join("browser", f));
if (f.startsWith("manifest")) {
const json = JSON.parse(content.toString("utf-8"));
json.version = VERSION;
- content = new TextEncoder().encode(JSON.stringify(json));
+ content = Buffer.from(new TextEncoder().encode(JSON.stringify(json)));
}
return [
@@ -210,7 +197,6 @@ if (!process.argv.includes("--skip-extension")) {
Zip.sync.zip("dist/firefox-unpacked").compress().save("dist/extension-firefox.zip");
console.info("Packed Firefox Extension written to dist/extension-firefox.zip");
-
} else {
await appendCssRuntime;
}
diff --git a/scripts/build/common.mjs b/scripts/build/common.mjs
index 5e71c8c5f..920e59267 100644
--- a/scripts/build/common.mjs
+++ b/scripts/build/common.mjs
@@ -16,11 +16,13 @@
* along with this program. If not, see .
*/
+// @ts-check
+
import "../suppressExperimentalWarnings.js";
import "../checkNodeVersion.js";
import { exec, execSync } from "child_process";
-import esbuild from "esbuild";
+import esbuild, { build, context } from "esbuild";
import { constants as FsConstants, readFileSync } from "fs";
import { access, readdir, readFile } from "fs/promises";
import { minify as minifyHtml } from "html-minifier-terser";
@@ -31,7 +33,7 @@ import { getPluginTarget } from "../utils.mjs";
import { builtinModules } from "module";
/** @type {import("../../package.json")} */
-const PackageJSON = JSON.parse(readFileSync("package.json"));
+const PackageJSON = JSON.parse(readFileSync("package.json", "utf-8"));
export const VERSION = PackageJSON.version;
// https://reproducible-builds.org/docs/source-date-epoch/
@@ -54,6 +56,34 @@ export const banner = {
`.trim()
};
+/**
+ * JSON.stringify all values in an object
+ * @type {(obj: Record) => Record}
+ */
+export function stringifyValues(obj) {
+ for (const key in obj) {
+ obj[key] = JSON.stringify(obj[key]);
+ }
+ return obj;
+}
+
+/**
+ * @param {import("esbuild").BuildOptions[]} buildConfigs
+ */
+export async function buildOrWatchAll(buildConfigs) {
+ if (watch) {
+ await Promise.all(buildConfigs.map(cfg =>
+ context(cfg).then(ctx => ctx.watch())
+ ));
+ } else {
+ await Promise.all(buildConfigs.map(cfg => build(cfg)))
+ .catch(error => {
+ console.error(error.message);
+ process.exit(1); // exit immediately to skip the rest of the builds
+ });
+ }
+}
+
const PluginDefinitionNameMatcher = /definePlugin\(\{\s*(["'])?name\1:\s*(["'`])(.+?)\2/;
/**
* @param {string} base
@@ -311,18 +341,16 @@ export const banImportPlugin = (filter, message) => ({
export const commonOpts = {
logLevel: "info",
bundle: true,
- watch,
minify: !watch && !IS_REPORTER,
- sourcemap: watch ? "inline" : "",
+ sourcemap: watch ? "inline" : "external",
legalComments: "linked",
banner,
plugins: [fileUrlPlugin, gitHashPlugin, gitRemotePlugin, stylePlugin],
external: ["~plugins", "~git-hash", "~git-remote", "/assets/*"],
inject: ["./scripts/build/inject/react.mjs"],
+ jsx: "transform",
jsxFactory: "VencordCreateElement",
- jsxFragment: "VencordFragment",
- // Work around https://github.com/evanw/esbuild/issues/2460
- tsconfig: "./scripts/build/tsconfig.esbuild.json"
+ jsxFragment: "VencordFragment"
};
const escapedBuiltinModules = builtinModules
@@ -335,5 +363,6 @@ export const commonRendererPlugins = [
banImportPlugin(/^react$/, "Cannot import from react. React and hooks should be imported from @webpack/common"),
banImportPlugin(/^electron(\/.*)?$/, "Cannot import electron in browser code. You need to use a native.ts file"),
banImportPlugin(/^ts-pattern$/, "Cannot import from ts-pattern. match and P should be imported from @webpack/common"),
+ // @ts-ignore this is never undefined
...commonOpts.plugins
];
diff --git a/scripts/build/tsconfig.esbuild.json b/scripts/build/tsconfig.esbuild.json
deleted file mode 100644
index e3e28a14d..000000000
--- a/scripts/build/tsconfig.esbuild.json
+++ /dev/null
@@ -1,7 +0,0 @@
-// Work around https://github.com/evanw/esbuild/issues/2460
-{
- "extends": "../../tsconfig.json",
- "compilerOptions": {
- "jsx": "react"
- }
-}