"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.kill = void 0;
const child_process_1 = require("child_process");
const events_1 = require("events");
async function kill(childProcess, code = 'SIGTERM') {
    childProcess.kill(code);
    if (childProcess.exitCode === null && childProcess.signalCode === null) {
        await (0, events_1.once)(childProcess, 'exit');
    }
}
exports.kill = kill;
function spawnChildFromSource(src, spawnOptions = {}, timeoutMs, _stdout = 'inherit', _stderr = 'inherit') {
    return new Promise(async (resolve, reject) => {
        const readyToken = Date.now().toString(32);
        const childProcess = (0, child_process_1.spawn)(process.execPath, {
            stdio: ['pipe', _stdout, _stderr, 'ipc'],
            ...spawnOptions,
        });
        if (!childProcess.stdin) {
            await kill(childProcess);
            return reject(new Error("Can't write src to the spawned process, missing stdin"));
        }
        let timeoutId;
        function cleanupListeners() {
            if (timeoutId) {
                clearTimeout(timeoutId);
            }
            if (childProcess.stdin) {
                childProcess.stdin.off('error', onWriteError);
            }
            childProcess.off('message', onMessage);
            childProcess.off('exit', onExit);
        }
        function onExit(exitCode) {
            if (exitCode && exitCode > 0) {
                cleanupListeners();
                reject(new Error('Child process exited with error before starting'));
            }
        }
        async function onWriteError(error) {
            cleanupListeners();
            await kill(childProcess);
            reject(error);
        }
        async function onTimeout() {
            cleanupListeners();
            await kill(childProcess);
            reject(new Error('Timed out while waiting for child process to start'));
        }
        function onMessage(data) {
            if (data === readyToken) {
                cleanupListeners();
                resolve(childProcess);
            }
        }
        childProcess.on('message', onMessage);
        childProcess.on('exit', onExit);
        childProcess.stdin.on('error', onWriteError);
        childProcess.stdin.write(src);
        childProcess.stdin.write(`;process.send(${JSON.stringify(readyToken)})`);
        childProcess.stdin.end();
        timeoutId =
            timeoutMs !== undefined ? setTimeout(onTimeout, timeoutMs) : null;
    });
}
exports.default = spawnChildFromSource;
//# sourceMappingURL=spawn-child-from-source.js.map