/** * Webpack Bundle Unpacker & Module Extractor * ------------------------------------------- * 依据 AGENTS.md §2.2 L1/L2 规范,将 Webpack 单文件打包解包为独立可读的模块文件。 */ const fs = require("fs"); const path = require("path"); const parser = require("@babel/parser"); const generate = require("@babel/generator").default; function unpackBundle(bundlePath, outputDir) { const code = fs.readFileSync(bundlePath, "utf-8"); console.log(`Parsing bundle ${bundlePath} (${code.length} bytes)...`); const ast = parser.parse(code, { sourceType: "script" }); const call = ast.program.body[0].expression.argument; const modulesArray = call.arguments[0].elements; console.log(`Found ${modulesArray.length} modules.`); fs.mkdirSync(outputDir, { recursive: true }); const index = []; modulesArray.forEach((modNode, idx) => { if (!modNode) { index.push({ id: idx, empty: true }); return; } const modCode = generate(modNode).code; const modFile = path.join(outputDir, `module_${idx.toString().padStart(3, "0")}.js`); fs.writeFileSync(modFile, modCode, "utf-8"); // Search keywords in module to create index const keywords = []; if (/verify/i.test(modCode)) keywords.push("verify"); if (/pow/i.test(modCode)) keywords.push("pow"); if (/tdc/i.test(modCode)) keywords.push("tdc"); if (/collect/i.test(modCode)) keywords.push("collect"); if (/getsig/i.test(modCode)) keywords.push("getsig"); if (/prehandle/i.test(modCode)) keywords.push("prehandle"); if (/subcapclass/i.test(modCode)) keywords.push("subcapclass"); if (/ticket/i.test(modCode)) keywords.push("ticket"); index.push({ id: idx, size: modCode.length, file: `module_${idx.toString().padStart(3, "0")}.js`, keywords, }); }); const indexFile = path.join(outputDir, "manifest.json"); fs.writeFileSync(indexFile, JSON.stringify(index, null, 2), "utf-8"); console.log(`Manifest written to ${indexFile}`); return index; } if (require.main === module) { const bundle = process.argv[2] || "tcaptcha/core_js/tcaptcha-frame.ba387dd1.js"; const outDir = process.argv[3] || "tcaptcha/core_js/frame_modules"; unpackBundle(bundle, outDir); } module.exports = { unpackBundle };