/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
* @format
*/
"use strict";
const concat = require("concat-stream");
const debug = require("debug")("Metro:Symbolication");
const net = require("net");
const temp = require("temp");
const xpipe = require("xpipe");
const _require = require("./util"),
LazyPromise = _require.LazyPromise,
LockingPromise = _require.LockingPromise;
const _require2 = require("child_process"),
fork = _require2.fork;
const affixes = {
prefix: "metro-symbolicate",
suffix: ".sock"
};
const childPath = require.resolve("./worker");
exports.createWorker = () => {
// There are issues with named sockets on windows that cause the connection to
// close too early so run the symbolicate server on a random localhost port.
const socket =
process.platform === "win32" ? 34712 : xpipe.eq(temp.path(affixes));
const child = new LockingPromise(new LazyPromise(() => startupChild(socket)));
return (stack, sourceMaps) =>
child
.then(() => connectAndSendJob(socket, message(stack, sourceMaps)))
.then(JSON.parse)
.then(
response =>
"error" in response
? Promise.reject(new Error(response.error))
: response.result
);
};
function startupChild(socket) {
const child = fork(childPath);
return new Promise((resolve, reject) => {
child.once("error", reject).once("message", () => {
child.removeAllListeners();
resolve(child);
});
child.send(socket);
});
}
function connectAndSendJob(socket, data) {
const job = new Promise((resolve, reject) => {
debug("Connecting to worker");
const connection = net.createConnection(socket);
connection.setEncoding("utf8");
connection.on("error", reject);
connection.pipe(concat(resolve));
debug("Sending data to worker");
connection.end(data);
});
job.then(() => debug("Received response from worker"));
return job;
}
function message(stack, sourceMaps) {
return JSON.stringify({
maps: Array.from(sourceMaps),
stack
});
}