Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make babel-node spawned process bubble msg #13037

Merged
merged 2 commits into from Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/babel-node/src/babel-node.js
Expand Up @@ -96,6 +96,7 @@ getV8Flags(async function (err, v8Flags) {
}
});
});
proc.on("message", message => process.send && process.send(message));
process.on("SIGINT", () => proc.kill("SIGINT"));
}
});
194 changes: 194 additions & 0 deletions packages/babel-node/test/fixtures.js
@@ -0,0 +1,194 @@
import readdir from "fs-readdir-recursive";
import * as helper from "@babel/helper-fixtures";
import rimraf from "rimraf";
import { sync as makeDirSync } from "make-dir";
import child from "child_process";
import path from "path";
import fs from "fs";
import { fileURLToPath } from "url";
import { createRequire } from "module";

const require = createRequire(import.meta.url);

const dirname = path.dirname(fileURLToPath(import.meta.url));
const fixtureLoc = path.join(dirname, "fixtures", "cli");
const tmpLoc = path.join(dirname, "tmp");
const binLoc = path.join(dirname, "../lib/babel-node");

const fileFilter = function (x) {
return x !== ".DS_Store";
};

const outputFileSync = function (filePath, data) {
makeDirSync(path.dirname(filePath));
fs.writeFileSync(filePath, data);
};

const readDir = function (loc, filter) {
const files = {};
if (fs.existsSync(loc)) {
readdir(loc, filter).forEach(function (filename) {
files[filename] = helper.readFile(path.join(loc, filename));
});
}
return files;
};

const saveInFiles = function (files) {
// Place an empty .babelrc in each test so tests won't unexpectedly get to repo-level config.
outputFileSync(".babelrc", "{}");

Object.keys(files).forEach(function (filename) {
const content = files[filename];
outputFileSync(filename, content);
});
};

const assertTest = function (stdout, stderr, opts) {
const expectStderr = opts.stderr.trim();
stderr = stderr.trim();

if (opts.stderr) {
if (opts.stderrContains) {
expect(stderr.includes(expectStderr)).toBeTruthy();
} else {
expect(stderr).toBe(expectStderr);
}
} else if (stderr) {
throw new Error("stderr:\n" + stderr + "\n\nstdout:\n" + stdout);
}

const expectStdout = opts.stdout.trim();
stdout = stdout.trim();
stdout = stdout.replace(/\\/g, "/");

if (opts.stdout) {
if (opts.stdoutContains) {
expect(stdout.includes(expectStdout)).toBeTruthy();
} else {
expect(stdout).toBe(expectStdout);
}
} else if (stdout) {
throw new Error("stdout:\n" + stdout);
}

if (opts.outFiles) {
const actualFiles = readDir(path.join(tmpLoc));

Object.keys(actualFiles).forEach(function (filename) {
if (!Object.prototype.hasOwnProperty.call(opts.inFiles, filename)) {
const expected = opts.outFiles[filename];
const actual = actualFiles[filename];

expect(expected).not.toBeUndefined();

if (expected) {
expect(actual).toBe(expected);
}
}
});

Object.keys(opts.outFiles).forEach(function (filename) {
expect(actualFiles).toHaveProperty(filename);
});
}
};

const buildTest = function (testName, opts) {
return function (callback) {
saveInFiles(opts.inFiles);
let args = [binLoc];
args.push("--config-file", "../config.json");
args = args.concat(opts.args);

const spawn = child.spawn(process.execPath, args);

let stderr = "";
let stdout = "";

spawn.stderr.on("data", function (chunk) {
stderr += chunk;
});

spawn.stdout.on("data", function (chunk) {
stdout += chunk;
});

spawn.on("close", function () {
let err;

try {
assertTest(stdout, stderr, opts);
} catch (e) {
err = e;
}

if (err) {
err.message =
args.map(arg => `"${arg}"`).join(" ") + ": " + err.message;
}

callback(err);
});

if (opts.stdin) {
spawn.stdin.write(opts.stdin);
spawn.stdin.end();
}
};
};

describe("bin/babel-node", function () {
let cwd;

beforeEach(() => {
cwd = process.cwd();

if (fs.existsSync(tmpLoc)) {
for (const child of fs.readdirSync(tmpLoc)) {
rimraf.sync(path.join(tmpLoc, child));
}
} else {
fs.mkdirSync(tmpLoc);
}

process.chdir(tmpLoc);
});

afterEach(() => {
process.chdir(cwd);
});

fs.readdirSync(fixtureLoc).forEach(function (testName) {
if (testName[0] === ".") return;

const testLoc = path.join(fixtureLoc, testName);

const opts = {
args: [],
};

const optionsLoc = path.join(testLoc, "options.json");
if (fs.existsSync(optionsLoc)) Object.assign(opts, require(optionsLoc));

["stdout", "stdin", "stderr"].forEach(function (key) {
const loc = path.join(testLoc, key + ".txt");
if (fs.existsSync(loc)) {
opts[key] = helper.readFile(loc);
} else {
opts[key] = opts[key] || "";
}
});

opts.outFiles = readDir(path.join(testLoc, "out-files"), fileFilter);
opts.inFiles = readDir(path.join(testLoc, "in-files"), fileFilter);

const babelrcLoc = path.join(testLoc, ".babelrc");
if (fs.existsSync(babelrcLoc)) {
// copy .babelrc file to tmp directory
opts.inFiles[".babelrc"] = helper.readFile(babelrcLoc);
}

it(testName, buildTest(testName, opts), 20000);
});
});
1 change: 1 addition & 0 deletions packages/babel-node/test/fixtures/misc/child.js
@@ -0,0 +1 @@
process.send("hello");