const fs = require('fs');
const path = require('path');
const { execFileSync } = require('child_process');
const [name, nodeVer, ...rest] = process.argv.slice(2);
const roMapIdx = rest.indexOf('--ro-map');
const roMap = roMapIdx >= 0 ? rest[roMapIdx + 1] : null;
const fixture = path.join('tests/fixtures/scripts', `${name}.js`);
const nodeBin = `${process.env.HOME}/.local/share/mise/installs/node/${nodeVer}/bin/node`;
const jsc = `/tmp/script-${name}-${nodeVer}.jsc`;
const run = (cmd, args, input) => {
try {
const out = execFileSync(cmd, args, { encoding: 'utf8', input, stdio: ['pipe', 'pipe', 'pipe'], timeout: 8000 });
return { out, code: 0 };
} catch (e) {
return { out: (e.stdout || '') + (e.stderr || ''), code: e.status === undefined ? -1 : e.status };
}
};
const result = { fixture: name, node: nodeVer, kind: 'script' };
const orig = run(nodeBin, [fixture]);
if (orig.code !== 0 && !orig.out) {
console.log(JSON.stringify({ ...result, status: 'compile-fail', detail: 'original run failed' }));
process.exit(0);
}
const comp = run(nodeBin, ['scripts/mkcorpus.js', fixture, jsc]);
if (comp.code !== 0) {
console.log(JSON.stringify({ ...result, status: 'compile-fail', detail: comp.out.trim().split('\n')[0] }));
process.exit(0);
}
const decArgs = ['decompile', jsc, '--runtime'];
if (roMap) decArgs.push('--ro-map', roMap);
let decoded = '';
try {
decoded = execFileSync('./target/release/jscd', decArgs, { encoding: 'utf8' });
} catch (e) {
console.log(JSON.stringify({ ...result, status: 'decompile-failed', detail: (e.stderr || '').trim().split('\n')[0] }));
process.exit(0);
}
const decFile = `/tmp/script-${name}-${nodeVer}.dec.js`;
fs.writeFileSync(decFile, decoded);
const mine = run(nodeBin, [decFile]);
const norm = (s) => s.replace(/\s+$/gm, '').trim();
result.matched = norm(orig.out) === norm(mine.out) && orig.code === mine.code;
if (result.matched) {
result.status = 'pass';
} else {
result.status = 'fail';
result.diffs = [{ origOut: norm(orig.out).slice(0, 400), mineOut: norm(mine.out).slice(0, 400), origCode: orig.code, mineCode: mine.code }];
}
console.log(JSON.stringify(result));