2025-04-02 06:50:39 -04:00

155 lines
5.0 KiB
JavaScript

'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.shutdown = exports.fabricateTwice = exports.fabricate = void 0;
const child_process_1 = require('child_process');
const log_1 = require('./log');
const script = `
var vm = require('vm');
var module = require('module');
var stdin = Buffer.alloc(0);
process.stdin.on('data', function (data) {
stdin = Buffer.concat([ stdin, data ]);
if (stdin.length >= 4) {
var sizeOfSnap = stdin.readInt32LE(0);
if (stdin.length >= 4 + sizeOfSnap + 4) {
var sizeOfBody = stdin.readInt32LE(4 + sizeOfSnap);
if (stdin.length >= 4 + sizeOfSnap + 4 + sizeOfBody) {
var snap = stdin.toString('utf8', 4, 4 + sizeOfSnap);
var body = Buffer.alloc(sizeOfBody);
var startOfBody = 4 + sizeOfSnap + 4;
stdin.copy(body, 0, startOfBody, startOfBody + sizeOfBody);
stdin = Buffer.alloc(0);
var code = module.wrap(body);
var s = new vm.Script(code, {
filename: snap,
produceCachedData: true,
sourceless: true
});
if (!s.cachedDataProduced) {
console.error('Pkg: Cached data not produced.');
process.exit(2);
}
var h = Buffer.alloc(4);
var b = s.cachedData;
h.writeInt32LE(b.length, 0);
process.stdout.write(h);
process.stdout.write(b);
}
}
}
});
process.stdin.resume();
`;
const children = {};
function fabricate(bakes, fabricator, snap, body, cb) {
const activeBakes = bakes.filter((bake) => {
// list of bakes that don't influence the bytecode
const bake2 = bake.replace(/_/g, '-');
return !['--prof', '--v8-options', '--trace-opt', '--trace-deopt'].includes(
bake2
);
});
const cmd = fabricator.binaryPath;
const key = JSON.stringify([cmd, activeBakes]);
let child = children[key];
if (!child) {
const stderr = log_1.log.debugMode ? process.stdout : 'ignore';
children[key] = (0, child_process_1.spawn)(
cmd,
activeBakes.concat('-e', script),
{
stdio: ['pipe', 'pipe', stderr],
env: { PKG_EXECPATH: 'PKG_INVOKE_NODEJS' },
}
);
child = children[key];
}
function kill() {
delete children[key];
child.kill();
}
let stdout = Buffer.alloc(0);
function onError(error) {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
removeListeners();
kill();
cb(
new Error(
`Failed to make bytecode ${fabricator.nodeRange}-${fabricator.arch} for file ${snap} error (${error.message})`
)
);
}
function onClose(code) {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
removeListeners();
kill();
if (code !== 0) {
return cb(
new Error(
`Failed to make bytecode ${fabricator.nodeRange}-${fabricator.arch} for file ${snap}`
)
);
}
// eslint-disable-next-line no-console
console.log(stdout.toString());
return cb(new Error(`${cmd} closed unexpectedly`));
}
function onData(data) {
stdout = Buffer.concat([stdout, data]);
if (stdout.length >= 4) {
const sizeOfBlob = stdout.readInt32LE(0);
if (stdout.length >= 4 + sizeOfBlob) {
const blob = Buffer.alloc(sizeOfBlob);
stdout.copy(blob, 0, 4, 4 + sizeOfBlob);
// eslint-disable-next-line @typescript-eslint/no-use-before-define
removeListeners();
return cb(undefined, blob);
}
}
}
function removeListeners() {
child.removeListener('error', onError);
child.removeListener('close', onClose);
child.stdin.removeListener('error', onError);
child.stdout.removeListener('error', onError);
child.stdout.removeListener('data', onData);
}
child.on('error', onError);
child.on('close', onClose);
child.stdin.on('error', onError);
child.stdout.on('error', onError);
child.stdout.on('data', onData);
const h = Buffer.alloc(4);
let b = Buffer.from(snap);
h.writeInt32LE(b.length, 0);
child.stdin.write(h);
child.stdin.write(b);
b = body;
h.writeInt32LE(b.length, 0);
child.stdin.write(h);
child.stdin.write(b);
}
exports.fabricate = fabricate;
function fabricateTwice(bakes, fabricator, snap, body, cb) {
fabricate(bakes, fabricator, snap, body, (error, buffer) => {
// node0 can not produce second time, even if first time produced fine,
// probably because of 'filename' cache. also, there are weird cases
// when node4 can not compile as well, for example file 'lib/js-yaml/dumper.js'
// of package js-yaml@3.9.0 does not get bytecode second time on node4-win-x64
if (error) return fabricate(bakes, fabricator, snap, body, cb);
cb(undefined, buffer);
});
}
exports.fabricateTwice = fabricateTwice;
function shutdown() {
for (const key in children) {
if (children[key]) {
const child = children[key];
delete children[key];
child.kill();
}
}
}
exports.shutdown = shutdown;
//# sourceMappingURL=fabricator.js.map