this repo has no description
1import { WebpackModule, WebpackModuleFunc, WebpackRequireType } from "@moonlight-mod/types"; 2import { Spacepack } from "@moonlight-mod/types/coreExtensions/spacepack"; 3import { processFind, testFind } from "@moonlight-mod/core/util/patch"; 4 5const webpackRequire = require as unknown as WebpackRequireType; 6const cache = webpackRequire.c; 7const modules = webpackRequire.m; 8 9const logger = moonlight.getLogger("spacepack"); 10 11export const spacepack: Spacepack = { 12 require: webpackRequire, 13 modules, 14 cache, 15 16 inspect: (module: number | string) => { 17 if (typeof module === "number") { 18 module = module.toString(); 19 } 20 21 if (module in moonlight.moonmap.modules) { 22 module = moonlight.moonmap.modules[module]; 23 } 24 25 if (!(module in modules)) { 26 return null; 27 } 28 29 const func = modules[module]; 30 if (func.__moonlight === true) { 31 return func; 32 } 33 34 const funcStr = func.toString(); 35 36 return new Function( 37 "module", 38 "exports", 39 "require", 40 `(${funcStr}).apply(this, arguments)\n` + `//# sourceURL=Webpack-Module/${module.slice(0, 3)}/${module}` 41 ) as WebpackModuleFunc; 42 }, 43 44 findByCode: (...args: (string | RegExp)[]) => { 45 const ret = Object.entries(modules) 46 .filter(([id, mod]) => !args.some((item) => !testFind(mod.toString(), processFind(item)))) 47 .map(([id]) => { 48 //if (!(id in cache)) require(id); 49 //return cache[id]; 50 51 let exports; 52 try { 53 exports = require(id); 54 } catch (e) { 55 logger.error(`findByCode: Error requiring module "${id}": `, args, e); 56 } 57 58 return { 59 id, 60 exports 61 }; 62 }) 63 .filter((item) => item !== null); 64 65 if (ret.length === 0) { 66 logger.warn("findByCode: Got zero results for", args, new Error().stack!.substring(5)); 67 } 68 69 return ret; 70 }, 71 72 findByExports: (...args: string[]) => { 73 return Object.entries(cache) 74 .filter( 75 ([id, { exports }]) => 76 !args.some( 77 (item) => 78 !( 79 exports !== undefined && 80 exports !== window && 81 (exports?.[item] || exports?.default?.[item] || exports?.Z?.[item] || exports?.ZP?.[item]) 82 ) 83 ) 84 ) 85 .map((item) => item[1]) 86 .reduce<WebpackModule[]>((prev, curr) => { 87 if (!prev.includes(curr)) prev.push(curr); 88 return prev; 89 }, []); 90 }, 91 92 findObjectFromKey: (exports: Record<string, any>, key: string) => { 93 let ret = null; 94 let subKey; 95 if (key.indexOf(".") > -1) { 96 const splitKey = key.split("."); 97 key = splitKey[0]; 98 subKey = splitKey[1]; 99 } 100 for (const exportKey in exports) { 101 const obj = exports[exportKey]; 102 if (obj && obj[key] !== undefined) { 103 if (subKey) { 104 if (obj[key][subKey]) { 105 ret = obj; 106 break; 107 } 108 } else { 109 ret = obj; 110 break; 111 } 112 } 113 } 114 115 if (ret == null) { 116 logger.warn("Failed to find object by key", key, "in", exports, new Error().stack!.substring(5)); 117 } 118 119 return ret; 120 }, 121 122 findObjectFromValue: (exports: Record<string, any>, value: any) => { 123 let ret = null; 124 for (const exportKey in exports) { 125 const obj = exports[exportKey]; 126 // eslint-disable-next-line eqeqeq 127 if (obj == value) { 128 ret = obj; 129 break; 130 } 131 for (const subKey in obj) { 132 // eslint-disable-next-line eqeqeq 133 if (obj && obj[subKey] == value) { 134 ret = obj; 135 break; 136 } 137 } 138 } 139 140 if (ret == null) { 141 logger.warn("Failed to find object by value", value, "in", exports, new Error().stack!.substring(5)); 142 } 143 144 return ret; 145 }, 146 147 findObjectFromKeyValuePair: (exports: Record<string, any>, key: string, value: any) => { 148 let ret = null; 149 for (const exportKey in exports) { 150 const obj = exports[exportKey]; 151 // eslint-disable-next-line eqeqeq 152 if (obj && obj[key] == value) { 153 ret = obj; 154 break; 155 } 156 } 157 158 if (ret == null) { 159 logger.warn( 160 "Failed to find object by key value pair", 161 key, 162 value, 163 "in", 164 exports, 165 new Error().stack!.substring(5) 166 ); 167 } 168 169 return null; 170 }, 171 172 findFunctionByStrings: (exports: Record<string, any>, ...strings: (string | RegExp)[]) => { 173 const ret = 174 Object.entries(exports).filter( 175 ([index, func]) => 176 typeof func === "function" && !strings.some((query) => !testFind(func.toString(), processFind(query))) 177 )?.[0]?.[1] ?? null; 178 179 if (ret == null) { 180 logger.warn("Failed to find function by strings", strings, "in", exports, new Error().stack!.substring(5)); 181 } 182 183 return ret; 184 }, 185 186 lazyLoad: (find: string | RegExp | (string | RegExp)[], chunk: RegExp, module: RegExp) => { 187 chunk = processFind(chunk); 188 module = processFind(module); 189 190 const mod = Array.isArray(find) ? spacepack.findByCode(...find) : spacepack.findByCode(find); 191 if (mod.length < 1) { 192 logger.warn("lazyLoad: Module find failed", find, chunk, module, new Error().stack!.substring(5)); 193 return Promise.reject("Module find failed"); 194 } 195 196 const findId = mod[0].id; 197 const findCode = webpackRequire.m[findId].toString().replace(/\n/g, ""); 198 199 let chunkIds; 200 if (chunk.flags.includes("g")) { 201 chunkIds = [...findCode.matchAll(chunk)].map(([, id]) => id); 202 } else { 203 const match = findCode.match(chunk); 204 if (match) chunkIds = [...match[0].matchAll(/"(\d+)"/g)].map(([, id]) => id); 205 } 206 207 if (!chunkIds || chunkIds.length === 0) { 208 logger.warn("lazyLoad: Chunk ID match failed", find, chunk, module, new Error().stack!.substring(5)); 209 return Promise.reject("Chunk ID match failed"); 210 } 211 212 const moduleId = findCode.match(module)?.[1]; 213 if (!moduleId) { 214 logger.warn("lazyLoad: Module ID match failed", find, chunk, module, new Error().stack!.substring(5)); 215 return Promise.reject("Module ID match failed"); 216 } 217 218 return Promise.all(chunkIds.map((c) => webpackRequire.e(c))).then(() => webpackRequire(moduleId)); 219 }, 220 221 filterReal: (modules: WebpackModule[]) => { 222 return modules.filter((module) => module.id.toString().match(/^\d+$/)); 223 } 224}; 225 226if (moonlight.getConfigOption<boolean>("spacepack", "addToGlobalScope") === true) { 227 window.spacepack = spacepack; 228} 229 230export default spacepack;