Fix script to extract maki methods from a directory of .wal files

This commit is contained in:
Jordan Eldredge 2019-09-10 14:59:26 -07:00
parent 98f59996bd
commit 3f43ab5aba
4 changed files with 168 additions and 45 deletions

View file

@ -3977,4 +3977,24 @@ function getObjectFunction(klass, functionName) {
return getObjectFunction(klass.parentClass, functionName);
}
module.exports = { objects, getFormattedId, getClass, getObjectFunction };
function getFunctionObject(klass, functionName) {
const method = klass.functions.find(func => {
// TODO: This could probably be normalized at load time, or evern sooner.
return func.name.toLowerCase() === functionName.toLowerCase();
});
if (method != null) {
return klass;
}
if (klass.parentClass == null) {
throw new Error(`Could not find method ${functionName} on ${klass.name}.`);
}
return getFunctionObject(klass.parentClass, functionName);
}
module.exports = {
objects,
getFormattedId,
getClass,
getObjectFunction,
getFunctionObject,
};

105
modern/src/maki-interpreter/tools/extract-functions.js Normal file → Executable file
View file

@ -1,48 +1,83 @@
const fs = require("fs");
const { parse } = require("../");
const JSZip = require("jszip");
#!/usr/bin/env node
async function getFunctionNames(absolutePath) {
const fs = require("fs");
const path = require("path");
const parse = require("../parser").default;
const JSZip = require("jszip");
const { getClass, getFunctionObject } = require("../objects");
const glob = require("glob");
function findWals(parentDir) {
return new Promise((resolve, reject) => {
glob("**/*.wal", { cwd: parentDir }, (err, files) => {
if (err) {
return reject(err);
}
resolve(files.map(filePath => path.join(parentDir, filePath)));
});
});
}
function sumCountObjects(obj1, obj2) {
return Object.keys(obj2).reduce((summaryObj, key) => {
if (summaryObj[key] == null) {
summaryObj[key] = 1;
} else {
summaryObj[key]++;
}
return summaryObj;
}, Object.assign({}, obj1));
}
async function getCallCountsFromWal(absolutePath) {
const buffer = fs.readFileSync(absolutePath);
const zip = await JSZip.loadAsync(buffer);
const files = zip.file(/\.maki$/);
const buffers = await Promise.all(
files.map(file => file.async("nodebuffer"))
);
const functionNames = buffers.reduce((_functionNames, buf) => {
const maki = parse(buf);
maki.functionNames.forEach(func => {
const className = maki.types[func.classType];
_functionNames.add(`${className}::${func.name}`);
});
return _functionNames;
}, new Set());
return functionNames;
return buffers.map(getCallCountsFromMaki).reduce(sumCountObjects);
}
async function main(paths) {
const results = await Promise.all(
paths.map(async path => {
const functionNames = await getFunctionNames(path);
return { path, functionNames };
function getCallCountsFromMaki(buffer) {
const maki = parse(buffer);
return maki.commands
.filter(command => command.opcode === 112)
.map(command => {
const method = maki.methods[command.arg];
const classId = maki.classes[method.typeOffset];
const klass = getClass(classId);
if (klass == null) {
throw new Error(`Unknown class ID: ${classId}`);
}
const parentClass = getFunctionObject(klass, method.name);
return `${parentClass.name}.${method.name.toLowerCase()}`;
})
);
const functionCounts = {};
results.forEach(skin => {
skin.functionNames.forEach(name => {
const originalCount = functionCounts[name];
functionCounts[name] = (originalCount || 0) + 1;
});
});
console.log({
totalFunctionCount: Object.keys(functionCounts).length,
// functionCounts
});
.map(methodName => ({ [methodName]: 1 }))
.reduce(sumCountObjects, {});
}
const paths = [
"/Volumes/Mobile Backup/skins/skins/dump/Stylish/micro/micro.wal",
"/Volumes/Mobile Backup/skins/skins/random/Winamp Skins/Skins/WTF/Almin_Agic_Skin.wal",
];
function setObjectValuesToOne(obj) {
const newObj = {};
Object.keys(obj).forEach(key => {
if (obj[key] != null) {
newObj[key] = 1;
}
});
main(paths);
return newObj;
}
async function main(parentDir) {
const paths = await findWals(parentDir);
const callCounts = await Promise.all(paths.map(getCallCountsFromWal));
const totalCalls = callCounts.reduce(sumCountObjects);
const foundInSkins = callCounts
.map(setObjectValuesToOne)
.reduce(sumCountObjects);
const result = { totalCalls, foundInSkins };
console.log(JSON.stringify(result, null, 2));
}
main(path.join(__dirname, "../../../skins/"));

View file

@ -31,7 +31,8 @@
"build-skin-png": "rm skins/base-2.91-png.wsz && cd skins/base-2.91-png && zip -x .* -x 'Skining Updates.txt' -r ../base-2.91-png.wsz .",
"compile-skin": "node scripts/compileSkin.js > css/base-skin.css",
"skin-info": "unzip -vl skins/base-2.91.wsz",
"build-presets": "node scripts/parsePresetFiles.js > presets/builtin.json"
"build-presets": "node scripts/parsePresetFiles.js > presets/builtin.json",
"analyze-wals": "babel-node --extensions=\".ts,.js,.tsx\" modern/src/maki-interpreter/tools/extract-functions.js > modern/resources/maki-skin-data.json"
},
"repository": {
"type": "git",
@ -51,6 +52,7 @@
"homepage": "https://github.com/captbaritone/webamp/",
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/node": "^7.6.1",
"@babel/plugin-proposal-class-properties": "^7.0.0",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
"@babel/plugin-syntax-dynamic-import": "^7.0.0",

View file

@ -237,6 +237,18 @@
esutils "^2.0.2"
js-tokens "^4.0.0"
"@babel/node@^7.6.1":
version "7.6.1"
resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.6.1.tgz#84f8f4f1d86647d99537a681f32e65e70bb59f19"
integrity sha512-q2sJw+7aES/5wwjccECJfOuIgM1XIbZcn7b63JZM6VpaZwvOq913jL+tXRIn41Eg/Hr+BeIGWnvnjLTuT579pA==
dependencies:
"@babel/polyfill" "^7.6.0"
"@babel/register" "^7.6.0"
commander "^2.8.1"
lodash "^4.17.13"
node-environment-flags "^1.0.5"
v8flags "^3.1.1"
"@babel/parser@^7.0.0", "@babel/parser@^7.2.2", "@babel/parser@^7.2.3":
version "7.2.3"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.2.3.tgz#32f5df65744b70888d17872ec106b02434ba1489"
@ -575,6 +587,14 @@
core-js "^2.5.7"
regenerator-runtime "^0.12.0"
"@babel/polyfill@^7.6.0":
version "7.6.0"
resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.6.0.tgz#6d89203f8b6cd323e8d946e47774ea35dc0619cc"
integrity sha512-q5BZJI0n/B10VaQQvln1IlDK3BTBJFbADx7tv+oXDPIDZuTo37H5Adb9jhlXm/fEN4Y7/64qD9mnrJJG7rmaTw==
dependencies:
core-js "^2.6.5"
regenerator-runtime "^0.13.2"
"@babel/preset-env@^7.0.0":
version "7.2.3"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.2.3.tgz#948c8df4d4609c99c7e0130169f052ea6a7a8933"
@ -638,6 +658,17 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-transform-typescript" "^7.1.0"
"@babel/register@^7.6.0":
version "7.6.0"
resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.6.0.tgz#76b6f466714680f4becafd45beeb2a7b87431abf"
integrity sha512-78BomdN8el+x/nkup9KwtjJXuptW5oXMFmP11WoM2VJBjxrKv4grC3qjpLL8RGGUYUGsm57xnjYFM2uom+jWUQ==
dependencies:
find-cache-dir "^2.0.0"
lodash "^4.17.13"
mkdirp "^0.5.1"
pirates "^4.0.0"
source-map-support "^0.5.9"
"@babel/runtime@^7.0.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.2.0.tgz#b03e42eeddf5898e00646e4c840fa07ba8dcad7f"
@ -2523,6 +2554,11 @@ commander@^2.18.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
commander@^2.8.1, commander@~2.20.0:
version "2.20.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
commander@^2.9.0:
version "2.15.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
@ -2535,11 +2571,6 @@ commander@~2.17.1:
version "2.17.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
commander@~2.20.0:
version "2.20.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
commander@~2.8.1:
version "2.8.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4"
@ -2715,7 +2746,7 @@ core-js@^2.4.0, core-js@^2.5.7:
version "2.6.1"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.1.tgz#87416ae817de957a3f249b3b5ca475d4aaed6042"
core-js@^2.5.0:
core-js@^2.5.0, core-js@^2.6.5:
version "2.6.9"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2"
integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==
@ -5065,6 +5096,13 @@ homedir-polyfill@^1.0.0:
dependencies:
parse-passwd "^1.0.0"
homedir-polyfill@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==
dependencies:
parse-passwd "^1.0.0"
hoopy@^0.1.2:
version "0.1.4"
resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d"
@ -6775,7 +6813,7 @@ lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.3
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.13.tgz#0bdc3a6adc873d2f4e0c4bac285df91b64fc7b93"
integrity sha512-vm3/XWXfWtRua0FkUyEHBZy8kCPjErNBT9fJx8Zvs+U6zjqPbTUOpkaoum3O5uiA8sm+yNMHXfYkTUHFoMxFNA==
lodash@^4.17.14, lodash@^4.17.15:
lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
@ -7350,6 +7388,14 @@ no-case@^2.2.0:
dependencies:
lower-case "^1.1.1"
node-environment-flags@^1.0.5:
version "1.0.6"
resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088"
integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==
dependencies:
object.getownpropertydescriptors "^2.0.3"
semver "^5.7.0"
node-fetch@^1.0.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
@ -8036,7 +8082,7 @@ pinkie@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
pirates@^4.0.1:
pirates@^4.0.0, pirates@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"
integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==
@ -9481,6 +9527,11 @@ semver@5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
semver@^5.7.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
send@0.16.1:
version "0.16.1"
resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3"
@ -9761,6 +9812,14 @@ source-map-support@^0.5.6:
buffer-from "^1.0.0"
source-map "^0.6.0"
source-map-support@^0.5.9:
version "0.5.13"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==
dependencies:
buffer-from "^1.0.0"
source-map "^0.6.0"
source-map-support@~0.5.6:
version "0.5.9"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f"
@ -10797,6 +10856,13 @@ v8-compile-cache@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c"
v8flags@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.3.tgz#fc9dc23521ca20c5433f81cc4eb9b3033bb105d8"
integrity sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==
dependencies:
homedir-polyfill "^1.0.1"
validate-npm-package-license@^3.0.1:
version "3.0.4"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"