Last active
November 4, 2022 14:15
-
-
Save Vendicated/ed1cd1e668c0d4b7fa22082e25296888 to your computer and use it in GitHub Desktop.
Discord Webpack Search with a WebWorker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const worker = makeWebpackSearchWorker(); // slooooow | |
const UserStore = await worker.byProps("getCurrentUser", "initialize") // blazingly fast and truly asynchronous | |
const fetchUser = await worker.byCode("USER(") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if (typeof wreq === "undefined") { | |
var wreq = webpackChunkdiscord_app.push([[Symbol()], {}, w => w]); | |
webpackChunkdiscord_app.pop(); | |
} | |
function makeWebpackSearchWorker() { | |
// Step 1: Build Export and Code map to pass to the worker. | |
// This is because you can't serialise functions, so we have to transform webpack first | |
var exportMap = {}; | |
var codeMap = {}; | |
function addExports(id, exports, path = "") { | |
if (!exports || exports === window || typeof exports !== "object" || Array.isArray(exports)) return; | |
const names = ((exportMap[id] ??= {})[path] ??= []); | |
for (const key in exports) { | |
if (!path && (key === "default" || key.length <= 3)) { | |
const m = exports[key]; | |
if (typeof m === "function") { | |
addFunction(id, key, m, path); | |
} else addExports(id, m, key); | |
} else { | |
if (typeof exports[key] === "function") | |
addFunction(id, key, exports[key], path); | |
names.push(key); | |
} | |
} | |
} | |
function addFunction(id, key, func, path) { | |
((codeMap[id] ??= {})[path] ??= []).push([key, func.toString()]); | |
} | |
for (const id in wreq.c) { | |
const m = wreq.c[id]?.exports; | |
if (!m || m === window) continue; | |
if (typeof m === "function") addFunction(id, "", m, ""); | |
else addExports(id, m); | |
} | |
// Step 2: The worker code | |
function workerCode() { | |
let exportMap, codeMap; | |
self.onmessage = ({ data }) => { | |
const [op, id, ...rest] = data; | |
switch (op) { | |
case "setMaps": | |
exportMap = data[1]; | |
codeMap = data[2]; | |
break; | |
case "findByProps": { | |
const props = rest[0]; | |
let found = null; | |
outer: | |
for (const id in exportMap) { | |
for (const path in exportMap[id]) { | |
const exports = exportMap[id][path]; | |
if (props.every(p => exports.includes(p))) { | |
found = [id, path]; | |
break outer; | |
} | |
} | |
} | |
self.postMessage([op, id, found]); | |
break; | |
} | |
case "findByCode": { | |
const code = rest[0]; | |
let found = null; | |
outer: | |
for (const id in codeMap) { | |
for (const path in codeMap[id]) { | |
const codes = codeMap[id][path]; | |
for (const [key, func] of codes) { | |
if (func.includes(code)) { | |
found = [id, path, key]; | |
break outer; | |
} | |
} | |
} | |
} | |
self.postMessage([op, id, found]); | |
break; | |
} | |
} | |
}; | |
} | |
// Step 3: Create worker with the code and set its maps | |
const worker = new Worker(`data:text/javascript,!${workerCode.toString()}()`); | |
worker.postMessage(["setMaps", exportMap, codeMap]); | |
// Step 4: Main thread logic | |
const resolvers = {}; | |
let id = 0; | |
worker.onmessage = ({ data }) => { | |
const [op, resolverId, d] = data; | |
const [id, path, key] = d ?? []; | |
if (!id) return void resolvers[resolverId](null); | |
let m = wreq(id); | |
if (path) m = m[path]; | |
resolvers[resolverId](op === "findByCode" && key ? m[key] : m); | |
delete resolvers[resolverId]; | |
}; | |
// Step 5: Wrapper functions | |
return { | |
byProps: (...props) => new Promise(r => { | |
const mId = id++; | |
resolvers[mId] = r; | |
worker.postMessage(["findByProps", mId, props]); | |
}), | |
byCode: code => new Promise(r => { | |
const mId = id++; | |
resolvers[mId] = r; | |
worker.postMessage(["findByCode", mId, code]); | |
}) | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment