Make babel-node a standalone package (#6023)
* Make babel-node a standalone package * New package `babel-node` previously `babel-cli/bin/babel-node` * updates
This commit is contained in:
parent
e32042f353
commit
6d965c0926
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,6 +23,7 @@ package-lock.json
|
|||||||
!/packages/babel-runtime/helpers/es6/toArray.js
|
!/packages/babel-runtime/helpers/es6/toArray.js
|
||||||
/packages/babel-register/test/.babel
|
/packages/babel-register/test/.babel
|
||||||
/packages/babel-cli/test/tmp
|
/packages/babel-cli/test/tmp
|
||||||
|
/packages/babel-node/test/tmp
|
||||||
/packages/*/lib
|
/packages/*/lib
|
||||||
.nyc_output
|
.nyc_output
|
||||||
/babel.sublime-workspace
|
/babel.sublime-workspace
|
||||||
|
|||||||
3
packages/babel-node/.npmignore
Normal file
3
packages/babel-node/.npmignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
src
|
||||||
|
test
|
||||||
|
node_modules
|
||||||
17
packages/babel-node/README.md
Normal file
17
packages/babel-node/README.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# babel-node
|
||||||
|
|
||||||
|
> A Babel-powered Node.js CLI
|
||||||
|
|
||||||
|
babel-node is a CLI that works exactly the same as the Node.js CLI, with the added benefit of compiling with Babel presets and plugins before running it.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save-dev babel-node
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```sh
|
||||||
|
babel-node [options] [ -e script | script.js ] [arguments]
|
||||||
|
```
|
||||||
3
packages/babel-node/bin/babel-node.js
Executable file
3
packages/babel-node/bin/babel-node.js
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
require("../lib/babel-node");
|
||||||
34
packages/babel-node/package.json
Normal file
34
packages/babel-node/package.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"name": "babel-node",
|
||||||
|
"version": "7.0.0-alpha.17",
|
||||||
|
"description": "Babel command line",
|
||||||
|
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||||
|
"homepage": "https://babeljs.io/",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "https://github.com/babel/babel/tree/master/packages/babel-node",
|
||||||
|
"keywords": [
|
||||||
|
"6to5",
|
||||||
|
"babel",
|
||||||
|
"es6",
|
||||||
|
"transpile",
|
||||||
|
"transpiler",
|
||||||
|
"babel-cli",
|
||||||
|
"compiler"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"babel-core": "7.0.0-alpha.17",
|
||||||
|
"babel-register": "7.0.0-alpha.17",
|
||||||
|
"babel-polyfill": "7.0.0-alpha.17",
|
||||||
|
"commander": "^2.8.1",
|
||||||
|
"fs-readdir-recursive": "^1.0.0",
|
||||||
|
"lodash": "^4.2.0",
|
||||||
|
"output-file-sync": "^2.0.0",
|
||||||
|
"v8flags": "^3.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-helper-fixtures": "7.0.0-alpha.17"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"babel-node": "./bin/babel-node.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
186
packages/babel-node/src/_babel-node.js
Normal file
186
packages/babel-node/src/_babel-node.js
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
import commander from "commander";
|
||||||
|
import Module from "module";
|
||||||
|
import { inspect } from "util";
|
||||||
|
import path from "path";
|
||||||
|
import repl from "repl";
|
||||||
|
import * as babel from "babel-core";
|
||||||
|
import vm from "vm";
|
||||||
|
import "babel-polyfill";
|
||||||
|
import register from "babel-register";
|
||||||
|
|
||||||
|
import pkg from "../package.json";
|
||||||
|
|
||||||
|
const program = new commander.Command("babel-node");
|
||||||
|
|
||||||
|
function collect(value, previousValue): Array<string> {
|
||||||
|
// If the user passed the option with no value, like "babel-node file.js --presets", do nothing.
|
||||||
|
if (typeof value !== "string") return previousValue;
|
||||||
|
|
||||||
|
const values = value.split(",");
|
||||||
|
|
||||||
|
return previousValue ? previousValue.concat(values) : values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable max-len */
|
||||||
|
program.option("-e, --eval [script]", "Evaluate script");
|
||||||
|
program.option("-p, --print [code]", "Evaluate script and print result");
|
||||||
|
program.option(
|
||||||
|
"-o, --only [globs]",
|
||||||
|
"A comma-separated list of glob patterns to compile",
|
||||||
|
collect,
|
||||||
|
);
|
||||||
|
program.option(
|
||||||
|
"-i, --ignore [globs]",
|
||||||
|
"A comma-separated list of glob patterns to skip compiling",
|
||||||
|
collect,
|
||||||
|
);
|
||||||
|
program.option(
|
||||||
|
"-x, --extensions [extensions]",
|
||||||
|
"List of extensions to hook into [.es6,.js,.es,.jsx,.mjs]",
|
||||||
|
collect,
|
||||||
|
);
|
||||||
|
program.option("-w, --plugins [string]", "", collect);
|
||||||
|
program.option("-b, --presets [string]", "", collect);
|
||||||
|
/* eslint-enable max-len */
|
||||||
|
|
||||||
|
program.version(pkg.version);
|
||||||
|
program.usage("[options] [ -e script | script.js ] [arguments]");
|
||||||
|
program.parse(process.argv);
|
||||||
|
|
||||||
|
register({
|
||||||
|
extensions: program.extensions,
|
||||||
|
ignore: program.ignore,
|
||||||
|
only: program.only,
|
||||||
|
plugins: program.plugins,
|
||||||
|
presets: program.presets,
|
||||||
|
});
|
||||||
|
|
||||||
|
const replPlugin = ({ types: t }) => ({
|
||||||
|
visitor: {
|
||||||
|
ModuleDeclaration(path) {
|
||||||
|
throw path.buildCodeFrameError("Modules aren't supported in the REPL");
|
||||||
|
},
|
||||||
|
|
||||||
|
VariableDeclaration(path) {
|
||||||
|
if (path.node.kind !== "var") {
|
||||||
|
throw path.buildCodeFrameError(
|
||||||
|
"Only `var` variables are supported in the REPL",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Program(path) {
|
||||||
|
if (path.get("body").some(child => child.isExpressionStatement())) return;
|
||||||
|
|
||||||
|
// If the executed code doesn't evaluate to a value,
|
||||||
|
// prevent implicit strict mode from printing 'use strict'.
|
||||||
|
path.pushContainer(
|
||||||
|
"body",
|
||||||
|
t.expressionStatement(t.identifier("undefined")),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const _eval = function(code, filename) {
|
||||||
|
code = code.trim();
|
||||||
|
if (!code) return undefined;
|
||||||
|
|
||||||
|
code = babel.transform(code, {
|
||||||
|
filename: filename,
|
||||||
|
presets: program.presets,
|
||||||
|
plugins: (program.plugins || []).concat([replPlugin]),
|
||||||
|
}).code;
|
||||||
|
|
||||||
|
return vm.runInThisContext(code, {
|
||||||
|
filename: filename,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (program.eval || program.print) {
|
||||||
|
let code = program.eval;
|
||||||
|
if (!code || code === true) code = program.print;
|
||||||
|
|
||||||
|
global.__filename = "[eval]";
|
||||||
|
global.__dirname = process.cwd();
|
||||||
|
|
||||||
|
const module = new Module(global.__filename);
|
||||||
|
module.filename = global.__filename;
|
||||||
|
module.paths = Module._nodeModulePaths(global.__dirname);
|
||||||
|
|
||||||
|
global.exports = module.exports;
|
||||||
|
global.module = module;
|
||||||
|
global.require = module.require.bind(module);
|
||||||
|
|
||||||
|
const result = _eval(code, global.__filename);
|
||||||
|
if (program.print) {
|
||||||
|
const output = typeof result === "string" ? result : inspect(result);
|
||||||
|
process.stdout.write(output + "\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (program.args.length) {
|
||||||
|
// slice all arguments up to the first filename since they're babel args that we handle
|
||||||
|
let args = process.argv.slice(2);
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
let ignoreNext = false;
|
||||||
|
args.some(function(arg, i2) {
|
||||||
|
if (ignoreNext) {
|
||||||
|
ignoreNext = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg[0] === "-") {
|
||||||
|
const parsedArg = program[arg.slice(2)];
|
||||||
|
if (parsedArg && parsedArg !== true) {
|
||||||
|
ignoreNext = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
i = i2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
args = args.slice(i);
|
||||||
|
|
||||||
|
// make the filename absolute
|
||||||
|
const filename = args[0];
|
||||||
|
if (!path.isAbsolute(filename)) {
|
||||||
|
args[0] = path.join(process.cwd(), filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add back on node and concat the sliced args
|
||||||
|
process.argv = ["node"].concat(args);
|
||||||
|
process.execArgv.unshift(__filename);
|
||||||
|
|
||||||
|
Module.runMain();
|
||||||
|
} else {
|
||||||
|
replStart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function replStart() {
|
||||||
|
repl.start({
|
||||||
|
prompt: "> ",
|
||||||
|
input: process.stdin,
|
||||||
|
output: process.stdout,
|
||||||
|
eval: replEval,
|
||||||
|
useGlobal: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function replEval(code, context, filename, callback) {
|
||||||
|
let err;
|
||||||
|
let result;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (code[0] === "(" && code[code.length - 1] === ")") {
|
||||||
|
code = code.slice(1, -1); // remove "(" and ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
result = _eval(code, filename);
|
||||||
|
} catch (e) {
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(err, result);
|
||||||
|
}
|
||||||
98
packages/babel-node/src/babel-node.js
Executable file
98
packages/babel-node/src/babel-node.js
Executable file
@ -0,0 +1,98 @@
|
|||||||
|
/**
|
||||||
|
* This tiny wrapper file checks for known node flags and appends them
|
||||||
|
* when found, before invoking the "real" _babel-node(1) executable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import getV8Flags from "v8flags";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
let args = [path.join(__dirname, "_babel-node")];
|
||||||
|
|
||||||
|
let babelArgs = process.argv.slice(2);
|
||||||
|
let userArgs;
|
||||||
|
|
||||||
|
// separate node arguments from script arguments
|
||||||
|
const argSeparator = babelArgs.indexOf("--");
|
||||||
|
if (argSeparator > -1) {
|
||||||
|
userArgs = babelArgs.slice(argSeparator); // including the --
|
||||||
|
babelArgs = babelArgs.slice(0, argSeparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace dashes with underscores in the v8Flag name
|
||||||
|
* Also ensure that if the arg contains a value (e.g. --arg=true)
|
||||||
|
* that only the flag is returned.
|
||||||
|
*/
|
||||||
|
function getNormalizedV8Flag(arg) {
|
||||||
|
const matches = arg.match(/--(.+)/);
|
||||||
|
|
||||||
|
if (matches) {
|
||||||
|
return `--${matches[1].replace(/-/g, "_")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
getV8Flags(function(err, v8Flags) {
|
||||||
|
babelArgs.forEach(function(arg) {
|
||||||
|
const flag = arg.split("=")[0];
|
||||||
|
|
||||||
|
switch (flag) {
|
||||||
|
case "-d":
|
||||||
|
args.unshift("--debug");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "debug":
|
||||||
|
case "--debug":
|
||||||
|
case "--debug-brk":
|
||||||
|
case "--inspect":
|
||||||
|
args.unshift(arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "-gc":
|
||||||
|
args.unshift("--expose-gc");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "--nolazy":
|
||||||
|
args.unshift(flag);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (
|
||||||
|
v8Flags.indexOf(getNormalizedV8Flag(flag)) >= 0 ||
|
||||||
|
arg.indexOf("--trace") === 0
|
||||||
|
) {
|
||||||
|
args.unshift(arg);
|
||||||
|
} else {
|
||||||
|
args.push(arg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// append arguments passed after --
|
||||||
|
if (argSeparator > -1) {
|
||||||
|
args = args.concat(userArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const kexec = require("kexec");
|
||||||
|
kexec(process.argv[0], args);
|
||||||
|
} catch (err) {
|
||||||
|
if (err.code !== "MODULE_NOT_FOUND") throw err;
|
||||||
|
|
||||||
|
const child_process = require("child_process");
|
||||||
|
const proc = child_process.spawn(process.argv[0], args, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
proc.on("exit", function(code, signal) {
|
||||||
|
process.on("exit", function() {
|
||||||
|
if (signal) {
|
||||||
|
process.kill(process.pid, signal);
|
||||||
|
} else {
|
||||||
|
process.exit(code);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
4
packages/babel-node/test/fixtures/babel-node/--eval/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/--eval/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"args": ["--eval", "console.log([1, 2, 3].map(x => x * x));"],
|
||||||
|
"stdout": "[ 1, 4, 9 ]"
|
||||||
|
}
|
||||||
1
packages/babel-node/test/fixtures/babel-node/--extensions/in-files/foo.bar
vendored
Normal file
1
packages/babel-node/test/fixtures/babel-node/--extensions/in-files/foo.bar
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
console.log([1, 2, 3].map(x => x * x));
|
||||||
4
packages/babel-node/test/fixtures/babel-node/--extensions/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/--extensions/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"args": ["foo", "--extensions", ".bar"],
|
||||||
|
"stdout": "[ 1, 4, 9 ]"
|
||||||
|
}
|
||||||
4
packages/babel-node/test/fixtures/babel-node/--print/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/--print/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"args": ["--print", "--eval", "([1, 2, 3].map(x => x * x))"],
|
||||||
|
"stdout": "[ 1, 4, 9 ]"
|
||||||
|
}
|
||||||
1
packages/babel-node/test/fixtures/babel-node/arguments/in-files/bar.js
vendored
Normal file
1
packages/babel-node/test/fixtures/babel-node/arguments/in-files/bar.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
console.log(process.argv[2]);
|
||||||
4
packages/babel-node/test/fixtures/babel-node/arguments/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/arguments/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"args": ["bar", "foo"],
|
||||||
|
"stdout": "foo"
|
||||||
|
}
|
||||||
2
packages/babel-node/test/fixtures/babel-node/directory/in-files/foo/index.js
vendored
Normal file
2
packages/babel-node/test/fixtures/babel-node/directory/in-files/foo/index.js
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
var foo = () => console.log("foo");
|
||||||
|
foo();
|
||||||
3
packages/babel-node/test/fixtures/babel-node/directory/options.json
vendored
Normal file
3
packages/babel-node/test/fixtures/babel-node/directory/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"args": ["foo"]
|
||||||
|
}
|
||||||
1
packages/babel-node/test/fixtures/babel-node/directory/stdout.txt
vendored
Normal file
1
packages/babel-node/test/fixtures/babel-node/directory/stdout.txt
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
foo
|
||||||
2
packages/babel-node/test/fixtures/babel-node/filename/in-files/bar.js
vendored
Normal file
2
packages/babel-node/test/fixtures/babel-node/filename/in-files/bar.js
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
var foo = () => console.log("foo");
|
||||||
|
foo();
|
||||||
3
packages/babel-node/test/fixtures/babel-node/filename/options.json
vendored
Normal file
3
packages/babel-node/test/fixtures/babel-node/filename/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"args": ["bar"]
|
||||||
|
}
|
||||||
1
packages/babel-node/test/fixtures/babel-node/filename/stdout.txt
vendored
Normal file
1
packages/babel-node/test/fixtures/babel-node/filename/stdout.txt
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
foo
|
||||||
4
packages/babel-node/test/fixtures/babel-node/no-strict/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/no-strict/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"args": ["--eval","--print", "var a = 1;"],
|
||||||
|
"stdout": "undefined"
|
||||||
|
}
|
||||||
2
packages/babel-node/test/fixtures/babel-node/require/in-files/bar2.js
vendored
Normal file
2
packages/babel-node/test/fixtures/babel-node/require/in-files/bar2.js
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
var bar = () => console.log("bar");
|
||||||
|
bar();
|
||||||
5
packages/babel-node/test/fixtures/babel-node/require/in-files/foo2.js
vendored
Normal file
5
packages/babel-node/test/fixtures/babel-node/require/in-files/foo2.js
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import "./bar2";
|
||||||
|
import "./not_node_modules";
|
||||||
|
|
||||||
|
var foo = () => console.log("foo");
|
||||||
|
foo();
|
||||||
10
packages/babel-node/test/fixtures/babel-node/require/in-files/not_node_modules.jsx
vendored
Normal file
10
packages/babel-node/test/fixtures/babel-node/require/in-files/not_node_modules.jsx
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
The purpose of this file is to test that the node_modules check in the require
|
||||||
|
hook doesn't mistakenly exclude something like "not_node_modules". To pass, this
|
||||||
|
file merely needs to be transpiled. The transpiled code won't, and doesn't need
|
||||||
|
to, execute without error. It won't execute because React will be undefined.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
<Some jsx="element" />;
|
||||||
|
}
|
||||||
|
catch (e) {}
|
||||||
3
packages/babel-node/test/fixtures/babel-node/require/options.json
vendored
Normal file
3
packages/babel-node/test/fixtures/babel-node/require/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"args": ["foo2"]
|
||||||
|
}
|
||||||
2
packages/babel-node/test/fixtures/babel-node/require/stdout.txt
vendored
Normal file
2
packages/babel-node/test/fixtures/babel-node/require/stdout.txt
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
bar
|
||||||
|
foo
|
||||||
4
packages/babel-node/test/fixtures/babel-node/v8Flag-dashed-with-param/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/v8Flag-dashed-with-param/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"args": ["--expose-gc-as=garbageCollector", "--eval", "console.log(typeof global.garbageCollector)"],
|
||||||
|
"stdout": "function"
|
||||||
|
}
|
||||||
4
packages/babel-node/test/fixtures/babel-node/v8Flag-dashed/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/v8Flag-dashed/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"args": ["--expose-gc", "--eval", "console.log(typeof global.gc)"],
|
||||||
|
"stdout": "function"
|
||||||
|
}
|
||||||
4
packages/babel-node/test/fixtures/babel-node/v8Flag-underscored-with-param/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/v8Flag-underscored-with-param/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"args": ["--expose_gc_as=garbageCollector", "--eval", "console.log(typeof global.garbageCollector)"],
|
||||||
|
"stdout": "function"
|
||||||
|
}
|
||||||
4
packages/babel-node/test/fixtures/babel-node/v8Flag-underscored/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/v8Flag-underscored/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"args": ["--expose_gc", "--eval", "console.log(typeof global.gc)"],
|
||||||
|
"stdout": "function"
|
||||||
|
}
|
||||||
213
packages/babel-node/test/index.js
Normal file
213
packages/babel-node/test/index.js
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
const includes = require("lodash/includes");
|
||||||
|
const readdir = require("fs-readdir-recursive");
|
||||||
|
const helper = require("babel-helper-fixtures");
|
||||||
|
const assert = require("assert");
|
||||||
|
const rimraf = require("rimraf");
|
||||||
|
const outputFileSync = require("output-file-sync");
|
||||||
|
const child = require("child_process");
|
||||||
|
const merge = require("lodash/merge");
|
||||||
|
const path = require("path");
|
||||||
|
const chai = require("chai");
|
||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
const fixtureLoc = path.join(__dirname, "fixtures");
|
||||||
|
const tmpLoc = path.join(__dirname, "tmp");
|
||||||
|
|
||||||
|
const fileFilter = function(x) {
|
||||||
|
return x !== ".DS_Store";
|
||||||
|
};
|
||||||
|
|
||||||
|
const presetLocs = [
|
||||||
|
path.join(__dirname, "../../babel-preset-es2015"),
|
||||||
|
path.join(__dirname, "../../babel-preset-react"),
|
||||||
|
].join(",");
|
||||||
|
|
||||||
|
const pluginLocs = [
|
||||||
|
path.join(__dirname, "/../../babel-plugin-transform-strict-mode"),
|
||||||
|
path.join(__dirname, "/../../babel-plugin-transform-es2015-modules-commonjs"),
|
||||||
|
].join(",");
|
||||||
|
|
||||||
|
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) {
|
||||||
|
assert.ok(
|
||||||
|
includes(stderr, expectStderr),
|
||||||
|
"stderr " +
|
||||||
|
JSON.stringify(stderr) +
|
||||||
|
" didn't contain " +
|
||||||
|
JSON.stringify(expectStderr),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
chai.expect(stderr).to.equal(expectStderr, "stderr didn't match");
|
||||||
|
}
|
||||||
|
} else if (stderr) {
|
||||||
|
throw new Error("stderr:\n" + stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const expectStdout = opts.stdout.trim();
|
||||||
|
stdout = stdout.trim();
|
||||||
|
stdout = stdout.replace(/\\/g, "/");
|
||||||
|
|
||||||
|
if (opts.stdout) {
|
||||||
|
if (opts.stdoutContains) {
|
||||||
|
assert.ok(
|
||||||
|
includes(stdout, expectStdout),
|
||||||
|
"stdout " +
|
||||||
|
JSON.stringify(stdout) +
|
||||||
|
" didn't contain " +
|
||||||
|
JSON.stringify(expectStdout),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
chai.expect(stdout).to.equal(expectStdout, "stdout didn't match");
|
||||||
|
}
|
||||||
|
} 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 (!opts.inFiles.hasOwnProperty(filename)) {
|
||||||
|
const expect = opts.outFiles[filename];
|
||||||
|
const actual = actualFiles[filename];
|
||||||
|
|
||||||
|
chai.expect(expect, "Output is missing: " + filename).to.not.be
|
||||||
|
.undefined;
|
||||||
|
|
||||||
|
if (expect) {
|
||||||
|
chai
|
||||||
|
.expect(actual)
|
||||||
|
.to.equal(expect, "Compiled output does not match: " + filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(opts.outFiles).forEach(function(filename) {
|
||||||
|
chai
|
||||||
|
.expect(actualFiles, "Extraneous file in output: " + filename)
|
||||||
|
.to.contain.key(filename);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildTest = function(binName, testName, opts) {
|
||||||
|
const binLoc = path.join(__dirname, "../lib", binName);
|
||||||
|
|
||||||
|
return function(callback) {
|
||||||
|
clear();
|
||||||
|
saveInFiles(opts.inFiles);
|
||||||
|
|
||||||
|
let args = [binLoc];
|
||||||
|
|
||||||
|
args.push("--presets", presetLocs, "--plugins", pluginLocs);
|
||||||
|
args.push("--only", "../../../../packages/*/test");
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const clear = function() {
|
||||||
|
process.chdir(__dirname);
|
||||||
|
if (fs.existsSync(tmpLoc)) rimraf.sync(tmpLoc);
|
||||||
|
fs.mkdirSync(tmpLoc);
|
||||||
|
process.chdir(tmpLoc);
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.readdirSync(fixtureLoc).forEach(function(binName) {
|
||||||
|
if (binName[0] === ".") return;
|
||||||
|
|
||||||
|
const suiteLoc = path.join(fixtureLoc, binName);
|
||||||
|
describe("bin/" + binName, function() {
|
||||||
|
fs.readdirSync(suiteLoc).forEach(function(testName) {
|
||||||
|
if (testName[0] === ".") return;
|
||||||
|
|
||||||
|
const testLoc = path.join(suiteLoc, testName);
|
||||||
|
|
||||||
|
const opts = {
|
||||||
|
args: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const optionsLoc = path.join(testLoc, "options.json");
|
||||||
|
if (fs.existsSync(optionsLoc)) merge(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(binName, testName, opts));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user