Merge branch 'dev' into stickercopy

This commit is contained in:
byeoon 2025-02-12 12:48:21 -05:00 committed by GitHub
commit b7be63b8f5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 642 additions and 620 deletions

View file

@ -36,7 +36,7 @@
"web_accessible_resources": [ "web_accessible_resources": [
{ {
"resources": ["dist/*", "third-party/*"], "resources": ["dist/*", "vendor/*"],
"matches": ["*://*.discord.com/*"] "matches": ["*://*.discord.com/*"]
} }
], ],

View file

@ -15,7 +15,7 @@ declare global {
const getTheme: () => string; const getTheme: () => string;
} }
const BASE = "/dist/monaco/vs"; const BASE = "/vendor/monaco/vs";
self.MonacoEnvironment = { self.MonacoEnvironment = {
getWorkerUrl(_moduleId: unknown, label: string) { getWorkerUrl(_moduleId: unknown, label: string) {

View file

@ -24,12 +24,12 @@
<script> <script>
const script = document.createElement("script"); const script = document.createElement("script");
script.src = new URL("/dist/monaco/index.js", baseUrl); script.src = new URL("/vendor/monaco/index.js", baseUrl);
const style = document.createElement("link"); const style = document.createElement("link");
style.type = "text/css"; style.type = "text/css";
style.rel = "stylesheet"; style.rel = "stylesheet";
style.href = new URL("/dist/monaco/index.css", baseUrl); style.href = new URL("/vendor/monaco/index.css", baseUrl);
document.body.append(style, script); document.body.append(style, script);
</script> </script>

View file

@ -134,7 +134,7 @@ export default tseslint.config(
"no-unsafe-optional-chaining": "error", "no-unsafe-optional-chaining": "error",
"no-useless-backreference": "error", "no-useless-backreference": "error",
"use-isnan": "error", "use-isnan": "error",
"prefer-const": "error", "prefer-const": ["error", { destructuring: "all" }],
"prefer-spread": "error", "prefer-spread": "error",
// Plugin Rules // Plugin Rules

View file

@ -30,13 +30,12 @@
"lint": "eslint", "lint": "eslint",
"lint-styles": "stylelint \"src/**/*.css\" --ignore-pattern src/userplugins", "lint-styles": "stylelint \"src/**/*.css\" --ignore-pattern src/userplugins",
"lint:fix": "pnpm lint --fix", "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", "testWeb": "pnpm lint && pnpm buildWeb && pnpm testTsc",
"testTsc": "tsc --noEmit" "testTsc": "tsc --noEmit"
}, },
"dependencies": { "dependencies": {
"@intrnl/xxhash64": "^0.1.2", "@intrnl/xxhash64": "^0.1.2",
"@sapphi-red/web-noise-suppressor": "0.3.5",
"@vap/core": "0.0.12", "@vap/core": "0.0.12",
"@vap/shiki": "0.10.5", "@vap/shiki": "0.10.5",
"fflate": "^0.8.2", "fflate": "^0.8.2",
@ -56,7 +55,7 @@
"@types/yazl": "^2.4.5", "@types/yazl": "^2.4.5",
"diff": "^7.0.0", "diff": "^7.0.0",
"discord-types": "^1.3.26", "discord-types": "^1.3.26",
"esbuild": "^0.15.18", "esbuild": "^0.25.0",
"eslint": "^9.17.0", "eslint": "^9.17.0",
"eslint-import-resolver-alias": "^1.1.2", "eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-path-alias": "2.1.0", "eslint-plugin-path-alias": "2.1.0",

482
pnpm-lock.yaml generated
View file

@ -19,9 +19,6 @@ importers:
'@intrnl/xxhash64': '@intrnl/xxhash64':
specifier: ^0.1.2 specifier: ^0.1.2
version: 0.1.2 version: 0.1.2
'@sapphi-red/web-noise-suppressor':
specifier: 0.3.5
version: 0.3.5
'@vap/core': '@vap/core':
specifier: 0.0.12 specifier: 0.0.12
version: 0.0.12 version: 0.0.12
@ -75,8 +72,8 @@ importers:
specifier: ^1.3.26 specifier: ^1.3.26
version: 1.3.26 version: 1.3.26
esbuild: esbuild:
specifier: ^0.15.18 specifier: ^0.25.0
version: 0.15.18 version: 0.25.0
eslint: eslint:
specifier: ^9.17.0 specifier: ^9.17.0
version: 9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4) version: 9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4)
@ -229,6 +226,12 @@ packages:
cpu: [ppc64] cpu: [ppc64]
os: [aix] 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': '@esbuild/android-arm64@0.17.19':
resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -241,10 +244,10 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@esbuild/android-arm@0.15.18': '@esbuild/android-arm64@0.25.0':
resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==} resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==}
engines: {node: '>=12'} engines: {node: '>=18'}
cpu: [arm] cpu: [arm64]
os: [android] os: [android]
'@esbuild/android-arm@0.17.19': '@esbuild/android-arm@0.17.19':
@ -259,6 +262,12 @@ packages:
cpu: [arm] cpu: [arm]
os: [android] 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': '@esbuild/android-x64@0.17.19':
resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -271,6 +280,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [android] 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': '@esbuild/darwin-arm64@0.17.19':
resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -283,6 +298,12 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [darwin] 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': '@esbuild/darwin-x64@0.17.19':
resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -295,6 +316,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [darwin] 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': '@esbuild/freebsd-arm64@0.17.19':
resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -307,6 +334,12 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [freebsd] 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': '@esbuild/freebsd-x64@0.17.19':
resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -319,6 +352,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [freebsd] 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': '@esbuild/linux-arm64@0.17.19':
resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -331,6 +370,12 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [linux] 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': '@esbuild/linux-arm@0.17.19':
resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -343,6 +388,12 @@ packages:
cpu: [arm] cpu: [arm]
os: [linux] 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': '@esbuild/linux-ia32@0.17.19':
resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -355,10 +406,10 @@ packages:
cpu: [ia32] cpu: [ia32]
os: [linux] os: [linux]
'@esbuild/linux-loong64@0.15.18': '@esbuild/linux-ia32@0.25.0':
resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==} resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==}
engines: {node: '>=12'} engines: {node: '>=18'}
cpu: [loong64] cpu: [ia32]
os: [linux] os: [linux]
'@esbuild/linux-loong64@0.17.19': '@esbuild/linux-loong64@0.17.19':
@ -373,6 +424,12 @@ packages:
cpu: [loong64] cpu: [loong64]
os: [linux] 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': '@esbuild/linux-mips64el@0.17.19':
resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -385,6 +442,12 @@ packages:
cpu: [mips64el] cpu: [mips64el]
os: [linux] 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': '@esbuild/linux-ppc64@0.17.19':
resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -397,6 +460,12 @@ packages:
cpu: [ppc64] cpu: [ppc64]
os: [linux] 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': '@esbuild/linux-riscv64@0.17.19':
resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -409,6 +478,12 @@ packages:
cpu: [riscv64] cpu: [riscv64]
os: [linux] 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': '@esbuild/linux-s390x@0.17.19':
resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -421,6 +496,12 @@ packages:
cpu: [s390x] cpu: [s390x]
os: [linux] 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': '@esbuild/linux-x64@0.17.19':
resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -433,6 +514,18 @@ packages:
cpu: [x64] cpu: [x64]
os: [linux] 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': '@esbuild/netbsd-x64@0.17.19':
resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -445,12 +538,24 @@ packages:
cpu: [x64] cpu: [x64]
os: [netbsd] 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': '@esbuild/openbsd-arm64@0.23.1':
resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [openbsd] 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': '@esbuild/openbsd-x64@0.17.19':
resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -463,6 +568,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [openbsd] 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': '@esbuild/sunos-x64@0.17.19':
resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -475,6 +586,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [sunos] 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': '@esbuild/win32-arm64@0.17.19':
resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -487,6 +604,12 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [win32] 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': '@esbuild/win32-ia32@0.17.19':
resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -499,6 +622,12 @@ packages:
cpu: [ia32] cpu: [ia32]
os: [win32] 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': '@esbuild/win32-x64@0.17.19':
resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -511,6 +640,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] 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': '@eslint-community/eslint-utils@4.4.1':
resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@ -609,9 +744,6 @@ packages:
'@rtsao/scc@1.1.0': '@rtsao/scc@1.1.0':
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} 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': '@stylistic/eslint-plugin@2.12.1':
resolution: {integrity: sha512-fubZKIHSPuo07FgRTn6S4Nl0uXPRPYVNpyZzIDGfp7Fny6JjNus6kReLD7NI380JXi4HtUTSOZ34LBuNPO1XLQ==} resolution: {integrity: sha512-fubZKIHSPuo07FgRTn6S4Nl0uXPRPYVNpyZzIDGfp7Fny6JjNus6kReLD7NI380JXi4HtUTSOZ34LBuNPO1XLQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 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==} resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
engines: {node: '>= 0.4'} 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: esbuild@0.17.19:
resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -1340,6 +1347,11 @@ packages:
engines: {node: '>=18'} engines: {node: '>=18'}
hasBin: true hasBin: true
esbuild@0.25.0:
resolution: {integrity: sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==}
engines: {node: '>=18'}
hasBin: true
escalade@3.2.0: escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -2889,13 +2901,16 @@ snapshots:
'@esbuild/aix-ppc64@0.23.1': '@esbuild/aix-ppc64@0.23.1':
optional: true optional: true
'@esbuild/aix-ppc64@0.25.0':
optional: true
'@esbuild/android-arm64@0.17.19': '@esbuild/android-arm64@0.17.19':
optional: true optional: true
'@esbuild/android-arm64@0.23.1': '@esbuild/android-arm64@0.23.1':
optional: true optional: true
'@esbuild/android-arm@0.15.18': '@esbuild/android-arm64@0.25.0':
optional: true optional: true
'@esbuild/android-arm@0.17.19': '@esbuild/android-arm@0.17.19':
@ -2904,55 +2919,79 @@ snapshots:
'@esbuild/android-arm@0.23.1': '@esbuild/android-arm@0.23.1':
optional: true optional: true
'@esbuild/android-arm@0.25.0':
optional: true
'@esbuild/android-x64@0.17.19': '@esbuild/android-x64@0.17.19':
optional: true optional: true
'@esbuild/android-x64@0.23.1': '@esbuild/android-x64@0.23.1':
optional: true optional: true
'@esbuild/android-x64@0.25.0':
optional: true
'@esbuild/darwin-arm64@0.17.19': '@esbuild/darwin-arm64@0.17.19':
optional: true optional: true
'@esbuild/darwin-arm64@0.23.1': '@esbuild/darwin-arm64@0.23.1':
optional: true optional: true
'@esbuild/darwin-arm64@0.25.0':
optional: true
'@esbuild/darwin-x64@0.17.19': '@esbuild/darwin-x64@0.17.19':
optional: true optional: true
'@esbuild/darwin-x64@0.23.1': '@esbuild/darwin-x64@0.23.1':
optional: true optional: true
'@esbuild/darwin-x64@0.25.0':
optional: true
'@esbuild/freebsd-arm64@0.17.19': '@esbuild/freebsd-arm64@0.17.19':
optional: true optional: true
'@esbuild/freebsd-arm64@0.23.1': '@esbuild/freebsd-arm64@0.23.1':
optional: true optional: true
'@esbuild/freebsd-arm64@0.25.0':
optional: true
'@esbuild/freebsd-x64@0.17.19': '@esbuild/freebsd-x64@0.17.19':
optional: true optional: true
'@esbuild/freebsd-x64@0.23.1': '@esbuild/freebsd-x64@0.23.1':
optional: true optional: true
'@esbuild/freebsd-x64@0.25.0':
optional: true
'@esbuild/linux-arm64@0.17.19': '@esbuild/linux-arm64@0.17.19':
optional: true optional: true
'@esbuild/linux-arm64@0.23.1': '@esbuild/linux-arm64@0.23.1':
optional: true optional: true
'@esbuild/linux-arm64@0.25.0':
optional: true
'@esbuild/linux-arm@0.17.19': '@esbuild/linux-arm@0.17.19':
optional: true optional: true
'@esbuild/linux-arm@0.23.1': '@esbuild/linux-arm@0.23.1':
optional: true optional: true
'@esbuild/linux-arm@0.25.0':
optional: true
'@esbuild/linux-ia32@0.17.19': '@esbuild/linux-ia32@0.17.19':
optional: true optional: true
'@esbuild/linux-ia32@0.23.1': '@esbuild/linux-ia32@0.23.1':
optional: true optional: true
'@esbuild/linux-loong64@0.15.18': '@esbuild/linux-ia32@0.25.0':
optional: true optional: true
'@esbuild/linux-loong64@0.17.19': '@esbuild/linux-loong64@0.17.19':
@ -2961,75 +3000,117 @@ snapshots:
'@esbuild/linux-loong64@0.23.1': '@esbuild/linux-loong64@0.23.1':
optional: true optional: true
'@esbuild/linux-loong64@0.25.0':
optional: true
'@esbuild/linux-mips64el@0.17.19': '@esbuild/linux-mips64el@0.17.19':
optional: true optional: true
'@esbuild/linux-mips64el@0.23.1': '@esbuild/linux-mips64el@0.23.1':
optional: true optional: true
'@esbuild/linux-mips64el@0.25.0':
optional: true
'@esbuild/linux-ppc64@0.17.19': '@esbuild/linux-ppc64@0.17.19':
optional: true optional: true
'@esbuild/linux-ppc64@0.23.1': '@esbuild/linux-ppc64@0.23.1':
optional: true optional: true
'@esbuild/linux-ppc64@0.25.0':
optional: true
'@esbuild/linux-riscv64@0.17.19': '@esbuild/linux-riscv64@0.17.19':
optional: true optional: true
'@esbuild/linux-riscv64@0.23.1': '@esbuild/linux-riscv64@0.23.1':
optional: true optional: true
'@esbuild/linux-riscv64@0.25.0':
optional: true
'@esbuild/linux-s390x@0.17.19': '@esbuild/linux-s390x@0.17.19':
optional: true optional: true
'@esbuild/linux-s390x@0.23.1': '@esbuild/linux-s390x@0.23.1':
optional: true optional: true
'@esbuild/linux-s390x@0.25.0':
optional: true
'@esbuild/linux-x64@0.17.19': '@esbuild/linux-x64@0.17.19':
optional: true optional: true
'@esbuild/linux-x64@0.23.1': '@esbuild/linux-x64@0.23.1':
optional: true optional: true
'@esbuild/linux-x64@0.25.0':
optional: true
'@esbuild/netbsd-arm64@0.25.0':
optional: true
'@esbuild/netbsd-x64@0.17.19': '@esbuild/netbsd-x64@0.17.19':
optional: true optional: true
'@esbuild/netbsd-x64@0.23.1': '@esbuild/netbsd-x64@0.23.1':
optional: true optional: true
'@esbuild/netbsd-x64@0.25.0':
optional: true
'@esbuild/openbsd-arm64@0.23.1': '@esbuild/openbsd-arm64@0.23.1':
optional: true optional: true
'@esbuild/openbsd-arm64@0.25.0':
optional: true
'@esbuild/openbsd-x64@0.17.19': '@esbuild/openbsd-x64@0.17.19':
optional: true optional: true
'@esbuild/openbsd-x64@0.23.1': '@esbuild/openbsd-x64@0.23.1':
optional: true optional: true
'@esbuild/openbsd-x64@0.25.0':
optional: true
'@esbuild/sunos-x64@0.17.19': '@esbuild/sunos-x64@0.17.19':
optional: true optional: true
'@esbuild/sunos-x64@0.23.1': '@esbuild/sunos-x64@0.23.1':
optional: true optional: true
'@esbuild/sunos-x64@0.25.0':
optional: true
'@esbuild/win32-arm64@0.17.19': '@esbuild/win32-arm64@0.17.19':
optional: true optional: true
'@esbuild/win32-arm64@0.23.1': '@esbuild/win32-arm64@0.23.1':
optional: true optional: true
'@esbuild/win32-arm64@0.25.0':
optional: true
'@esbuild/win32-ia32@0.17.19': '@esbuild/win32-ia32@0.17.19':
optional: true optional: true
'@esbuild/win32-ia32@0.23.1': '@esbuild/win32-ia32@0.23.1':
optional: true optional: true
'@esbuild/win32-ia32@0.25.0':
optional: true
'@esbuild/win32-x64@0.17.19': '@esbuild/win32-x64@0.17.19':
optional: true optional: true
'@esbuild/win32-x64@0.23.1': '@esbuild/win32-x64@0.23.1':
optional: true optional: true
'@esbuild/win32-x64@0.25.0':
optional: true
'@eslint-community/eslint-utils@4.4.1(eslint@9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4))': '@eslint-community/eslint-utils@4.4.1(eslint@9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4))':
dependencies: dependencies:
eslint: 9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4) eslint: 9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4)
@ -3135,8 +3216,6 @@ snapshots:
'@rtsao/scc@1.1.0': {} '@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)': '@stylistic/eslint-plugin@2.12.1(eslint@9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4))(typescript@5.7.2)':
dependencies: dependencies:
'@typescript-eslint/utils': 8.18.1(eslint@9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4))(typescript@5.7.2) '@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-date-object: 1.1.0
is-symbol: 1.1.1 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: esbuild@0.17.19:
optionalDependencies: optionalDependencies:
'@esbuild/android-arm': 0.17.19 '@esbuild/android-arm': 0.17.19
@ -4073,6 +4067,34 @@ snapshots:
'@esbuild/win32-ia32': 0.23.1 '@esbuild/win32-ia32': 0.23.1
'@esbuild/win32-x64': 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: {} escalade@3.2.0: {}
escape-string-regexp@4.0.0: {} escape-string-regexp@4.0.0: {}

View file

@ -17,38 +17,41 @@
* 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 esbuild from "esbuild"; // @ts-check
import { readdir } from "fs/promises"; import { readdir } from "fs/promises";
import { join } from "path"; 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_STANDALONE,
IS_DEV, IS_DEV,
IS_REPORTER, IS_REPORTER,
IS_UPDATER_DISABLED, IS_UPDATER_DISABLED,
IS_WEB: false, IS_WEB: false,
IS_EXTENSION: false, IS_EXTENSION: false,
VERSION: JSON.stringify(VERSION), VERSION,
BUILD_TIMESTAMP BUILD_TIMESTAMP
}; });
if (defines.IS_STANDALONE === false) if (defines.IS_STANDALONE === "false") {
// If this is a local build (not standalone), optimize // If this is a local build (not standalone), optimize
// for the specific platform we're on // for the specific platform we're on
defines["process.platform"] = JSON.stringify(process.platform); defines["process.platform"] = JSON.stringify(process.platform);
}
/** /**
* @type {esbuild.BuildOptions} * @type {import("esbuild").BuildOptions}
*/ */
const nodeCommonOpts = { const nodeCommonOpts = {
...commonOpts, ...commonOpts,
define: defines,
format: "cjs", format: "cjs",
platform: "node", platform: "node",
target: ["esnext"], target: ["esnext"],
external: ["electron", "original-fs", "~pluginNatives", ...commonOpts.external], // @ts-ignore this is never undefined
define: defines external: ["electron", "original-fs", "~pluginNatives", ...commonOpts.external]
}; };
const sourceMapFooter = s => watch ? "" : `//# sourceMappingURL=vencord://${s}.js.map`; 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 // Discord Desktop main & renderer & preload
esbuild.build({ {
...nodeCommonOpts, ...nodeCommonOpts,
entryPoints: ["src/main/index.ts"], entryPoints: ["src/main/index.ts"],
outfile: "dist/patcher.js", outfile: "dist/patcher.js",
footer: { js: "//# sourceURL=VencordPatcher\n" + sourceMapFooter("patcher") }, footer: { js: "//# sourceURL=VencordPatcher\n" + sourceMapFooter("patcher") },
sourcemap, sourcemap,
define: {
...defines,
IS_DISCORD_DESKTOP: true,
IS_VESKTOP: false
},
plugins: [ plugins: [
// @ts-ignore this is never undefined
...nodeCommonOpts.plugins, ...nodeCommonOpts.plugins,
globNativesPlugin globNativesPlugin
] ],
}), define: {
esbuild.build({ ...defines,
IS_DISCORD_DESKTOP: "true",
IS_VESKTOP: "false"
}
},
{
...commonOpts, ...commonOpts,
entryPoints: ["src/Vencord.ts"], entryPoints: ["src/Vencord.ts"],
outfile: "dist/renderer.js", outfile: "dist/renderer.js",
@ -135,11 +140,11 @@ await Promise.all([
], ],
define: { define: {
...defines, ...defines,
IS_DISCORD_DESKTOP: true, IS_DISCORD_DESKTOP: "true",
IS_VESKTOP: false IS_VESKTOP: "false"
} }
}), },
esbuild.build({ {
...nodeCommonOpts, ...nodeCommonOpts,
entryPoints: ["src/preload.ts"], entryPoints: ["src/preload.ts"],
outfile: "dist/preload.js", outfile: "dist/preload.js",
@ -147,29 +152,29 @@ await Promise.all([
sourcemap, sourcemap,
define: { define: {
...defines, ...defines,
IS_DISCORD_DESKTOP: true, IS_DISCORD_DESKTOP: "true",
IS_VESKTOP: false IS_VESKTOP: "false"
} }
}), },
// Vencord Desktop main & renderer & preload // Vencord Desktop main & renderer & preload
esbuild.build({ {
...nodeCommonOpts, ...nodeCommonOpts,
entryPoints: ["src/main/index.ts"], entryPoints: ["src/main/index.ts"],
outfile: "dist/vencordDesktopMain.js", outfile: "dist/vencordDesktopMain.js",
footer: { js: "//# sourceURL=VencordDesktopMain\n" + sourceMapFooter("vencordDesktopMain") }, footer: { js: "//# sourceURL=VencordDesktopMain\n" + sourceMapFooter("vencordDesktopMain") },
sourcemap, sourcemap,
define: {
...defines,
IS_DISCORD_DESKTOP: false,
IS_VESKTOP: true
},
plugins: [ plugins: [
...nodeCommonOpts.plugins, ...nodeCommonOpts.plugins,
globNativesPlugin globNativesPlugin
] ],
}), define: {
esbuild.build({ ...defines,
IS_DISCORD_DESKTOP: "false",
IS_VESKTOP: "true"
}
},
{
...commonOpts, ...commonOpts,
entryPoints: ["src/Vencord.ts"], entryPoints: ["src/Vencord.ts"],
outfile: "dist/vencordDesktopRenderer.js", outfile: "dist/vencordDesktopRenderer.js",
@ -184,11 +189,11 @@ await Promise.all([
], ],
define: { define: {
...defines, ...defines,
IS_DISCORD_DESKTOP: false, IS_DISCORD_DESKTOP: "false",
IS_VESKTOP: true IS_VESKTOP: "true"
} }
}), },
esbuild.build({ {
...nodeCommonOpts, ...nodeCommonOpts,
entryPoints: ["src/preload.ts"], entryPoints: ["src/preload.ts"],
outfile: "dist/vencordDesktopPreload.js", outfile: "dist/vencordDesktopPreload.js",
@ -196,14 +201,10 @@ await Promise.all([
sourcemap, sourcemap,
define: { define: {
...defines, ...defines,
IS_DISCORD_DESKTOP: false, IS_DISCORD_DESKTOP: "false",
IS_VESKTOP: true IS_VESKTOP: "true"
} }
}), }
]).catch(err => { ]);
console.error("Build failed");
console.error(err.message); await buildOrWatchAll(buildConfigs);
// make ci fail
if (!commonOpts.watch)
process.exitCode = 1;
});

View file

@ -17,29 +17,30 @@
* 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 esbuild from "esbuild"; // @ts-check
import { readFileSync } from "fs"; import { readFileSync } from "fs";
import { appendFile, mkdir, readdir, readFile, rm, writeFile } from "fs/promises"; import { appendFile, mkdir, readdir, readFile, rm, writeFile } from "fs/promises";
import { join } from "path"; import { join } from "path";
import Zip from "zip-local"; 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 = { const commonOptions = {
...commonOpts, ...commonOpts,
entryPoints: ["browser/Vencord.ts"], entryPoints: ["browser/Vencord.ts"],
globalName: "Vencord",
format: "iife", format: "iife",
globalName: "Vencord",
external: ["~plugins", "~git-hash", "/assets/*"], external: ["~plugins", "~git-hash", "/assets/*"],
target: ["esnext"],
plugins: [ plugins: [
globPlugins("web"), globPlugins("web"),
...commonRendererPlugins ...commonRendererPlugins
], ],
target: ["esnext"], define: stringifyValues({
define: {
IS_WEB: true, IS_WEB: true,
IS_EXTENSION: false, IS_EXTENSION: false,
IS_STANDALONE: true, IS_STANDALONE: true,
@ -48,9 +49,9 @@ const commonOptions = {
IS_DISCORD_DESKTOP: false, IS_DISCORD_DESKTOP: false,
IS_VESKTOP: false, IS_VESKTOP: false,
IS_UPDATER_DISABLED: true, IS_UPDATER_DISABLED: true,
VERSION: JSON.stringify(VERSION), VERSION,
BUILD_TIMESTAMP BUILD_TIMESTAMP
} })
}; };
const MonacoWorkerEntryPoints = [ const MonacoWorkerEntryPoints = [
@ -58,52 +59,45 @@ const MonacoWorkerEntryPoints = [
"vs/editor/editor.worker.js" "vs/editor/editor.worker.js"
]; ];
const RnNoiseFiles = [ /** @type {import("esbuild").BuildOptions[]} */
"dist/rnnoise.wasm", const buildConfigs = [
"dist/rnnoise_simd.wasm", {
"dist/rnnoise/workletProcessor.js",
"LICENSE"
];
await Promise.all(
[
esbuild.build({
entryPoints: MonacoWorkerEntryPoints.map(entry => `node_modules/monaco-editor/esm/${entry}`), entryPoints: MonacoWorkerEntryPoints.map(entry => `node_modules/monaco-editor/esm/${entry}`),
bundle: true, bundle: true,
minify: true, minify: true,
format: "iife", format: "iife",
outbase: "node_modules/monaco-editor/esm/", outbase: "node_modules/monaco-editor/esm/",
outdir: "dist/monaco" outdir: "dist/vendor/monaco"
}), },
esbuild.build({ {
entryPoints: ["browser/monaco.ts"], entryPoints: ["browser/monaco.ts"],
bundle: true, bundle: true,
minify: true, minify: true,
format: "iife", format: "iife",
outfile: "dist/monaco/index.js", outfile: "dist/vendor/monaco/index.js",
loader: { loader: {
".ttf": "file" ".ttf": "file"
} }
}), },
esbuild.build({ {
...commonOptions, ...commonOptions,
outfile: "dist/browser.js", outfile: "dist/browser.js",
footer: { js: "//# sourceURL=VencordWeb" } footer: { js: "//# sourceURL=VencordWeb" }
}), },
esbuild.build({ {
...commonOptions, ...commonOptions,
outfile: "dist/extension.js", outfile: "dist/extension.js",
define: { define: {
...commonOptions?.define, ...commonOptions.define,
IS_EXTENSION: true, IS_EXTENSION: "true"
}, },
footer: { js: "//# sourceURL=VencordWeb" } footer: { js: "//# sourceURL=VencordWeb" }
}), },
esbuild.build({ {
...commonOptions, ...commonOptions,
inject: ["browser/GMPolyfill.js", ...(commonOptions?.inject || [])], inject: ["browser/GMPolyfill.js", ...(commonOptions?.inject || [])],
define: { define: {
...(commonOptions?.define), ...commonOptions.define,
window: "unsafeWindow", window: "unsafeWindow",
}, },
outfile: "dist/Vencord.user.js", outfile: "dist/Vencord.user.js",
@ -114,14 +108,10 @@ await Promise.all(
// UserScripts get wrapped in an iife, so define Vencord prop on window that returns our local // UserScripts get wrapped in an iife, so define Vencord prop on window that returns our local
js: "Object.defineProperty(unsafeWindow,'Vencord',{get:()=>Vencord});" js: "Object.defineProperty(unsafeWindow,'Vencord',{get:()=>Vencord});"
} }
}) }
] ];
).catch(err => {
console.error("Build failed"); await buildOrWatchAll(buildConfigs);
console.error(err.message);
if (!commonOpts.watch)
process.exit(1);
});;
/** /**
* @type {(dir: string) => Promise<string[]>} * @type {(dir: string) => Promise<string[]>}
@ -155,16 +145,13 @@ async function buildExtension(target, files) {
const entries = { const entries = {
"dist/Vencord.js": await readFile("dist/extension.js"), "dist/Vencord.js": await readFile("dist/extension.js"),
"dist/Vencord.css": await readFile("dist/extension.css"), "dist/Vencord.css": await readFile("dist/extension.css"),
...await loadDir("dist/monaco"), ...await loadDir("dist/vendor/monaco", "dist/"),
...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}`)]
))),
...Object.fromEntries(await Promise.all(files.map(async f => { ...Object.fromEntries(await Promise.all(files.map(async f => {
let content = await readFile(join("browser", f)); let content = await readFile(join("browser", f));
if (f.startsWith("manifest")) { if (f.startsWith("manifest")) {
const json = JSON.parse(content.toString("utf-8")); const json = JSON.parse(content.toString("utf-8"));
json.version = VERSION; json.version = VERSION;
content = new TextEncoder().encode(JSON.stringify(json)); content = Buffer.from(new TextEncoder().encode(JSON.stringify(json)));
} }
return [ return [
@ -210,7 +197,6 @@ if (!process.argv.includes("--skip-extension")) {
Zip.sync.zip("dist/firefox-unpacked").compress().save("dist/extension-firefox.zip"); Zip.sync.zip("dist/firefox-unpacked").compress().save("dist/extension-firefox.zip");
console.info("Packed Firefox Extension written to dist/extension-firefox.zip"); console.info("Packed Firefox Extension written to dist/extension-firefox.zip");
} else { } else {
await appendCssRuntime; await appendCssRuntime;
} }

View file

@ -16,11 +16,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
// @ts-check
import "../suppressExperimentalWarnings.js"; import "../suppressExperimentalWarnings.js";
import "../checkNodeVersion.js"; import "../checkNodeVersion.js";
import { exec, execSync } from "child_process"; import { exec, execSync } from "child_process";
import esbuild from "esbuild"; import esbuild, { build, context } from "esbuild";
import { constants as FsConstants, readFileSync } from "fs"; import { constants as FsConstants, readFileSync } from "fs";
import { access, readdir, readFile } from "fs/promises"; import { access, readdir, readFile } from "fs/promises";
import { minify as minifyHtml } from "html-minifier-terser"; import { minify as minifyHtml } from "html-minifier-terser";
@ -31,7 +33,7 @@ import { getPluginTarget } from "../utils.mjs";
import { builtinModules } from "module"; import { builtinModules } from "module";
/** @type {import("../../package.json")} */ /** @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; export const VERSION = PackageJSON.version;
// https://reproducible-builds.org/docs/source-date-epoch/ // https://reproducible-builds.org/docs/source-date-epoch/
@ -54,6 +56,34 @@ export const banner = {
`.trim() `.trim()
}; };
/**
* JSON.stringify all values in an object
* @type {(obj: Record<string, any>) => Record<string, string>}
*/
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/; const PluginDefinitionNameMatcher = /definePlugin\(\{\s*(["'])?name\1:\s*(["'`])(.+?)\2/;
/** /**
* @param {string} base * @param {string} base
@ -311,18 +341,16 @@ export const banImportPlugin = (filter, message) => ({
export const commonOpts = { export const commonOpts = {
logLevel: "info", logLevel: "info",
bundle: true, bundle: true,
watch,
minify: !watch && !IS_REPORTER, minify: !watch && !IS_REPORTER,
sourcemap: watch ? "inline" : "", sourcemap: watch ? "inline" : "external",
legalComments: "linked", legalComments: "linked",
banner, banner,
plugins: [fileUrlPlugin, gitHashPlugin, gitRemotePlugin, stylePlugin], plugins: [fileUrlPlugin, gitHashPlugin, gitRemotePlugin, stylePlugin],
external: ["~plugins", "~git-hash", "~git-remote", "/assets/*"], external: ["~plugins", "~git-hash", "~git-remote", "/assets/*"],
inject: ["./scripts/build/inject/react.mjs"], inject: ["./scripts/build/inject/react.mjs"],
jsx: "transform",
jsxFactory: "VencordCreateElement", jsxFactory: "VencordCreateElement",
jsxFragment: "VencordFragment", jsxFragment: "VencordFragment"
// Work around https://github.com/evanw/esbuild/issues/2460
tsconfig: "./scripts/build/tsconfig.esbuild.json"
}; };
const escapedBuiltinModules = builtinModules 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(/^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(/^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"), 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 ...commonOpts.plugins
]; ];

View file

@ -1,7 +0,0 @@
// Work around https://github.com/evanw/esbuild/issues/2460
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"jsx": "react"
}
}

View file

@ -16,11 +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/>.
*/ */
/* eslint-disable no-fallthrough */
// eslint-disable-next-line spaced-comment
/// <reference types="../src/globals" /> /// <reference types="../src/globals" />
// eslint-disable-next-line spaced-comment
/// <reference types="../src/modules" /> /// <reference types="../src/modules" />
import { createHmac } from "crypto"; import { createHmac } from "crypto";

View file

@ -8,7 +8,7 @@ import { Logger } from "@utils/Logger";
import { canonicalizeMatch } from "@utils/patches"; import { canonicalizeMatch } from "@utils/patches";
import * as Webpack from "@webpack"; import * as Webpack from "@webpack";
import { wreq } from "@webpack"; import { wreq } from "@webpack";
import { AnyModuleFactory, ModuleFactory } from "webpack"; import { AnyModuleFactory, ModuleFactory } from "@webpack/wreq.d";
export async function loadLazyChunks() { export async function loadLazyChunks() {
const LazyChunkLoaderLogger = new Logger("LazyChunkLoader"); const LazyChunkLoaderLogger = new Logger("LazyChunkLoader");
@ -140,8 +140,8 @@ export async function loadLazyChunks() {
} }
Webpack.factoryListeners.add(factoryListener); Webpack.factoryListeners.add(factoryListener);
for (const factoryId in wreq.m) { for (const moduleId in wreq.m) {
factoryListener(wreq.m[factoryId]); factoryListener(wreq.m[moduleId]);
} }
await chunksSearchingDone; await chunksSearchingDone;

View file

@ -6,9 +6,9 @@
import { Logger } from "@utils/Logger"; import { Logger } from "@utils/Logger";
import * as Webpack from "@webpack"; import * as Webpack from "@webpack";
import { addPatch, patches } from "plugins"; import { getBuildNumber, patchTimings } from "@webpack/patcher";
import { getBuildNumber } from "webpack/patchWebpack";
import { addPatch, patches } from "../plugins";
import { loadLazyChunks } from "./loadLazyChunks"; import { loadLazyChunks } from "./loadLazyChunks";
async function runReporter() { 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) { if (totalTime > 5) {
new Logger("WebpackInterceptor").warn(`Patch by ${plugin} took ${Math.round(totalTime * 100) / 100}ms (Module id is ${String(moduleId)}): ${match}`); new Logger("WebpackInterceptor").warn(`Patch by ${plugin} took ${Math.round(totalTime * 100) / 100}ms (Module id is ${String(moduleId)}): ${match}`);
} }

View file

@ -20,7 +20,7 @@ import { definePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import { Logger } from "@utils/Logger"; import { Logger } from "@utils/Logger";
import definePlugin, { OptionType, StartAt } from "@utils/types"; import definePlugin, { OptionType, StartAt } from "@utils/types";
import { WebpackRequire } from "webpack"; import { WebpackRequire } from "@webpack/wreq.d";
const settings = definePluginSettings({ const settings = definePluginSettings({
disableAnalytics: { disableAnalytics: {

View file

@ -31,6 +31,7 @@ import { Logger } from "@utils/Logger";
import { canonicalizeFind, canonicalizeReplacement } from "@utils/patches"; import { canonicalizeFind, canonicalizeReplacement } from "@utils/patches";
import { Patch, Plugin, PluginDef, ReporterTestable, StartAt } from "@utils/types"; import { Patch, Plugin, PluginDef, ReporterTestable, StartAt } from "@utils/types";
import { FluxDispatcher } from "@webpack/common"; import { FluxDispatcher } from "@webpack/common";
import { patches } from "@webpack/patcher";
import { FluxEvents } from "@webpack/types"; import { FluxEvents } from "@webpack/types";
import Plugins from "~plugins"; import Plugins from "~plugins";
@ -41,7 +42,7 @@ const logger = new Logger("PluginManager", "#a6d189");
export const PMLogger = logger; export const PMLogger = logger;
export const plugins = Plugins; 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 */ /** Whether we have subscribed to flux events of all the enabled plugins when FluxDispatcher was ready */
let enabledPluginsSubscribedFlux = false; let enabledPluginsSubscribedFlux = false;

View file

@ -9,32 +9,23 @@ import { makeLazy } from "@utils/lazy";
import { Logger } from "@utils/Logger"; import { Logger } from "@utils/Logger";
import { interpolateIfDefined } from "@utils/misc"; import { interpolateIfDefined } from "@utils/misc";
import { canonicalizeReplacement } from "@utils/patches"; import { canonicalizeReplacement } from "@utils/patches";
import { PatchReplacement } from "@utils/types"; import { Patch, PatchReplacement } from "@utils/types";
import { traceFunctionWithResults } from "../debug/Tracer"; import { traceFunctionWithResults } from "../debug/Tracer";
import { patches } from "../plugins"; import { _initWebpack, _shouldIgnoreModule, factoryListeners, findModuleId, moduleListeners, waitForSubscriptions, wreq } from "./webpack";
import { _initWebpack, _shouldIgnoreModule, AnyModuleFactory, AnyWebpackRequire, factoryListeners, findModuleId, MaybeWrappedModuleFactory, ModuleExports, moduleListeners, waitForSubscriptions, WebpackRequire, WrappedModuleFactory, wreq } from "."; 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_ORIGINAL_FACTORY = Symbol("WebpackPatcher.originalFactory");
export const SYM_PATCHED_SOURCE = Symbol("WebpackPatcher.patchedSource"); export const SYM_PATCHED_SOURCE = Symbol("WebpackPatcher.patchedSource");
export const SYM_PATCHED_BY = Symbol("WebpackPatcher.patchedBy"); export const SYM_PATCHED_BY = Symbol("WebpackPatcher.patchedBy");
/** A set with all the Webpack instances */
export const allWebpackInstances = new Set<AnyWebpackRequire>(); export const allWebpackInstances = new Set<AnyWebpackRequire>();
export const patchTimings = [] as Array<[plugin: string, moduleId: PropertyKey, match: string | RegExp, totalTime: number]>;
const logger = new Logger("WebpackInterceptor", "#8caaee"); export const patchTimings = [] as Array<[plugin: string, moduleId: PropertyKey, match: PatchReplacement["match"], totalTime: number]>;
/** 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 getBuildNumber = makeLazy(() => { export const getBuildNumber = makeLazy(() => {
try { try {
shouldPatchFactories = false;
try { try {
if (wreq.m[128014]?.toString().includes("Trying to open a changelog for an invalid build number")) { if (wreq.m[128014]?.toString().includes("Trying to open a changelog for an invalid build number")) {
const hardcodedGetBuildNumber = wreq(128014).b as () => number; const hardcodedGetBuildNumber = wreq(128014).b as () => number;
@ -59,13 +50,23 @@ export const getBuildNumber = makeLazy(() => {
return typeof buildNumber === "number" ? buildNumber : -1; return typeof buildNumber === "number" ? buildNumber : -1;
} catch { } catch {
return -1; return -1;
} finally {
shouldPatchFactories = true;
} }
}); });
type Define = typeof Reflect.defineProperty; export function getFactoryPatchedSource(moduleId: PropertyKey, webpackRequire = wreq as AnyWebpackRequire) {
const define: Define = (target, p, attributes) => { 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")) { if (Object.hasOwn(attributes, "value")) {
attributes.writable = true; attributes.writable = true;
} }
@ -77,22 +78,17 @@ const define: Define = (target, p, attributes) => {
}); });
}; };
export function getOriginalFactory(id: PropertyKey, webpackRequire = wreq as AnyWebpackRequire) { // wreq.m is the Webpack object containing module factories. It is pre-populated with factories, and is also populated via webpackGlobal.push
const moduleFactory = webpackRequire.m[id]; // We use this setter to intercept when wreq.m is defined and apply patching to its factories.
return (moduleFactory?.[SYM_ORIGINAL_FACTORY] ?? moduleFactory) as AnyModuleFactory | undefined;
}
export function getFactoryPatchedSource(id: PropertyKey, webpackRequire = wreq as AnyWebpackRequire) { // Factories can be patched in two ways. Eagerly or lazily.
return webpackRequire.m[id]?.[SYM_PATCHED_SOURCE]; // 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) { // Factories are always wrapped in a proxy, which allows us to intercept the call to them, patch if they werent eagerly patched,
return webpackRequire.m[id]?.[SYM_PATCHED_BY]; // 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 // 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.
// 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.
// If this is the main Webpack, we also set up the internal references to WebpackRequire. // If this is the main Webpack, we also set up the internal references to WebpackRequire.
define(Function.prototype, "m", { define(Function.prototype, "m", {
@ -131,13 +127,17 @@ define(Function.prototype, "m", {
const setterTimeout = setTimeout(() => Reflect.deleteProperty(this, "e"), 0); const setterTimeout = setTimeout(() => Reflect.deleteProperty(this, "e"), 0);
// Patch the pre-populated factories // Patch the pre-populated factories
for (const id in originalModules) { for (const moduleId in originalModules) {
if (updateExistingFactory(originalModules, id, originalModules[id], true)) { const originalFactory = originalModules[moduleId];
if (updateExistingFactory(originalModules, moduleId, originalFactory, originalModules, true)) {
continue; continue;
} }
notifyFactoryListeners(originalModules[id]); notifyFactoryListeners(moduleId, originalFactory);
defineModulesFactoryGetter(id, Settings.eagerPatches && shouldPatchFactories ? wrapAndPatchFactory(id, originalModules[id]) : originalModules[id]);
const proxiedFactory = new Proxy(Settings.eagerPatches ? patchFactory(moduleId, originalFactory) : originalFactory, moduleFactoryHandler);
define(originalModules, moduleId, { value: proxiedFactory });
} }
define(originalModules, Symbol.toStringTag, { define(originalModules, Symbol.toStringTag, {
@ -145,7 +145,6 @@ define(Function.prototype, "m", {
enumerable: false 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); 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 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<AnyWebpackRequire["m"]> = { const moduleFactoriesHandler: ProxyHandler<AnyWebpackRequire["m"]> = {
/* /*
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 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<AnyWebpackRequire["m"]> = {
}, },
*/ */
// The set trap for patching or defining getters for the module factories when new module factories are loaded
set(target, p, newValue, receiver) { set(target, p, newValue, receiver) {
if (updateExistingFactory(target, p, newValue)) { if (updateExistingFactory(target, p, newValue, receiver)) {
return true; return true;
} }
notifyFactoryListeners(newValue); notifyFactoryListeners(p, newValue);
defineModulesFactoryGetter(p, Settings.eagerPatches && shouldPatchFactories ? wrapAndPatchFactory(p, newValue) : 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<MaybePatchedModuleFactory> = {
apply(target, thisArg: unknown, argArray: Parameters<AnyModuleFactory>) {
// 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. * 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 moduleFactoriesTarget The module factories where this new original factory is being set
* @param id The id of the module * @param moduleId The id of the module
* @param newFactory The new original factory * @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 * @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 * @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<AnyModuleFactory> | undefined; let existingFactory: TypedPropertyDescriptor<AnyModuleFactory> | undefined;
let moduleFactoriesWithFactory: AnyWebpackRequire["m"] | undefined; let moduleFactoriesWithFactory: AnyWebpackRequire["m"] | undefined;
for (const wreq of allWebpackInstances) { for (const wreq of allWebpackInstances) {
if (ignoreExistingInTarget && wreq.m === moduleFactoriesTarget) continue; if (ignoreExistingInTarget && wreq.m === moduleFactoriesTarget) {
continue;
}
if (Object.hasOwn(wreq.m, id)) { if (Object.hasOwn(wreq.m, moduleId)) {
existingFactory = Reflect.getOwnPropertyDescriptor(wreq.m, id); existingFactory = Reflect.getOwnPropertyDescriptor(wreq.m, moduleId);
moduleFactoriesWithFactory = wreq.m; moduleFactoriesWithFactory = wreq.m;
break; break;
} }
} }
if (existingFactory != null) { if (existingFactory != null) {
// If existingFactory exists in any Webpack instance, it's either wrapped in defineModuleFactoryGetter, or it has already been required. // If existingFactory exists in any Webpack instance, it's either wrapped in our proxy, 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, // In the case it is wrapped in our proxy, we need the Webpack instance with this new original factory to also have our proxy.
// and let the correct logic apply (normal set, or defineModuleFactoryGetter setter) // So, define the descriptor of the existing factory on it.
if (moduleFactoriesWithFactory !== moduleFactoriesTarget) { 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 const existingFactoryValue = moduleFactoriesWithFactory![moduleId];
if (IS_DEV && existingFactory.value != null) {
newFactory[SYM_PATCHED_SOURCE] = existingFactory.value[SYM_PATCHED_SOURCE]; // Update with the new original factory, if it does have a current original factory
newFactory[SYM_PATCHED_BY] = existingFactory.value[SYM_PATCHED_BY]; 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; return false;
@ -231,12 +270,13 @@ function updateExistingFactory(moduleFactoriesTarget: AnyWebpackRequire["m"], id
/** /**
* Notify all factory listeners. * Notify all factory listeners.
* *
* @param moduleId The id of the module
* @param factory The original factory to notify for * @param factory The original factory to notify for
*/ */
function notifyFactoryListeners(factory: AnyModuleFactory) { function notifyFactoryListeners(moduleId: PropertyKey, factory: AnyModuleFactory) {
for (const factoryListener of factoryListeners) { for (const factoryListener of factoryListeners) {
try { try {
factoryListener(factory); factoryListener(factory, moduleId);
} catch (err) { } catch (err) {
logger.error("Error in Webpack factory listener:\n", err, factoryListener); logger.error("Error in Webpack factory listener:\n", err, factoryListener);
} }
@ -244,64 +284,27 @@ 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 * @param moduleId The id of the module
* and only be patched when accessed for the first time. * @param patchedFactory The (possibly) patched module factory
* * @param thisArg The `value` of the call to the factory
* @param id The id of the module * @param argArray The arguments of the call to the factory
* @param factory The original or patched module factory
*/ */
function defineModulesFactoryGetter(id: PropertyKey, factory: MaybeWrappedModuleFactory) { function runFactoryWithWrap(moduleId: PropertyKey, patchedFactory: PatchedModuleFactory, thisArg: unknown, argArray: Parameters<MaybePatchedModuleFactory>) {
const descriptor: PropertyDescriptor = { const originalFactory = patchedFactory[SYM_ORIGINAL_FACTORY];
get() {
// SYM_ORIGINAL_FACTORY means the factory is already patched if (patchedFactory === originalFactory) {
if (!shouldPatchFactories || factory[SYM_ORIGINAL_FACTORY] != null) { // @ts-expect-error Clear up ORIGINAL_FACTORY if the factory did not have any patch applied
return factory; delete patchedFactory[SYM_ORIGINAL_FACTORY];
} }
return (factory = wrapAndPatchFactory(id, factory)); // Restore the original factory in all the module factories objects, discarding our proxy and allowing it to be garbage collected
},
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) { for (const wreq of allWebpackInstances) {
define(wreq.m, id, descriptor); define(wreq.m, moduleId, { value: originalFactory });
}
} }
/** let [module, exports, require] = argArray;
* 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);
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] });
}
// eslint-disable-next-line prefer-const
let [module, exports, require] = args;
if (wreq == null) { if (wreq == null) {
if (!wreqFallbackApplied) { if (!wreqFallbackApplied) {
@ -313,33 +316,33 @@ function wrapAndPatchFactory(id: PropertyKey, originalFactory: AnyModuleFactory)
const webpackInstanceFileName = stack?.match(/\/assets\/(.+?\.js)/)?.[1]; const webpackInstanceFileName = stack?.match(/\/assets\/(.+?\.js)/)?.[1];
logger.warn( logger.warn(
"WebpackRequire was not initialized, falling back to WebpackRequire passed to the first called patched module factory (" + "WebpackRequire was not initialized, falling back to WebpackRequire passed to the first called wrapped module factory (" +
`id: ${String(id)}` + interpolateIfDefined`, WebpackInstance origin: ${webpackInstanceFileName}` + `id: ${String(moduleId)}` + interpolateIfDefined`, WebpackInstance origin: ${webpackInstanceFileName}` +
")" ")"
); );
// Could technically be wrong, but it's better than nothing
_initWebpack(require as WebpackRequire); _initWebpack(require as WebpackRequire);
} else if (IS_DEV) { } else if (IS_DEV) {
logger.error("WebpackRequire was not initialized, running modules without patches instead."); logger.error("WebpackRequire was not initialized, running modules without patches instead.");
return wrappedFactory[SYM_ORIGINAL_FACTORY].apply(this, args); return originalFactory.apply(thisArg, argArray);
} }
} else if (IS_DEV) { } else if (IS_DEV) {
return wrappedFactory[SYM_ORIGINAL_FACTORY].apply(this, args); return originalFactory.apply(thisArg, argArray);
} }
} }
let factoryReturn: unknown; let factoryReturn: unknown;
try { try {
// Call the patched factory factoryReturn = patchedFactory.apply(thisArg, argArray);
factoryReturn = patchedFactory.apply(this, args);
} catch (err) { } catch (err) {
// Just re-throw Discord errors // Just re-throw Discord errors
if (patchedFactory === wrappedFactory[SYM_ORIGINAL_FACTORY]) { if (patchedFactory === originalFactory) {
throw err; throw err;
} }
logger.error("Error in patched module factory:\n", err); logger.error("Error in patched module factory:\n", err);
return wrappedFactory[SYM_ORIGINAL_FACTORY].apply(this, args); return originalFactory.apply(thisArg, argArray);
} }
exports = module.exports; exports = module.exports;
@ -352,8 +355,8 @@ function wrapAndPatchFactory(id: PropertyKey, originalFactory: AnyModuleFactory)
if (shouldIgnoreModule) { if (shouldIgnoreModule) {
if (require.c != null) { if (require.c != null) {
Object.defineProperty(require.c, id, { Object.defineProperty(require.c, moduleId, {
value: require.c[id], value: require.c[moduleId],
enumerable: false, enumerable: false,
configurable: true, configurable: true,
writable: true writable: true
@ -366,7 +369,7 @@ function wrapAndPatchFactory(id: PropertyKey, originalFactory: AnyModuleFactory)
for (const callback of moduleListeners) { for (const callback of moduleListeners) {
try { try {
callback(exports, id); callback(exports, moduleId);
} catch (err) { } catch (err) {
logger.error("Error in Webpack module listener:\n", err, callback); logger.error("Error in Webpack module listener:\n", err, callback);
} }
@ -376,7 +379,7 @@ function wrapAndPatchFactory(id: PropertyKey, originalFactory: AnyModuleFactory)
try { try {
if (filter(exports)) { if (filter(exports)) {
waitForSubscriptions.delete(filter); waitForSubscriptions.delete(filter);
callback(exports, id); callback(exports, moduleId);
continue; continue;
} }
@ -389,7 +392,7 @@ function wrapAndPatchFactory(id: PropertyKey, originalFactory: AnyModuleFactory)
if (exportValue != null && filter(exportValue)) { if (exportValue != null && filter(exportValue)) {
waitForSubscriptions.delete(filter); waitForSubscriptions.delete(filter);
callback(exportValue, id); callback(exportValue, moduleId);
break; break;
} }
} }
@ -399,35 +402,20 @@ function wrapAndPatchFactory(id: PropertyKey, originalFactory: AnyModuleFactory)
} }
return factoryReturn; 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;
} }
/** /**
* Patches a module factory. * Patches a module factory.
* *
* @param id The id of the module * @param moduleId The id of the module
* @param factory The original module factory * @param originalFactory The original module factory
* @returns The patched module factory, the patched source of it, and the plugins that patched it * @returns The patched module factory
*/ */
function patchFactory(id: PropertyKey, factory: AnyModuleFactory): [patchedFactory: AnyModuleFactory, patchedSource: string, patchedBy: Set<string>] { function patchFactory(moduleId: PropertyKey, originalFactory: AnyModuleFactory): PatchedModuleFactory {
// 0, prefix to turn it into an expression: 0,function(){} would be invalid syntax without the 0, // 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 patchedSource = code;
let patchedFactory = factory; let patchedFactory = originalFactory;
const patchedBy = new Set<string>(); const patchedBy = new Set<string>();
@ -442,8 +430,8 @@ function patchFactory(id: PropertyKey, factory: AnyModuleFactory): [patchedFacto
continue; continue;
} }
// Reporter eagerly patches and cannot retrieve the build number because this code runs before the module for it is loaded // Eager patches cannot retrieve the build number because this code runs before the module for it is loaded
const buildNumber = IS_REPORTER ? -1 : getBuildNumber(); const buildNumber = Settings.eagerPatches ? -1 : getBuildNumber();
const shouldCheckBuildNumber = !Settings.eagerPatches && buildNumber !== -1; const shouldCheckBuildNumber = !Settings.eagerPatches && buildNumber !== -1;
if ( if (
@ -463,7 +451,7 @@ function patchFactory(id: PropertyKey, factory: AnyModuleFactory): [patchedFacto
}); });
const previousCode = code; const previousCode = code;
const previousFactory = factory; const previousFactory = originalFactory;
let markedAsPatched = false; let markedAsPatched = false;
// We change all patch.replacement to array in plugins/index // 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 lastCode = code;
const lastFactory = factory; const lastFactory = originalFactory;
try { try {
const [newCode, totalTime] = executePatch(replacement.match, replacement.replace as string); const [newCode, totalTime] = executePatch(replacement.match, replacement.replace as string);
if (IS_REPORTER) { if (IS_REPORTER) {
patchTimings.push([patch.plugin, id, replacement.match, totalTime]); patchTimings.push([patch.plugin, moduleId, replacement.match, totalTime]);
} }
if (newCode === code) { if (newCode === code) {
if (!patch.noWarn) { 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) { if (IS_DEV) {
logger.debug("Function Source:\n", code); logger.debug("Function Source:\n", code);
} }
@ -515,7 +503,7 @@ function patchFactory(id: PropertyKey, factory: AnyModuleFactory): [patchedFacto
} }
code = newCode; 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); patchedFactory = (0, eval)(patchedSource);
if (!patchedBy.has(patch.plugin)) { if (!patchedBy.has(patch.plugin)) {
@ -523,7 +511,7 @@ function patchFactory(id: PropertyKey, factory: AnyModuleFactory): [patchedFacto
markedAsPatched = true; markedAsPatched = true;
} }
} catch (err) { } 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) { if (IS_DEV) {
diffErroredPatch(code, lastCode, lastCode.match(replacement.match)!); 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) { function diffErroredPatch(code: string, lastCode: string, match: RegExpMatchArray) {

View file

@ -90,7 +90,7 @@ export const filters = {
}; };
export type CallbackFn = (module: ModuleExports, id: PropertyKey) => void; 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<FilterFn, CallbackFn>(); export const waitForSubscriptions = new Map<FilterFn, CallbackFn>();
export const moduleListeners = new Set<CallbackFn>(); export const moduleListeners = new Set<CallbackFn>();

View file

@ -200,12 +200,10 @@ export type AnyModuleFactory = ((this: ModuleExports, module: Module, exports: M
[SYM_PATCHED_BY]?: Set<string>; [SYM_PATCHED_BY]?: Set<string>;
}; };
export type WrappedModuleFactory = AnyModuleFactory & { export type PatchedModuleFactory = AnyModuleFactory & {
[SYM_ORIGINAL_FACTORY]: AnyModuleFactory; [SYM_ORIGINAL_FACTORY]: AnyModuleFactory;
[SYM_PATCHED_SOURCE]?: string; [SYM_PATCHED_SOURCE]?: string;
[SYM_PATCHED_BY]?: Set<string>; [SYM_PATCHED_BY]?: Set<string>;
}; };
export type MaybeWrappedModuleFactory = AnyModuleFactory | WrappedModuleFactory; export type MaybePatchedModuleFactory = PatchedModuleFactory | AnyModuleFactory;
export type WrappedModuleFactories = Record<PropertyKey, WrappedModuleFactory>;

View file

@ -29,7 +29,9 @@
"@shared/*": ["./shared/*"], "@shared/*": ["./shared/*"],
"@webpack/types": ["./webpack/common/types"], "@webpack/types": ["./webpack/common/types"],
"@webpack/common": ["./webpack/common"], "@webpack/common": ["./webpack/common"],
"@webpack": ["./webpack/webpack"] "@webpack": ["./webpack/webpack"],
"@webpack/patcher": ["./webpack/patchWebpack"],
"@webpack/wreq.d": ["./webpack/wreq.d"],
}, },
"plugins": [ "plugins": [