Convert the TTX driver code to promises

This commit removes the final callbacks in this code by switching to a
promises-based interface, overall simplifying the code. Moreover, we
document why we write to files on disk and modernize the code using e.g.
template strings.
This commit is contained in:
Tim van der Meij 2024-04-05 13:03:22 +02:00
parent 64065141b6
commit ac03d7054d
No known key found for this signature in database
GPG key ID: 8C3FD2925A5F2762
2 changed files with 43 additions and 32 deletions

View file

@ -21,42 +21,51 @@ import { spawn } from "child_process";
let ttxTaskId = Date.now(); let ttxTaskId = Date.now();
function runTtx(fontPath, callback) { function runTtx(fontPath) {
const ttx = spawn("ttx", [fontPath], { stdio: "ignore" }); return new Promise((resolve, reject) => {
let ttxRunError; const ttx = spawn("ttx", [fontPath], { stdio: "ignore" });
ttx.on("error", function (errorTtx) { ttx.on("error", () => {
ttxRunError = errorTtx; reject(
callback( new Error(
"Unable to execute `ttx`; make sure the `fonttools` dependency is installed" "Unable to execute `ttx`; make sure the `fonttools` dependency is installed"
); )
}); );
ttx.on("close", function (code) { });
if (ttxRunError) { ttx.on("close", () => {
return; resolve();
} });
callback();
}); });
} }
function translateFont(content, callback) { async function translateFont(content) {
const buffer = Buffer.from(content, "base64"); const buffer = Buffer.from(content, "base64");
const taskId = (ttxTaskId++).toString(); const taskId = (ttxTaskId++).toString();
const fontPath = path.join(os.tmpdir(), `pdfjs-font-test-${taskId}.otf`); const fontPath = path.join(os.tmpdir(), `pdfjs-font-test-${taskId}.otf`);
const resultPath = path.join(os.tmpdir(), `pdfjs-font-test-${taskId}.ttx`); const resultPath = path.join(os.tmpdir(), `pdfjs-font-test-${taskId}.ttx`);
// Write the font data to a temporary file on disk (because TTX only accepts
// files as input).
fs.writeFileSync(fontPath, buffer); fs.writeFileSync(fontPath, buffer);
runTtx(fontPath, function (err) {
fs.unlinkSync(fontPath); // Run TTX on the temporary font file.
if (err) { let ttxError;
console.error(err); try {
callback(err); await runTtx(fontPath);
} else if (!fs.existsSync(resultPath)) { } catch (error) {
callback("Output was not generated"); ttxError = error;
} else { }
callback(null, fs.readFileSync(resultPath));
fs.unlinkSync(resultPath); // Remove the temporary font/result files and report on the outcome.
} fs.unlinkSync(fontPath);
}); if (ttxError) {
throw ttxError;
}
if (!fs.existsSync(resultPath)) {
throw new Error("TTX did not generate output");
}
const xml = fs.readFileSync(resultPath);
fs.unlinkSync(resultPath);
return xml;
} }
export { translateFont }; export { translateFont };

View file

@ -840,12 +840,14 @@ function unitTestPostHandler(req, res) {
req.on("data", function (data) { req.on("data", function (data) {
body += data; body += data;
}); });
req.on("end", function () { req.on("end", async function () {
if (pathname === "/ttx") { if (pathname === "/ttx") {
translateFont(body, function (err, xml) { res.writeHead(200, { "Content-Type": "text/xml" });
res.writeHead(200, { "Content-Type": "text/xml" }); try {
res.end(err ? "<error>" + err + "</error>" : xml); res.end(await translateFont(body));
}); } catch (error) {
res.end(`<error>${error}</error>`);
}
return; return;
} }