feat: add CJS module name mapping - extracted modules now use descriptive paths instead of numeric IDs
This commit is contained in:
parent
d3c5248716
commit
6b47fef1b5
3 changed files with 73 additions and 6 deletions
|
|
@ -7,6 +7,7 @@ export const workFolder = "tmp";
|
|||
export const apksFolder = join(workFolder, "apks");
|
||||
export const codePath = join(workFolder, "code.js");
|
||||
export const modulesPath = join(workFolder, "modules");
|
||||
export const moduleMapPath = join(workFolder, "module-map.json");
|
||||
export const apkSplits = ["base", "config.hdpi", "config.xxhdpi"] as const;
|
||||
|
||||
export const oprevFiles = ["source.jsonl"] as const;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,20 @@ import { mkdir, rm, readdir, stat } from "node:fs/promises";
|
|||
import { join as pathJoin } from "node:path";
|
||||
import { commit } from "../git";
|
||||
import type { Progress } from "../progress";
|
||||
import { commitAnyway, cuteVersion, modulesPath } from "../shared";
|
||||
import { commitAnyway, cuteVersion, moduleMapPath, modulesPath } from "../shared";
|
||||
import { join, sortEntries } from "../utils";
|
||||
|
||||
const moduleIdRegex = /^module_(\d+)\.js$/;
|
||||
|
||||
interface CjsModule {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
function sanitizePath(name: string): string {
|
||||
return name.replace(/[<>:"|?*]/g, "_").replace(/\.\./g, "__");
|
||||
}
|
||||
|
||||
export default async function code(progress: Progress, _code: string[]) {
|
||||
progress.start("code_getting");
|
||||
|
||||
|
|
@ -12,6 +23,24 @@ export default async function code(progress: Progress, _code: string[]) {
|
|||
throw new Error(`Modules directory not found at ${modulesPath}`);
|
||||
}
|
||||
|
||||
const moduleMap = new Map<number, string>();
|
||||
try {
|
||||
const mapRaw = await Bun.file(moduleMapPath).json();
|
||||
if (Array.isArray(mapRaw)) {
|
||||
for (const entry of mapRaw as CjsModule[]) {
|
||||
if (entry.name?.trim()) moduleMap.set(entry.id, entry.name);
|
||||
}
|
||||
} else if (mapRaw && typeof mapRaw === "object") {
|
||||
for (const [key, value] of Object.entries(mapRaw)) {
|
||||
const id = Number(key);
|
||||
if (!Number.isNaN(id) && typeof value === "string" && value.trim()) {
|
||||
moduleMap.set(id, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
console.log(`Loaded ${moduleMap.size} module name mappings`);
|
||||
|
||||
async function scanDir(dir: string, basePath: string): Promise<Map<string, number>> {
|
||||
const files = new Map<string, number>();
|
||||
const entries = await readdir(dir, { withFileTypes: true });
|
||||
|
|
@ -29,7 +58,24 @@ export default async function code(progress: Progress, _code: string[]) {
|
|||
return files;
|
||||
}
|
||||
|
||||
const files = await scanDir(modulesPath, modulesPath);
|
||||
const rawFiles = await scanDir(modulesPath, modulesPath);
|
||||
const files = new Map<string, number>();
|
||||
|
||||
for (const [relativePath, fileSize] of rawFiles) {
|
||||
const match = relativePath.match(moduleIdRegex);
|
||||
if (match) {
|
||||
const id = Number.parseInt(match[1], 10);
|
||||
const mappedName = moduleMap.get(id);
|
||||
if (mappedName) {
|
||||
const newPath = sanitizePath(mappedName) + ".js";
|
||||
files.set(newPath, fileSize);
|
||||
} else {
|
||||
files.set(relativePath, fileSize);
|
||||
}
|
||||
} else {
|
||||
files.set(relativePath, fileSize);
|
||||
}
|
||||
}
|
||||
|
||||
await Bun.write(
|
||||
"../data/source.jsonl",
|
||||
|
|
@ -47,10 +93,22 @@ export default async function code(progress: Progress, _code: string[]) {
|
|||
await rm(filePrefix, { recursive: true, force: true });
|
||||
|
||||
await Promise.all(
|
||||
[...files.keys()].map(async (file) => {
|
||||
const dest = join(filePrefix, file);
|
||||
[...rawFiles.entries()].map(async ([relativePath]) => {
|
||||
const match = relativePath.match(moduleIdRegex);
|
||||
let dest: string;
|
||||
if (match) {
|
||||
const id = Number.parseInt(match[1], 10);
|
||||
const mappedName = moduleMap.get(id);
|
||||
if (mappedName) {
|
||||
dest = join(filePrefix, sanitizePath(mappedName) + ".js");
|
||||
} else {
|
||||
dest = join(filePrefix, relativePath);
|
||||
}
|
||||
} else {
|
||||
dest = join(filePrefix, relativePath);
|
||||
}
|
||||
await mkdir(pathJoin(dest, ".."), { recursive: true });
|
||||
await Bun.write(dest, Bun.file(join(modulesPath, file)));
|
||||
await Bun.write(dest, Bun.file(join(modulesPath, relativePath)));
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { exists } from "node:fs/promises";
|
||||
import { commit } from "../git";
|
||||
import type { Progress } from "../progress";
|
||||
import { codePath, commitAnyway, cuteVersion, modulesPath, workFolder } from "../shared";
|
||||
import { codePath, commitAnyway, cuteVersion, moduleMapPath, modulesPath, workFolder } from "../shared";
|
||||
import { handleShellErr, join } from "../utils";
|
||||
|
||||
const gzipWorkerURL = new URL("decompile-gzip.ts", import.meta.url).href;
|
||||
|
|
@ -45,6 +45,14 @@ export default async function decompile(progress: Progress, pathToBundle: string
|
|||
.then(handleShellErr);
|
||||
}
|
||||
|
||||
if (!(await Bun.file(moduleMapPath).exists())) {
|
||||
await Bun.$`${decompilerBin} dump ${pathToBundle} --kind cjs-modules --json`
|
||||
.quiet()
|
||||
.nothrow()
|
||||
.then(handleShellErr)
|
||||
.then((out) => Bun.write(moduleMapPath, out.stdout));
|
||||
}
|
||||
|
||||
progress.update("decompile_decompiling", true);
|
||||
|
||||
if (process.env.NODE_ENV !== "test" && !commitAnyway) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue