Run prettier

This commit is contained in:
Brian Ng 2017-06-27 12:15:00 -05:00
parent 93cc22dae1
commit e4b35f680d
No known key found for this signature in database
GPG Key ID: 3F2380E1E1508CA9
307 changed files with 6742 additions and 4080 deletions

View File

@ -22,26 +22,35 @@ function swapSrcWithLib(srcPath) {
gulp.task("default", ["build"]); gulp.task("default", ["build"]);
gulp.task("build", function() { gulp.task("build", function() {
return gulp.src(scripts, { base: base }) return gulp
.pipe(plumber({ .src(scripts, { base: base })
.pipe(
plumber({
errorHandler: function(err) { errorHandler: function(err) {
gutil.log(err.stack); gutil.log(err.stack);
}, },
})) })
.pipe(newer({ )
.pipe(
newer({
dest: base, dest: base,
map: swapSrcWithLib, map: swapSrcWithLib,
})) })
.pipe(through.obj(function (file, enc, callback) { )
.pipe(
through.obj(function(file, enc, callback) {
gutil.log("Compiling", "'" + chalk.cyan(file.relative) + "'..."); gutil.log("Compiling", "'" + chalk.cyan(file.relative) + "'...");
callback(null, file); callback(null, file);
})) })
)
.pipe(babel()) .pipe(babel())
.pipe(through.obj(function (file, enc, callback) { .pipe(
through.obj(function(file, enc, callback) {
// Passing 'file.relative' because newer() above uses a relative path and this keeps it consistent. // Passing 'file.relative' because newer() above uses a relative path and this keeps it consistent.
file.path = path.resolve(file.base, swapSrcWithLib(file.relative)); file.path = path.resolve(file.base, swapSrcWithLib(file.relative));
callback(null, file); callback(null, file);
})) })
)
.pipe(gulp.dest(base)); .pipe(gulp.dest(base));
}); });

View File

@ -24,9 +24,21 @@ function collect(value, previousValue): Array<string> {
/* eslint-disable max-len */ /* eslint-disable max-len */
program.option("-e, --eval [script]", "Evaluate script"); program.option("-e, --eval [script]", "Evaluate script");
program.option("-p, --print [code]", "Evaluate script and print result"); 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(
program.option("-i, --ignore [globs]", "A comma-separated list of glob patterns to skip compiling", collect); "-o, --only [globs]",
program.option("-x, --extensions [extensions]", "List of extensions to hook into [.es6,.js,.es,.jsx,.mjs]", collect); "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("-w, --plugins [string]", "", collect);
program.option("-b, --presets [string]", "", collect); program.option("-b, --presets [string]", "", collect);
/* eslint-enable max-len */ /* eslint-enable max-len */
@ -55,16 +67,21 @@ const replPlugin = ({ types: t }) => ({
VariableDeclaration(path) { VariableDeclaration(path) {
if (path.node.kind !== "var") { if (path.node.kind !== "var") {
throw path.buildCodeFrameError("Only `var` variables are supported in the REPL"); throw path.buildCodeFrameError(
"Only `var` variables are supported in the REPL",
);
} }
}, },
Program(path) { Program(path) {
if (path.get("body").some((child) => child.isExpressionStatement())) return; if (path.get("body").some(child => child.isExpressionStatement())) return;
// If the executed code doesn't evaluate to a value, // If the executed code doesn't evaluate to a value,
// prevent implicit strict mode from printing 'use strict'. // prevent implicit strict mode from printing 'use strict'.
path.pushContainer("body", t.expressionStatement(t.identifier("undefined"))); path.pushContainer(
"body",
t.expressionStatement(t.identifier("undefined")),
);
}, },
}, },
}); });
@ -133,7 +150,9 @@ if (program.eval || program.print) {
// make the filename absolute // make the filename absolute
const filename = args[0]; const filename = args[0];
if (!path.isAbsolute(filename)) args[0] = path.join(process.cwd(), filename); if (!path.isAbsolute(filename)) {
args[0] = path.join(process.cwd(), filename);
}
// add back on node and concat the sliced args // add back on node and concat the sliced args
process.argv = ["node"].concat(args); process.argv = ["node"].concat(args);

View File

@ -10,8 +10,16 @@ function collect(value, previousValue): Array<string> {
return previousValue ? previousValue.concat(values) : values; return previousValue ? previousValue.concat(values) : values;
} }
commander.option("-l, --whitelist [whitelist]", "Whitelist of helpers to ONLY include", collect); commander.option(
commander.option("-t, --output-type [type]", "Type of output (global|umd|var)", "global"); "-l, --whitelist [whitelist]",
"Whitelist of helpers to ONLY include",
collect,
);
commander.option(
"-t, --output-type [type]",
"Type of output (global|umd|var)",
"global",
);
commander.usage("[options]"); commander.usage("[options]");
commander.parse(process.argv); commander.parse(process.argv);

View File

@ -59,7 +59,10 @@ getV8Flags(function (err, v8Flags) {
break; break;
default: default:
if (v8Flags.indexOf(getNormalizedV8Flag(flag)) >= 0 || arg.indexOf("--trace") === 0) { if (
v8Flags.indexOf(getNormalizedV8Flag(flag)) >= 0 ||
arg.indexOf("--trace") === 0
) {
args.unshift(arg); args.unshift(arg);
} else { } else {
args.push(arg); args.push(arg);
@ -80,7 +83,9 @@ getV8Flags(function (err, v8Flags) {
if (err.code !== "MODULE_NOT_FOUND") throw err; if (err.code !== "MODULE_NOT_FOUND") throw err;
const child_process = require("child_process"); const child_process = require("child_process");
const proc = child_process.spawn(process.argv[0], args, { stdio: "inherit" }); const proc = child_process.spawn(process.argv[0], args, {
stdio: "inherit",
});
proc.on("exit", function(code, signal) { proc.on("exit", function(code, signal) {
process.on("exit", function() { process.on("exit", function() {
if (signal) { if (signal) {

View File

@ -8,17 +8,25 @@ import * as util from "./util";
export default function(commander, filenames, opts) { export default function(commander, filenames, opts) {
function write(src, relative) { function write(src, relative) {
if (!util.isCompilableExtension(relative, commander.extensions)) return false; if (!util.isCompilableExtension(relative, commander.extensions)) {
return false;
}
// remove extension and then append back on .js // remove extension and then append back on .js
relative = relative.replace(/\.(\w*?)$/, "") + ".js"; relative = relative.replace(/\.(\w*?)$/, "") + ".js";
const dest = path.join(commander.outDir, relative); const dest = path.join(commander.outDir, relative);
const data = util.compile(src, defaults({ const data = util.compile(
src,
defaults(
{
sourceFileName: slash(path.relative(dest + "/..", src)), sourceFileName: slash(path.relative(dest + "/..", src)),
sourceMapTarget: path.basename(relative), sourceMapTarget: path.basename(relative),
}, opts)); },
opts,
),
);
if (!data) return false; if (!data) return false;

View File

@ -39,14 +39,17 @@ export default function (commander, filenames, opts) {
column: mapping.generatedColumn, column: mapping.generatedColumn,
}, },
source: mapping.source, source: mapping.source,
original: mapping.source == null ? null : { original:
mapping.source == null
? null
: {
line: mapping.originalLine, line: mapping.originalLine,
column: mapping.originalColumn, column: mapping.originalColumn,
}, },
}); });
}); });
sources.forEach((source) => { sources.forEach(source => {
const content = consumer.sourceContentFor(source, true); const content = consumer.sourceContentFor(source, true);
if (content !== null) { if (content !== null) {
map.setSourceContent(source, content); map.setSourceContent(source, content);
@ -59,7 +62,10 @@ export default function (commander, filenames, opts) {
// add the inline sourcemap comment if we've either explicitly asked for inline source // add the inline sourcemap comment if we've either explicitly asked for inline source
// maps, or we've requested them without any output file // maps, or we've requested them without any output file
if (commander.sourceMaps === "inline" || (!commander.outFile && commander.sourceMaps)) { if (
commander.sourceMaps === "inline" ||
(!commander.outFile && commander.sourceMaps)
) {
code += "\n" + convertSourceMap.fromObject(map).toComment(); code += "\n" + convertSourceMap.fromObject(map).toComment();
} }
@ -97,9 +103,18 @@ export default function (commander, filenames, opts) {
}); });
process.stdin.on("end", function() { process.stdin.on("end", function() {
results.push(util.transform(commander.filename, code, defaults({ results.push(
util.transform(
commander.filename,
code,
defaults(
{
sourceFileName: "stdin", sourceFileName: "stdin",
}, opts))); },
opts,
),
),
);
output(); output();
}); });
}; };
@ -126,13 +141,22 @@ export default function (commander, filenames, opts) {
_filenames.forEach(function(filename) { _filenames.forEach(function(filename) {
let sourceFilename = filename; let sourceFilename = filename;
if (commander.outFile) { if (commander.outFile) {
sourceFilename = path.relative(path.dirname(commander.outFile), sourceFilename); sourceFilename = path.relative(
path.dirname(commander.outFile),
sourceFilename,
);
} }
sourceFilename = slash(sourceFilename); sourceFilename = slash(sourceFilename);
const data = util.compile(filename, defaults({ const data = util.compile(
filename,
defaults(
{
sourceFileName: sourceFilename, sourceFileName: sourceFilename,
}, opts)); },
opts,
),
);
if (!data) return; if (!data) return;
@ -143,22 +167,25 @@ export default function (commander, filenames, opts) {
}; };
const files = function() { const files = function() {
if (!commander.skipInitialBuild) { if (!commander.skipInitialBuild) {
walk(); walk();
} }
if (commander.watch) { if (commander.watch) {
const chokidar = util.requireChokidar(); const chokidar = util.requireChokidar();
chokidar.watch(filenames, { chokidar
.watch(filenames, {
persistent: true, persistent: true,
ignoreInitial: true, ignoreInitial: true,
awaitWriteFinish: { awaitWriteFinish: {
stabilityThreshold: 50, stabilityThreshold: 50,
pollInterval: 10, pollInterval: 10,
}, },
}).on("all", function (type, filename) { })
if (!util.isCompilableExtension(filename, commander.extensions)) return; .on("all", function(type, filename) {
if (!util.isCompilableExtension(filename, commander.extensions)) {
return;
}
if (type === "add" || type === "change") { if (type === "add" || type === "change") {
util.log(type + " " + filename); util.log(type + " " + filename);

View File

@ -34,45 +34,117 @@ function collect(value, previousValue): Array<string> {
/* eslint-disable max-len */ /* eslint-disable max-len */
// Standard Babel input configs. // Standard Babel input configs.
commander.option("-f, --filename [filename]", "filename to use when reading from stdin - this will be used in source-maps, errors etc"); commander.option(
commander.option("--presets [list]", "comma-separated list of preset names", collect); "-f, --filename [filename]",
commander.option("--plugins [list]", "comma-separated list of plugin names", collect); "filename to use when reading from stdin - this will be used in source-maps, errors etc",
);
commander.option(
"--presets [list]",
"comma-separated list of preset names",
collect,
);
commander.option(
"--plugins [list]",
"comma-separated list of plugin names",
collect,
);
// Basic file input configuration. // Basic file input configuration.
commander.option("--source-type [script|module]", ""); commander.option("--source-type [script|module]", "");
commander.option("--no-babelrc", "Whether or not to look up .babelrc and .babelignore files"); commander.option(
commander.option("--ignore [list]", "list of glob paths to **not** compile", collect); "--no-babelrc",
commander.option("--only [list]", "list of glob paths to **only** compile", collect); "Whether or not to look up .babelrc and .babelignore files",
);
commander.option(
"--ignore [list]",
"list of glob paths to **not** compile",
collect,
);
commander.option(
"--only [list]",
"list of glob paths to **only** compile",
collect,
);
// Misc babel config. // Misc babel config.
commander.option("--no-highlight-code", "enable/disable ANSI syntax highlighting of code frames (on by default)"); commander.option(
"--no-highlight-code",
"enable/disable ANSI syntax highlighting of code frames (on by default)",
);
// General output formatting. // General output formatting.
commander.option("--no-comments", "write comments to generated output (true by default)"); commander.option(
commander.option("--retain-lines", "retain line numbers - will result in really ugly code"); "--no-comments",
commander.option("--compact [true|false|auto]", "do not include superfluous whitespace characters and line terminators", booleanify); "write comments to generated output (true by default)",
);
commander.option(
"--retain-lines",
"retain line numbers - will result in really ugly code",
);
commander.option(
"--compact [true|false|auto]",
"do not include superfluous whitespace characters and line terminators",
booleanify,
);
commander.option("--minified", "save as much bytes when printing [true|false]"); commander.option("--minified", "save as much bytes when printing [true|false]");
commander.option("--auxiliary-comment-before [string]", "print a comment before any injected non-user code"); commander.option(
commander.option("--auxiliary-comment-after [string]", "print a comment after any injected non-user code"); "--auxiliary-comment-before [string]",
"print a comment before any injected non-user code",
);
commander.option(
"--auxiliary-comment-after [string]",
"print a comment after any injected non-user code",
);
// General soucemap formatting. // General soucemap formatting.
commander.option("-s, --source-maps [true|false|inline|both]", "", booleanify); commander.option("-s, --source-maps [true|false|inline|both]", "", booleanify);
commander.option("--source-map-target [string]", "set `file` on returned source map"); commander.option(
commander.option("--source-file-name [string]", "set `sources[0]` on returned source map"); "--source-map-target [string]",
commander.option("--source-root [filename]", "the root from which all sources are relative"); "set `file` on returned source map",
);
commander.option(
"--source-file-name [string]",
"set `sources[0]` on returned source map",
);
commander.option(
"--source-root [filename]",
"the root from which all sources are relative",
);
// Config params for certain module output formats. // Config params for certain module output formats.
commander.option("--module-root [filename]", "optional prefix for the AMD module formatter that will be prepend to the filename on module definitions"); commander.option(
"--module-root [filename]",
"optional prefix for the AMD module formatter that will be prepend to the filename on module definitions",
);
commander.option("-M, --module-ids", "insert an explicit id for modules"); commander.option("-M, --module-ids", "insert an explicit id for modules");
commander.option("--module-id [string]", "specify a custom name for module ids"); commander.option(
"--module-id [string]",
"specify a custom name for module ids",
);
// "babel" command specific arguments that are not passed to babel-core. // "babel" command specific arguments that are not passed to babel-core.
commander.option("-x, --extensions [extensions]", "List of extensions to compile when a directory has been input [.es6,.js,.es,.jsx,.mjs]", collect); commander.option(
"-x, --extensions [extensions]",
"List of extensions to compile when a directory has been input [.es6,.js,.es,.jsx,.mjs]",
collect,
);
commander.option("-w, --watch", "Recompile files on changes"); commander.option("-w, --watch", "Recompile files on changes");
commander.option("--skip-initial-build", "Do not compile files before watching"); commander.option(
commander.option("-o, --out-file [out]", "Compile all input files into a single file"); "--skip-initial-build",
commander.option("-d, --out-dir [out]", "Compile an input directory of modules into an output directory"); "Do not compile files before watching",
commander.option("-D, --copy-files", "When compiling a directory copy over non-compilable files"); );
commander.option(
"-o, --out-file [out]",
"Compile all input files into a single file",
);
commander.option(
"-d, --out-dir [out]",
"Compile an input directory of modules into an output directory",
);
commander.option(
"-D, --copy-files",
"When compiling a directory copy over non-compilable files",
);
commander.option("-q, --quiet", "Don't log anything"); commander.option("-q, --quiet", "Don't log anything");
/* eslint-enable max-len */ /* eslint-enable max-len */

View File

@ -20,7 +20,10 @@ export { readdir };
/** /**
* Test if a filename ends with a compilable extension. * Test if a filename ends with a compilable extension.
*/ */
export function isCompilableExtension(filename: string, altExts?: Array<string>): boolean { export function isCompilableExtension(
filename: string,
altExts?: Array<string>,
): boolean {
const exts = altExts || babel.DEFAULT_EXTENSIONS; const exts = altExts || babel.DEFAULT_EXTENSIONS;
const ext = path.extname(filename); const ext = path.extname(filename);
return includes(exts, ext); return includes(exts, ext);
@ -74,7 +77,7 @@ export function requireChokidar() {
} catch (err) { } catch (err) {
console.error( console.error(
"The optional dependency chokidar failed to install and is required for " + "The optional dependency chokidar failed to install and is required for " +
"--watch. Chokidar is likely not supported on your platform." "--watch. Chokidar is likely not supported on your platform.",
); );
throw err; throw err;
} }

View File

@ -53,8 +53,13 @@ const assertTest = function (stdout, stderr, opts) {
if (opts.stderr) { if (opts.stderr) {
if (opts.stderrContains) { if (opts.stderrContains) {
assert.ok(includes(stderr, expectStderr), "stderr " + JSON.stringify(stderr) + assert.ok(
" didn't contain " + JSON.stringify(expectStderr)); includes(stderr, expectStderr),
"stderr " +
JSON.stringify(stderr) +
" didn't contain " +
JSON.stringify(expectStderr),
);
} else { } else {
chai.expect(stderr).to.equal(expectStderr, "stderr didn't match"); chai.expect(stderr).to.equal(expectStderr, "stderr didn't match");
} }
@ -68,8 +73,13 @@ const assertTest = function (stdout, stderr, opts) {
if (opts.stdout) { if (opts.stdout) {
if (opts.stdoutContains) { if (opts.stdoutContains) {
assert.ok(includes(stdout, expectStdout), "stdout " + JSON.stringify(stdout) + assert.ok(
" didn't contain " + JSON.stringify(expectStdout)); includes(stdout, expectStdout),
"stdout " +
JSON.stringify(stdout) +
" didn't contain " +
JSON.stringify(expectStdout),
);
} else { } else {
chai.expect(stdout).to.equal(expectStdout, "stdout didn't match"); chai.expect(stdout).to.equal(expectStdout, "stdout didn't match");
} }
@ -85,16 +95,20 @@ const assertTest = function (stdout, stderr, opts) {
const expect = opts.outFiles[filename]; const expect = opts.outFiles[filename];
const actual = actualFiles[filename]; const actual = actualFiles[filename];
chai.expect(expect, "Output is missing: " + filename).to.not.be.undefined; chai.expect(expect, "Output is missing: " + filename).to.not.be
.undefined;
if (expect) { if (expect) {
chai.expect(actual).to.equal(expect, "Compiled output does not match: " + filename); chai
.expect(actual)
.to.equal(expect, "Compiled output does not match: " + filename);
} }
} }
}); });
Object.keys(opts.outFiles).forEach(function(filename) { Object.keys(opts.outFiles).forEach(function(filename) {
chai.expect(actualFiles, "Extraneous file in output: " + filename) chai
.expect(actualFiles, "Extraneous file in output: " + filename)
.to.contain.key(filename); .to.contain.key(filename);
}); });
} }
@ -142,7 +156,8 @@ const buildTest = function (binName, testName, opts) {
} }
if (err) { if (err) {
err.message = args.map((arg) => `"${ arg }"`).join(" ") + ": " + err.message; err.message =
args.map(arg => `"${arg}"`).join(" ") + ": " + err.message;
} }
callback(err); callback(err);

View File

@ -94,7 +94,7 @@ function highlight(defs: Object, text: string) {
const type = getTokenType(args); const type = getTokenType(args);
const colorize = defs[type]; const colorize = defs[type];
if (colorize) { if (colorize) {
return args[0].split(NEWLINE).map((str) => colorize(str)).join("\n"); return args[0].split(NEWLINE).map(str => colorize(str)).join("\n");
} else { } else {
return args[0]; return args[0];
} }
@ -106,9 +106,15 @@ function highlight(defs: Object, text: string) {
*/ */
function getMarkerLines( function getMarkerLines(
loc: NodeLocation, source: Array<string>, opts: Object loc: NodeLocation,
source: Array<string>,
opts: Object,
): { start: number, end: number, markerLines: Object } { ): { start: number, end: number, markerLines: Object } {
const startLoc: Location = Object.assign({}, { column: 0, line: -1 }, loc.start); const startLoc: Location = Object.assign(
{},
{ column: 0, line: -1 },
loc.start,
);
const endLoc: Location = Object.assign({}, startLoc, loc.end); const endLoc: Location = Object.assign({}, startLoc, loc.end);
const linesAbove = opts.linesAbove || 2; const linesAbove = opts.linesAbove || 2;
const linesBelow = opts.linesBelow || 3; const linesBelow = opts.linesBelow || 3;
@ -170,7 +176,8 @@ export function codeFrameColumns (
loc: NodeLocation, loc: NodeLocation,
opts: Object = {}, opts: Object = {},
): string { ): string {
const highlighted = (opts.highlightCode && Chalk.supportsColor) || opts.forceColor; const highlighted =
(opts.highlightCode && Chalk.supportsColor) || opts.forceColor;
let chalk = Chalk; let chalk = Chalk;
if (opts.forceColor) { if (opts.forceColor) {
chalk = new Chalk.constructor({ enabled: true }); chalk = new Chalk.constructor({ enabled: true });
@ -186,7 +193,9 @@ export function codeFrameColumns (
const numberMaxWidth = String(end).length; const numberMaxWidth = String(end).length;
const frame = lines.slice(start, end).map((line, index) => { const frame = lines
.slice(start, end)
.map((line, index) => {
const number = start + 1 + index; const number = start + 1 + index;
const paddedNumber = ` ${number}`.slice(-numberMaxWidth); const paddedNumber = ` ${number}`.slice(-numberMaxWidth);
const gutter = ` ${paddedNumber} | `; const gutter = ` ${paddedNumber} | `;
@ -194,7 +203,9 @@ export function codeFrameColumns (
if (hasMarker) { if (hasMarker) {
let markerLine = ""; let markerLine = "";
if (Array.isArray(hasMarker)) { if (Array.isArray(hasMarker)) {
const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replace(/[^\t]/g, " "); const markerSpacing = line
.slice(0, Math.max(hasMarker[0] - 1, 0))
.replace(/[^\t]/g, " ");
const numberOfMarkers = hasMarker[1] || 1; const numberOfMarkers = hasMarker[1] || 1;
markerLine = [ markerLine = [
@ -213,7 +224,8 @@ export function codeFrameColumns (
} else { } else {
return ` ${maybeHighlight(defs.gutter, gutter)}${line}`; return ` ${maybeHighlight(defs.gutter, gutter)}${line}`;
} }
}).join("\n"); })
.join("\n");
if (highlighted) { if (highlighted) {
return chalk.reset(frame); return chalk.reset(frame);
@ -236,7 +248,7 @@ export default function (
deprecationWarningShown = true; deprecationWarningShown = true;
const deprecationError = new Error( const deprecationError = new Error(
"Passing lineNumber and colNumber is deprecated to babel-code-frame. Please use `codeFrameColumns`." "Passing lineNumber and colNumber is deprecated to babel-code-frame. Please use `codeFrameColumns`.",
); );
deprecationError.name = "DeprecationWarning"; deprecationError.name = "DeprecationWarning";
@ -249,7 +261,9 @@ export default function (
colNumber = Math.max(colNumber, 0); colNumber = Math.max(colNumber, 0);
const location: NodeLocation = { start: { column: colNumber, line: lineNumber } }; const location: NodeLocation = {
start: { column: colNumber, line: lineNumber },
};
return codeFrameColumns(rawLines, location, opts); return codeFrameColumns(rawLines, location, opts);
} }

View File

@ -4,30 +4,24 @@ import codeFrame, { codeFrameColumns } from "..";
describe("babel-code-frame", function() { describe("babel-code-frame", function() {
it("basic usage", function() { it("basic usage", function() {
const rawLines = [ const rawLines = ["class Foo {", " constructor()", "};"].join("\n");
"class Foo {", assert.equal(
" constructor()", codeFrame(rawLines, 2, 16),
"};", [
].join("\n");
assert.equal(codeFrame(rawLines, 2, 16), [
" 1 | class Foo {", " 1 | class Foo {",
"> 2 | constructor()", "> 2 | constructor()",
" | ^", " | ^",
" 3 | };", " 3 | };",
].join("\n")); ].join("\n"),
);
}); });
it("optional column number", function() { it("optional column number", function() {
const rawLines = [ const rawLines = ["class Foo {", " constructor()", "};"].join("\n");
"class Foo {", assert.equal(
" constructor()", codeFrame(rawLines, 2, null),
"};", [" 1 | class Foo {", "> 2 | constructor()", " 3 | };"].join("\n"),
].join("\n"); );
assert.equal(codeFrame(rawLines, 2, null), [
" 1 | class Foo {",
"> 2 | constructor()",
" 3 | };",
].join("\n"));
}); });
it("maximum context lines and padding", function() { it("maximum context lines and padding", function() {
@ -44,7 +38,9 @@ describe("babel-code-frame", function () {
" return a + b", " return a + b",
"}", "}",
].join("\n"); ].join("\n");
assert.equal(codeFrame(rawLines, 7, 2), [ assert.equal(
codeFrame(rawLines, 7, 2),
[
" 5 | * @param b Number", " 5 | * @param b Number",
" 6 | * @returns Number", " 6 | * @returns Number",
"> 7 | */", "> 7 | */",
@ -52,7 +48,8 @@ describe("babel-code-frame", function () {
" 8 | ", " 8 | ",
" 9 | function sum(a, b) {", " 9 | function sum(a, b) {",
" 10 | return a + b", " 10 | return a + b",
].join("\n")); ].join("\n"),
);
}); });
it("no unnecessary padding due to one-off errors", function() { it("no unnecessary padding due to one-off errors", function() {
@ -69,7 +66,9 @@ describe("babel-code-frame", function () {
" return a + b", " return a + b",
"}", "}",
].join("\n"); ].join("\n");
assert.equal(codeFrame(rawLines, 6, 2), [ assert.equal(
codeFrame(rawLines, 6, 2),
[
" 4 | * @param a Number", " 4 | * @param a Number",
" 5 | * @param b Number", " 5 | * @param b Number",
"> 6 | * @returns Number", "> 6 | * @returns Number",
@ -77,7 +76,8 @@ describe("babel-code-frame", function () {
" 7 | */", " 7 | */",
" 8 | ", " 8 | ",
" 9 | function sum(a, b) {", " 9 | function sum(a, b) {",
].join("\n")); ].join("\n"),
);
}); });
it("tabs", function() { it("tabs", function() {
@ -86,12 +86,15 @@ describe("babel-code-frame", function () {
"\t \t\t constructor\t(\t)", "\t \t\t constructor\t(\t)",
"\t};", "\t};",
].join("\n"); ].join("\n");
assert.equal(codeFrame(rawLines, 2, 25), [ assert.equal(
codeFrame(rawLines, 2, 25),
[
" 1 | \tclass Foo {", " 1 | \tclass Foo {",
"> 2 | \t \t\t constructor\t(\t)", "> 2 | \t \t\t constructor\t(\t)",
" | \t \t\t \t \t ^", " | \t \t\t \t \t ^",
" 3 | \t};", " 3 | \t};",
].join("\n")); ].join("\n"),
);
}); });
it("opts.highlightCode", function() { it("opts.highlightCode", function() {
@ -99,10 +102,10 @@ describe("babel-code-frame", function () {
const result = codeFrame(rawLines, 1, 9, { highlightCode: true }); const result = codeFrame(rawLines, 1, 9, { highlightCode: true });
const stripped = chalk.stripColor(result); const stripped = chalk.stripColor(result);
assert.ok(result.length > stripped.length); assert.ok(result.length > stripped.length);
assert.equal(stripped, [ assert.equal(
"> 1 | console.log('babel')", stripped,
" | ^", ["> 1 | console.log('babel')", " | ^"].join("\n"),
].join("\n")); );
}); });
it("opts.linesAbove", function() { it("opts.linesAbove", function() {
@ -119,14 +122,17 @@ describe("babel-code-frame", function () {
" return a + b", " return a + b",
"}", "}",
].join("\n"); ].join("\n");
assert.equal(codeFrame(rawLines, 7, 2, { linesAbove: 1 }), [ assert.equal(
codeFrame(rawLines, 7, 2, { linesAbove: 1 }),
[
" 6 | * @returns Number", " 6 | * @returns Number",
"> 7 | */", "> 7 | */",
" | ^", " | ^",
" 8 | ", " 8 | ",
" 9 | function sum(a, b) {", " 9 | function sum(a, b) {",
" 10 | return a + b", " 10 | return a + b",
].join("\n")); ].join("\n"),
);
}); });
it("opts.linesBelow", function() { it("opts.linesBelow", function() {
@ -143,13 +149,16 @@ describe("babel-code-frame", function () {
" return a + b", " return a + b",
"}", "}",
].join("\n"); ].join("\n");
assert.equal(codeFrame(rawLines, 7, 2, { linesBelow: 1 }), [ assert.equal(
codeFrame(rawLines, 7, 2, { linesBelow: 1 }),
[
" 5 | * @param b Number", " 5 | * @param b Number",
" 6 | * @returns Number", " 6 | * @returns Number",
"> 7 | */", "> 7 | */",
" | ^", " | ^",
" 8 | ", " 8 | ",
].join("\n")); ].join("\n"),
);
}); });
it("opts.linesAbove and opts.linesBelow", function() { it("opts.linesAbove and opts.linesBelow", function() {
@ -166,78 +175,82 @@ describe("babel-code-frame", function () {
" return a + b", " return a + b",
"}", "}",
].join("\n"); ].join("\n");
assert.equal(codeFrame(rawLines, 7, 2, { linesAbove: 1, linesBelow: 1 }), [ assert.equal(
" 6 | * @returns Number", codeFrame(rawLines, 7, 2, { linesAbove: 1, linesBelow: 1 }),
"> 7 | */", [" 6 | * @returns Number", "> 7 | */", " | ^", " 8 | "].join(
" | ^", "\n",
" 8 | ", ),
].join("\n")); );
}); });
it("opts.forceColor", function() { it("opts.forceColor", function() {
const marker = chalk.red.bold; const marker = chalk.red.bold;
const gutter = chalk.grey; const gutter = chalk.grey;
const rawLines = [ const rawLines = ["", "", "", ""].join("\n");
"", assert.equal(
"", codeFrame(rawLines, 3, null, {
"", linesAbove: 1,
"", linesBelow: 1,
].join("\n"); forceColor: true,
assert.equal(codeFrame(rawLines, 3, null, { linesAbove: 1, linesBelow: 1, forceColor: true }), }),
chalk.reset([ chalk.reset(
[
" " + gutter(" 2 | "), " " + gutter(" 2 | "),
marker(">") + gutter(" 3 | "), marker(">") + gutter(" 3 | "),
" " + gutter(" 4 | "), " " + gutter(" 4 | "),
].join("\n")) ].join("\n"),
),
); );
}); });
it("basic usage, new API", function() { it("basic usage, new API", function() {
const rawLines = [ const rawLines = ["class Foo {", " constructor()", "};"].join("\n");
"class Foo {", assert.equal(
" constructor()", codeFrameColumns(rawLines, { start: { line: 2, column: 16 } }),
"};", [
].join("\n");
assert.equal(codeFrameColumns(rawLines, { start: { line: 2, column: 16 } }), [
" 1 | class Foo {", " 1 | class Foo {",
"> 2 | constructor()", "> 2 | constructor()",
" | ^", " | ^",
" 3 | };", " 3 | };",
].join("\n")); ].join("\n"),
);
}); });
it("mark multiple columns", function() { it("mark multiple columns", function() {
const rawLines = [ const rawLines = ["class Foo {", " constructor()", "};"].join("\n");
"class Foo {",
" constructor()",
"};",
].join("\n");
assert.equal( assert.equal(
codeFrameColumns(rawLines, { start: { line: 2, column: 3 }, end: { line: 2, column: 16 } }), [ codeFrameColumns(rawLines, {
start: { line: 2, column: 3 },
end: { line: 2, column: 16 },
}),
[
" 1 | class Foo {", " 1 | class Foo {",
"> 2 | constructor()", "> 2 | constructor()",
" | ^^^^^^^^^^^^^", " | ^^^^^^^^^^^^^",
" 3 | };", " 3 | };",
].join("\n")); ].join("\n"),
);
}); });
it("mark multiple columns across lines", function() { it("mark multiple columns across lines", function() {
const rawLines = [ const rawLines = ["class Foo {", " constructor() {", " }", "};"].join(
"class Foo {", "\n",
" constructor() {", );
" }",
"};",
].join("\n");
assert.equal( assert.equal(
codeFrameColumns(rawLines, { start: { line: 2, column: 17 }, end: { line: 3, column: 3 } }), [ codeFrameColumns(rawLines, {
start: { line: 2, column: 17 },
end: { line: 3, column: 3 },
}),
[
" 1 | class Foo {", " 1 | class Foo {",
"> 2 | constructor() {", "> 2 | constructor() {",
" | ^", " | ^",
"> 3 | }", "> 3 | }",
" | ^^^", " | ^^^",
" 4 | };", " 4 | };",
].join("\n")); ].join("\n"),
);
}); });
it("mark multiple columns across multiple lines", function() { it("mark multiple columns across multiple lines", function() {
@ -249,7 +262,11 @@ describe("babel-code-frame", function () {
"};", "};",
].join("\n"); ].join("\n");
assert.equal( assert.equal(
codeFrameColumns(rawLines, { start: { line: 2, column: 17 }, end: { line: 4, column: 3 } }), [ codeFrameColumns(rawLines, {
start: { line: 2, column: 17 },
end: { line: 4, column: 3 },
}),
[
" 1 | class Foo {", " 1 | class Foo {",
"> 2 | constructor() {", "> 2 | constructor() {",
" | ^", " | ^",
@ -258,7 +275,8 @@ describe("babel-code-frame", function () {
"> 4 | }", "> 4 | }",
" | ^^^", " | ^^^",
" 5 | };", " 5 | };",
].join("\n")); ].join("\n"),
);
}); });
it("mark across multiple lines without columns", function() { it("mark across multiple lines without columns", function() {
@ -270,12 +288,14 @@ describe("babel-code-frame", function () {
"};", "};",
].join("\n"); ].join("\n");
assert.equal( assert.equal(
codeFrameColumns(rawLines, { start: { line: 2 }, end: { line: 4 } }), [ codeFrameColumns(rawLines, { start: { line: 2 }, end: { line: 4 } }),
[
" 1 | class Foo {", " 1 | class Foo {",
"> 2 | constructor() {", "> 2 | constructor() {",
"> 3 | console.log(arguments);", "> 3 | console.log(arguments);",
"> 4 | }", "> 4 | }",
" 5 | };", " 5 | };",
].join("\n")); ].join("\n"),
);
}); });
}); });

View File

@ -57,16 +57,14 @@ class ConfigChainBuilder {
/** /**
* Tests if a filename should be ignored based on "ignore" and "only" options. * Tests if a filename should be ignored based on "ignore" and "only" options.
*/ */
shouldIgnore( shouldIgnore(ignore: mixed, only: mixed, dirname: string): boolean {
ignore: mixed,
only: mixed,
dirname: string,
): boolean {
if (!this.filename) return false; if (!this.filename) return false;
if (ignore) { if (ignore) {
if (!Array.isArray(ignore)) { if (!Array.isArray(ignore)) {
throw new Error(`.ignore should be an array, ${JSON.stringify(ignore)} given`); throw new Error(
`.ignore should be an array, ${JSON.stringify(ignore)} given`,
);
} }
if (this.matchesPatterns(ignore, dirname)) return true; if (this.matchesPatterns(ignore, dirname)) return true;
@ -74,7 +72,9 @@ class ConfigChainBuilder {
if (only) { if (only) {
if (!Array.isArray(only)) { if (!Array.isArray(only)) {
throw new Error(`.only should be an array, ${JSON.stringify(only)} given`); throw new Error(
`.only should be an array, ${JSON.stringify(only)} given`,
);
} }
if (!this.matchesPatterns(only, dirname)) return true; if (!this.matchesPatterns(only, dirname)) return true;
@ -89,21 +89,27 @@ class ConfigChainBuilder {
*/ */
matchesPatterns(patterns: Array<mixed>, dirname: string) { matchesPatterns(patterns: Array<mixed>, dirname: string) {
const filename = this.filename; const filename = this.filename;
if (!filename) throw new Error("Assertion failure: .filename should always exist here"); if (!filename) {
throw new Error("Assertion failure: .filename should always exist here");
}
const res = []; const res = [];
const strings = []; const strings = [];
const fns = []; const fns = [];
patterns.forEach((pattern) => { patterns.forEach(pattern => {
if (typeof pattern === "string") strings.push(pattern); if (typeof pattern === "string") strings.push(pattern);
else if (typeof pattern === "function") fns.push(pattern); else if (typeof pattern === "function") fns.push(pattern);
else if (pattern instanceof RegExp) res.push(pattern); else if (pattern instanceof RegExp) res.push(pattern);
else throw new Error("Patterns must be a string, function, or regular expression"); else {
throw new Error(
"Patterns must be a string, function, or regular expression",
);
}
}); });
if (res.some((re) => re.test(filename))) return true; if (res.some(re => re.test(filename))) return true;
if (fns.some((fn) => fn(filename))) return true; if (fns.some(fn => fn(filename))) return true;
if (strings.length > 0) { if (strings.length > 0) {
let possibleDirs = this.possibleDirs; let possibleDirs = this.possibleDirs;
@ -123,7 +129,7 @@ class ConfigChainBuilder {
} }
} }
const absolutePatterns = strings.map((pattern) => { const absolutePatterns = strings.map(pattern => {
// Preserve the "!" prefix so that micromatch can use it for negation. // Preserve the "!" prefix so that micromatch can use it for negation.
const negate = pattern[0] === "!"; const negate = pattern[0] === "!";
if (negate) pattern = pattern.slice(1); if (negate) pattern = pattern.slice(1);
@ -131,7 +137,9 @@ class ConfigChainBuilder {
return (negate ? "!" : "") + path.resolve(dirname, pattern); return (negate ? "!" : "") + path.resolve(dirname, pattern);
}); });
if (micromatch(possibleDirs, absolutePatterns, { nocase: true }).length > 0) { if (
micromatch(possibleDirs, absolutePatterns, { nocase: true }).length > 0
) {
return true; return true;
} }
} }
@ -150,16 +158,16 @@ class ConfigChainBuilder {
}); });
} }
mergeConfig({ mergeConfig({ type, options: rawOpts, alias, dirname }) {
type,
options: rawOpts,
alias,
dirname,
}) {
// Bail out ASAP if this file is ignored so that we run as little logic as possible on ignored files. // Bail out ASAP if this file is ignored so that we run as little logic as possible on ignored files.
if (this.filename && this.shouldIgnore(rawOpts.ignore || null, rawOpts.only || null, dirname)) { if (
this.filename &&
this.shouldIgnore(rawOpts.ignore || null, rawOpts.only || null, dirname)
) {
// TODO(logan): This is a really cross way to bail out. Avoid this in rewrite. // TODO(logan): This is a really cross way to bail out. Avoid this in rewrite.
throw Object.assign((new Error("This file has been ignored."): any), { code: "BABEL_IGNORED_FILE" }); throw Object.assign((new Error("This file has been ignored."): any), {
code: "BABEL_IGNORED_FILE",
});
} }
const options = Object.assign({}, rawOpts); const options = Object.assign({}, rawOpts);
@ -168,13 +176,19 @@ class ConfigChainBuilder {
const envKey = getEnv(); const envKey = getEnv();
if (rawOpts.env != null && (typeof rawOpts.env !== "object" || Array.isArray(rawOpts.env))) { if (
rawOpts.env != null &&
(typeof rawOpts.env !== "object" || Array.isArray(rawOpts.env))
) {
throw new Error(".env block must be an object, null, or undefined"); throw new Error(".env block must be an object, null, or undefined");
} }
const envOpts = rawOpts.env && rawOpts.env[envKey]; const envOpts = rawOpts.env && rawOpts.env[envKey];
if (envOpts != null && (typeof envOpts !== "object" || Array.isArray(envOpts))) { if (
envOpts != null &&
(typeof envOpts !== "object" || Array.isArray(envOpts))
) {
throw new Error(".env[...] block must be an object, null, or undefined"); throw new Error(".env[...] block must be an object, null, or undefined");
} }
@ -196,11 +210,13 @@ class ConfigChainBuilder {
}); });
if (rawOpts.extends) { if (rawOpts.extends) {
if (typeof rawOpts.extends !== "string") throw new Error(".extends must be a string"); if (typeof rawOpts.extends !== "string") {
throw new Error(".extends must be a string");
}
const extendsConfig = loadConfig(rawOpts.extends, dirname); const extendsConfig = loadConfig(rawOpts.extends, dirname);
const existingConfig = this.configs.some((config) => { const existingConfig = this.configs.some(config => {
return config.alias === extendsConfig.filepath; return config.alias === extendsConfig.filepath;
}); });
if (!existingConfig) { if (!existingConfig) {
@ -214,4 +230,3 @@ class ConfigChainBuilder {
} }
} }
} }

View File

@ -22,7 +22,7 @@ type CacheEntry<ResultT> = Array<[ ResultT, () => boolean ]>;
export function makeStrongCache<ArgT, ResultT>( export function makeStrongCache<ArgT, ResultT>(
handler: (ArgT, CacheConfigurator) => ResultT, handler: (ArgT, CacheConfigurator) => ResultT,
autoPermacache?: boolean, autoPermacache?: boolean,
): (ArgT) => ResultT { ): ArgT => ResultT {
return makeCachedFunction(new Map(), handler, autoPermacache); return makeCachedFunction(new Map(), handler, autoPermacache);
} }
@ -34,17 +34,19 @@ export function makeStrongCache<ArgT, ResultT>(
export function makeWeakCache<ArgT: {}, ResultT>( export function makeWeakCache<ArgT: {}, ResultT>(
handler: (ArgT, CacheConfigurator) => ResultT, handler: (ArgT, CacheConfigurator) => ResultT,
autoPermacache?: boolean, autoPermacache?: boolean,
): (ArgT) => ResultT { ): ArgT => ResultT {
return makeCachedFunction(new WeakMap(), handler, autoPermacache); return makeCachedFunction(new WeakMap(), handler, autoPermacache);
} }
type CacheMap<ArgT, ResultT> = Map<ArgT, CacheEntry<ResultT>>|WeakMap<ArgT, CacheEntry<ResultT>>; type CacheMap<ArgT, ResultT> =
| Map<ArgT, CacheEntry<ResultT>>
| WeakMap<ArgT, CacheEntry<ResultT>>;
function makeCachedFunction<ArgT, ResultT, Cache: CacheMap<ArgT, ResultT>>( function makeCachedFunction<ArgT, ResultT, Cache: CacheMap<ArgT, ResultT>>(
callCache: Cache, callCache: Cache,
handler: (ArgT, CacheConfigurator) => ResultT, handler: (ArgT, CacheConfigurator) => ResultT,
autoPermacache: boolean = true, autoPermacache: boolean = true,
): (ArgT) => ResultT { ): ArgT => ResultT {
return function cachedFunction(arg) { return function cachedFunction(arg) {
let cachedValue: CacheEntry<ResultT> | void = callCache.get(arg); let cachedValue: CacheEntry<ResultT> | void = callCache.get(arg);
@ -64,7 +66,8 @@ function makeCachedFunction<ArgT, ResultT, Cache: CacheMap<ArgT, ResultT>>(
if (!result.configured) { if (!result.configured) {
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
throw new Error([ throw new Error(
[
"Caching was left unconfigured. Babel's plugins, presets, and .babelrc.js files can be configured", "Caching was left unconfigured. Babel's plugins, presets, and .babelrc.js files can be configured",
"for various types of caching, using the first param of their handler functions:", "for various types of caching, using the first param of their handler functions:",
"", "",
@ -83,12 +86,12 @@ function makeCachedFunction<ArgT, ResultT, Cache: CacheMap<ArgT, ResultT>>(
"", "",
" // If testing for a specific env, we recommend specifics to avoid instantiating a plugin for", " // If testing for a specific env, we recommend specifics to avoid instantiating a plugin for",
" // any possible NODE_ENV value that might come up during plugin execution.", " // any possible NODE_ENV value that might come up during plugin execution.",
" var isProd = api.cache(() => process.env.NODE_ENV === \"production\");", ' var isProd = api.cache(() => process.env.NODE_ENV === "production");',
"", "",
" // .cache(fn) will perform a linear search though instances to find the matching plugin based", " // .cache(fn) will perform a linear search though instances to find the matching plugin based",
" // based on previous instantiated plugins. If you want to recreate the plugin and discard the", " // based on previous instantiated plugins. If you want to recreate the plugin and discard the",
" // previous instance whenever something changes, you may use:", " // previous instance whenever something changes, you may use:",
" var isProd = api.cache.invalidate(() => process.env.NODE_ENV === \"production\");", ' var isProd = api.cache.invalidate(() => process.env.NODE_ENV === "production");',
"", "",
" // Note, we also expose the following more-verbose versions of the above examples:", " // Note, we also expose the following more-verbose versions of the above examples:",
" api.cache.forever(); // api.cache(true)", " api.cache.forever(); // api.cache(true)",
@ -98,18 +101,15 @@ function makeCachedFunction<ArgT, ResultT, Cache: CacheMap<ArgT, ResultT>>(
" // Return the value that will be cached.", " // Return the value that will be cached.",
" return { };", " return { };",
"};", "};",
].join("\n")); ].join("\n"),
);
} }
if (!result.never) { if (!result.never) {
if (result.forever) { if (result.forever) {
cachedValue = [ cachedValue = [[value, () => true]];
[value, () => true],
];
} else if (result.invalidate) { } else if (result.invalidate) {
cachedValue = [ cachedValue = [[value, result.valid]];
[value, result.valid],
];
} else { } else {
cachedValue = cachedValue || []; cachedValue = cachedValue || [];
cachedValue.push([value, result.valid]); cachedValue.push([value, result.valid]);
@ -121,7 +121,11 @@ function makeCachedFunction<ArgT, ResultT, Cache: CacheMap<ArgT, ResultT>>(
}; };
} }
function makeCacheConfig(): { cache: CacheConfigurator, result: *, deactivate: () => void } { function makeCacheConfig(): {
cache: CacheConfigurator,
result: *,
deactivate: () => void,
} {
const pairs = []; const pairs = [];
const result = { const result = {
@ -137,7 +141,8 @@ function makeCacheConfig(): { cache: CacheConfigurator, result: *, deactivate: (
active = false; active = false;
}; };
const cache: CacheConfigurator = Object.assign((function cacheFn(val) { const cache: CacheConfigurator = Object.assign(
(function cacheFn(val) {
if (typeof val === "boolean") { if (typeof val === "boolean") {
if (val) cache.forever(); if (val) cache.forever();
else cache.never(); else cache.never();
@ -145,23 +150,44 @@ function makeCacheConfig(): { cache: CacheConfigurator, result: *, deactivate: (
} }
return cache.using(val); return cache.using(val);
}: any), ({ }: any),
({
forever() { forever() {
if (!active) throw new Error("Cannot change caching after evaluation has completed."); if (!active) {
if (result.never) throw new Error("Caching has already been configured with .never()"); throw new Error(
"Cannot change caching after evaluation has completed.",
);
}
if (result.never) {
throw new Error("Caching has already been configured with .never()");
}
result.forever = true; result.forever = true;
result.configured = true; result.configured = true;
}, },
never() { never() {
if (!active) throw new Error("Cannot change caching after evaluation has completed."); if (!active) {
if (result.forever) throw new Error("Caching has already been configured with .forever()"); throw new Error(
"Cannot change caching after evaluation has completed.",
);
}
if (result.forever) {
throw new Error(
"Caching has already been configured with .forever()",
);
}
result.never = true; result.never = true;
result.configured = true; result.configured = true;
}, },
using<T>(handler: () => T): T { using<T>(handler: () => T): T {
if (!active) throw new Error("Cannot change caching after evaluation has completed."); if (!active) {
throw new Error(
"Cannot change caching after evaluation has completed.",
);
}
if (result.never || result.forever) { if (result.never || result.forever) {
throw new Error("Caching has already been configured with .never or .forever()"); throw new Error(
"Caching has already been configured with .never or .forever()",
);
} }
result.configured = true; result.configured = true;
@ -170,9 +196,15 @@ function makeCacheConfig(): { cache: CacheConfigurator, result: *, deactivate: (
return key; return key;
}, },
invalidate<T>(handler: () => T): T { invalidate<T>(handler: () => T): T {
if (!active) throw new Error("Cannot change caching after evaluation has completed."); if (!active) {
throw new Error(
"Cannot change caching after evaluation has completed.",
);
}
if (result.never || result.forever) { if (result.never || result.forever) {
throw new Error("Caching has already been configured with .never or .forever()"); throw new Error(
"Caching has already been configured with .never or .forever()",
);
} }
result.invalidate = true; result.invalidate = true;
result.configured = true; result.configured = true;
@ -181,7 +213,8 @@ function makeCacheConfig(): { cache: CacheConfigurator, result: *, deactivate: (
pairs.push([key, handler]); pairs.push([key, handler]);
return key; return key;
}, },
}: CacheConfiguratorObj)); }: CacheConfiguratorObj),
);
return { cache, result, deactivate }; return { cache, result, deactivate };
} }

View File

@ -1,7 +1,5 @@
// @flow // @flow
export function getEnv(defaultValue: string = "development"): string { export function getEnv(defaultValue: string = "development"): string {
return process.env.BABEL_ENV return process.env.BABEL_ENV || process.env.NODE_ENV || defaultValue;
|| process.env.NODE_ENV
|| defaultValue;
} }

View File

@ -46,8 +46,11 @@ export function findConfigs(dirname: string): Array<ConfigFile> {
const config = readConfig(filepath); const config = readConfig(filepath);
if (config && previousConfig) { if (config && previousConfig) {
throw new Error(`Multiple configuration files found. Please remove one:\n- ${ throw new Error(
path.basename(previousConfig.filepath)}\n- ${name}\nfrom ${loc}`); `Multiple configuration files found. Please remove one:\n- ${path.basename(
previousConfig.filepath,
)}\n- ${name}\nfrom ${loc}`,
);
} }
return config || previousConfig; return config || previousConfig;
@ -73,7 +76,9 @@ export function loadConfig(name: string, dirname: string): ConfigFile {
const filepath = resolve.sync(name, { basedir: dirname }); const filepath = resolve.sync(name, { basedir: dirname });
const conf = readConfig(filepath); const conf = readConfig(filepath);
if (!conf) throw new Error(`Config file ${filepath} contains no configuration data`); if (!conf) {
throw new Error(`Config file ${filepath} contains no configuration data`);
}
return conf; return conf;
} }
@ -83,7 +88,9 @@ export function loadConfig(name: string, dirname: string): ConfigFile {
* throw if there are parsing errors while loading a config. * throw if there are parsing errors while loading a config.
*/ */
function readConfig(filepath) { function readConfig(filepath) {
return (path.extname(filepath) === ".js") ? readConfigJS(filepath) : readConfigFile(filepath); return path.extname(filepath) === ".js"
? readConfigJS(filepath)
: readConfigFile(filepath);
} }
const readConfigJS = makeStrongCache((filepath, cache) => { const readConfigJS = makeStrongCache((filepath, cache) => {
@ -96,7 +103,10 @@ const readConfigJS = makeStrongCache((filepath, cache) => {
try { try {
// $FlowIssue // $FlowIssue
const configModule = (require(filepath): mixed); const configModule = (require(filepath): mixed);
options = configModule && configModule.__esModule ? (configModule.default || undefined) : configModule; options =
configModule && configModule.__esModule
? configModule.default || undefined
: configModule;
} catch (err) { } catch (err) {
err.message = `${filepath}: Error while loading config - ${err.message}`; err.message = `${filepath}: Error while loading config - ${err.message}`;
throw err; throw err;
@ -113,7 +123,9 @@ const readConfigJS = makeStrongCache((filepath, cache) => {
} }
if (!options || typeof options !== "object" || Array.isArray(options)) { if (!options || typeof options !== "object" || Array.isArray(options)) {
throw new Error(`${filepath}: Configuration should be an exported JavaScript object.`); throw new Error(
`${filepath}: Configuration should be an exported JavaScript object.`,
);
} }
return { return {
@ -144,8 +156,12 @@ const readConfigFile = makeStaticFileCache((filepath, content) => {
if (!options) throw new Error(`${filepath}: No config detected`); if (!options) throw new Error(`${filepath}: No config detected`);
} }
if (typeof options !== "object") throw new Error(`${filepath}: Config returned typeof ${typeof options}`); if (typeof options !== "object") {
if (Array.isArray(options)) throw new Error(`${filepath}: Expected config object but found array`); throw new Error(`${filepath}: Config returned typeof ${typeof options}`);
}
if (Array.isArray(options)) {
throw new Error(`${filepath}: Expected config object but found array`);
}
return { return {
filepath, filepath,
@ -157,8 +173,8 @@ const readConfigFile = makeStaticFileCache((filepath, content) => {
const readIgnoreConfig = makeStaticFileCache((filepath, content) => { const readIgnoreConfig = makeStaticFileCache((filepath, content) => {
const ignore = content const ignore = content
.split("\n") .split("\n")
.map((line) => line.replace(/#(.*?)$/, "").trim()) .map(line => line.replace(/#(.*?)$/, "").trim())
.filter((line) => !!line); .filter(line => !!line);
return { return {
filepath, filepath,
@ -167,7 +183,7 @@ const readIgnoreConfig = makeStaticFileCache((filepath, content) => {
}; };
}); });
function makeStaticFileCache<T>(fn: (string, string) => T): (string) => T|null { function makeStaticFileCache<T>(fn: (string, string) => T): string => T | null {
return makeStrongCache((filepath, cache) => { return makeStrongCache((filepath, cache) => {
if (cache.invalidate(() => fileMtime(filepath)) === null) { if (cache.invalidate(() => fileMtime(filepath)) === null) {
cache.forever(); cache.forever();

View File

@ -25,18 +25,38 @@ export function resolvePreset(name: string, dirname: string): string|null {
return null; return null;
} }
export function loadPlugin(name: string, dirname: string): { filepath: string, value: mixed } { export function loadPlugin(
throw new Error(`Cannot load plugin ${name} relative to ${dirname} in a browser`); name: string,
dirname: string,
): { filepath: string, value: mixed } {
throw new Error(
`Cannot load plugin ${name} relative to ${dirname} in a browser`,
);
} }
export function loadPreset(name: string, dirname: string): { filepath: string, value: mixed } { export function loadPreset(
throw new Error(`Cannot load preset ${name} relative to ${dirname} in a browser`); name: string,
dirname: string,
): { filepath: string, value: mixed } {
throw new Error(
`Cannot load preset ${name} relative to ${dirname} in a browser`,
);
} }
export function loadParser(name: string, dirname: string): { filepath: string, value: Function } { export function loadParser(
throw new Error(`Cannot load parser ${name} relative to ${dirname} in a browser`); name: string,
dirname: string,
): { filepath: string, value: Function } {
throw new Error(
`Cannot load parser ${name} relative to ${dirname} in a browser`,
);
} }
export function loadGenerator(name: string, dirname: string): { filepath: string, value: Function } { export function loadGenerator(
throw new Error(`Cannot load generator ${name} relative to ${dirname} in a browser`); name: string,
dirname: string,
): { filepath: string, value: Function } {
throw new Error(
`Cannot load generator ${name} relative to ${dirname} in a browser`,
);
} }

View File

@ -23,9 +23,14 @@ export function resolvePreset(name: string, dirname: string): string|null {
return resolveStandardizedName("preset", name, dirname); return resolveStandardizedName("preset", name, dirname);
} }
export function loadPlugin(name: string, dirname: string): { filepath: string, value: mixed } { export function loadPlugin(
name: string,
dirname: string,
): { filepath: string, value: mixed } {
const filepath = resolvePlugin(name, dirname); const filepath = resolvePlugin(name, dirname);
if (!filepath) throw new Error(`Plugin ${name} not found relative to ${dirname}`); if (!filepath) {
throw new Error(`Plugin ${name} not found relative to ${dirname}`);
}
return { return {
filepath, filepath,
@ -33,9 +38,14 @@ export function loadPlugin(name: string, dirname: string): { filepath: string, v
}; };
} }
export function loadPreset(name: string, dirname: string): { filepath: string, value: mixed } { export function loadPreset(
name: string,
dirname: string,
): { filepath: string, value: mixed } {
const filepath = resolvePreset(name, dirname); const filepath = resolvePreset(name, dirname);
if (!filepath) throw new Error(`Preset ${name} not found relative to ${dirname}`); if (!filepath) {
throw new Error(`Preset ${name} not found relative to ${dirname}`);
}
return { return {
filepath, filepath,
@ -43,16 +53,23 @@ export function loadPreset(name: string, dirname: string): { filepath: string, v
}; };
} }
export function loadParser(name: string, dirname: string): { filepath: string, value: Function } { export function loadParser(
name: string,
dirname: string,
): { filepath: string, value: Function } {
const filepath = resolve.sync(name, { basedir: dirname }); const filepath = resolve.sync(name, { basedir: dirname });
const mod = requireModule(filepath); const mod = requireModule(filepath);
if (!mod) { if (!mod) {
throw new Error(`Parser ${name} relative to ${dirname} does not export an object`); throw new Error(
`Parser ${name} relative to ${dirname} does not export an object`,
);
} }
if (typeof mod.parse !== "function") { if (typeof mod.parse !== "function") {
throw new Error(`Parser ${name} relative to ${dirname} does not export a .parse function`); throw new Error(
`Parser ${name} relative to ${dirname} does not export a .parse function`,
);
} }
return { return {
@ -61,16 +78,23 @@ export function loadParser(name: string, dirname: string): { filepath: string, v
}; };
} }
export function loadGenerator(name: string, dirname: string): { filepath: string, value: Function } { export function loadGenerator(
name: string,
dirname: string,
): { filepath: string, value: Function } {
const filepath = resolve.sync(name, { basedir: dirname }); const filepath = resolve.sync(name, { basedir: dirname });
const mod = requireModule(filepath); const mod = requireModule(filepath);
if (!mod) { if (!mod) {
throw new Error(`Generator ${name} relative to ${dirname} does not export an object`); throw new Error(
`Generator ${name} relative to ${dirname} does not export an object`,
);
} }
if (typeof mod.print !== "function") { if (typeof mod.print !== "function") {
throw new Error(`Generator ${name} relative to ${dirname} does not export a .print function`); throw new Error(
`Generator ${name} relative to ${dirname} does not export a .print function`,
);
} }
return { return {
@ -85,18 +109,33 @@ function standardizeName(type: "plugin"|"preset", name: string) {
const isPreset = type === "preset"; const isPreset = type === "preset";
return name return (
name
// foo -> babel-preset-foo // foo -> babel-preset-foo
.replace(isPreset ? BABEL_PRESET_PREFIX_RE : BABEL_PLUGIN_PREFIX_RE, `babel-${type}-`) .replace(
isPreset ? BABEL_PRESET_PREFIX_RE : BABEL_PLUGIN_PREFIX_RE,
`babel-${type}-`,
)
// @babel/es2015 -> @babel/preset-es2015 // @babel/es2015 -> @babel/preset-es2015
.replace(isPreset ? BABEL_PRESET_ORG_RE : BABEL_PLUGIN_ORG_RE, `$1${type}-`) .replace(
isPreset ? BABEL_PRESET_ORG_RE : BABEL_PLUGIN_ORG_RE,
`$1${type}-`,
)
// @foo/mypreset -> @foo/babel-preset-mypreset // @foo/mypreset -> @foo/babel-preset-mypreset
.replace(isPreset ? OTHER_PRESET_ORG_RE : OTHER_PLUGIN_ORG_RE, `$1babel-${type}-`) .replace(
isPreset ? OTHER_PRESET_ORG_RE : OTHER_PLUGIN_ORG_RE,
`$1babel-${type}-`,
)
// module:mypreset -> mypreset // module:mypreset -> mypreset
.replace(EXACT_RE, ""); .replace(EXACT_RE, "")
);
} }
function resolveStandardizedName(type: "plugin"|"preset", name: string, dirname: string = process.cwd()) { function resolveStandardizedName(
type: "plugin" | "preset",
name: string,
dirname: string = process.cwd(),
) {
const standardizedName = standardizeName(type, name); const standardizedName = standardizeName(type, name);
try { try {
@ -119,7 +158,9 @@ function resolveStandardizedName(type: "plugin"|"preset", name: string, dirname:
let resolvedBabel = false; let resolvedBabel = false;
try { try {
resolve.sync(standardizeName(type, "@babel/" + name), { basedir: dirname }); resolve.sync(standardizeName(type, "@babel/" + name), {
basedir: dirname,
});
resolvedBabel = true; resolvedBabel = true;
} catch (e2) {} } catch (e2) {}

View File

@ -11,14 +11,19 @@ import path from "path";
import traverse from "babel-traverse"; import traverse from "babel-traverse";
import clone from "lodash/clone"; import clone from "lodash/clone";
import { loadPlugin, loadPreset, loadParser, loadGenerator } from "./loading/files"; import {
loadPlugin,
loadPreset,
loadParser,
loadGenerator,
} from "./loading/files";
type MergeOptions = { type MergeOptions = {
+type: "arguments" | "options" | "preset", +type: "arguments" | "options" | "preset",
options: {}, options: {},
alias: string, alias: string,
loc: string, loc: string,
dirname: string dirname: string,
}; };
const optionNames = new Set([ const optionNames = new Set([
@ -100,9 +105,12 @@ class OptionManager {
mergeOptions(config: MergeOptions, pass?: Array<[Plugin, ?{}]>) { mergeOptions(config: MergeOptions, pass?: Array<[Plugin, ?{}]>) {
const result = loadConfig(config); const result = loadConfig(config);
const plugins = result.plugins.map((descriptor) => loadPluginDescriptor(descriptor)); const plugins = result.plugins.map(descriptor =>
const presets = result.presets.map((descriptor) => loadPresetDescriptor(descriptor)); loadPluginDescriptor(descriptor),
);
const presets = result.presets.map(descriptor =>
loadPresetDescriptor(descriptor),
);
if ( if (
config.options.passPerPreset != null && config.options.passPerPreset != null &&
@ -148,7 +156,8 @@ class OptionManager {
// There are a few case where thrown errors will try to annotate themselves multiple times, so // There are a few case where thrown errors will try to annotate themselves multiple times, so
// to keep things simple we just bail out if re-wrapping the message. // to keep things simple we just bail out if re-wrapping the message.
if (!/^\[BABEL\]/.test(e.message)) { if (!/^\[BABEL\]/.test(e.message)) {
const filename = typeof opts.filename === "string" ? opts.filename : null; const filename =
typeof opts.filename === "string" ? opts.filename : null;
e.message = `[BABEL] ${filename || "unknown"}: ${e.message}`; e.message = `[BABEL] ${filename || "unknown"}: ${e.message}`;
} }
@ -160,9 +169,10 @@ class OptionManager {
// Tack the passes onto the object itself so that, if this object is passed back to Babel a second time, // Tack the passes onto the object itself so that, if this object is passed back to Babel a second time,
// it will be in the right structure to not change behavior. // it will be in the right structure to not change behavior.
opts.plugins = this.passes[0]; opts.plugins = this.passes[0];
opts.presets = this.passes.slice(1) opts.presets = this.passes
.filter((plugins) => plugins.length > 0) .slice(1)
.map((plugins) => ({ plugins })); .filter(plugins => plugins.length > 0)
.map(plugins => ({ plugins }));
if (opts.inputSourceMap) { if (opts.inputSourceMap) {
opts.sourceMaps = true; opts.sourceMaps = true;
@ -209,19 +219,28 @@ type BasicDescriptor = {
/** /**
* Load and validate the given config into a set of options, plugins, and presets. * Load and validate the given config into a set of options, plugins, and presets.
*/ */
function loadConfig(config): { function loadConfig(
config,
): {
options: {}, options: {},
plugins: Array<BasicDescriptor>, plugins: Array<BasicDescriptor>,
presets: Array<BasicDescriptor>, presets: Array<BasicDescriptor>,
} { } {
const options = normalizeOptions(config); const options = normalizeOptions(config);
if (config.options.plugins != null && !Array.isArray(config.options.plugins)) { if (
config.options.plugins != null &&
!Array.isArray(config.options.plugins)
) {
throw new Error(".plugins should be an array, null, or undefined"); throw new Error(".plugins should be an array, null, or undefined");
} }
const plugins = (config.options.plugins || []).map((plugin, index) => { const plugins = (config.options.plugins || []).map((plugin, index) => {
const { filepath, value, options } = normalizePair(plugin, loadPlugin, config.dirname); const { filepath, value, options } = normalizePair(
plugin,
loadPlugin,
config.dirname,
);
return { return {
alias: filepath || `${config.loc}$${index}`, alias: filepath || `${config.loc}$${index}`,
@ -232,12 +251,19 @@ function loadConfig(config): {
}; };
}); });
if (config.options.presets != null && !Array.isArray(config.options.presets)) { if (
config.options.presets != null &&
!Array.isArray(config.options.presets)
) {
throw new Error(".presets should be an array, null, or undefined"); throw new Error(".presets should be an array, null, or undefined");
} }
const presets = (config.options.presets || []).map((preset, index) => { const presets = (config.options.presets || []).map((preset, index) => {
const { filepath, value, options } = normalizePair(preset, loadPreset, config.dirname); const { filepath, value, options } = normalizePair(
preset,
loadPreset,
config.dirname,
);
return { return {
alias: filepath || `${config.loc}$${index}`, alias: filepath || `${config.loc}$${index}`,
@ -255,7 +281,9 @@ function loadConfig(config): {
* Load a generic plugin/preset from the given descriptor loaded from the config object. * Load a generic plugin/preset from the given descriptor loaded from the config object.
*/ */
function loadDescriptor(descriptor, skipOptions) { function loadDescriptor(descriptor, skipOptions) {
if (typeof descriptor.value !== "function") return { value: descriptor.value, descriptor }; if (typeof descriptor.value !== "function") {
return { value: descriptor.value, descriptor };
}
const { value, options } = descriptor; const { value, options } = descriptor;
let item; let item;
@ -266,7 +294,9 @@ function loadDescriptor(descriptor, skipOptions) {
item = value(context, options, { dirname: descriptor.dirname }); item = value(context, options, { dirname: descriptor.dirname });
} }
} catch (e) { } catch (e) {
if (descriptor.alias) e.message += ` (While processing: ${JSON.stringify(descriptor.alias)})`; if (descriptor.alias) {
e.message += ` (While processing: ${JSON.stringify(descriptor.alias)})`;
}
throw e; throw e;
} }
@ -282,11 +312,15 @@ function loadDescriptor(descriptor, skipOptions) {
*/ */
const PLUGIN_CACHE = new WeakMap(); const PLUGIN_CACHE = new WeakMap();
function loadPluginDescriptor(descriptor) { function loadPluginDescriptor(descriptor) {
if (descriptor.value instanceof Plugin) return [ descriptor.value, descriptor.options ]; if (descriptor.value instanceof Plugin) {
return [descriptor.value, descriptor.options];
}
let result = PLUGIN_CACHE.get(descriptor.value); let result = PLUGIN_CACHE.get(descriptor.value);
if (!result) { if (!result) {
result = instantiatePlugin(loadDescriptor(descriptor, true /* skipOptions */)); result = instantiatePlugin(
loadDescriptor(descriptor, true /* skipOptions */),
);
PLUGIN_CACHE.set(descriptor.value, result); PLUGIN_CACHE.set(descriptor.value, result);
} }
@ -294,14 +328,21 @@ function loadPluginDescriptor(descriptor) {
} }
function instantiatePlugin({ value: pluginObj, descriptor }) { function instantiatePlugin({ value: pluginObj, descriptor }) {
Object.keys(pluginObj).forEach((key) => { Object.keys(pluginObj).forEach(key => {
if (!ALLOWED_PLUGIN_KEYS.has(key)) { if (!ALLOWED_PLUGIN_KEYS.has(key)) {
throw new Error(messages.get("pluginInvalidProperty", descriptor.alias, key)); throw new Error(
messages.get("pluginInvalidProperty", descriptor.alias, key),
);
} }
}); });
if (pluginObj.visitor && (pluginObj.visitor.enter || pluginObj.visitor.exit)) { if (
throw new Error("Plugins aren't allowed to specify catch-all enter/exit handlers. " + pluginObj.visitor &&
"Please target individual nodes."); (pluginObj.visitor.enter || pluginObj.visitor.exit)
) {
throw new Error(
"Plugins aren't allowed to specify catch-all enter/exit handlers. " +
"Please target individual nodes.",
);
} }
const plugin = Object.assign({}, pluginObj, { const plugin = Object.assign({}, pluginObj, {
@ -325,8 +366,14 @@ function instantiatePlugin({ value: pluginObj, descriptor }) {
plugin.pre = chain(inherits.pre, plugin.pre); plugin.pre = chain(inherits.pre, plugin.pre);
plugin.post = chain(inherits.post, plugin.post); plugin.post = chain(inherits.post, plugin.post);
plugin.manipulateOptions = chain(inherits.manipulateOptions, plugin.manipulateOptions); plugin.manipulateOptions = chain(
plugin.visitor = traverse.visitors.merge([inherits.visitor, plugin.visitor]); inherits.manipulateOptions,
plugin.manipulateOptions,
);
plugin.visitor = traverse.visitors.merge([
inherits.visitor,
plugin.visitor,
]);
} }
return new Plugin(plugin, descriptor.alias); return new Plugin(plugin, descriptor.alias);
@ -371,10 +418,18 @@ function normalizeOptions(config) {
} }
if (type === "preset") { if (type === "preset") {
if (options.only !== undefined) throw new Error(`${alias}.only is not supported in a preset`); if (options.only !== undefined) {
if (options.ignore !== undefined) throw new Error(`${alias}.ignore is not supported in a preset`); throw new Error(`${alias}.only is not supported in a preset`);
if (options.extends !== undefined) throw new Error(`${alias}.extends is not supported in a preset`); }
if (options.env !== undefined) throw new Error(`${alias}.env is not supported in a preset`); if (options.ignore !== undefined) {
throw new Error(`${alias}.ignore is not supported in a preset`);
}
if (options.extends !== undefined) {
throw new Error(`${alias}.extends is not supported in a preset`);
}
if (options.env !== undefined) {
throw new Error(`${alias}.env is not supported in a preset`);
}
} }
if (options.sourceMap !== undefined) { if (options.sourceMap !== undefined) {
@ -390,7 +445,10 @@ function normalizeOptions(config) {
// check for an unknown option // check for an unknown option
if (!optionNames.has(key)) { if (!optionNames.has(key)) {
if (removed[key]) { if (removed[key]) {
throw new ReferenceError(`Using removed Babel 5 option: ${alias}.${key} - ${removed[key].message}`); throw new ReferenceError(
`Using removed Babel 5 option: ${alias}.${key} - ${removed[key]
.message}`,
);
} else { } else {
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
const unknownOptErr = `Unknown option: ${alias}.${key}. Check out http://babeljs.io/docs/usage/options/ for more information about options.`; const unknownOptErr = `Unknown option: ${alias}.${key}. Check out http://babeljs.io/docs/usage/options/ for more information about options.`;
@ -402,12 +460,21 @@ function normalizeOptions(config) {
if (options.parserOpts && typeof options.parserOpts.parser === "string") { if (options.parserOpts && typeof options.parserOpts.parser === "string") {
options.parserOpts = Object.assign({}, options.parserOpts); options.parserOpts = Object.assign({}, options.parserOpts);
options.parserOpts.parser = loadParser(options.parserOpts.parser, config.dirname).value; options.parserOpts.parser = loadParser(
options.parserOpts.parser,
config.dirname,
).value;
} }
if (options.generatorOpts && typeof options.generatorOpts.generator === "string") { if (
options.generatorOpts &&
typeof options.generatorOpts.generator === "string"
) {
options.generatorOpts = Object.assign({}, options.generatorOpts); options.generatorOpts = Object.assign({}, options.generatorOpts);
options.generatorOpts.generator = loadGenerator(options.generatorOpts.generator, config.dirname).value; options.generatorOpts.generator = loadGenerator(
options.generatorOpts.generator,
config.dirname,
).value;
} }
delete options.passPerPreset; delete options.passPerPreset;
@ -420,7 +487,11 @@ function normalizeOptions(config) {
/** /**
* Given a plugin/preset item, resolve it into a standard format. * Given a plugin/preset item, resolve it into a standard format.
*/ */
function normalizePair(pair: mixed, resolver, dirname): { function normalizePair(
pair: mixed,
resolver,
dirname,
): {
filepath: string | null, filepath: string | null,
value: {} | Function, value: {} | Function,
options: ?{}, options: ?{},
@ -429,7 +500,9 @@ function normalizePair(pair: mixed, resolver, dirname): {
let value = pair; let value = pair;
if (Array.isArray(pair)) { if (Array.isArray(pair)) {
if (pair.length > 2) { if (pair.length > 2) {
throw new Error(`Unexpected extra options ${JSON.stringify(pair.slice(2))}.`); throw new Error(
`Unexpected extra options ${JSON.stringify(pair.slice(2))}.`,
);
} }
[value, options] = pair; [value, options] = pair;
@ -437,10 +510,7 @@ function normalizePair(pair: mixed, resolver, dirname): {
let filepath = null; let filepath = null;
if (typeof value === "string") { if (typeof value === "string") {
({ ({ filepath, value } = resolver(value, dirname));
filepath,
value,
} = resolver(value, dirname));
} }
if (!value) { if (!value) {
@ -456,11 +526,15 @@ function normalizePair(pair: mixed, resolver, dirname): {
} }
if (typeof value !== "object" && typeof value !== "function") { if (typeof value !== "object" && typeof value !== "function") {
throw new Error(`Unsupported format: ${typeof value}. Expected an object or a function.`); throw new Error(
`Unsupported format: ${typeof value}. Expected an object or a function.`,
);
} }
if (options != null && typeof options !== "object") { if (options != null && typeof options !== "object") {
throw new Error("Plugin/Preset options must be an object, null, or undefined"); throw new Error(
"Plugin/Preset options must be an object, null, or undefined",
);
} }
return { filepath, value, options }; return { filepath, value, options };

View File

@ -5,8 +5,13 @@ export default class Plugin {
if (plugin.name != null && typeof plugin.name !== "string") { if (plugin.name != null && typeof plugin.name !== "string") {
throw new Error("Plugin .name must be a string, null, or undefined"); throw new Error("Plugin .name must be a string, null, or undefined");
} }
if (plugin.manipulateOptions != null && typeof plugin.manipulateOptions !== "function") { if (
throw new Error("Plugin .manipulateOptions must be a function, null, or undefined"); plugin.manipulateOptions != null &&
typeof plugin.manipulateOptions !== "function"
) {
throw new Error(
"Plugin .manipulateOptions must be a function, null, or undefined",
);
} }
if (plugin.post != null && typeof plugin.post !== "function") { if (plugin.post != null && typeof plugin.post !== "function") {
throw new Error("Plugin .post must be a function, null, or undefined"); throw new Error("Plugin .post must be a function, null, or undefined");

View File

@ -2,52 +2,58 @@
/* eslint max-len: "off" */ /* eslint max-len: "off" */
export default { export default {
"auxiliaryComment": { auxiliaryComment: {
"message": "Use `auxiliaryCommentBefore` or `auxiliaryCommentAfter`", message: "Use `auxiliaryCommentBefore` or `auxiliaryCommentAfter`",
}, },
"blacklist": { blacklist: {
"message": "Put the specific transforms you want in the `plugins` option", message: "Put the specific transforms you want in the `plugins` option",
}, },
"breakConfig": { breakConfig: {
"message": "This is not a necessary option in Babel 6", message: "This is not a necessary option in Babel 6",
}, },
"experimental": { experimental: {
"message": "Put the specific transforms you want in the `plugins` option", message: "Put the specific transforms you want in the `plugins` option",
}, },
"externalHelpers": { externalHelpers: {
"message": "Use the `external-helpers` plugin instead. Check out http://babeljs.io/docs/plugins/external-helpers/", message:
"Use the `external-helpers` plugin instead. Check out http://babeljs.io/docs/plugins/external-helpers/",
}, },
"extra": { extra: {
"message": "", message: "",
}, },
"jsxPragma": { jsxPragma: {
"message": "use the `pragma` option in the `react-jsx` plugin . Check out http://babeljs.io/docs/plugins/transform-react-jsx/", message:
"use the `pragma` option in the `react-jsx` plugin . Check out http://babeljs.io/docs/plugins/transform-react-jsx/",
}, },
// "keepModuleIdExtensions": { // "keepModuleIdExtensions": {
// "message": "" // "message": ""
// }, // },
"loose": { loose: {
"message": "Specify the `loose` option for the relevant plugin you are using or use a preset that sets the option.", message:
"Specify the `loose` option for the relevant plugin you are using or use a preset that sets the option.",
}, },
"metadataUsedHelpers": { metadataUsedHelpers: {
"message": "Not required anymore as this is enabled by default", message: "Not required anymore as this is enabled by default",
}, },
"modules": { modules: {
"message": "Use the corresponding module transform plugin in the `plugins` option. Check out http://babeljs.io/docs/plugins/#modules", message:
"Use the corresponding module transform plugin in the `plugins` option. Check out http://babeljs.io/docs/plugins/#modules",
}, },
"nonStandard": { nonStandard: {
"message": "Use the `react-jsx` and `flow-strip-types` plugins to support JSX and Flow. Also check out the react preset http://babeljs.io/docs/plugins/preset-react/", message:
"Use the `react-jsx` and `flow-strip-types` plugins to support JSX and Flow. Also check out the react preset http://babeljs.io/docs/plugins/preset-react/",
}, },
"optional": { optional: {
"message": "Put the specific transforms you want in the `plugins` option", message: "Put the specific transforms you want in the `plugins` option",
}, },
"sourceMapName": { sourceMapName: {
"message": "Use the `sourceMapTarget` option", message: "Use the `sourceMapTarget` option",
}, },
"stage": { stage: {
"message": "Check out the corresponding stage-x presets http://babeljs.io/docs/plugins/#presets", message:
"Check out the corresponding stage-x presets http://babeljs.io/docs/plugins/#presets",
}, },
"whitelist": { whitelist: {
"message": "Put the specific transforms you want in the `plugins` option", message: "Put the specific transforms you want in the `plugins` option",
}, },
}; };

View File

@ -41,4 +41,10 @@ export {
* Recommended set of compilable extensions. Not used in babel-core directly, but meant as * Recommended set of compilable extensions. Not used in babel-core directly, but meant as
* as an easy source for tooling making use of babel-core. * as an easy source for tooling making use of babel-core.
*/ */
export const DEFAULT_EXTENSIONS = Object.freeze([".js", ".jsx", ".es6", ".es", ".mjs"]); export const DEFAULT_EXTENSIONS = Object.freeze([
".js",
".jsx",
".es6",
".es",
".mjs",
]);

View File

@ -20,17 +20,29 @@ const buildUmdWrapper = template(`
function buildGlobal(namespace, builder) { function buildGlobal(namespace, builder) {
const body = []; const body = [];
const container = t.functionExpression(null, [t.identifier("global")], t.blockStatement(body)); const container = t.functionExpression(
null,
[t.identifier("global")],
t.blockStatement(body),
);
const tree = t.program([ const tree = t.program([
t.expressionStatement(t.callExpression(container, [helpers.get("selfGlobal")]))]); t.expressionStatement(
t.callExpression(container, [helpers.get("selfGlobal")]),
),
]);
body.push(t.variableDeclaration("var", [ body.push(
t.variableDeclaration("var", [
t.variableDeclarator( t.variableDeclarator(
namespace, namespace,
t.assignmentExpression("=", t.memberExpression(t.identifier("global"), namespace), t.assignmentExpression(
t.objectExpression([])) "=",
t.memberExpression(t.identifier("global"), namespace),
t.objectExpression([]),
), ),
])); ),
]),
);
builder(body); builder(body);
@ -39,9 +51,11 @@ function buildGlobal(namespace, builder) {
function buildUmd(namespace, builder) { function buildUmd(namespace, builder) {
const body = []; const body = [];
body.push(t.variableDeclaration("var", [ body.push(
t.variableDeclaration("var", [
t.variableDeclarator(namespace, t.identifier("global")), t.variableDeclarator(namespace, t.identifier("global")),
])); ]),
);
builder(body); builder(body);
@ -51,7 +65,7 @@ function buildUmd(namespace, builder) {
BROWSER_ARGUMENTS: t.assignmentExpression( BROWSER_ARGUMENTS: t.assignmentExpression(
"=", "=",
t.memberExpression(t.identifier("root"), namespace), t.memberExpression(t.identifier("root"), namespace),
t.objectExpression([]) t.objectExpression([]),
), ),
COMMON_ARGUMENTS: t.identifier("exports"), COMMON_ARGUMENTS: t.identifier("exports"),
AMD_ARGUMENTS: t.arrayExpression([t.stringLiteral("exports")]), AMD_ARGUMENTS: t.arrayExpression([t.stringLiteral("exports")]),
@ -63,9 +77,11 @@ function buildUmd(namespace, builder) {
function buildVar(namespace, builder) { function buildVar(namespace, builder) {
const body = []; const body = [];
body.push(t.variableDeclaration("var", [ body.push(
t.variableDeclaration("var", [
t.variableDeclarator(namespace, t.objectExpression([])), t.variableDeclarator(namespace, t.objectExpression([])),
])); ]),
);
builder(body); builder(body);
body.push(t.expressionStatement(namespace)); body.push(t.expressionStatement(namespace));
return t.program(body); return t.program(body);
@ -76,9 +92,15 @@ function buildHelpers(body, namespace, whitelist) {
if (whitelist && whitelist.indexOf(name) < 0) return; if (whitelist && whitelist.indexOf(name) < 0) return;
const key = t.identifier(name); const key = t.identifier(name);
body.push(t.expressionStatement( body.push(
t.assignmentExpression("=", t.memberExpression(namespace, key), helpers.get(name)) t.expressionStatement(
)); t.assignmentExpression(
"=",
t.memberExpression(namespace, key),
helpers.get(name),
),
),
);
}); });
} }
export default function( export default function(

View File

@ -150,7 +150,7 @@ export default class File extends Store {
if (opts.sourceRoot != null) { if (opts.sourceRoot != null) {
// remove sourceRoot from filename // remove sourceRoot from filename
const sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "\/?"); const sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "/?");
filenameRelative = filenameRelative.replace(sourceRootRegEx, ""); filenameRelative = filenameRelative.replace(sourceRootRegEx, "");
} }
@ -172,17 +172,25 @@ export default class File extends Store {
resolveModuleSource(source: string): string { resolveModuleSource(source: string): string {
const resolveModuleSource = this.opts.resolveModuleSource; const resolveModuleSource = this.opts.resolveModuleSource;
if (resolveModuleSource) source = resolveModuleSource(source, this.opts.filename); if (resolveModuleSource) {
source = resolveModuleSource(source, this.opts.filename);
}
return source; return source;
} }
addImport(source: string, imported: string, name?: string = imported): Object { addImport(
source: string,
imported: string,
name?: string = imported,
): Object {
const alias = `${source}:${imported}`; const alias = `${source}:${imported}`;
let id = this.dynamicImportIds[alias]; let id = this.dynamicImportIds[alias];
if (!id) { if (!id) {
source = this.resolveModuleSource(source); source = this.resolveModuleSource(source);
id = this.dynamicImportIds[alias] = this.scope.generateUidIdentifier(name); id = this.dynamicImportIds[alias] = this.scope.generateUidIdentifier(
name,
);
const specifiers = []; const specifiers = [];
@ -222,7 +230,9 @@ export default class File extends Store {
} }
const ref = getHelper(name); const ref = getHelper(name);
const uid = this.declarations[name] = this.scope.generateUidIdentifier(name); const uid = (this.declarations[name] = this.scope.generateUidIdentifier(
name,
));
if (t.isFunctionExpression(ref) && !ref.id) { if (t.isFunctionExpression(ref) && !ref.id) {
ref.body._compact = true; ref.body._compact = true;
@ -257,7 +267,9 @@ export default class File extends Store {
const declar = this.declarations[name]; const declar = this.declarations[name];
if (declar) return declar; if (declar) return declar;
const uid = this.declarations[name] = this.scope.generateUidIdentifier("templateObject"); const uid = (this.declarations[name] = this.scope.generateUidIdentifier(
"templateObject",
));
const helperId = this.addHelper(helperName); const helperId = this.addHelper(helperName);
const init = t.callExpression(helperId, [strings, raw]); const init = t.callExpression(helperId, [strings, raw]);
@ -270,7 +282,11 @@ export default class File extends Store {
return uid; return uid;
} }
buildCodeFrameError(node: Object, msg: string, Error: typeof Error = SyntaxError): Error { buildCodeFrameError(
node: Object,
msg: string,
Error: typeof Error = SyntaxError,
): Error {
const loc = node && (node.loc || node._loc); const loc = node && (node.loc || node._loc);
const err = new Error(msg); const err = new Error(msg);
@ -280,7 +296,8 @@ export default class File extends Store {
} else { } else {
traverse(node, errorVisitor, this.scope, err); traverse(node, errorVisitor, this.scope, err);
err.message += " (This is an error on an internal node. Probably an internal error"; err.message +=
" (This is an error on an internal node. Probably an internal error";
if (err.loc) { if (err.loc) {
err.message += ". Location has been estimated."; err.message += ". Location has been estimated.";
@ -318,7 +335,10 @@ export default class File extends Store {
mergedGenerator.addMapping({ mergedGenerator.addMapping({
source: mapping.source, source: mapping.source,
original: mapping.source == null ? null : { original:
mapping.source == null
? null
: {
line: mapping.originalLine, line: mapping.originalLine,
column: mapping.originalColumn, column: mapping.originalColumn,
}, },
@ -401,7 +421,11 @@ export default class File extends Store {
debug(this.opts, "Start transform traverse"); debug(this.opts, "Start transform traverse");
// merge all plugin visitors into a single visitor // merge all plugin visitors into a single visitor
const visitor = traverse.visitors.merge(visitors, passes, this.opts.wrapPluginVisitorMethod); const visitor = traverse.visitors.merge(
visitors,
passes,
this.opts.wrapPluginVisitorMethod,
);
traverse(this.ast, visitor, this.scope); traverse(this.ast, visitor, this.scope);
debug(this.opts, "End transform traverse"); debug(this.opts, "End transform traverse");
@ -410,7 +434,6 @@ export default class File extends Store {
const fn = plugin.post; const fn = plugin.post;
if (fn) fn.call(pass, this); if (fn) fn.call(pass, this);
} }
} }
return this.generate(); return this.generate();
@ -428,7 +451,7 @@ export default class File extends Store {
err._babel = true; err._babel = true;
} }
let message = err.message = `${this.opts.filename}: ${err.message}`; let message = (err.message = `${this.opts.filename}: ${err.message}`);
const loc = err.loc; const loc = err.loc;
if (loc) { if (loc) {
@ -530,8 +553,11 @@ export default class File extends Store {
debug(this.opts, "Generation start"); debug(this.opts, "Generation start");
const _result = gen(ast, opts.generatorOpts ? Object.assign(opts, opts.generatorOpts) : opts, const _result = gen(
this.code); ast,
opts.generatorOpts ? Object.assign(opts, opts.generatorOpts) : opts,
this.code,
);
result.code = _result.code; result.code = _result.code;
result.map = _result.map; result.map = _result.map;

View File

@ -5,7 +5,11 @@ import * as t from "babel-types";
import File from "./file"; import File from "./file";
import loadConfig from "../config"; import loadConfig from "../config";
export function analyse(code: string, opts: Object = {}, visitor?: Object): ?BabelFileMetadata { export function analyse(
code: string,
opts: Object = {},
visitor?: Object,
): ?BabelFileMetadata {
opts.code = false; opts.code = false;
if (visitor) { if (visitor) {
opts.plugins = opts.plugins || []; opts.plugins = opts.plugins || [];
@ -26,7 +30,11 @@ export function transform(code: string, opts?: Object): BabelFileResult {
}); });
} }
export function transformFromAst(ast: Object, code: string, opts: Object): BabelFileResult { export function transformFromAst(
ast: Object,
code: string,
opts: Object,
): BabelFileResult {
const config = loadConfig(opts); const config = loadConfig(opts);
if (config === null) return null; if (config === null) return null;
@ -44,7 +52,11 @@ export function transformFromAst(ast: Object, code: string, opts: Object): Babel
}); });
} }
export function transformFile(filename: string, opts?: Object, callback: Function) { export function transformFile(
filename: string,
opts?: Object,
callback: Function,
) {
if (typeof opts === "function") { if (typeof opts === "function") {
callback = opts; callback = opts;
opts = {}; opts = {};
@ -78,7 +90,10 @@ export function transformFile(filename: string, opts?: Object, callback: Functio
}); });
} }
export function transformFileSync(filename: string, opts?: Object = {}): string { export function transformFileSync(
filename: string,
opts?: Object = {},
): string {
opts.filename = filename; opts.filename = filename;
const config = loadConfig(opts); const config = loadConfig(opts);
if (config === null) return null; if (config === null) return null;

View File

@ -55,11 +55,14 @@ describe("parser and generator options", function() {
it("experimental syntax", function() { it("experimental syntax", function() {
const experimental = "var a: number = 1;"; const experimental = "var a: number = 1;";
assert.deepEqual(newTransform(experimental).ast, babel.transform(experimental, { assert.deepEqual(
newTransform(experimental).ast,
babel.transform(experimental, {
parserOpts: { parserOpts: {
plugins: ["flow"], plugins: ["flow"],
}, },
}).ast); }).ast,
);
assert.equal(newTransform(experimental).code, experimental); assert.equal(newTransform(experimental).code, experimental);
function newTransformWithPlugins(string) { function newTransformWithPlugins(string) {
@ -74,22 +77,28 @@ describe("parser and generator options", function() {
}); });
} }
assert.deepEqual(newTransformWithPlugins(experimental).ast, babel.transform(experimental, { assert.deepEqual(
newTransformWithPlugins(experimental).ast,
babel.transform(experimental, {
parserOpts: { parserOpts: {
plugins: ["flow"], plugins: ["flow"],
}, },
}).ast); }).ast,
);
assert.equal(newTransformWithPlugins(experimental).code, experimental); assert.equal(newTransformWithPlugins(experimental).code, experimental);
}); });
it("other options", function() { it("other options", function() {
const experimental = "if (true) {\n import a from 'a';\n}"; const experimental = "if (true) {\n import a from 'a';\n}";
assert.notEqual(newTransform(experimental).ast, babel.transform(experimental, { assert.notEqual(
newTransform(experimental).ast,
babel.transform(experimental, {
parserOpts: { parserOpts: {
allowImportExportEverywhere: true, allowImportExportEverywhere: true,
}, },
}).ast); }).ast,
);
assert.equal(newTransform(experimental).code, experimental); assert.equal(newTransform(experimental).code, experimental);
}); });
}); });
@ -98,58 +107,78 @@ describe("api", function () {
it("analyze", function() { it("analyze", function() {
assert.equal(babel.analyse("foobar;").marked.length, 0); assert.equal(babel.analyse("foobar;").marked.length, 0);
assert.equal(babel.analyse("foobar;", { assert.equal(
plugins: [new Plugin({ babel.analyse("foobar;", {
plugins: [
new Plugin({
visitor: { visitor: {
Program: function(path) { Program: function(path) {
path.mark("category", "foobar"); path.mark("category", "foobar");
}, },
}, },
})], }),
}).marked[0].message, "foobar"); ],
}).marked[0].message,
"foobar",
);
assert.equal(babel.analyse("foobar;", {}, { assert.equal(
babel.analyse(
"foobar;",
{},
{
Program: function(path) { Program: function(path) {
path.mark("category", "foobar"); path.mark("category", "foobar");
}, },
}).marked[0].message, "foobar"); },
).marked[0].message,
"foobar",
);
}); });
it("exposes the resolvePlugin method", function() { it("exposes the resolvePlugin method", function() {
assert.throws(() => babel.resolvePlugin("nonexistent-plugin"), assert.throws(
/Cannot find module 'babel-plugin-nonexistent-plugin'/); () => babel.resolvePlugin("nonexistent-plugin"),
/Cannot find module 'babel-plugin-nonexistent-plugin'/,
);
}); });
it("exposes the resolvePreset method", function() { it("exposes the resolvePreset method", function() {
assert.throws(() => babel.resolvePreset("nonexistent-preset"), assert.throws(
/Cannot find module 'babel-preset-nonexistent-preset'/); () => babel.resolvePreset("nonexistent-preset"),
/Cannot find module 'babel-preset-nonexistent-preset'/,
);
}); });
it("transformFile", function(done) { it("transformFile", function(done) {
babel.transformFile(__dirname + "/fixtures/api/file.js", { babel.transformFile(
__dirname + "/fixtures/api/file.js",
{
babelrc: false, babelrc: false,
}, function (err, res) { },
function(err, res) {
if (err) return done(err); if (err) return done(err);
assert.equal(res.code, "foo();"); assert.equal(res.code, "foo();");
done(); done();
}); },
);
}); });
it("transformFileSync", function() { it("transformFileSync", function() {
assert.equal(babel.transformFileSync(__dirname + "/fixtures/api/file.js", { assert.equal(
babel.transformFileSync(__dirname + "/fixtures/api/file.js", {
babelrc: false, babelrc: false,
}).code, "foo();"); }).code,
"foo();",
);
}); });
it("options throw on falsy true", function() { it("options throw on falsy true", function() {
return assert.throws( return assert.throws(function() {
function () {
babel.transform("", { babel.transform("", {
plugins: [__dirname + "/../../babel-plugin-syntax-jsx", false], plugins: [__dirname + "/../../babel-plugin-syntax-jsx", false],
}); });
}, }, /Error: \[BABEL\] unknown: Unexpected falsy value: false/);
/Error: \[BABEL\] unknown: Unexpected falsy value: false/
);
}); });
it("options merge backwards", function() { it("options merge backwards", function() {
@ -157,7 +186,11 @@ describe("api", function () {
presets: [__dirname + "/../../babel-preset-es2015"], presets: [__dirname + "/../../babel-preset-es2015"],
plugins: [__dirname + "/../../babel-plugin-syntax-jsx"], plugins: [__dirname + "/../../babel-plugin-syntax-jsx"],
}).then(function(result) { }).then(function(result) {
assert.ok(result.options.plugins[0][0].manipulateOptions.toString().indexOf("jsx") >= 0); assert.ok(
result.options.plugins[0][0].manipulateOptions
.toString()
.indexOf("jsx") >= 0,
);
}); });
}); });
@ -179,14 +212,16 @@ describe("api", function () {
}; };
}, },
plugins: [new Plugin({ plugins: [
new Plugin({
name: "foobar", name: "foobar",
visitor: { visitor: {
"Program|Identifier": function() { "Program|Identifier": function() {
calledRaw++; calledRaw++;
}, },
}, },
})], }),
],
}); });
assert.equal(calledRaw, 4); assert.equal(calledRaw, 4);
@ -207,7 +242,9 @@ describe("api", function () {
new Plugin({ new Plugin({
visitor: { visitor: {
Function: function(path) { Function: function(path) {
const alias = path.scope.getProgramParent().path.get("body")[0].node; const alias = path.scope
.getProgramParent()
.path.get("body")[0].node;
if (!babel.types.isTypeAlias(alias)) return; if (!babel.types.isTypeAlias(alias)) return;
// In case of `passPerPreset` being `false`, the // In case of `passPerPreset` being `false`, the
@ -234,7 +271,8 @@ describe("api", function () {
return { return {
plugins: [ plugins: [
require(__dirname + "/../../babel-plugin-syntax-flow"), require(__dirname + "/../../babel-plugin-syntax-flow"),
require(__dirname + "/../../babel-plugin-transform-flow-strip-types"), require(__dirname +
"/../../babel-plugin-transform-flow-strip-types"),
], ],
}; };
}, },
@ -248,13 +286,16 @@ describe("api", function () {
assert.equal(aliasBaseType, "NumberTypeAnnotation"); assert.equal(aliasBaseType, "NumberTypeAnnotation");
assert.deepEqual([ assert.deepEqual(
"\"use strict\";", [
'"use strict";',
"", "",
"var x = function x(y) {", "var x = function x(y) {",
" return y;", " return y;",
"};", "};",
].join("\n"), result.code); ].join("\n"),
result.code,
);
// 2. passPerPreset: false // 2. passPerPreset: false
@ -264,14 +305,16 @@ describe("api", function () {
assert.equal(aliasBaseType, null); assert.equal(aliasBaseType, null);
assert.deepEqual([ assert.deepEqual(
"\"use strict\";", [
'"use strict";',
"", "",
"var x = function x(y) {", "var x = function x(y) {",
" return y;", " return y;",
"};", "};",
].join("\n"), result.code); ].join("\n"),
result.code,
);
}); });
it("complex plugin and preset ordering", function() { it("complex plugin and preset ordering", function() {
@ -279,7 +322,10 @@ describe("api", function () {
return { return {
visitor: { visitor: {
Program(path) { Program(path) {
path.pushContainer("body", babel.types.expressionStatement(babel.types.identifier(str))); path.pushContainer(
"body",
babel.types.expressionStatement(babel.types.identifier(str)),
);
}, },
}, },
}; };
@ -290,32 +336,31 @@ describe("api", function () {
} }
const result = babel.transform("", { const result = babel.transform("", {
filename: path.join(__dirname, "fixtures", "config", "complex-plugin-config", "file.js"), filename: path.join(
presets: [ __dirname,
pushPreset("argone"), "fixtures",
pushPreset("argtwo"), "config",
], "complex-plugin-config",
"file.js",
),
presets: [pushPreset("argone"), pushPreset("argtwo")],
env: { env: {
development: { development: {
passPerPreset: true, passPerPreset: true,
presets: [ presets: [pushPreset("argthree"), pushPreset("argfour")],
pushPreset("argthree"),
pushPreset("argfour"),
],
env: { env: {
development: { development: {
passPerPreset: true, passPerPreset: true,
presets: [ presets: [pushPreset("argfive"), pushPreset("argsix")],
pushPreset("argfive"),
pushPreset("argsix"),
],
}, },
}, },
}, },
}, },
}); });
assert.equal(result.code, [ assert.equal(
result.code,
[
"argtwo;", "argtwo;",
"argone;", "argone;",
"eleven;", "eleven;",
@ -342,13 +387,15 @@ describe("api", function () {
"eight;", "eight;",
"nine;", "nine;",
"ten;", "ten;",
].join("\n")); ].join("\n"),
);
}); });
it("source map merging", function() { it("source map merging", function() {
const result = babel.transform([ const result = babel.transform(
[
/* eslint-disable max-len */ /* eslint-disable max-len */
"function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }", 'function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }',
"", "",
"let Foo = function Foo() {", "let Foo = function Foo() {",
" _classCallCheck(this, Foo);", " _classCallCheck(this, Foo);",
@ -356,37 +403,47 @@ describe("api", function () {
"", "",
"//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZG91dCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztJQUFNLEdBQUcsWUFBSCxHQUFHO3dCQUFILEdBQUciLCJmaWxlIjoidW5kZWZpbmVkIiwic291cmNlc0NvbnRlbnQiOlsiY2xhc3MgRm9vIHt9XG4iXX0=", "//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZG91dCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztJQUFNLEdBQUcsWUFBSCxHQUFHO3dCQUFILEdBQUciLCJmaWxlIjoidW5kZWZpbmVkIiwic291cmNlc0NvbnRlbnQiOlsiY2xhc3MgRm9vIHt9XG4iXX0=",
/* eslint-enable max-len */ /* eslint-enable max-len */
].join("\n"), { ].join("\n"),
{
sourceMap: true, sourceMap: true,
}); },
);
assert.deepEqual([ assert.deepEqual(
[
"function _classCallCheck(instance, Constructor) {", "function _classCallCheck(instance, Constructor) {",
" if (!(instance instanceof Constructor)) {", " if (!(instance instanceof Constructor)) {",
" throw new TypeError(\"Cannot call a class as a function\");", ' throw new TypeError("Cannot call a class as a function");',
" }", " }",
"}", "}",
"", "",
"let Foo = function Foo() {", "let Foo = function Foo() {",
" _classCallCheck(this, Foo);", " _classCallCheck(this, Foo);",
"};", "};",
].join("\n"), result.code); ].join("\n"),
result.code,
);
const consumer = new sourceMap.SourceMapConsumer(result.map); const consumer = new sourceMap.SourceMapConsumer(result.map);
assert.deepEqual(consumer.originalPositionFor({ assert.deepEqual(
consumer.originalPositionFor({
line: 7, line: 7,
column: 4, column: 4,
}), { }),
{
name: null, name: null,
source: "stdout", source: "stdout",
line: 1, line: 1,
column: 6, column: 6,
}); },
);
}); });
it("code option false", function() { it("code option false", function() {
return transformAsync("foo('bar');", { code: false }).then(function (result) { return transformAsync("foo('bar');", { code: false }).then(function(
result,
) {
assert.ok(!result.code); assert.ok(!result.code);
}); });
}); });
@ -401,62 +458,84 @@ describe("api", function () {
return transformAsync("class Foo {}", { return transformAsync("class Foo {}", {
auxiliaryCommentBefore: "before", auxiliaryCommentBefore: "before",
auxiliaryCommentAfter: "after", auxiliaryCommentAfter: "after",
plugins: [function (babel) { plugins: [
function(babel) {
const t = babel.types; const t = babel.types;
return { return {
visitor: { visitor: {
Program: function(path) { Program: function(path) {
path.unshiftContainer("body", t.expressionStatement(t.identifier("start"))); path.unshiftContainer(
path.pushContainer("body", t.expressionStatement(t.identifier("end"))); "body",
t.expressionStatement(t.identifier("start")),
);
path.pushContainer(
"body",
t.expressionStatement(t.identifier("end")),
);
}, },
}, },
}; };
}], },
],
}).then(function(result) { }).then(function(result) {
assert.equal(result.code, assert.equal(
"/*before*/start;\n/*after*/class Foo {}\n/*before*/end;\n/*after*/"); result.code,
"/*before*/start;\n/*after*/class Foo {}\n/*before*/end;\n/*after*/",
);
}); });
}); });
it("modules metadata", function() { it("modules metadata", function() {
return Promise.all([ return Promise.all([
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
transformAsync("import { externalName as localName } from \"external\";").then(function (result) { transformAsync(
'import { externalName as localName } from "external";',
).then(function(result) {
assert.deepEqual(result.metadata.modules.imports[0], { assert.deepEqual(result.metadata.modules.imports[0], {
source: "external", source: "external",
imported: ["externalName"], imported: ["externalName"],
specifiers: [{ specifiers: [
{
kind: "named", kind: "named",
imported: "externalName", imported: "externalName",
local: "localName", local: "localName",
}], },
],
}); });
}), }),
transformAsync("import * as localName2 from \"external\";").then(function (result) { transformAsync('import * as localName2 from "external";').then(function(
result,
) {
assert.deepEqual(result.metadata.modules.imports[0], { assert.deepEqual(result.metadata.modules.imports[0], {
source: "external", source: "external",
imported: ["*"], imported: ["*"],
specifiers: [{ specifiers: [
{
kind: "namespace", kind: "namespace",
local: "localName2", local: "localName2",
}], },
],
}); });
}), }),
transformAsync("import localName3 from \"external\";").then(function (result) { transformAsync('import localName3 from "external";').then(function(
result,
) {
assert.deepEqual(result.metadata.modules.imports[0], { assert.deepEqual(result.metadata.modules.imports[0], {
source: "external", source: "external",
imported: ["default"], imported: ["default"],
specifiers: [{ specifiers: [
{
kind: "named", kind: "named",
imported: "default", imported: "default",
local: "localName3", local: "localName3",
}], },
],
}); });
}), }),
transformAsync("import localName from \"./array\";", { transformAsync('import localName from "./array";', {
resolveModuleSource: function() { resolveModuleSource: function() {
return "override-source"; return "override-source";
}, },
@ -467,105 +546,129 @@ describe("api", function () {
imported: ["default"], imported: ["default"],
specifiers: [ specifiers: [
{ {
"kind": "named", kind: "named",
"imported": "default", imported: "default",
"local": "localName", local: "localName",
}, },
], ],
}, },
]); ]);
}), }),
transformAsync("export * as externalName1 from \"external\";", { transformAsync('export * as externalName1 from "external";', {
plugins: [require("../../babel-plugin-syntax-export-extensions")], plugins: [require("../../babel-plugin-syntax-export-extensions")],
}).then(function(result) { }).then(function(result) {
assert.deepEqual(result.metadata.modules.exports, { assert.deepEqual(result.metadata.modules.exports, {
exported: ["externalName1"], exported: ["externalName1"],
specifiers: [{ specifiers: [
{
kind: "external-namespace", kind: "external-namespace",
exported: "externalName1", exported: "externalName1",
source: "external", source: "external",
}], },
],
}); });
}), }),
transformAsync("export externalName2 from \"external\";", { transformAsync('export externalName2 from "external";', {
plugins: [require("../../babel-plugin-syntax-export-extensions")], plugins: [require("../../babel-plugin-syntax-export-extensions")],
}).then(function(result) { }).then(function(result) {
assert.deepEqual(result.metadata.modules.exports, { assert.deepEqual(result.metadata.modules.exports, {
exported: ["externalName2"], exported: ["externalName2"],
specifiers: [{ specifiers: [
{
kind: "external", kind: "external",
local: "externalName2", local: "externalName2",
exported: "externalName2", exported: "externalName2",
source: "external", source: "external",
}], },
],
}); });
}), }),
transformAsync("export function namedFunction() {}").then(function (result) { transformAsync("export function namedFunction() {}").then(function(
result,
) {
assert.deepEqual(result.metadata.modules.exports, { assert.deepEqual(result.metadata.modules.exports, {
exported: ["namedFunction"], exported: ["namedFunction"],
specifiers: [{ specifiers: [
{
kind: "local", kind: "local",
local: "namedFunction", local: "namedFunction",
exported: "namedFunction", exported: "namedFunction",
}], },
],
}); });
}), }),
transformAsync("export var foo = \"bar\";").then(function (result) { transformAsync('export var foo = "bar";').then(function(result) {
assert.deepEqual(result.metadata.modules.exports, { assert.deepEqual(result.metadata.modules.exports, {
"exported": ["foo"], exported: ["foo"],
specifiers: [{ specifiers: [
{
kind: "local", kind: "local",
local: "foo", local: "foo",
exported: "foo", exported: "foo",
}], },
],
}); });
}), }),
transformAsync("export { localName as externalName3 };").then(function (result) { transformAsync("export { localName as externalName3 };").then(function(
result,
) {
assert.deepEqual(result.metadata.modules.exports, { assert.deepEqual(result.metadata.modules.exports, {
exported: ["externalName3"], exported: ["externalName3"],
specifiers: [{ specifiers: [
{
kind: "local", kind: "local",
local: "localName", local: "localName",
exported: "externalName3", exported: "externalName3",
}], },
],
}); });
}), }),
transformAsync("export { externalName4 } from \"external\";").then(function (result) { transformAsync('export { externalName4 } from "external";').then(function(
result,
) {
assert.deepEqual(result.metadata.modules.exports, { assert.deepEqual(result.metadata.modules.exports, {
exported: ["externalName4"], exported: ["externalName4"],
specifiers: [{ specifiers: [
{
kind: "external", kind: "external",
local: "externalName4", local: "externalName4",
exported: "externalName4", exported: "externalName4",
source: "external", source: "external",
}], },
],
}); });
}), }),
transformAsync("export * from \"external\";").then(function (result) { transformAsync('export * from "external";').then(function(result) {
assert.deepEqual(result.metadata.modules.exports, { assert.deepEqual(result.metadata.modules.exports, {
exported: [], exported: [],
specifiers: [{ specifiers: [
{
kind: "external-all", kind: "external-all",
source: "external", source: "external",
}], },
],
}); });
}), }),
transformAsync("export default function defaultFunction() {}").then(function (result) { transformAsync(
"export default function defaultFunction() {}",
).then(function(result) {
assert.deepEqual(result.metadata.modules.exports, { assert.deepEqual(result.metadata.modules.exports, {
exported: ["defaultFunction"], exported: ["defaultFunction"],
specifiers: [{ specifiers: [
{
kind: "local", kind: "local",
local: "defaultFunction", local: "defaultFunction",
exported: "default", exported: "default",
}], },
],
}); });
}), }),
]); ]);
@ -698,8 +801,10 @@ describe("api", function () {
it("resolveModuleSource option", function() { it("resolveModuleSource option", function() {
/* eslint-disable max-len */ /* eslint-disable max-len */
const actual = "import foo from \"foo-import-default\";\nimport \"foo-import-bare\";\nexport { foo } from \"foo-export-named\";"; const actual =
const expected = "import foo from \"resolved/foo-import-default\";\nimport \"resolved/foo-import-bare\";\nexport { foo } from \"resolved/foo-export-named\";"; 'import foo from "foo-import-default";\nimport "foo-import-bare";\nexport { foo } from "foo-export-named";';
const expected =
'import foo from "resolved/foo-import-default";\nimport "resolved/foo-import-bare";\nexport { foo } from "resolved/foo-export-named";';
/* eslint-enable max-len */ /* eslint-enable max-len */
return transformAsync(actual, { return transformAsync(actual, {

View File

@ -5,7 +5,9 @@ import vm from "vm";
describe("browserify", function() { describe("browserify", function() {
it("babel/register may be used without breaking browserify", function(done) { it("babel/register may be used without breaking browserify", function(done) {
const bundler = browserify(path.join(__dirname, "fixtures/browserify/register.js")); const bundler = browserify(
path.join(__dirname, "fixtures/browserify/register.js"),
);
bundler.bundle(function(err, bundle) { bundler.bundle(function(err, bundle) {
if (err) return done(err); if (err) return done(err);

View File

@ -27,7 +27,6 @@ describe("caching API", () => {
return { arg, count: count++ }; return { arg, count: count++ };
}); });
assert.deepEqual(fn("one"), { arg: "one", count: 0 }); assert.deepEqual(fn("one"), { arg: "one", count: 0 });
assert.equal(fn("one"), fn("one")); assert.equal(fn("one"), fn("one"));
@ -210,44 +209,93 @@ describe("caching API", () => {
return { arg, val, val2, count: count++ }; return { arg, val, val2, count: count++ };
}); });
assert.deepEqual(fn("one"), { arg: "one", val: "default", val2: "another", count: 0 }); assert.deepEqual(fn("one"), {
arg: "one",
val: "default",
val2: "another",
count: 0,
});
assert.equal(fn("one"), fn("one")); assert.equal(fn("one"), fn("one"));
assert.deepEqual(fn("two"), { arg: "two", val: "default", val2: "another", count: 1 }); assert.deepEqual(fn("two"), {
arg: "two",
val: "default",
val2: "another",
count: 1,
});
assert.equal(fn("two"), fn("two")); assert.equal(fn("two"), fn("two"));
other = "new"; other = "new";
assert.deepEqual(fn("one"), { arg: "one", val: "new", val2: "another", count: 2 }); assert.deepEqual(fn("one"), {
arg: "one",
val: "new",
val2: "another",
count: 2,
});
assert.equal(fn("one"), fn("one")); assert.equal(fn("one"), fn("one"));
assert.deepEqual(fn("two"), { arg: "two", val: "new", val2: "another", count: 3 }); assert.deepEqual(fn("two"), {
arg: "two",
val: "new",
val2: "another",
count: 3,
});
assert.equal(fn("two"), fn("two")); assert.equal(fn("two"), fn("two"));
other = "default"; other = "default";
assert.deepEqual(fn("one"), { arg: "one", val: "default", val2: "another", count: 4 }); assert.deepEqual(fn("one"), {
arg: "one",
val: "default",
val2: "another",
count: 4,
});
assert.equal(fn("one"), fn("one")); assert.equal(fn("one"), fn("one"));
assert.deepEqual(fn("two"), { arg: "two", val: "default", val2: "another", count: 5 }); assert.deepEqual(fn("two"), {
arg: "two",
val: "default",
val2: "another",
count: 5,
});
assert.equal(fn("two"), fn("two")); assert.equal(fn("two"), fn("two"));
other = "new"; other = "new";
assert.deepEqual(fn("one"), { arg: "one", val: "new", val2: "another", count: 6 }); assert.deepEqual(fn("one"), {
arg: "one",
val: "new",
val2: "another",
count: 6,
});
assert.equal(fn("one"), fn("one")); assert.equal(fn("one"), fn("one"));
assert.deepEqual(fn("two"), { arg: "two", val: "new", val2: "another", count: 7 }); assert.deepEqual(fn("two"), {
arg: "two",
val: "new",
val2: "another",
count: 7,
});
assert.equal(fn("two"), fn("two")); assert.equal(fn("two"), fn("two"));
another = "second"; another = "second";
assert.deepEqual(fn("one"), { arg: "one", val: "new", val2: "second", count: 8 }); assert.deepEqual(fn("one"), {
arg: "one",
val: "new",
val2: "second",
count: 8,
});
assert.equal(fn("one"), fn("one")); assert.equal(fn("one"), fn("one"));
assert.deepEqual(fn("two"), { arg: "two", val: "new", val2: "second", count: 9 }); assert.deepEqual(fn("two"), {
arg: "two",
val: "new",
val2: "second",
count: 9,
});
assert.equal(fn("two"), fn("two")); assert.equal(fn("two"), fn("two"));
}); });
it("should throw if caching is never configured and not defaulting", () => { it("should throw if caching is never configured and not defaulting", () => {
@ -259,7 +307,7 @@ describe("caching API", () => {
it("should auto-permacache by default", () => { it("should auto-permacache by default", () => {
let count = 0; let count = 0;
const fn = makeStrongCache((arg) => ({ arg, count: count++ })); const fn = makeStrongCache(arg => ({ arg, count: count++ }));
assert.deepEqual(fn("one"), { arg: "one", count: 0 }); assert.deepEqual(fn("one"), { arg: "one", count: 0 });
assert.equal(fn("one"), fn("one")); assert.equal(fn("one"), fn("one"));
@ -333,7 +381,10 @@ describe("caching API", () => {
it("should throw if you configure .forever after exiting", () => { it("should throw if you configure .forever after exiting", () => {
const fn = makeStrongCache((arg, cache) => cache); const fn = makeStrongCache((arg, cache) => cache);
assert.throws(() => fn().forever(), /Cannot change caching after evaluation/); assert.throws(
() => fn().forever(),
/Cannot change caching after evaluation/,
);
}); });
it("should throw if you configure .never after exiting", () => { it("should throw if you configure .never after exiting", () => {
@ -345,12 +396,18 @@ describe("caching API", () => {
it("should throw if you configure .using after exiting", () => { it("should throw if you configure .using after exiting", () => {
const fn = makeStrongCache((arg, cache) => cache); const fn = makeStrongCache((arg, cache) => cache);
assert.throws(() => fn().using(() => null), /Cannot change caching after evaluation/); assert.throws(
() => fn().using(() => null),
/Cannot change caching after evaluation/,
);
}); });
it("should throw if you configure .invalidate after exiting", () => { it("should throw if you configure .invalidate after exiting", () => {
const fn = makeStrongCache((arg, cache) => cache); const fn = makeStrongCache((arg, cache) => cache);
assert.throws(() => fn().invalidate(() => null), /Cannot change caching after evaluation/); assert.throws(
() => fn().invalidate(() => null),
/Cannot change caching after evaluation/,
);
}); });
}); });

View File

@ -61,9 +61,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["extended"],
"extended",
],
}, },
alias: fixture("extended.babelrc.json"), alias: fixture("extended.babelrc.json"),
loc: fixture("extended.babelrc.json"), loc: fixture("extended.babelrc.json"),
@ -72,9 +70,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["root"],
"root",
],
}, },
alias: fixture(".babelrc"), alias: fixture(".babelrc"),
loc: fixture(".babelrc"), loc: fixture(".babelrc"),
@ -83,9 +79,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["root-ignore"],
"root-ignore",
],
}, },
alias: fixture(".babelignore"), alias: fixture(".babelignore"),
loc: fixture(".babelignore"), loc: fixture(".babelignore"),
@ -114,9 +108,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["root-ignore"],
"root-ignore",
],
}, },
alias: fixture(".babelignore"), alias: fixture(".babelignore"),
loc: fixture(".babelignore"), loc: fixture(".babelignore"),
@ -125,9 +117,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["dir2"],
"dir2",
],
}, },
alias: fixture("dir2", ".babelrc"), alias: fixture("dir2", ".babelrc"),
loc: fixture("dir2", ".babelrc"), loc: fixture("dir2", ".babelrc"),
@ -156,9 +146,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["extended"],
"extended",
],
}, },
alias: fixture("extended.babelrc.json"), alias: fixture("extended.babelrc.json"),
loc: fixture("extended.babelrc.json"), loc: fixture("extended.babelrc.json"),
@ -167,9 +155,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["root"],
"root",
],
}, },
alias: fixture(".babelrc"), alias: fixture(".babelrc"),
loc: fixture(".babelrc"), loc: fixture(".babelrc"),
@ -178,9 +164,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["root-ignore"],
"root-ignore",
],
}, },
alias: fixture(".babelignore"), alias: fixture(".babelignore"),
loc: fixture(".babelignore"), loc: fixture(".babelignore"),
@ -209,9 +193,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["root-ignore"],
"root-ignore",
],
}, },
alias: fixture(".babelignore"), alias: fixture(".babelignore"),
loc: fixture(".babelignore"), loc: fixture(".babelignore"),
@ -220,9 +202,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["env-base"],
"env-base",
],
}, },
alias: fixture("env", ".babelrc"), alias: fixture("env", ".babelrc"),
loc: fixture("env", ".babelrc"), loc: fixture("env", ".babelrc"),
@ -253,9 +233,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["root-ignore"],
"root-ignore",
],
}, },
alias: fixture(".babelignore"), alias: fixture(".babelignore"),
loc: fixture(".babelignore"), loc: fixture(".babelignore"),
@ -264,9 +242,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["env-base"],
"env-base",
],
}, },
alias: fixture("env", ".babelrc"), alias: fixture("env", ".babelrc"),
loc: fixture("env", ".babelrc"), loc: fixture("env", ".babelrc"),
@ -275,9 +251,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["env-foo"],
"env-foo",
],
}, },
alias: fixture("env", ".babelrc.env.foo"), alias: fixture("env", ".babelrc.env.foo"),
loc: fixture("env", ".babelrc.env.foo"), loc: fixture("env", ".babelrc.env.foo"),
@ -309,9 +283,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["root-ignore"],
"root-ignore",
],
}, },
alias: fixture(".babelignore"), alias: fixture(".babelignore"),
loc: fixture(".babelignore"), loc: fixture(".babelignore"),
@ -320,9 +292,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["env-base"],
"env-base",
],
}, },
alias: fixture("env", ".babelrc"), alias: fixture("env", ".babelrc"),
loc: fixture("env", ".babelrc"), loc: fixture("env", ".babelrc"),
@ -331,9 +301,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["env-bar"],
"env-bar",
],
}, },
alias: fixture("env", ".babelrc.env.bar"), alias: fixture("env", ".babelrc.env.bar"),
loc: fixture("env", ".babelrc.env.bar"), loc: fixture("env", ".babelrc.env.bar"),
@ -353,7 +321,6 @@ describe("buildConfigChain", function () {
assert.deepEqual(chain, expected); assert.deepEqual(chain, expected);
}); });
it("env - foo", function() { it("env - foo", function() {
process.env.NODE_ENV = "foo"; process.env.NODE_ENV = "foo";
@ -403,9 +370,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["root-ignore"],
"root-ignore",
],
}, },
alias: fixture(".babelignore"), alias: fixture(".babelignore"),
loc: fixture(".babelignore"), loc: fixture(".babelignore"),
@ -414,10 +379,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["foo", "bar"],
"foo",
"bar",
],
}, },
alias: fixture("js-config", ".babelrc.js"), alias: fixture("js-config", ".babelrc.js"),
loc: fixture("js-config", ".babelrc.js"), loc: fixture("js-config", ".babelrc.js"),
@ -446,9 +408,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["root-ignore"],
"root-ignore",
],
}, },
alias: fixture(".babelignore"), alias: fixture(".babelignore"),
loc: fixture(".babelignore"), loc: fixture(".babelignore"),
@ -486,9 +446,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["root-ignore"],
"root-ignore",
],
}, },
alias: fixture(".babelignore"), alias: fixture(".babelignore"),
loc: fixture(".babelignore"), loc: fixture(".babelignore"),
@ -497,10 +455,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["foo", "bar"],
"foo",
"bar",
],
}, },
alias: fixture("js-config-default", ".babelrc.js"), alias: fixture("js-config-default", ".babelrc.js"),
loc: fixture("js-config-default", ".babelrc.js"), loc: fixture("js-config-default", ".babelrc.js"),
@ -528,9 +483,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["root-ignore"],
"root-ignore",
],
}, },
alias: fixture(".babelignore"), alias: fixture(".babelignore"),
loc: fixture(".babelignore"), loc: fixture(".babelignore"),
@ -539,9 +492,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["extended"],
"extended",
],
}, },
alias: fixture("extended.babelrc.json"), alias: fixture("extended.babelrc.json"),
loc: fixture("extended.babelrc.json"), loc: fixture("extended.babelrc.json"),
@ -550,10 +501,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["foo", "bar"],
"foo",
"bar",
],
}, },
alias: fixture("js-config-extended", ".babelrc.js"), alias: fixture("js-config-extended", ".babelrc.js"),
loc: fixture("js-config-extended", ".babelrc.js"), loc: fixture("js-config-extended", ".babelrc.js"),
@ -573,8 +521,10 @@ describe("buildConfigChain", function () {
assert.deepEqual(chain, expected); assert.deepEqual(chain, expected);
}); });
it("json-pkg-config-no-babel - should not throw if" + it(
" package.json doesn't contain a `babel` field", function () { "json-pkg-config-no-babel - should not throw if" +
" package.json doesn't contain a `babel` field",
function() {
const chain = buildConfigChain({ const chain = buildConfigChain({
filename: fixture("json-pkg-config-no-babel", "src.js"), filename: fixture("json-pkg-config-no-babel", "src.js"),
}); });
@ -583,9 +533,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["root-ignore"],
"root-ignore",
],
}, },
alias: fixture(".babelignore"), alias: fixture(".babelignore"),
loc: fixture(".babelignore"), loc: fixture(".babelignore"),
@ -594,9 +542,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
plugins: [ plugins: ["json"],
"json",
],
}, },
alias: fixture("json-pkg-config-no-babel", ".babelrc"), alias: fixture("json-pkg-config-no-babel", ".babelrc"),
loc: fixture("json-pkg-config-no-babel", ".babelrc"), loc: fixture("json-pkg-config-no-babel", ".babelrc"),
@ -614,7 +560,8 @@ describe("buildConfigChain", function () {
]; ];
assert.deepEqual(chain, expected); assert.deepEqual(chain, expected);
}); },
);
it("should not ignore file matching negated file pattern", function() { it("should not ignore file matching negated file pattern", function() {
const chain = buildConfigChain({ const chain = buildConfigChain({
@ -625,9 +572,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["root-ignore"],
"root-ignore",
],
}, },
alias: fixture(".babelignore"), alias: fixture(".babelignore"),
loc: fixture(".babelignore"), loc: fixture(".babelignore"),
@ -636,10 +581,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["*", "!src.js"],
"*",
"!src.js",
],
}, },
alias: fixture("ignore-negate", ".babelrc"), alias: fixture("ignore-negate", ".babelrc"),
loc: fixture("ignore-negate", ".babelrc"), loc: fixture("ignore-negate", ".babelrc"),
@ -674,9 +616,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["root-ignore"],
"root-ignore",
],
}, },
alias: fixture(".babelignore"), alias: fixture(".babelignore"),
loc: fixture(".babelignore"), loc: fixture(".babelignore"),
@ -685,10 +625,7 @@ describe("buildConfigChain", function () {
{ {
type: "options", type: "options",
options: { options: {
ignore: [ ignore: ["*", "!folder"],
"*",
"!folder",
],
}, },
alias: fixture("ignore-negate-folder", ".babelrc"), alias: fixture("ignore-negate-folder", ".babelrc"),
loc: fixture("ignore-negate-folder", ".babelrc"), loc: fixture("ignore-negate-folder", ".babelrc"),
@ -714,83 +651,71 @@ describe("buildConfigChain", function () {
assert.equal(chain2, null); assert.equal(chain2, null);
}); });
it("js-json-config - should throw an error if both a .babelrc" + it(
" and a .babelrc.js are present", function () { "js-json-config - should throw an error if both a .babelrc" +
assert.throws( " and a .babelrc.js are present",
function() { function() {
assert.throws(function() {
buildConfigChain({ buildConfigChain({
filename: fixture("js-json-config", "src.js"), filename: fixture("js-json-config", "src.js"),
}); });
}, /Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*\.babelrc\.js/);
}, },
/Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*\.babelrc\.js/
); );
});
it("js-pkg-config - should throw an error if both a .babelrc.js" + it(
" and a package.json with a babel field are present", function () { "js-pkg-config - should throw an error if both a .babelrc.js" +
assert.throws( " and a package.json with a babel field are present",
function() { function() {
assert.throws(function() {
buildConfigChain({ buildConfigChain({
filename: fixture("js-pkg-config", "src.js"), filename: fixture("js-pkg-config", "src.js"),
}); });
}, /Multiple configuration files found\.(.|\n)*\.babelrc\.js(.|\n)*package\.json/);
}, },
/Multiple configuration files found\.(.|\n)*\.babelrc\.js(.|\n)*package\.json/
); );
});
it("json-pkg-config - should throw an error if both a .babelrc" + it(
" and a package.json with a babel field are present", function () { "json-pkg-config - should throw an error if both a .babelrc" +
assert.throws( " and a package.json with a babel field are present",
function() { function() {
assert.throws(function() {
buildConfigChain({ buildConfigChain({
filename: fixture("json-pkg-config", "src.js"), filename: fixture("json-pkg-config", "src.js"),
}); });
}, /Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*package\.json/);
}, },
/Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*package\.json/
); );
});
it("js-config-error", function() { it("js-config-error", function() {
assert.throws( assert.throws(function() {
function () {
buildConfigChain({ buildConfigChain({
filename: fixture("js-config-error", "src.js"), filename: fixture("js-config-error", "src.js"),
}); });
}, }, /Error while loading config/);
/Error while loading config/
);
}); });
it("js-config-error2", function() { it("js-config-error2", function() {
assert.throws( assert.throws(function() {
function () {
buildConfigChain({ buildConfigChain({
filename: fixture("js-config-error2", "src.js"), filename: fixture("js-config-error2", "src.js"),
}); });
}, }, /Configuration should be an exported JavaScript object/);
/Configuration should be an exported JavaScript object/
);
}); });
it("js-config-error3", function() { it("js-config-error3", function() {
assert.throws( assert.throws(function() {
function () {
buildConfigChain({ buildConfigChain({
filename: fixture("js-config-error3", "src.js"), filename: fixture("js-config-error3", "src.js"),
}); });
}, }, /Configuration should be an exported JavaScript object/);
/Configuration should be an exported JavaScript object/
);
}); });
it("json-config-error", function() { it("json-config-error", function() {
assert.throws( assert.throws(function() {
function () {
buildConfigChain({ buildConfigChain({
filename: fixture("json-config-error", "src.js"), filename: fixture("json-config-error", "src.js"),
}); });
}, }, /Error while parsing config/);
/Error while parsing config/
);
}); });
}); });

View File

@ -13,9 +13,12 @@ describe("evaluation", function () {
assert.deepEqual(evaluate.value, value); assert.deepEqual(evaluate.value, value);
}; };
traverse(parse(code, { traverse(
parse(code, {
plugins: ["*"], plugins: ["*"],
}), visitor); }),
visitor,
);
}); });
} }
@ -56,14 +59,39 @@ describe("evaluation", function () {
addTest("'abc' === 'xyz' || 1 === 1", "LogicalExpression", true); addTest("'abc' === 'xyz' || 1 === 1", "LogicalExpression", true);
addTest("'abc' === 'xyz' || 1 === 10", "LogicalExpression", false); addTest("'abc' === 'xyz' || 1 === 10", "LogicalExpression", false);
addTest("'abc' === 'abc' || config.flag === 1", "LogicalExpression", true); addTest("'abc' === 'abc' || config.flag === 1", "LogicalExpression", true);
addTest("obj.a === 'abc' || config.flag === 1", "LogicalExpression", undefined, true); addTest(
"obj.a === 'abc' || config.flag === 1",
"LogicalExpression",
undefined,
true,
);
addTest("'abc' !== 'abc' && config.flag === 1", "LogicalExpression", false); addTest("'abc' !== 'abc' && config.flag === 1", "LogicalExpression", false);
addTest("obj.a === 'abc' && 1 === 1", "LogicalExpression", undefined, true); addTest("obj.a === 'abc' && 1 === 1", "LogicalExpression", undefined, true);
addTest("'abc' === 'abc' && (1 === 1 || config.flag)", "LogicalExpression", true); addTest(
addTest("'abc' === 'xyz' || (1 === 1 && config.flag)", "LogicalExpression", undefined, true); "'abc' === 'abc' && (1 === 1 || config.flag)",
addTest("'abc' === 'xyz' || (1 === 1 && 'four' === 'four')", "LogicalExpression", true); "LogicalExpression",
addTest("'abc' === 'abc' && (1 === 1 && 'four' === 'four')", "LogicalExpression", true); true,
);
addTest(
"'abc' === 'xyz' || (1 === 1 && config.flag)",
"LogicalExpression",
undefined,
true,
);
addTest(
"'abc' === 'xyz' || (1 === 1 && 'four' === 'four')",
"LogicalExpression",
true,
);
addTest(
"'abc' === 'abc' && (1 === 1 && 'four' === 'four')",
"LogicalExpression",
true,
);
addTest("({})", "ObjectExpression", {}); addTest("({})", "ObjectExpression", {});
addTest("({a: '1'})", "ObjectExpression", { a: "1" }); addTest("({a: '1'})", "ObjectExpression", { a: "1" });
addTest("({['a' + 'b']: 10 * 20, 'z': [1, 2, 3]})", "ObjectExpression", { ab: 200, z: [1, 2, 3] }); addTest("({['a' + 'b']: 10 * 20, 'z': [1, 2, 3]})", "ObjectExpression", {
ab: 200,
z: [1, 2, 3],
});
}); });

View File

@ -6,47 +6,41 @@ describe("option-manager", () => {
it("throws for babel 5 plugin", () => { it("throws for babel 5 plugin", () => {
return assert.throws(() => { return assert.throws(() => {
manageOptions({ manageOptions({
plugins: [ plugins: [({ Plugin }) => new Plugin("object-assign", {})],
({ Plugin }) => new Plugin("object-assign", {}),
],
}); });
}, /Babel 5 plugin is being run with Babel 6/); }, /Babel 5 plugin is being run with Babel 6/);
}); });
describe("mergeOptions", () => { describe("mergeOptions", () => {
it("throws for removed babel 5 options", () => { it("throws for removed babel 5 options", () => {
return assert.throws( return assert.throws(() => {
() => {
manageOptions({ manageOptions({
"randomOption": true, randomOption: true,
}); });
}, }, /Unknown option: base.randomOption/);
/Unknown option: base.randomOption/
);
}); });
it("throws for removed babel 5 options", () => { it("throws for removed babel 5 options", () => {
return assert.throws( return assert.throws(
() => { () => {
manageOptions({ manageOptions({
"auxiliaryComment": true, auxiliaryComment: true,
"blacklist": true, blacklist: true,
}); });
}, },
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/Using removed Babel 5 option: base.auxiliaryComment - Use `auxiliaryCommentBefore` or `auxiliaryCommentAfter`/ /Using removed Babel 5 option: base.auxiliaryComment - Use `auxiliaryCommentBefore` or `auxiliaryCommentAfter`/,
); );
}); });
it("throws for resolved but erroring preset", () => { it("throws for resolved but erroring preset", () => {
return assert.throws( return assert.throws(() => {
() => {
manageOptions({ manageOptions({
"presets": [path.join(__dirname, "fixtures/option-manager/not-a-preset")], presets: [
path.join(__dirname, "fixtures/option-manager/not-a-preset"),
],
}); });
}, }, /While processing: .*option-manager(?:\/|\\\\)not-a-preset\.js/);
/While processing: .*option-manager(?:\/|\\\\)not-a-preset\.js/
);
}); });
}); });
@ -54,7 +48,9 @@ describe("option-manager", () => {
function presetTest(name) { function presetTest(name) {
it(name, function() { it(name, function() {
const { options, passes } = manageOptions({ const { options, passes } = manageOptions({
"presets": [path.join(__dirname, "fixtures/option-manager/presets", name)], presets: [
path.join(__dirname, "fixtures/option-manager/presets", name),
],
}); });
assert.equal(true, Array.isArray(options.plugins)); assert.equal(true, Array.isArray(options.plugins));
@ -66,9 +62,15 @@ describe("option-manager", () => {
function presetThrowsTest(name, msg) { function presetThrowsTest(name, msg) {
it(name, function() { it(name, function() {
assert.throws(() => manageOptions({ assert.throws(
"presets": [path.join(__dirname, "fixtures/option-manager/presets", name)], () =>
}), msg); manageOptions({
presets: [
path.join(__dirname, "fixtures/option-manager/presets", name),
],
}),
msg,
);
}); });
} }
@ -77,7 +79,10 @@ describe("option-manager", () => {
presetTest("es2015_default_function"); presetTest("es2015_default_function");
presetTest("es2015_default_object"); presetTest("es2015_default_object");
presetThrowsTest("es2015_named", /Must export a default export when using ES6 modules/); presetThrowsTest(
"es2015_named",
/Must export a default export when using ES6 modules/,
);
presetThrowsTest("es2015_invalid", /Unsupported format: string/); presetThrowsTest("es2015_invalid", /Unsupported format: string/);
presetThrowsTest("es5_invalid", /Unsupported format: string/); presetThrowsTest("es5_invalid", /Unsupported format: string/);
}); });

View File

@ -7,13 +7,15 @@ describe("traversal path", function () {
const expectCode = "function foo() {}"; const expectCode = "function foo() {}";
const actualCode = transform(expectCode, { const actualCode = transform(expectCode, {
plugins: [new Plugin({ plugins: [
new Plugin({
visitor: { visitor: {
FunctionDeclaration: function(path) { FunctionDeclaration: function(path) {
path.replaceWithSourceString("console.whatever()"); path.replaceWithSourceString("console.whatever()");
}, },
}, },
})], }),
],
}).code; }).code;
chai.expect(actualCode).to.be.equal("console.whatever();"); chai.expect(actualCode).to.be.equal("console.whatever();");
@ -23,22 +25,26 @@ describe("traversal path", function () {
const expectCode = "var fn = () => true;"; const expectCode = "var fn = () => true;";
const actualCode = transform(expectCode, { const actualCode = transform(expectCode, {
plugins: [new Plugin({ plugins: [
new Plugin({
visitor: { visitor: {
ArrowFunctionExpression: function(path) { ArrowFunctionExpression: function(path) {
path.get("body").replaceWith({ path.get("body").replaceWith({
type: "BlockStatement", type: "BlockStatement",
body: [{ body: [
{
type: "ReturnStatement", type: "ReturnStatement",
argument: { argument: {
type: "BooleanLiteral", type: "BooleanLiteral",
value: true, value: true,
}, },
}], },
],
}); });
}, },
}, },
})], }),
],
}).code; }).code;
chai.expect(actualCode).to.be.equal("var fn = () => {\n return true;\n};"); chai.expect(actualCode).to.be.equal("var fn = () => {\n return true;\n};");
@ -48,7 +54,8 @@ describe("traversal path", function () {
const expectCode = "var fn = () => { return true; }"; const expectCode = "var fn = () => { return true; }";
const actualCode = transform(expectCode, { const actualCode = transform(expectCode, {
plugins: [new Plugin({ plugins: [
new Plugin({
visitor: { visitor: {
ArrowFunctionExpression: function(path) { ArrowFunctionExpression: function(path) {
path.get("body").replaceWith({ path.get("body").replaceWith({
@ -57,7 +64,8 @@ describe("traversal path", function () {
}); });
}, },
}, },
})], }),
],
}).code; }).code;
chai.expect(actualCode).to.be.equal("var fn = () => true;"); chai.expect(actualCode).to.be.equal("var fn = () => true;");
@ -67,23 +75,27 @@ describe("traversal path", function () {
const expectCode = "for (KEY in right);"; const expectCode = "for (KEY in right);";
const actualCode = transform(expectCode, { const actualCode = transform(expectCode, {
plugins: [new Plugin({ plugins: [
new Plugin({
visitor: { visitor: {
ForInStatement: function(path) { ForInStatement: function(path) {
path.get("left").replaceWith({ path.get("left").replaceWith({
type: "VariableDeclaration", type: "VariableDeclaration",
kind: "var", kind: "var",
declarations: [{ declarations: [
{
type: "VariableDeclarator", type: "VariableDeclarator",
id: { id: {
type: "Identifier", type: "Identifier",
name: "KEY", name: "KEY",
}, },
}], },
],
}); });
}, },
}, },
})], }),
],
}).code; }).code;
chai.expect(actualCode).to.be.equal("for (var KEY in right);"); chai.expect(actualCode).to.be.equal("for (var KEY in right);");
@ -93,7 +105,8 @@ describe("traversal path", function () {
const expectCode = "for (var KEY in right);"; const expectCode = "for (var KEY in right);";
const actualCode = transform(expectCode, { const actualCode = transform(expectCode, {
plugins: [new Plugin({ plugins: [
new Plugin({
visitor: { visitor: {
ForInStatement: function(path) { ForInStatement: function(path) {
path.get("left").replaceWith({ path.get("left").replaceWith({
@ -102,7 +115,8 @@ describe("traversal path", function () {
}); });
}, },
}, },
})], }),
],
}).code; }).code;
chai.expect(actualCode).to.be.equal("for (KEY in right);"); chai.expect(actualCode).to.be.equal("for (KEY in right);");
@ -112,23 +126,27 @@ describe("traversal path", function () {
const expectCode = "for (KEY;;);"; const expectCode = "for (KEY;;);";
const actualCode = transform(expectCode, { const actualCode = transform(expectCode, {
plugins: [new Plugin({ plugins: [
new Plugin({
visitor: { visitor: {
ForStatement: function(path) { ForStatement: function(path) {
path.get("init").replaceWith({ path.get("init").replaceWith({
type: "VariableDeclaration", type: "VariableDeclaration",
kind: "var", kind: "var",
declarations: [{ declarations: [
{
type: "VariableDeclarator", type: "VariableDeclarator",
id: { id: {
type: "Identifier", type: "Identifier",
name: "KEY", name: "KEY",
}, },
}], },
],
}); });
}, },
}, },
})], }),
],
}).code; }).code;
chai.expect(actualCode).to.be.equal("for (var KEY;;);"); chai.expect(actualCode).to.be.equal("for (var KEY;;);");
@ -138,7 +156,8 @@ describe("traversal path", function () {
const expectCode = "for (var KEY;;);"; const expectCode = "for (var KEY;;);";
const actualCode = transform(expectCode, { const actualCode = transform(expectCode, {
plugins: [new Plugin({ plugins: [
new Plugin({
visitor: { visitor: {
ForStatement: function(path) { ForStatement: function(path) {
path.get("init").replaceWith({ path.get("init").replaceWith({
@ -147,7 +166,8 @@ describe("traversal path", function () {
}); });
}, },
}, },
})], }),
],
}).code; }).code;
chai.expect(actualCode).to.be.equal("for (KEY;;);"); chai.expect(actualCode).to.be.equal("for (KEY;;);");

View File

@ -20,9 +20,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["module:preset"],
"module:preset",
],
}); });
}); });
@ -32,9 +30,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["module:plugin"],
"module:plugin",
],
}); });
}); });
@ -44,9 +40,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["mod"],
"mod",
],
}); });
}); });
@ -56,9 +50,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["mod"],
"mod",
],
}); });
}); });
@ -68,9 +60,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["babel-preset-mod"],
"babel-preset-mod",
],
}); });
}); });
@ -80,9 +70,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["babel-plugin-mod"],
"babel-plugin-mod",
],
}); });
}); });
@ -92,9 +80,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["@babel/foo"],
"@babel/foo",
],
}); });
}); });
@ -104,9 +90,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["@babel/foo"],
"@babel/foo",
],
}); });
}); });
@ -116,9 +100,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["@babel/preset-foo"],
"@babel/preset-foo",
],
}); });
}); });
@ -128,9 +110,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["@babel/plugin-foo"],
"@babel/plugin-foo",
],
}); });
}); });
@ -140,9 +120,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["@foo/mod"],
"@foo/mod",
],
}); });
}); });
@ -152,9 +130,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["@foo/mod"],
"@foo/mod",
],
}); });
}); });
@ -164,9 +140,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["@foo/babel-preset-mod"],
"@foo/babel-preset-mod",
],
}); });
}); });
@ -176,9 +150,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["@foo/babel-plugin-mod"],
"@foo/babel-plugin-mod",
],
}); });
}); });
@ -188,9 +160,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["./dir/preset.js"],
"./dir/preset.js",
],
}); });
}); });
@ -200,9 +170,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["./dir/plugin.js"],
"./dir/plugin.js",
],
}); });
}); });
@ -212,9 +180,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["mod/preset"],
"mod/preset",
],
}); });
}); });
@ -224,9 +190,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["mod/plugin"],
"mod/plugin",
],
}); });
}); });
@ -236,9 +200,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["@foo/mod/preset"],
"@foo/mod/preset",
],
}); });
}); });
@ -248,9 +210,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["@foo/mod/plugin"],
"@foo/mod/plugin",
],
}); });
}); });
@ -260,9 +220,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["@babel/mod/preset"],
"@babel/mod/preset",
],
}); });
}); });
@ -272,9 +230,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["@babel/mod/plugin"],
"@babel/mod/plugin",
],
}); });
}); });
@ -285,9 +241,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["foo"],
"foo",
],
}); });
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
}, /Cannot find module 'babel-preset-foo'.*\n- If you want to resolve "foo", use "module:foo"/); }, /Cannot find module 'babel-preset-foo'.*\n- If you want to resolve "foo", use "module:foo"/);
@ -300,9 +254,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["foo"],
"foo",
],
}); });
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
}, /Cannot find module 'babel-plugin-foo'.*\n- If you want to resolve "foo", use "module:foo"/); }, /Cannot find module 'babel-plugin-foo'.*\n- If you want to resolve "foo", use "module:foo"/);
@ -315,9 +267,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["foo"],
"foo",
],
}); });
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
}, /Cannot find module 'babel-preset-foo'.*\n- Did you mean "@babel\/foo"\?/); }, /Cannot find module 'babel-preset-foo'.*\n- Did you mean "@babel\/foo"\?/);
@ -330,9 +280,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["foo"],
"foo",
],
}); });
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
}, /Cannot find module 'babel-plugin-foo'.*\n- Did you mean "@babel\/foo"\?/); }, /Cannot find module 'babel-plugin-foo'.*\n- Did you mean "@babel\/foo"\?/);
@ -345,9 +293,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["testplugin"],
"testplugin",
],
}); });
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
}, /Cannot find module 'babel-preset-testplugin'.*\n- Did you accidentally pass a preset as a plugin\?/); }, /Cannot find module 'babel-preset-testplugin'.*\n- Did you accidentally pass a preset as a plugin\?/);
@ -360,9 +306,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["testpreset"],
"testpreset",
],
}); });
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
}, /Cannot find module 'babel-plugin-testpreset'.*\n- Did you accidentally pass a plugin as a preset\?/); }, /Cannot find module 'babel-plugin-testpreset'.*\n- Did you accidentally pass a plugin as a preset\?/);
@ -375,9 +319,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
presets: [ presets: ["foo"],
"foo",
],
}); });
}, /Cannot find module 'babel-preset-foo'/); }, /Cannot find module 'babel-preset-foo'/);
}); });
@ -389,9 +331,7 @@ describe("addon resolution", function () {
babel.transform("", { babel.transform("", {
filename: "filename.js", filename: "filename.js",
babelrc: false, babelrc: false,
plugins: [ plugins: ["foo"],
"foo",
],
}); });
}, /Cannot find module 'babel-plugin-foo'/); }, /Cannot find module 'babel-plugin-foo'/);
}); });

View File

@ -54,7 +54,7 @@ export default class Buffer {
configurable: true, configurable: true,
enumerable: true, enumerable: true,
get() { get() {
return this.map = map.get(); return (this.map = map.get());
}, },
set(value) { set(value) {
Object.defineProperty(this, "map", { value, writable: true }); Object.defineProperty(this, "map", { value, writable: true });
@ -81,7 +81,11 @@ export default class Buffer {
queue(str: string): void { queue(str: string): void {
// Drop trailing spaces when a newline is inserted. // Drop trailing spaces when a newline is inserted.
if (str === "\n") while (this._queue.length > 0 && SPACES_RE.test(this._queue[0][0])) this._queue.shift(); if (str === "\n") {
while (this._queue.length > 0 && SPACES_RE.test(this._queue[0][0])) {
this._queue.shift();
}
}
const { line, column, filename, identifierName } = this._sourcePosition; const { line, column, filename, identifierName } = this._sourcePosition;
this._queue.unshift([str, line, column, identifierName, filename]); this._queue.unshift([str, line, column, identifierName, filename]);
@ -89,13 +93,26 @@ export default class Buffer {
_flush(): void { _flush(): void {
let item; let item;
while (item = this._queue.pop()) this._append(...item); while ((item = this._queue.pop())) this._append(...item);
} }
_append(str: string, line: number, column: number, identifierName: ?string, filename: ?string): void { _append(
str: string,
line: number,
column: number,
identifierName: ?string,
filename: ?string,
): void {
// If there the line is ending, adding a new mapping marker is redundant // If there the line is ending, adding a new mapping marker is redundant
if (this._map && str[0] !== "\n") { if (this._map && str[0] !== "\n") {
this._map.mark(this._position.line, this._position.column, line, column, identifierName, filename); this._map.mark(
this._position.line,
this._position.column,
line,
column,
identifierName,
filename,
);
} }
this._buf.push(str); this._buf.push(str);
@ -112,11 +129,15 @@ export default class Buffer {
} }
removeTrailingNewline(): void { removeTrailingNewline(): void {
if (this._queue.length > 0 && this._queue[0][0] === "\n") this._queue.shift(); if (this._queue.length > 0 && this._queue[0][0] === "\n") {
this._queue.shift();
}
} }
removeLastSemicolon(): void { removeLastSemicolon(): void {
if (this._queue.length > 0 && this._queue[0][0] === ";") this._queue.shift(); if (this._queue.length > 0 && this._queue[0][0] === ";") {
this._queue.shift();
}
} }
endsWith(suffix: string): boolean { endsWith(suffix: string): boolean {
@ -133,7 +154,8 @@ export default class Buffer {
return last === suffix; return last === suffix;
} }
const end = this._last + this._queue.reduce((acc, item) => item[0] + acc, ""); const end =
this._last + this._queue.reduce((acc, item) => item[0] + acc, "");
if (suffix.length <= end.length) { if (suffix.length <= end.length) {
return end.slice(-suffix.length) === suffix; return end.slice(-suffix.length) === suffix;
} }
@ -157,10 +179,10 @@ export default class Buffer {
const pos = loc ? loc[prop] : null; const pos = loc ? loc[prop] : null;
this._sourcePosition.identifierName = loc && loc.identifierName || null; this._sourcePosition.identifierName = (loc && loc.identifierName) || null;
this._sourcePosition.line = pos ? pos.line : null; this._sourcePosition.line = pos ? pos.line : null;
this._sourcePosition.column = pos ? pos.column : null; this._sourcePosition.column = pos ? pos.column : null;
this._sourcePosition.filename = loc && loc.filename || null; this._sourcePosition.filename = (loc && loc.filename) || null;
} }
/** /**
@ -190,7 +212,9 @@ export default class Buffer {
const extra = this._queue.reduce((acc, item) => item[0] + acc, ""); const extra = this._queue.reduce((acc, item) => item[0] + acc, "");
const lastIndex = extra.lastIndexOf("\n"); const lastIndex = extra.lastIndexOf("\n");
return lastIndex === -1 ? this._position.column + extra.length : (extra.length - 1 - lastIndex); return lastIndex === -1
? this._position.column + extra.length
: extra.length - 1 - lastIndex;
} }
getCurrentLine(): number { getCurrentLine(): number {

View File

@ -1,9 +1,12 @@
import * as t from "babel-types"; import * as t from "babel-types";
import * as n from "../node"; import * as n from "../node";
export function UnaryExpression(node: Object) { export function UnaryExpression(node: Object) {
if (node.operator === "void" || node.operator === "delete" || node.operator === "typeof") { if (
node.operator === "void" ||
node.operator === "delete" ||
node.operator === "typeof"
) {
this.word(node.operator); this.word(node.operator);
this.space(); this.space();
} else { } else {
@ -51,12 +54,16 @@ export function NewExpression(node: Object, parent: Object) {
this.word("new"); this.word("new");
this.space(); this.space();
this.print(node.callee, node); this.print(node.callee, node);
if (this.format.minified && if (
this.format.minified &&
node.arguments.length === 0 && node.arguments.length === 0 &&
!node.optional && !node.optional &&
!t.isCallExpression(parent, { callee: node }) && !t.isCallExpression(parent, { callee: node }) &&
!t.isMemberExpression(parent) && !t.isMemberExpression(parent) &&
!t.isNewExpression(parent)) return; !t.isNewExpression(parent)
) {
return;
}
if (node.optional) { if (node.optional) {
this.token("?."); this.token("?.");
@ -164,7 +171,9 @@ export function AssignmentPattern(node: Object) {
export function AssignmentExpression(node: Object, parent: Object) { export function AssignmentExpression(node: Object, parent: Object) {
// Somewhere inside a for statement `init` node but doesn't usually // Somewhere inside a for statement `init` node but doesn't usually
// needs a paren except for `in` expressions: `for (a in b ? a : b;;)` // needs a paren except for `in` expressions: `for (a in b ? a : b;;)`
const parens = this.inForStatementInitCounter && node.operator === "in" && const parens =
this.inForStatementInitCounter &&
node.operator === "in" &&
!n.needsParens(node, parent); !n.needsParens(node, parent);
if (parens) { if (parens) {

View File

@ -159,7 +159,10 @@ export function FunctionTypeAnnotation(node: Object, parent: Object) {
this.token(")"); this.token(")");
// this node type is overloaded, not sure why but it makes it EXTREMELY annoying // this node type is overloaded, not sure why but it makes it EXTREMELY annoying
if (parent.type === "ObjectTypeCallProperty" || parent.type === "DeclareFunction") { if (
parent.type === "ObjectTypeCallProperty" ||
parent.type === "DeclareFunction"
) {
this.token(":"); this.token(":");
} else { } else {
this.space(); this.space();
@ -183,7 +186,10 @@ export function InterfaceExtends(node: Object) {
this.print(node.typeParameters, node); this.print(node.typeParameters, node);
} }
export { InterfaceExtends as ClassImplements, InterfaceExtends as GenericTypeAnnotation }; export {
InterfaceExtends as ClassImplements,
InterfaceExtends as GenericTypeAnnotation,
};
export function _interfaceish(node: Object) { export function _interfaceish(node: Object) {
this.print(node.id, node); this.print(node.id, node);

View File

@ -4,7 +4,7 @@ export function _params(node: Object) {
this.print(node.typeParameters, node); this.print(node.typeParameters, node);
this.token("("); this.token("(");
this.printList(node.params, node, { this.printList(node.params, node, {
iterator: (node) => { iterator: node => {
if (node.optional) this.token("?"); if (node.optional) this.token("?");
this.print(node.typeAnnotation, node); this.print(node.typeAnnotation, node);
}, },
@ -79,7 +79,11 @@ export function ArrowFunctionExpression(node: Object) {
const firstParam = node.params[0]; const firstParam = node.params[0];
if (node.params.length === 1 && t.isIdentifier(firstParam) && !hasTypes(node, firstParam)) { if (
node.params.length === 1 &&
t.isIdentifier(firstParam) &&
!hasTypes(node, firstParam)
) {
this.print(firstParam, node); this.print(firstParam, node);
} else { } else {
this._params(node); this._params(node);
@ -93,6 +97,11 @@ export function ArrowFunctionExpression(node: Object) {
} }
function hasTypes(node, param) { function hasTypes(node, param) {
return node.typeParameters || node.returnType || param.typeAnnotation || param.optional || return (
param.trailingComments; node.typeParameters ||
node.returnType ||
param.typeAnnotation ||
param.optional ||
param.trailingComments
);
} }

View File

@ -91,7 +91,10 @@ function ExportDeclaration(node: Object) {
let hasSpecial = false; let hasSpecial = false;
while (true) { while (true) {
const first = specifiers[0]; const first = specifiers[0];
if (t.isExportDefaultSpecifier(first) || t.isExportNamespaceSpecifier(first)) { if (
t.isExportDefaultSpecifier(first) ||
t.isExportNamespaceSpecifier(first)
) {
hasSpecial = true; hasSpecial = true;
this.print(specifiers.shift(), node); this.print(specifiers.shift(), node);
if (specifiers.length) { if (specifiers.length) {
@ -138,7 +141,10 @@ export function ImportDeclaration(node: Object) {
// print "special" specifiers first // print "special" specifiers first
while (true) { while (true) {
const first = specifiers[0]; const first = specifiers[0];
if (t.isImportDefaultSpecifier(first) || t.isImportNamespaceSpecifier(first)) { if (
t.isImportDefaultSpecifier(first) ||
t.isImportNamespaceSpecifier(first)
) {
this.print(specifiers.shift(), node); this.print(specifiers.shift(), node);
if (specifiers.length) { if (specifiers.length) {
this.token(","); this.token(",");

View File

@ -17,7 +17,8 @@ export function IfStatement(node: Object) {
this.token(")"); this.token(")");
this.space(); this.space();
const needsBlock = node.alternate && t.isIfStatement(getLastStatement(node.consequent)); const needsBlock =
node.alternate && t.isIfStatement(getLastStatement(node.consequent));
if (needsBlock) { if (needsBlock) {
this.token("{"); this.token("{");
this.newline(); this.newline();
@ -261,7 +262,10 @@ export function VariableDeclaration(node: Object, parent: Object) {
let separator; let separator;
if (hasInits) { if (hasInits) {
separator = node.kind === "const" ? constDeclarationIndent : variableDeclarationIndent; separator =
node.kind === "const"
? constDeclarationIndent
: variableDeclarationIndent;
} }
// //

View File

@ -10,9 +10,7 @@ export function RestElement(node: Object) {
this.print(node.argument, node); this.print(node.argument, node);
} }
export { export { RestElement as SpreadElement };
RestElement as SpreadElement,
};
export function ObjectExpression(node: Object) { export function ObjectExpression(node: Object) {
const props = node.properties; const props = node.properties;
@ -45,8 +43,11 @@ export function ObjectProperty(node: Object) {
this.token("]"); this.token("]");
} else { } else {
// print `({ foo: foo = 5 } = {})` as `({ foo = 5 } = {});` // print `({ foo: foo = 5 } = {})` as `({ foo = 5 } = {});`
if (t.isAssignmentPattern(node.value) && t.isIdentifier(node.key) && if (
node.key.name === node.value.left.name) { t.isAssignmentPattern(node.value) &&
t.isIdentifier(node.key) &&
node.key.name === node.value.left.name
) {
this.print(node.value, node); this.print(node.value, node);
return; return;
} }
@ -54,10 +55,12 @@ export function ObjectProperty(node: Object) {
this.print(node.key, node); this.print(node.key, node);
// shorthand! // shorthand!
if (node.shorthand && if (
node.shorthand &&
(t.isIdentifier(node.key) && (t.isIdentifier(node.key) &&
t.isIdentifier(node.value) && t.isIdentifier(node.value) &&
node.key.name === node.value.name)) { node.key.name === node.value.name)
) {
return; return;
} }
} }

View File

@ -61,9 +61,13 @@ function normalizeOptions(code, opts): Format {
if (format.minified) { if (format.minified) {
format.compact = true; format.compact = true;
format.shouldPrintComment = format.shouldPrintComment || (() => format.comments); format.shouldPrintComment =
format.shouldPrintComment || (() => format.comments);
} else { } else {
format.shouldPrintComment = format.shouldPrintComment || ((value) => format.comments || format.shouldPrintComment =
format.shouldPrintComment ||
(value =>
format.comments ||
(value.indexOf("@license") >= 0 || value.indexOf("@preserve") >= 0)); (value.indexOf("@license") >= 0 || value.indexOf("@preserve") >= 0));
} }
@ -71,7 +75,9 @@ function normalizeOptions(code, opts): Format {
format.compact = code.length > 500_000; // 500KB format.compact = code.length > 500_000; // 500KB
if (format.compact) { if (format.compact) {
console.error("[BABEL] " + messages.get("codeGeneratorDeopt", opts.filename, "500KB")); console.error(
"[BABEL] " + messages.get("codeGeneratorDeopt", opts.filename, "500KB"),
);
} }
} }

View File

@ -7,15 +7,16 @@ function expandAliases(obj) {
function add(type, func) { function add(type, func) {
const fn = newObj[type]; const fn = newObj[type];
newObj[type] = fn ? function(node, parent, stack) { newObj[type] = fn
? function(node, parent, stack) {
const result = fn(node, parent, stack); const result = fn(node, parent, stack);
return result == null ? func(node, parent, stack) : result; return result == null ? func(node, parent, stack) : result;
} : func; }
: func;
} }
for (const type of Object.keys(obj)) { for (const type of Object.keys(obj)) {
const aliases = t.FLIPPED_ALIAS_KEYS[type]; const aliases = t.FLIPPED_ALIAS_KEYS[type];
if (aliases) { if (aliases) {
for (const alias of aliases) { for (const alias of aliases) {
@ -46,8 +47,10 @@ function isOrHasCallExpression(node) {
} }
if (t.isMemberExpression(node)) { if (t.isMemberExpression(node)) {
return isOrHasCallExpression(node.object) || return (
(!node.computed && isOrHasCallExpression(node.property)); isOrHasCallExpression(node.object) ||
(!node.computed && isOrHasCallExpression(node.property))
);
} else { } else {
return false; return false;
} }

View File

@ -38,11 +38,19 @@ export function UpdateExpression(node: Object, parent: Object): boolean {
return t.isMemberExpression(parent) && parent.object === node; return t.isMemberExpression(parent) && parent.object === node;
} }
export function ObjectExpression(node: Object, parent: Object, printStack: Array<Object>): boolean { export function ObjectExpression(
node: Object,
parent: Object,
printStack: Array<Object>,
): boolean {
return isFirstInStatement(printStack, { considerArrow: true }); return isFirstInStatement(printStack, { considerArrow: true });
} }
export function DoExpression(node: Object, parent: Object, printStack: Array<Object>): boolean { export function DoExpression(
node: Object,
parent: Object,
printStack: Array<Object>,
): boolean {
return isFirstInStatement(printStack); return isFirstInStatement(printStack);
} }
@ -55,7 +63,8 @@ export function Binary(node: Object, parent: Object): boolean {
} }
if ( if (
((t.isCallExpression(parent) || t.isNewExpression(parent)) && parent.callee === node) || ((t.isCallExpression(parent) || t.isNewExpression(parent)) &&
parent.callee === node) ||
t.isUnaryLike(parent) || t.isUnaryLike(parent) ||
(t.isMemberExpression(parent) && parent.object === node) || (t.isMemberExpression(parent) && parent.object === node) ||
t.isAwaitExpression(parent) t.isAwaitExpression(parent)
@ -72,7 +81,9 @@ export function Binary(node: Object, parent: Object): boolean {
if ( if (
// Logical expressions with the same precedence don't need parens. // Logical expressions with the same precedence don't need parens.
(parentPos === nodePos && parent.right === node && !t.isLogicalExpression(parent)) || (parentPos === nodePos &&
parent.right === node &&
!t.isLogicalExpression(parent)) ||
parentPos > nodePos parentPos > nodePos
) { ) {
return true; return true;
@ -85,11 +96,13 @@ export function Binary(node: Object, parent: Object): boolean {
export function BinaryExpression(node: Object, parent: Object): boolean { export function BinaryExpression(node: Object, parent: Object): boolean {
// let i = (1 in []); // let i = (1 in []);
// for ((1 in []);;); // for ((1 in []);;);
return node.operator === "in" && (t.isVariableDeclarator(parent) || t.isFor(parent)); return (
node.operator === "in" &&
(t.isVariableDeclarator(parent) || t.isFor(parent))
);
} }
export function SequenceExpression(node: Object, parent: Object): boolean { export function SequenceExpression(node: Object, parent: Object): boolean {
if ( if (
// Although parentheses wouldn"t hurt around sequence // Although parentheses wouldn"t hurt around sequence
// expressions in the head of for loops, traditional style // expressions in the head of for loops, traditional style
@ -113,29 +126,40 @@ export function SequenceExpression(node: Object, parent: Object): boolean {
} }
export function YieldExpression(node: Object, parent: Object): boolean { export function YieldExpression(node: Object, parent: Object): boolean {
return t.isBinary(parent) || return (
t.isBinary(parent) ||
t.isUnaryLike(parent) || t.isUnaryLike(parent) ||
t.isCallExpression(parent) || t.isCallExpression(parent) ||
t.isMemberExpression(parent) || t.isMemberExpression(parent) ||
t.isNewExpression(parent) || t.isNewExpression(parent) ||
(t.isConditionalExpression(parent) && node === parent.test); (t.isConditionalExpression(parent) && node === parent.test)
);
} }
export { YieldExpression as AwaitExpression }; export { YieldExpression as AwaitExpression };
export function ClassExpression(node: Object, parent: Object, printStack: Array<Object>): boolean { export function ClassExpression(
node: Object,
parent: Object,
printStack: Array<Object>,
): boolean {
return isFirstInStatement(printStack, { considerDefaultExports: true }); return isFirstInStatement(printStack, { considerDefaultExports: true });
} }
export function UnaryLike(node: Object, parent: Object): boolean { export function UnaryLike(node: Object, parent: Object): boolean {
return t.isMemberExpression(parent, { object: node }) || return (
t.isMemberExpression(parent, { object: node }) ||
t.isCallExpression(parent, { callee: node }) || t.isCallExpression(parent, { callee: node }) ||
t.isNewExpression(parent, { callee: node }) || t.isNewExpression(parent, { callee: node }) ||
t.isBinaryExpression(parent, { operator: "**", left: node }); t.isBinaryExpression(parent, { operator: "**", left: node })
);
} }
export function FunctionExpression(node: Object, parent: Object, printStack: Array<Object>): boolean { export function FunctionExpression(
node: Object,
parent: Object,
printStack: Array<Object>,
): boolean {
return isFirstInStatement(printStack, { considerDefaultExports: true }); return isFirstInStatement(printStack, { considerDefaultExports: true });
} }
@ -167,10 +191,10 @@ export function AssignmentExpression(node: Object): boolean {
// Walk up the print stack to deterimine if our node can come first // Walk up the print stack to deterimine if our node can come first
// in statement. // in statement.
function isFirstInStatement(printStack: Array<Object>, { function isFirstInStatement(
considerArrow = false, printStack: Array<Object>,
considerDefaultExports = false, { considerArrow = false, considerDefaultExports = false } = {},
} = {}): boolean { ): boolean {
let i = printStack.length - 1; let i = printStack.length - 1;
let node = printStack[i]; let node = printStack[i];
i--; i--;
@ -179,8 +203,9 @@ function isFirstInStatement(printStack: Array<Object>, {
if ( if (
t.isExpressionStatement(parent, { expression: node }) || t.isExpressionStatement(parent, { expression: node }) ||
t.isTaggedTemplateExpression(parent) || t.isTaggedTemplateExpression(parent) ||
considerDefaultExports && t.isExportDefaultDeclaration(parent, { declaration: node }) || (considerDefaultExports &&
considerArrow && t.isArrowFunctionExpression(parent, { body: node }) t.isExportDefaultDeclaration(parent, { declaration: node })) ||
(considerArrow && t.isArrowFunctionExpression(parent, { body: node }))
) { ) {
return true; return true;
} }

View File

@ -3,7 +3,7 @@ import * as t from "babel-types";
type WhitespaceObject = { type WhitespaceObject = {
before?: boolean, before?: boolean,
after?: boolean after?: boolean,
}; };
/** /**
@ -45,15 +45,22 @@ function isHelper(node) {
} else if (t.isCallExpression(node)) { } else if (t.isCallExpression(node)) {
return isHelper(node.callee); return isHelper(node.callee);
} else if (t.isBinary(node) || t.isAssignmentExpression(node)) { } else if (t.isBinary(node) || t.isAssignmentExpression(node)) {
return (t.isIdentifier(node.left) && isHelper(node.left)) || isHelper(node.right); return (
(t.isIdentifier(node.left) && isHelper(node.left)) || isHelper(node.right)
);
} else { } else {
return false; return false;
} }
} }
function isType(node) { function isType(node) {
return t.isLiteral(node) || t.isObjectExpression(node) || t.isArrayExpression(node) || return (
t.isIdentifier(node) || t.isMemberExpression(node); t.isLiteral(node) ||
t.isObjectExpression(node) ||
t.isArrayExpression(node) ||
t.isIdentifier(node) ||
t.isMemberExpression(node)
);
} }
/** /**
@ -61,7 +68,6 @@ function isType(node) {
*/ */
export const nodes = { export const nodes = {
/** /**
* Test if AssignmentExpression needs whitespace. * Test if AssignmentExpression needs whitespace.
*/ */
@ -164,9 +170,10 @@ export const nodes = {
* Test if Property needs whitespace. * Test if Property needs whitespace.
*/ */
nodes.ObjectProperty = nodes.ObjectProperty = nodes.ObjectTypeProperty = nodes.ObjectMethod = function(
nodes.ObjectTypeProperty = node: Object,
nodes.ObjectMethod = function (node: Object, parent): ?WhitespaceObject { parent,
): ?WhitespaceObject {
if (parent.properties[0] === node) { if (parent.properties[0] === node) {
return { return {
before: true, before: true,
@ -179,7 +186,6 @@ nodes.ObjectMethod = function (node: Object, parent): ?WhitespaceObject {
*/ */
export const list = { export const list = {
/** /**
* Return VariableDeclaration declarations init properties. * Return VariableDeclaration declarations init properties.
*/ */

View File

@ -14,21 +14,21 @@ const ZERO_DECIMAL_INTEGER = /\.0+$/;
const NON_DECIMAL_LITERAL = /^0[box]/; const NON_DECIMAL_LITERAL = /^0[box]/;
export type Format = { export type Format = {
shouldPrintComment: (comment: string) => boolean; shouldPrintComment: (comment: string) => boolean,
retainLines: boolean; retainLines: boolean,
retainFunctionParens: boolean; retainFunctionParens: boolean,
comments: boolean; comments: boolean,
auxiliaryCommentBefore: string; auxiliaryCommentBefore: string,
auxiliaryCommentAfter: string; auxiliaryCommentAfter: string,
compact: boolean | "auto"; compact: boolean | "auto",
minified: boolean; minified: boolean,
quotes: "single" | "double"; quotes: "single" | "double",
concise: boolean; concise: boolean,
indent: { indent: {
adjustMultilineComment: boolean; adjustMultilineComment: boolean,
style: string; style: string,
base: number; base: number,
} },
}; };
export default class Printer { export default class Printer {
@ -107,7 +107,10 @@ export default class Printer {
space(force: boolean = false): void { space(force: boolean = false): void {
if (this.format.compact) return; if (this.format.compact) return;
if ((this._buf.hasContent() && !this.endsWith(" ") && !this.endsWith("\n")) || force) { if (
(this._buf.hasContent() && !this.endsWith(" ") && !this.endsWith("\n")) ||
force
) {
this._space(); this._space();
} }
} }
@ -149,14 +152,14 @@ export default class Printer {
token(str: string): void { token(str: string): void {
// space is mandatory to avoid outputting <!-- // space is mandatory to avoid outputting <!--
// http://javascript.spec.whatwg.org/#comment-syntax // http://javascript.spec.whatwg.org/#comment-syntax
if ((str === "--" && this.endsWith("!")) || if (
(str === "--" && this.endsWith("!")) ||
// Need spaces for operators of the same kind to avoid: `a+++b` // Need spaces for operators of the same kind to avoid: `a+++b`
(str[0] === "+" && this.endsWith("+")) || (str[0] === "+" && this.endsWith("+")) ||
(str[0] === "-" && this.endsWith("-")) || (str[0] === "-" && this.endsWith("-")) ||
// Needs spaces to avoid changing '34' to '34.', which would still be a valid number. // Needs spaces to avoid changing '34' to '34.', which would still be a valid number.
(str[0] === "." && this._endsWithInteger)) { (str[0] === "." && this._endsWithInteger)
) {
this._space(); this._space();
} }
@ -294,9 +297,9 @@ export default class Printer {
*/ */
startTerminatorless(): Object { startTerminatorless(): Object {
return this._parenPushNewlineState = { return (this._parenPushNewlineState = {
printed: false, printed: false,
}; });
} }
/** /**
@ -322,7 +325,11 @@ export default class Printer {
const printMethod = this[node.type]; const printMethod = this[node.type];
if (!printMethod) { if (!printMethod) {
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
throw new ReferenceError(`unknown node of type ${JSON.stringify(node.type)} with constructor ${JSON.stringify(node && node.constructor.name)}`); throw new ReferenceError(
`unknown node of type ${JSON.stringify(
node.type,
)} with constructor ${JSON.stringify(node && node.constructor.name)}`,
);
} }
this._printStack.push(node); this._printStack.push(node);
@ -335,7 +342,8 @@ export default class Printer {
if ( if (
this.format.retainFunctionParens && this.format.retainFunctionParens &&
node.type === "FunctionExpression" && node.type === "FunctionExpression" &&
node.extra && node.extra.parenthesized node.extra &&
node.extra.parenthesized
) { ) {
needsParens = true; needsParens = true;
} }
@ -343,7 +351,7 @@ export default class Printer {
this._printLeadingComments(node, parent); this._printLeadingComments(node, parent);
const loc = (t.isProgram(node) || t.isFile(node)) ? null : node.loc; const loc = t.isProgram(node) || t.isFile(node) ? null : node.loc;
this.withSource("start", loc, () => { this.withSource("start", loc, () => {
this[node.type](node, parent); this[node.type](node, parent);
}); });
@ -392,7 +400,12 @@ export default class Printer {
getPossibleRaw(node) { getPossibleRaw(node) {
const extra = node.extra; const extra = node.extra;
if (extra && extra.raw != null && extra.rawValue != null && node.value === extra.rawValue) { if (
extra &&
extra.raw != null &&
extra.rawValue != null &&
node.value === extra.rawValue
) {
return extra.raw; return extra.raw;
} }
} }
@ -490,14 +503,24 @@ export default class Printer {
// user node // user node
if (leading) { if (leading) {
const comments = node.leadingComments; const comments = node.leadingComments;
const comment = comments && find(comments, (comment) => const comment =
!!comment.loc && this.format.shouldPrintComment(comment.value)); comments &&
find(
comments,
comment =>
!!comment.loc && this.format.shouldPrintComment(comment.value),
);
lines = this._whitespace.getNewlinesBefore(comment || node); lines = this._whitespace.getNewlinesBefore(comment || node);
} else { } else {
const comments = node.trailingComments; const comments = node.trailingComments;
const comment = comments && findLast(comments, (comment) => const comment =
!!comment.loc && this.format.shouldPrintComment(comment.value)); comments &&
findLast(
comments,
comment =>
!!comment.loc && this.format.shouldPrintComment(comment.value),
);
lines = this._whitespace.getNewlinesAfter(comment || node); lines = this._whitespace.getNewlinesAfter(comment || node);
} }
@ -520,7 +543,9 @@ export default class Printer {
_getComments(leading, node) { _getComments(leading, node) {
// Note, we use a boolean flag here instead of passing in the attribute name as it is faster // Note, we use a boolean flag here instead of passing in the attribute name as it is faster
// because this is called extremely frequently. // because this is called extremely frequently.
return (node && (leading ? node.leadingComments : node.trailingComments)) || []; return (
(node && (leading ? node.leadingComments : node.trailingComments)) || []
);
} }
_printComment(comment) { _printComment(comment) {
@ -539,21 +564,32 @@ export default class Printer {
} }
// whitespace before // whitespace before
this.newline(this._whitespace ? this._whitespace.getNewlinesBefore(comment) : 0); this.newline(
this._whitespace ? this._whitespace.getNewlinesBefore(comment) : 0,
);
if (!this.endsWith("[") && !this.endsWith("{")) this.space(); if (!this.endsWith("[") && !this.endsWith("{")) this.space();
let val = comment.type === "CommentLine" ? `//${comment.value}\n` : `/*${comment.value}*/`; let val =
comment.type === "CommentLine"
? `//${comment.value}\n`
: `/*${comment.value}*/`;
// //
if (comment.type === "CommentBlock" && this.format.indent.adjustMultilineComment) { if (
comment.type === "CommentBlock" &&
this.format.indent.adjustMultilineComment
) {
const offset = comment.loc && comment.loc.start.column; const offset = comment.loc && comment.loc.start.column;
if (offset) { if (offset) {
const newlineRegex = new RegExp("\\n\\s{1," + offset + "}", "g"); const newlineRegex = new RegExp("\\n\\s{1," + offset + "}", "g");
val = val.replace(newlineRegex, "\n"); val = val.replace(newlineRegex, "\n");
} }
const indentSize = Math.max(this._getIndent().length, this._buf.getCurrentColumn()); const indentSize = Math.max(
this._getIndent().length,
this._buf.getCurrentColumn(),
);
val = val.replace(/\n(?!$)/g, `\n${repeat(" ", indentSize)}`); val = val.replace(/\n(?!$)/g, `\n${repeat(" ", indentSize)}`);
} }
@ -565,9 +601,11 @@ export default class Printer {
}); });
// whitespace after // whitespace after
this.newline((this._whitespace ? this._whitespace.getNewlinesAfter(comment) : 0) + this.newline(
(this._whitespace ? this._whitespace.getNewlinesAfter(comment) : 0) +
// Subtract one to account for the line force-added above. // Subtract one to account for the line force-added above.
(comment.type === "CommentLine" ? -1 : 0)); (comment.type === "CommentLine" ? -1 : 0),
);
} }
_printComments(comments?: Array<Object>) { _printComments(comments?: Array<Object>) {

View File

@ -18,16 +18,16 @@ export default class SourceMap {
get() { get() {
if (!this._cachedMap) { if (!this._cachedMap) {
const map = this._cachedMap = new sourceMap.SourceMapGenerator({ const map = (this._cachedMap = new sourceMap.SourceMapGenerator({
file: this._opts.sourceMapTarget, file: this._opts.sourceMapTarget,
sourceRoot: this._opts.sourceRoot, sourceRoot: this._opts.sourceRoot,
}); }));
const code = this._code; const code = this._code;
if (typeof code === "string") { if (typeof code === "string") {
map.setSourceContent(this._opts.sourceFileName, code); map.setSourceContent(this._opts.sourceFileName, code);
} else if (typeof code === "object") { } else if (typeof code === "object") {
Object.keys(code).forEach((sourceFileName) => { Object.keys(code).forEach(sourceFileName => {
map.setSourceContent(sourceFileName, code[sourceFileName]); map.setSourceContent(sourceFileName, code[sourceFileName]);
}); });
} }
@ -60,8 +60,11 @@ export default class SourceMap {
// If this mapping points to the same source location as the last one, we can ignore it since // If this mapping points to the same source location as the last one, we can ignore it since
// the previous one covers it. // the previous one covers it.
if (this._lastGenLine === generatedLine && this._lastSourceLine === line && if (
this._lastSourceColumn === column) { this._lastGenLine === generatedLine &&
this._lastSourceLine === line &&
this._lastSourceColumn === column
) {
return; return;
} }
@ -80,7 +83,10 @@ export default class SourceMap {
column: generatedColumn, column: generatedColumn,
}, },
source: line == null ? undefined : filename || this._opts.sourceFileName, source: line == null ? undefined : filename || this._opts.sourceFileName,
original: line == null ? undefined : { original:
line == null
? undefined
: {
line: line, line: line,
column: column, column: column,
}, },

View File

@ -17,7 +17,11 @@ export default class Whitespace {
let endToken; let endToken;
const tokens = this.tokens; const tokens = this.tokens;
let index = this._findToken((token) => token.start - node.start, 0, tokens.length); let index = this._findToken(
token => token.start - node.start,
0,
tokens.length,
);
if (index >= 0) { if (index >= 0) {
while (index && node.start === tokens[index - 1].start) --index; while (index && node.start === tokens[index - 1].start) --index;
startToken = tokens[index - 1]; startToken = tokens[index - 1];
@ -36,7 +40,11 @@ export default class Whitespace {
let endToken; let endToken;
const tokens = this.tokens; const tokens = this.tokens;
let index = this._findToken((token) => token.end - node.end, 0, tokens.length); let index = this._findToken(
token => token.end - node.end,
0,
tokens.length,
);
if (index >= 0) { if (index >= 0) {
while (index && node.end === tokens[index - 1].end) --index; while (index && node.end === tokens[index - 1].end) --index;
startToken = tokens[index]; startToken = tokens[index];

View File

@ -27,103 +27,142 @@ describe("generation", function () {
"b.js": "hi('hello');\n", "b.js": "hi('hello');\n",
}; };
const parsed = Object.keys(sources).reduce(function(_parsed, filename) { const parsed = Object.keys(sources).reduce(function(_parsed, filename) {
_parsed[filename] = parse(sources[filename], { sourceFilename: filename }); _parsed[filename] = parse(sources[filename], {
sourceFilename: filename,
});
return _parsed; return _parsed;
}, {}); }, {});
const combinedAst = { const combinedAst = {
"type": "File", type: "File",
"program": { program: {
"type": "Program", type: "Program",
"sourceType": "module", sourceType: "module",
"body": [].concat(parsed["a.js"].program.body, parsed["b.js"].program.body), body: [].concat(
parsed["a.js"].program.body,
parsed["b.js"].program.body,
),
}, },
}; };
const generated = generate(combinedAst, { sourceMaps: true }, sources); const generated = generate(combinedAst, { sourceMaps: true }, sources);
chai.expect(generated.map).to.deep.equal({ chai.expect(generated.map).to.deep.equal(
{
version: 3, version: 3,
sources: ["a.js", "b.js"], sources: ["a.js", "b.js"],
mappings: "AAAA,SAASA,EAAT,CAAaC,GAAb,EAAkB;AAAEC,UAAQC,GAAR,CAAYF,GAAZ;AAAmB;;ACAvCD,GAAG,OAAH", mappings:
names: [ "AAAA,SAASA,EAAT,CAAaC,GAAb,EAAkB;AAAEC,UAAQC,GAAR,CAAYF,GAAZ;AAAmB;;ACAvCD,GAAG,OAAH",
"hi", names: ["hi", "msg", "console", "log"],
"msg",
"console",
"log",
],
sourcesContent: [ sourcesContent: [
"function hi (msg) { console.log(msg); }\n", "function hi (msg) { console.log(msg); }\n",
"hi('hello');\n", "hi('hello');\n",
], ],
}, "sourcemap was incorrectly generated"); },
"sourcemap was incorrectly generated",
);
chai.expect(generated.rawMappings).to.deep.equal([ chai.expect(generated.rawMappings).to.deep.equal(
{ name: undefined, [
{
name: undefined,
generated: { line: 1, column: 0 }, generated: { line: 1, column: 0 },
source: "a.js", source: "a.js",
original: { line: 1, column: 0 } }, original: { line: 1, column: 0 },
{ name: "hi", },
{
name: "hi",
generated: { line: 1, column: 9 }, generated: { line: 1, column: 9 },
source: "a.js", source: "a.js",
original: { line: 1, column: 9 } }, original: { line: 1, column: 9 },
{ name: undefined, },
{
name: undefined,
generated: { line: 1, column: 11 }, generated: { line: 1, column: 11 },
source: "a.js", source: "a.js",
original: { line: 1, column: 0 } }, original: { line: 1, column: 0 },
{ name: "msg", },
{
name: "msg",
generated: { line: 1, column: 12 }, generated: { line: 1, column: 12 },
source: "a.js", source: "a.js",
original: { line: 1, column: 13 } }, original: { line: 1, column: 13 },
{ name: undefined, },
{
name: undefined,
generated: { line: 1, column: 15 }, generated: { line: 1, column: 15 },
source: "a.js", source: "a.js",
original: { line: 1, column: 0 } }, original: { line: 1, column: 0 },
{ name: undefined, },
{
name: undefined,
generated: { line: 1, column: 17 }, generated: { line: 1, column: 17 },
source: "a.js", source: "a.js",
original: { line: 1, column: 18 } }, original: { line: 1, column: 18 },
{ name: "console", },
{
name: "console",
generated: { line: 2, column: 0 }, generated: { line: 2, column: 0 },
source: "a.js", source: "a.js",
original: { line: 1, column: 20 } }, original: { line: 1, column: 20 },
{ name: "log", },
{
name: "log",
generated: { line: 2, column: 10 }, generated: { line: 2, column: 10 },
source: "a.js", source: "a.js",
original: { line: 1, column: 28 } }, original: { line: 1, column: 28 },
{ name: undefined, },
{
name: undefined,
generated: { line: 2, column: 13 }, generated: { line: 2, column: 13 },
source: "a.js", source: "a.js",
original: { line: 1, column: 20 } }, original: { line: 1, column: 20 },
{ name: "msg", },
{
name: "msg",
generated: { line: 2, column: 14 }, generated: { line: 2, column: 14 },
source: "a.js", source: "a.js",
original: { line: 1, column: 32 } }, original: { line: 1, column: 32 },
{ name: undefined, },
{
name: undefined,
generated: { line: 2, column: 17 }, generated: { line: 2, column: 17 },
source: "a.js", source: "a.js",
original: { line: 1, column: 20 } }, original: { line: 1, column: 20 },
{ name: undefined, },
{
name: undefined,
generated: { line: 3, column: 0 }, generated: { line: 3, column: 0 },
source: "a.js", source: "a.js",
original: { line: 1, column: 39 } }, original: { line: 1, column: 39 },
{ name: "hi", },
{
name: "hi",
generated: { line: 5, column: 0 }, generated: { line: 5, column: 0 },
source: "b.js", source: "b.js",
original: { line: 1, column: 0 } }, original: { line: 1, column: 0 },
{ name: undefined, },
{
name: undefined,
generated: { line: 5, column: 3 }, generated: { line: 5, column: 3 },
source: "b.js", source: "b.js",
original: { line: 1, column: 3 } }, original: { line: 1, column: 3 },
{ name: undefined, },
{
name: undefined,
generated: { line: 5, column: 10 }, generated: { line: 5, column: 10 },
source: "b.js", source: "b.js",
original: { line: 1, column: 0 } }, original: { line: 1, column: 0 },
], "raw mappings were incorrectly generated"); },
],
"raw mappings were incorrectly generated",
);
chai.expect(generated.code).to.equal( chai
.expect(generated.code)
.to.equal(
"function hi(msg) {\n console.log(msg);\n}\n\nhi('hello');", "function hi(msg) {\n console.log(msg);\n}\n\nhi('hello');",
"code was incorrectly generated" "code was incorrectly generated",
); );
}); });
@ -141,50 +180,74 @@ describe("generation", function () {
id2.name += "2"; id2.name += "2";
id2.loc.identiferName = "bar"; id2.loc.identiferName = "bar";
const generated = generate(ast, { const generated = generate(
ast,
{
filename: "inline", filename: "inline",
sourceFileName: "inline", sourceFileName: "inline",
sourceMaps: true, sourceMaps: true,
}, code); },
code,
);
chai.expect(generated.map).to.deep.equal({ chai.expect(generated.map).to.deep.equal(
{
version: 3, version: 3,
sources: ["inline"], sources: ["inline"],
names: ["foo", "bar"], names: ["foo", "bar"],
mappings: "AAAA,SAASA,IAAT,GAAe;AAAEC;AAAM", mappings: "AAAA,SAASA,IAAT,GAAe;AAAEC;AAAM",
sourcesContent: ["function foo() { bar; }\n"], sourcesContent: ["function foo() { bar; }\n"],
}, "sourcemap was incorrectly generated"); },
"sourcemap was incorrectly generated",
);
chai.expect(generated.rawMappings).to.deep.equal([ chai.expect(generated.rawMappings).to.deep.equal(
{ name: undefined, [
{
name: undefined,
generated: { line: 1, column: 0 }, generated: { line: 1, column: 0 },
source: "inline", source: "inline",
original: { line: 1, column: 0 } }, original: { line: 1, column: 0 },
{ name: "foo", },
{
name: "foo",
generated: { line: 1, column: 9 }, generated: { line: 1, column: 9 },
source: "inline", source: "inline",
original: { line: 1, column: 9 } }, original: { line: 1, column: 9 },
{ name: undefined, },
{
name: undefined,
generated: { line: 1, column: 13 }, generated: { line: 1, column: 13 },
source: "inline", source: "inline",
original: { line: 1, column: 0 } }, original: { line: 1, column: 0 },
{ name: undefined, },
{
name: undefined,
generated: { line: 1, column: 16 }, generated: { line: 1, column: 16 },
source: "inline", source: "inline",
original: { line: 1, column: 15 } }, original: { line: 1, column: 15 },
{ name: "bar", },
{
name: "bar",
generated: { line: 2, column: 0 }, generated: { line: 2, column: 0 },
source: "inline", source: "inline",
original: { line: 1, column: 17 } }, original: { line: 1, column: 17 },
{ name: undefined, },
{
name: undefined,
generated: { line: 3, column: 0 }, generated: { line: 3, column: 0 },
source: "inline", source: "inline",
original: { line: 1, column: 23 } }, original: { line: 1, column: 23 },
], "raw mappings were incorrectly generated"); },
],
"raw mappings were incorrectly generated",
);
chai.expect(generated.code).to.equal( chai
.expect(generated.code)
.to.equal(
"function foo2() {\n bar2;\n}", "function foo2() {\n bar2;\n}",
"code was incorrectly generated" "code was incorrectly generated",
); );
}); });
@ -199,17 +262,22 @@ describe("generation", function () {
chai.expect(generated.rawMappings).to.be.an("array"); chai.expect(generated.rawMappings).to.be.an("array");
chai.expect(generated).ownPropertyDescriptor("map").not.to.have.property("value"); chai
.expect(generated)
.ownPropertyDescriptor("map")
.not.to.have.property("value");
chai.expect(generated.map).to.be.an("object"); chai.expect(generated.map).to.be.an("object");
}); });
}); });
describe("programmatic generation", function() { describe("programmatic generation", function() {
it("numeric member expression", function() { it("numeric member expression", function() {
// Should not generate `0.foo` // Should not generate `0.foo`
const mem = t.memberExpression(t.numericLiteral(60702), t.identifier("foo")); const mem = t.memberExpression(
t.numericLiteral(60702),
t.identifier("foo"),
);
new Function(generate(mem).code); new Function(generate(mem).code);
}); });
@ -220,10 +288,10 @@ describe("programmatic generation", function() {
t.stringLiteral("while cond"), t.stringLiteral("while cond"),
t.ifStatement( t.ifStatement(
t.stringLiteral("nested"), t.stringLiteral("nested"),
t.expressionStatement(t.numericLiteral(1)) t.expressionStatement(t.numericLiteral(1)),
)
), ),
t.expressionStatement(t.stringLiteral("alt")) ),
t.expressionStatement(t.stringLiteral("alt")),
); );
const ast = parse(generate(ifStatement).code); const ast = parse(generate(ifStatement).code);
@ -233,35 +301,22 @@ describe("programmatic generation", function() {
it("prints directives in block with empty body", function() { it("prints directives in block with empty body", function() {
const blockStatement = t.blockStatement( const blockStatement = t.blockStatement(
[], [],
[t.directive(t.directiveLiteral("use strict"))] [t.directive(t.directiveLiteral("use strict"))],
); );
const output = generate(blockStatement).code; const output = generate(blockStatement).code;
assert.equal(output, [ assert.equal(output, ["{", ' "use strict";', "}"].join("\n"));
"{",
" \"use strict\";",
"}",
].join("\n"));
}); });
it("flow object indentation", function() { it("flow object indentation", function() {
const objectStatement = t.objectTypeAnnotation( const objectStatement = t.objectTypeAnnotation(
[ [t.objectTypeProperty(t.identifier("bar"), t.stringTypeAnnotation())],
t.objectTypeProperty( null,
t.identifier("bar"),
t.stringTypeAnnotation()
),
],
null, null,
null
); );
const output = generate(objectStatement).code; const output = generate(objectStatement).code;
assert.equal(output, [ assert.equal(output, ["{", " bar: string,", "}"].join("\n"));
"{",
" bar: string,",
"}",
].join("\n"));
}); });
it("flow object indentation with empty leading ObjectTypeProperty", function() { it("flow object indentation with empty leading ObjectTypeProperty", function() {
@ -273,16 +328,12 @@ describe("programmatic generation", function() {
t.anyTypeAnnotation(), t.anyTypeAnnotation(),
t.identifier("Test"), t.identifier("Test"),
), ),
] ],
); );
const output = generate(objectStatement).code; const output = generate(objectStatement).code;
assert.equal(output, [ assert.equal(output, ["{", " [key: any]: Test,", "}"].join("\n"));
"{",
" [key: any]: Test,",
"}",
].join("\n"));
}); });
}); });
@ -298,7 +349,10 @@ const suites = fixtures(`${__dirname}/fixtures`);
suites.forEach(function(testSuite) { suites.forEach(function(testSuite) {
describe("generation/" + testSuite.title, function() { describe("generation/" + testSuite.title, function() {
testSuite.tests.forEach(function(task) { testSuite.tests.forEach(function(task) {
it(task.title, !task.disabled && function () { it(
task.title,
!task.disabled &&
function() {
const expect = task.expect; const expect = task.expect;
const actual = task.actual; const actual = task.actual;
const actualCode = actual.code; const actualCode = actual.code;
@ -326,16 +380,21 @@ suites.forEach(function (testSuite) {
const result = generate(actualAst, task.options, actualCode); const result = generate(actualAst, task.options, actualCode);
if ( if (
!expect.code && result.code && fs.statSync(path.dirname(expect.loc)).isDirectory() && !expect.code &&
result.code &&
fs.statSync(path.dirname(expect.loc)).isDirectory() &&
!process.env.CI !process.env.CI
) { ) {
console.log(`New test file created: ${expect.loc}`); console.log(`New test file created: ${expect.loc}`);
fs.writeFileSync(expect.loc, result.code); fs.writeFileSync(expect.loc, result.code);
} else { } else {
chai.expect(result.code).to.be.equal(expect.code, actual.loc + " !== " + expect.loc); chai
.expect(result.code)
.to.be.equal(expect.code, actual.loc + " !== " + expect.loc);
} }
} }
}); },
);
}); });
}); });
}); });

View File

@ -1,7 +1,9 @@
import type { NodePath } from "babel-traverse"; import type { NodePath } from "babel-traverse";
import * as t from "babel-types"; import * as t from "babel-types";
export default function bindifyDecorators(decorators: Array<NodePath>): Array<NodePath> { export default function bindifyDecorators(
decorators: Array<NodePath>,
): Array<NodePath> {
for (const decoratorPath of decorators) { for (const decoratorPath of decorators) {
const decorator = decoratorPath.node; const decorator = decoratorPath.node;
const expression = decorator.expression; const expression = decorator.expression;
@ -19,13 +21,15 @@ export default function bindifyDecorators(decorators: Array<NodePath>): Array<No
ref = expression.object; ref = expression.object;
} }
nodes.push(t.callExpression( nodes.push(
t.callExpression(
t.memberExpression( t.memberExpression(
t.memberExpression(ref, expression.property, expression.computed), t.memberExpression(ref, expression.property, expression.computed),
t.identifier("bind") t.identifier("bind"),
), ),
[ref] [ref],
)); ),
);
if (nodes.length === 1) { if (nodes.length === 1) {
decorator.expression = nodes[0]; decorator.expression = nodes[0];

View File

@ -1,10 +1,7 @@
import explode from "babel-helper-explode-assignable-expression"; import explode from "babel-helper-explode-assignable-expression";
import * as t from "babel-types"; import * as t from "babel-types";
export default function (opts: { export default function(opts: { build: Function, operator: string }): Object {
build: Function;
operator: string;
}): Object {
const visitor = {}; const visitor = {};
function isAssignment(node) { function isAssignment(node) {
@ -25,9 +22,11 @@ export default function (opts: {
const nodes = []; const nodes = [];
const exploded = explode(expr.left, nodes, file, path.scope, true); const exploded = explode(expr.left, nodes, file, path.scope, true);
nodes.push(t.expressionStatement( nodes.push(
buildAssignment(exploded.ref, opts.build(exploded.uid, expr.right)) t.expressionStatement(
)); buildAssignment(exploded.ref, opts.build(exploded.uid, expr.right)),
),
);
path.replaceWithMultiple(nodes); path.replaceWithMultiple(nodes);
}; };
@ -38,7 +37,9 @@ export default function (opts: {
const nodes = []; const nodes = [];
const exploded = explode(node.left, nodes, file, scope); const exploded = explode(node.left, nodes, file, scope);
nodes.push(buildAssignment(exploded.ref, opts.build(exploded.uid, node.right))); nodes.push(
buildAssignment(exploded.ref, opts.build(exploded.uid, node.right)),
);
path.replaceWithMultiple(nodes); path.replaceWithMultiple(nodes);
}; };

View File

@ -2,19 +2,21 @@ import esutils from "esutils";
import * as t from "babel-types"; import * as t from "babel-types";
type ElementState = { type ElementState = {
tagExpr: Object; // tag node tagExpr: Object, // tag node
tagName: string; // raw string tag name tagName: string, // raw string tag name
args: Array<Object>; // array of call arguments args: Array<Object>, // array of call arguments
call?: Object; // optional call property that can be set to override the call expression returned call?: Object, // optional call property that can be set to override the call expression returned
pre?: Function; // function called with (state: ElementState) before building attribs pre?: Function, // function called with (state: ElementState) before building attribs
post?: Function; // function called with (state: ElementState) after building attribs post?: Function, // function called with (state: ElementState) after building attribs
}; };
export default function(opts) { export default function(opts) {
const visitor = {}; const visitor = {};
visitor.JSXNamespacedName = function(path) { visitor.JSXNamespacedName = function(path) {
throw path.buildCodeFrameError("Namespace tags are not supported. ReactJSX is not XML."); throw path.buildCodeFrameError(
"Namespace tags are not supported. ReactJSX is not XML.",
);
}; };
visitor.JSXElement = { visitor.JSXElement = {
@ -45,7 +47,7 @@ export default function (opts) {
} else if (t.isJSXMemberExpression(node)) { } else if (t.isJSXMemberExpression(node)) {
return t.memberExpression( return t.memberExpression(
convertJSXIdentifier(node.object, node), convertJSXIdentifier(node.object, node),
convertJSXIdentifier(node.property, node) convertJSXIdentifier(node.property, node),
); );
} }
@ -127,7 +129,6 @@ export default function (opts) {
return []; return [];
} }
/** /**
* The logic for this is quite terse. It's because we need to * The logic for this is quite terse. It's because we need to
* support spread elements. We loop over all attributes, * support spread elements. We loop over all attributes,
@ -141,8 +142,10 @@ export default function (opts) {
const useBuiltIns = file.opts.useBuiltIns || false; const useBuiltIns = file.opts.useBuiltIns || false;
if (typeof useBuiltIns !== "boolean") { if (typeof useBuiltIns !== "boolean") {
throw new Error("transform-react-jsx currently only accepts a boolean option for " + throw new Error(
"useBuiltIns (defaults to false)"); "transform-react-jsx currently only accepts a boolean option for " +
"useBuiltIns (defaults to false)",
);
} }
while (attribs.length) { while (attribs.length) {
@ -166,9 +169,9 @@ export default function (opts) {
objs.unshift(t.objectExpression([])); objs.unshift(t.objectExpression([]));
} }
const helper = useBuiltIns ? const helper = useBuiltIns
t.memberExpression(t.identifier("Object"), t.identifier("assign")) : ? t.memberExpression(t.identifier("Object"), t.identifier("assign"))
file.addHelper("extends"); : file.addHelper("extends");
// spread it // spread it
attribs = t.callExpression(helper, objs); attribs = t.callExpression(helper, objs);

View File

@ -20,13 +20,19 @@ const visitor = {
export default function(path: NodePath, scope = path.scope) { export default function(path: NodePath, scope = path.scope) {
const { node } = path; const { node } = path;
const container = t.functionExpression(null, [], node.body, node.generator, node.async); const container = t.functionExpression(
null,
[],
node.body,
node.generator,
node.async,
);
let callee = container; let callee = container;
let args = []; let args = [];
// todo: only hoist if necessary // todo: only hoist if necessary
hoistVariables(path, (id) => scope.push({ id })); hoistVariables(path, id => scope.push({ id }));
const state = { const state = {
foundThis: false, foundThis: false,

View File

@ -12,7 +12,13 @@ function toKind(node: Object) {
return "value"; return "value";
} }
export function push(mutatorMap: Object, node: Object, kind: string, file, scope?): Object { export function push(
mutatorMap: Object,
node: Object,
kind: string,
file,
scope?,
): Object {
const alias = t.toKeyAlias(node); const alias = t.toKeyAlias(node);
// //
@ -33,9 +39,11 @@ export function push(mutatorMap: Object, node: Object, kind: string, file, scope
} }
if (node.decorators) { if (node.decorators) {
const decorators = map.decorators = map.decorators || t.arrayExpression([]); const decorators = (map.decorators =
map.decorators || t.arrayExpression([]));
decorators.elements = decorators.elements.concat( decorators.elements = decorators.elements.concat(
node.decorators.map((dec) => dec.expression).reverse()); node.decorators.map(dec => dec.expression).reverse(),
);
} }
if (map.value || map.initializer) { if (map.value || map.initializer) {
@ -45,14 +53,24 @@ export function push(mutatorMap: Object, node: Object, kind: string, file, scope
let key, value; let key, value;
// save the key so we can possibly do function name inferences // save the key so we can possibly do function name inferences
if (t.isObjectProperty(node) || t.isObjectMethod(node) || t.isClassMethod(node)) { if (
t.isObjectProperty(node) ||
t.isObjectMethod(node) ||
t.isClassMethod(node)
) {
key = t.toComputedKey(node, node.key); key = t.toComputedKey(node, node.key);
} }
if (t.isObjectProperty(node) || t.isClassProperty(node)) { if (t.isObjectProperty(node) || t.isClassProperty(node)) {
value = node.value; value = node.value;
} else if (t.isObjectMethod(node) || t.isClassMethod(node)) { } else if (t.isObjectMethod(node) || t.isClassMethod(node)) {
value = t.functionExpression(null, node.params, node.body, node.generator, node.async); value = t.functionExpression(
null,
node.params,
node.body,
node.generator,
node.async,
);
value.returnType = node.returnType; value.returnType = node.returnType;
} }
@ -62,8 +80,12 @@ export function push(mutatorMap: Object, node: Object, kind: string, file, scope
} }
// infer function name // infer function name
if (scope && t.isStringLiteral(key) && (kind === "value" || kind === "initializer") && if (
t.isFunctionExpression(value)) { scope &&
t.isStringLiteral(key) &&
(kind === "value" || kind === "initializer") &&
t.isFunctionExpression(value)
) {
value = nameFunction({ id: key, node: value, scope }); value = nameFunction({ id: key, node: value, scope });
} }
@ -90,7 +112,9 @@ export function toComputedObjectFromClass(obj: Object): Object {
for (let i = 0; i < obj.properties.length; i++) { for (let i = 0; i < obj.properties.length; i++) {
const prop = obj.properties[i]; const prop = obj.properties[i];
const val = prop.value; const val = prop.value;
val.properties.unshift(t.objectProperty(t.identifier("key"), t.toComputedKey(prop))); val.properties.unshift(
t.objectProperty(t.identifier("key"), t.toComputedKey(prop)),
);
objExpr.elements.push(val); objExpr.elements.push(val);
} }

View File

@ -20,7 +20,7 @@ function getObjRef(node, nodes, file, scope) {
} else if (t.isMemberExpression(node)) { } else if (t.isMemberExpression(node)) {
ref = node.object; ref = node.object;
if (t.isSuper(ref) || t.isIdentifier(ref) && scope.hasBinding(ref.name)) { if (t.isSuper(ref) || (t.isIdentifier(ref) && scope.hasBinding(ref.name))) {
// the object reference that we need to save is locally declared // the object reference that we need to save is locally declared
// so as per the previous comment we can be 100% sure evaluating // so as per the previous comment we can be 100% sure evaluating
// it multiple times will be safe // it multiple times will be safe
@ -32,9 +32,7 @@ function getObjRef(node, nodes, file, scope) {
} }
const temp = scope.generateUidIdentifierBasedOnNode(ref); const temp = scope.generateUidIdentifierBasedOnNode(ref);
nodes.push(t.variableDeclaration("var", [ nodes.push(t.variableDeclaration("var", [t.variableDeclarator(temp, ref)]));
t.variableDeclarator(temp, ref),
]));
return temp; return temp;
} }
@ -44,9 +42,7 @@ function getPropRef(node, nodes, file, scope) {
if (t.isLiteral(key) && t.isPureish(key)) return key; if (t.isLiteral(key) && t.isPureish(key)) return key;
const temp = scope.generateUidIdentifierBasedOnNode(prop); const temp = scope.generateUidIdentifierBasedOnNode(prop);
nodes.push(t.variableDeclaration("var", [ nodes.push(t.variableDeclaration("var", [t.variableDeclarator(temp, prop)]));
t.variableDeclarator(temp, prop),
]));
return temp; return temp;
} }
@ -57,8 +53,8 @@ export default function (
scope: Scope, scope: Scope,
allowedSingleIdent?: boolean, allowedSingleIdent?: boolean,
): { ): {
uid: Object; uid: Object,
ref: Object; ref: Object,
} { } {
let obj; let obj;
if (t.isIdentifier(node) && allowedSingleIdent) { if (t.isIdentifier(node) && allowedSingleIdent) {

View File

@ -44,6 +44,8 @@ export default function (classPath) {
} }
if (memoisedExpressions) { if (memoisedExpressions) {
classPath.insertBefore(memoisedExpressions.map((expr) => t.expressionStatement(expr))); classPath.insertBefore(
memoisedExpressions.map(expr => t.expressionStatement(expr)),
);
} }
} }

View File

@ -15,25 +15,25 @@ function humanize(val, noext) {
} }
type TestFile = { type TestFile = {
loc: string; loc: string,
code: string; code: string,
filename: string; filename: string,
}; };
type Test = { type Test = {
title: string; title: string,
disabled: boolean; disabled: boolean,
options: Object; options: Object,
exec: TestFile; exec: TestFile,
actual: TestFile; actual: TestFile,
expected: TestFile; expected: TestFile,
}; };
type Suite = { type Suite = {
options: Object; options: Object,
tests: Array<Test>; tests: Array<Test>,
title: string; title: string,
filename: string; filename: string,
}; };
function assertDirectory(loc) { function assertDirectory(loc) {
@ -50,7 +50,9 @@ function shouldIgnore(name, blacklist?: Array<string>) {
const ext = path.extname(name); const ext = path.extname(name);
const base = path.basename(name, ext); const base = path.basename(name, ext);
return name[0] === "." || ext === ".md" || base === "LICENSE" || base === "options"; return (
name[0] === "." || ext === ".md" || base === "LICENSE" || base === "options"
);
} }
export default function get(entryLoc): Array<Suite> { export default function get(entryLoc): Array<Suite> {
@ -133,7 +135,9 @@ export default function get(entryLoc): Array<Suite> {
const minimumVersion = semver.clean(taskOpts.minNodeVersion); const minimumVersion = semver.clean(taskOpts.minNodeVersion);
if (minimumVersion == null) { if (minimumVersion == null) {
throw new Error(`'minNodeVersion' has invalid semver format: ${taskOpts.minNodeVersion}`); throw new Error(
`'minNodeVersion' has invalid semver format: ${taskOpts.minNodeVersion}`,
);
} }
if (semver.lt(nodeVersion, minimumVersion)) { if (semver.lt(nodeVersion, minimumVersion)) {

View File

@ -56,7 +56,9 @@ function wrap(state, method, id, scope) {
// need to add a wrapper since we can't change the references // need to add a wrapper since we can't change the references
let build = buildPropertyMethodAssignmentWrapper; let build = buildPropertyMethodAssignmentWrapper;
if (method.generator) build = buildGeneratorPropertyMethodAssignmentWrapper; if (method.generator) {
build = buildGeneratorPropertyMethodAssignmentWrapper;
}
const template = build({ const template = build({
FUNCTION: method, FUNCTION: method,
FUNCTION_ID: id, FUNCTION_ID: id,
@ -129,8 +131,11 @@ export default function ({ node, parent, scope, id }) {
// has an `id` so we don't need to infer one // has an `id` so we don't need to infer one
if (node.id) return; if (node.id) return;
if ((t.isObjectProperty(parent) || t.isObjectMethod(parent, { kind: "method" })) && if (
(!parent.computed || t.isLiteral(parent.key))) { (t.isObjectProperty(parent) ||
t.isObjectMethod(parent, { kind: "method" })) &&
(!parent.computed || t.isLiteral(parent.key))
) {
// { foo() {} }; // { foo() {} };
id = parent.key; id = parent.key;
} else if (t.isVariableDeclarator(parent)) { } else if (t.isVariableDeclarator(parent)) {
@ -139,7 +144,11 @@ export default function ({ node, parent, scope, id }) {
if (t.isIdentifier(id)) { if (t.isIdentifier(id)) {
const binding = scope.parent.getBinding(id.name); const binding = scope.parent.getBinding(id.name);
if (binding && binding.constant && scope.getBinding(id.name) === binding) { if (
binding &&
binding.constant &&
scope.getBinding(id.name) === binding
) {
// always going to reference this method // always going to reference this method
node.id = id; node.id = id;
node.id[t.NOT_LOCAL_BINDING] = true; node.id[t.NOT_LOCAL_BINDING] = true;

View File

@ -21,9 +21,11 @@ const visitor = {
firstId = declar.node.id; firstId = declar.node.id;
if (declar.node.init) { if (declar.node.init) {
nodes.push(t.expressionStatement( nodes.push(
t.assignmentExpression("=", declar.node.id, declar.node.init) t.expressionStatement(
)); t.assignmentExpression("=", declar.node.id, declar.node.init),
),
);
} }
for (const name in declar.getBindingIdentifiers()) { for (const name in declar.getBindingIdentifiers()) {

View File

@ -1,17 +1,20 @@
import * as t from "babel-types"; import * as t from "babel-types";
export default function(callee, thisNode, args) { export default function(callee, thisNode, args) {
if (args.length === 1 && t.isSpreadElement(args[0]) && if (
t.isIdentifier(args[0].argument, { name: "arguments" })) { args.length === 1 &&
t.isSpreadElement(args[0]) &&
t.isIdentifier(args[0].argument, { name: "arguments" })
) {
// eg. super(...arguments); // eg. super(...arguments);
return t.callExpression( return t.callExpression(t.memberExpression(callee, t.identifier("apply")), [
t.memberExpression(callee, t.identifier("apply")), thisNode,
[thisNode, args[0].argument] args[0].argument,
); ]);
} else { } else {
return t.callExpression( return t.callExpression(t.memberExpression(callee, t.identifier("call")), [
t.memberExpression(callee, t.identifier("call")), thisNode,
[thisNode, ...args] ...args,
); ]);
} }
} }

View File

@ -48,7 +48,11 @@ const forAwaitVisitor = {
const callee = path.node.callee; const callee = path.node.callee;
// if no await wrapping is being applied, unwrap the call expression // if no await wrapping is being applied, unwrap the call expression
if (t.isIdentifier(callee) && callee.name === "AWAIT" && !replacements.AWAIT) { if (
t.isIdentifier(callee) &&
callee.name === "AWAIT" &&
!replacements.AWAIT
) {
path.replaceWith(path.node.arguments[0]); path.replaceWith(path.node.arguments[0]);
} }
}, },
@ -64,7 +68,9 @@ export default function (path, helpers) {
if (t.isIdentifier(left) || t.isPattern(left) || t.isMemberExpression(left)) { if (t.isIdentifier(left) || t.isPattern(left) || t.isMemberExpression(left)) {
// for await (i of test), for await ({ i } of test) // for await (i of test), for await ({ i } of test)
declar = t.expressionStatement(t.assignmentExpression("=", left, stepValue)); declar = t.expressionStatement(
t.assignmentExpression("=", left, stepValue),
);
} else if (t.isVariableDeclaration(left)) { } else if (t.isVariableDeclaration(left)) {
// for await (let i of test) // for await (let i of test)
declar = t.variableDeclaration(left.kind, [ declar = t.variableDeclaration(left.kind, [
@ -76,7 +82,9 @@ export default function (path, helpers) {
traverse(template, forAwaitVisitor, null, { traverse(template, forAwaitVisitor, null, {
ITERATOR_HAD_ERROR_KEY: scope.generateUidIdentifier("didIteratorError"), ITERATOR_HAD_ERROR_KEY: scope.generateUidIdentifier("didIteratorError"),
ITERATOR_COMPLETION: scope.generateUidIdentifier("iteratorNormalCompletion"), ITERATOR_COMPLETION: scope.generateUidIdentifier(
"iteratorNormalCompletion",
),
ITERATOR_ERROR_KEY: scope.generateUidIdentifier("iteratorError"), ITERATOR_ERROR_KEY: scope.generateUidIdentifier("iteratorError"),
ITERATOR_KEY: scope.generateUidIdentifier("iterator"), ITERATOR_KEY: scope.generateUidIdentifier("iterator"),
GET_ITERATOR: helpers.getAsyncIterator, GET_ITERATOR: helpers.getAsyncIterator,

View File

@ -70,7 +70,6 @@ const awaitVisitor = {
path.replaceWithMultiple(build.node); path.replaceWithMultiple(build.node);
} }
}, },
}; };
function classOrObjectMethod(path: NodePath, callId: Object) { function classOrObjectMethod(path: NodePath, callId: Object) {
@ -79,12 +78,16 @@ function classOrObjectMethod(path: NodePath, callId: Object) {
node.async = false; node.async = false;
const container = t.functionExpression(null, [], t.blockStatement(body.body), true); const container = t.functionExpression(
null,
[],
t.blockStatement(body.body),
true,
);
body.body = [ body.body = [
t.returnStatement(t.callExpression( t.returnStatement(
t.callExpression(callId, [container]), t.callExpression(t.callExpression(callId, [container]), []),
[] ),
)),
]; ];
// Regardless of whether or not the wrapped function is a an async method // Regardless of whether or not the wrapped function is a an async method
@ -92,7 +95,9 @@ function classOrObjectMethod(path: NodePath, callId: Object) {
node.generator = false; node.generator = false;
// Unwrap the wrapper IIFE's environment so super and this and such still work. // Unwrap the wrapper IIFE's environment so super and this and such still work.
path.get("body.body.0.argument.callee.arguments.0").unwrapFunctionEnvironment(); path
.get("body.body.0.argument.callee.arguments.0")
.unwrapFunctionEnvironment();
} }
function plainFunction(path: NodePath, callId: Object) { function plainFunction(path: NodePath, callId: Object) {
@ -121,25 +126,29 @@ function plainFunction(path: NodePath, callId: Object) {
NAME: asyncFnId || null, NAME: asyncFnId || null,
REF: path.scope.generateUidIdentifier("ref"), REF: path.scope.generateUidIdentifier("ref"),
FUNCTION: built, FUNCTION: built,
PARAMS: node.params.reduce((acc, param) => { PARAMS: node.params.reduce(
acc.done = acc.done || t.isAssignmentPattern(param) || t.isRestElement(param); (acc, param) => {
acc.done =
acc.done || t.isAssignmentPattern(param) || t.isRestElement(param);
if (!acc.done) { if (!acc.done) {
acc.params.push(path.scope.generateUidIdentifier("x")); acc.params.push(path.scope.generateUidIdentifier("x"));
} }
return acc; return acc;
}, { },
{
params: [], params: [],
done: false, done: false,
}).params, },
).params,
}).expression; }).expression;
if (isDeclaration) { if (isDeclaration) {
const declar = t.variableDeclaration("let", [ const declar = t.variableDeclaration("let", [
t.variableDeclarator( t.variableDeclarator(
t.identifier(asyncFnId.name), t.identifier(asyncFnId.name),
t.callExpression(container, []) t.callExpression(container, []),
), ),
]); ]);
declar._blockHoist = true; declar._blockHoist = true;
@ -149,14 +158,12 @@ function plainFunction(path: NodePath, callId: Object) {
// the identifier into an expressionStatement // the identifier into an expressionStatement
path.parentPath.insertBefore(declar); path.parentPath.insertBefore(declar);
path.parentPath.replaceWith( path.parentPath.replaceWith(
t.exportNamedDeclaration(null, t.exportNamedDeclaration(null, [
[
t.exportSpecifier( t.exportSpecifier(
t.identifier(asyncFnId.name), t.identifier(asyncFnId.name),
t.identifier("default") t.identifier("default"),
), ),
] ]),
)
); );
return; return;
} }

View File

@ -30,16 +30,19 @@ function isMemberExpressionSuper(node) {
* CLASS.prototype.__proto__ || Object.getPrototypeOf(CLASS.prototype) * CLASS.prototype.__proto__ || Object.getPrototypeOf(CLASS.prototype)
*/ */
function getPrototypeOfExpression(objectRef, isStatic) { function getPrototypeOfExpression(objectRef, isStatic) {
const targetRef = isStatic ? objectRef : t.memberExpression(objectRef, t.identifier("prototype")); const targetRef = isStatic
? objectRef
: t.memberExpression(objectRef, t.identifier("prototype"));
return t.logicalExpression( return t.logicalExpression(
"||", "||",
t.memberExpression(targetRef, t.identifier("__proto__")), t.memberExpression(targetRef, t.identifier("__proto__")),
t.callExpression( t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")), t.memberExpression(
[ t.identifier("Object"),
targetRef, t.identifier("getPrototypeOf"),
] ),
[targetRef],
), ),
); );
} }
@ -119,14 +122,14 @@ export default class ReplaceSupers {
scope: Scope; scope: Scope;
file; file;
opts: { opts: {
forceSuperMemoisation: boolean; forceSuperMemoisation: boolean,
getObjetRef: Function; getObjetRef: Function,
methodPath: NodePath; methodPath: NodePath,
methodNode: Object; methodNode: Object,
superRef: Object; superRef: Object,
isStatic: boolean; isStatic: boolean,
isLoose: boolean; isLoose: boolean,
file: any; file: any,
}; };
getObjectRef() { getObjectRef() {
@ -143,16 +146,17 @@ export default class ReplaceSupers {
* *
*/ */
setSuperProperty(property: Object, value: Object, isComputed: boolean): Object { setSuperProperty(
return t.callExpression( property: Object,
this.file.addHelper("set"), value: Object,
[ isComputed: boolean,
): Object {
return t.callExpression(this.file.addHelper("set"), [
getPrototypeOfExpression(this.getObjectRef(), this.isStatic), getPrototypeOfExpression(this.getObjectRef(), this.isStatic),
isComputed ? property : t.stringLiteral(property.name), isComputed ? property : t.stringLiteral(property.name),
value, value,
t.thisExpression(), t.thisExpression(),
] ]);
);
} }
/** /**
@ -165,14 +169,11 @@ export default class ReplaceSupers {
*/ */
getSuperProperty(property: Object, isComputed: boolean): Object { getSuperProperty(property: Object, isComputed: boolean): Object {
return t.callExpression( return t.callExpression(this.file.addHelper("get"), [
this.file.addHelper("get"),
[
getPrototypeOfExpression(this.getObjectRef(), this.isStatic), getPrototypeOfExpression(this.getObjectRef(), this.isStatic),
isComputed ? property : t.stringLiteral(property.name), isComputed ? property : t.stringLiteral(property.name),
t.thisExpression(), t.thisExpression(),
] ]);
);
} }
replace() { replace() {
@ -214,16 +215,23 @@ export default class ReplaceSupers {
specHandleAssignmentExpression(ref, path, node) { specHandleAssignmentExpression(ref, path, node) {
if (node.operator === "=") { if (node.operator === "=") {
// super.name = "val"; -> _set(Object.getPrototypeOf(objectRef.prototype), "name", this); // super.name = "val"; -> _set(Object.getPrototypeOf(objectRef.prototype), "name", this);
return this.setSuperProperty(node.left.property, node.right, node.left.computed); return this.setSuperProperty(
node.left.property,
node.right,
node.left.computed,
);
} else { } else {
// super.age += 2; -> let _ref = super.age; super.age = _ref + 2; // super.age += 2; -> let _ref = super.age; super.age = _ref + 2;
ref = ref || path.scope.generateUidIdentifier("ref"); ref = ref || path.scope.generateUidIdentifier("ref");
return [ return [
t.variableDeclaration("var", [ t.variableDeclaration("var", [t.variableDeclarator(ref, node.left)]),
t.variableDeclarator(ref, node.left), t.expressionStatement(
]), t.assignmentExpression(
t.expressionStatement(t.assignmentExpression("=", node.left, "=",
t.binaryExpression(node.operator.slice(0, -1), ref, node.right))), node.left,
t.binaryExpression(node.operator.slice(0, -1), ref, node.right),
),
),
]; ];
} }
} }
@ -258,8 +266,15 @@ export default class ReplaceSupers {
// _get(Object.getPrototypeOf(objectRef.prototype), "name", this); // _get(Object.getPrototypeOf(objectRef.prototype), "name", this);
property = node.property; property = node.property;
computed = node.computed; computed = node.computed;
} else if (t.isUpdateExpression(node) && isMemberExpressionSuper(node.argument)) { } else if (
const binary = t.assignmentExpression(node.operator[0] + "=", node.argument, t.numericLiteral(1)); t.isUpdateExpression(node) &&
isMemberExpressionSuper(node.argument)
) {
const binary = t.assignmentExpression(
node.operator[0] + "=",
node.argument,
t.numericLiteral(1),
);
if (node.prefix) { if (node.prefix) {
// ++super.foo; // ++super.foo;
// to // to
@ -270,9 +285,14 @@ export default class ReplaceSupers {
// to // to
// let _ref = super.foo; super.foo = _ref + 1; // let _ref = super.foo; super.foo = _ref + 1;
const ref = path.scope.generateUidIdentifier("ref"); const ref = path.scope.generateUidIdentifier("ref");
return this.specHandleAssignmentExpression(ref, path, binary).concat(t.expressionStatement(ref)); return this.specHandleAssignmentExpression(ref, path, binary).concat(
t.expressionStatement(ref),
);
} }
} else if (t.isAssignmentExpression(node) && isMemberExpressionSuper(node.left)) { } else if (
t.isAssignmentExpression(node) &&
isMemberExpressionSuper(node.left)
) {
return this.specHandleAssignmentExpression(null, path, node); return this.specHandleAssignmentExpression(null, path, node);
} }

View File

@ -4,13 +4,9 @@ export function assertNoOwnProperties(obj) {
assert.equal(Object.getOwnPropertyNames(obj).length, 0); assert.equal(Object.getOwnPropertyNames(obj).length, 0);
} }
export function assertHasOwnProperty() { export function assertHasOwnProperty() {}
} export function assertLacksOwnProperty() {}
export function assertLacksOwnProperty() {
}
export function multiline(arr) { export function multiline(arr) {
return arr.join("\n"); return arr.join("\n");

View File

@ -38,7 +38,9 @@ runCodeInTestContext(buildExternalHelpers());
* This allows us to run our unittests * This allows us to run our unittests
*/ */
function runModuleInTestContext(id: string, relativeFilename: string) { function runModuleInTestContext(id: string, relativeFilename: string) {
const filename = resolve.sync(id, { basedir: path.dirname(relativeFilename) }); const filename = resolve.sync(id, {
basedir: path.dirname(relativeFilename),
});
// Expose Node-internal modules if the tests want them. Note, this will not execute inside // Expose Node-internal modules if the tests want them. Note, this will not execute inside
// the context's global scope. // the context's global scope.
@ -46,20 +48,22 @@ function runModuleInTestContext(id: string, relativeFilename: string) {
if (moduleCache[filename]) return moduleCache[filename].exports; if (moduleCache[filename]) return moduleCache[filename].exports;
const module = moduleCache[filename] = { const module = (moduleCache[filename] = {
id: filename, id: filename,
exports: {}, exports: {},
}; });
const dirname = path.dirname(filename); const dirname = path.dirname(filename);
const req = (id) => runModuleInTestContext(id, filename); const req = id => runModuleInTestContext(id, filename);
const src = fs.readFileSync(filename, "utf8"); const src = fs.readFileSync(filename, "utf8");
const code = `(function (exports, require, module, __filename, __dirname) {${src}\n});`; const code = `(function (exports, require, module, __filename, __dirname) {${src}\n});`;
vm.runInContext(code, testContext, { vm
.runInContext(code, testContext, {
filename, filename,
displayErrors: true, displayErrors: true,
}).call(module.exports, module.exports, req, module, filename, dirname); })
.call(module.exports, module.exports, req, module, filename, dirname);
return module.exports; return module.exports;
} }
@ -69,10 +73,13 @@ function runModuleInTestContext(id: string, relativeFilename: string) {
* *
* Exposed for unit tests, not for use as an API. * Exposed for unit tests, not for use as an API.
*/ */
export function runCodeInTestContext(code: string, opts: {filename?: string} = {}) { export function runCodeInTestContext(
code: string,
opts: { filename?: string } = {},
) {
const filename = opts.filename || null; const filename = opts.filename || null;
const dirname = filename ? path.dirname(filename) : null; const dirname = filename ? path.dirname(filename) : null;
const req = filename ? ((id) => runModuleInTestContext(id, filename)) : null; const req = filename ? id => runModuleInTestContext(id, filename) : null;
const module = { const module = {
id: filename, id: filename,
@ -95,16 +102,16 @@ function wrapPackagesArray(type, names, optionsDir) {
// relative path (outside of monorepo) // relative path (outside of monorepo)
if (val[0][0] === ".") { if (val[0][0] === ".") {
if (!optionsDir) { if (!optionsDir) {
throw new Error("Please provide an options.json in test dir when using a " + throw new Error(
"relative plugin path."); "Please provide an options.json in test dir when using a " +
"relative plugin path.",
);
} }
val[0] = path.resolve(optionsDir, val[0]); val[0] = path.resolve(optionsDir, val[0]);
} } else {
// check node_modules/babel-x-y // check node_modules/babel-x-y
else {
val[0] = __dirname + "/../../babel-" + type + "-" + val[0]; val[0] = __dirname + "/../../babel-" + type + "-" + val[0];
} }
@ -120,15 +127,25 @@ function run(task) {
const optionsDir = task.optionsDir; const optionsDir = task.optionsDir;
function getOpts(self) { function getOpts(self) {
const newOpts = merge({ const newOpts = merge(
{
filename: self.loc, filename: self.loc,
}, opts); },
opts,
);
newOpts.plugins = wrapPackagesArray("plugin", newOpts.plugins, optionsDir); newOpts.plugins = wrapPackagesArray("plugin", newOpts.plugins, optionsDir);
newOpts.presets = wrapPackagesArray("preset", newOpts.presets, optionsDir).map(function (val) { newOpts.presets = wrapPackagesArray(
"preset",
newOpts.presets,
optionsDir,
).map(function(val) {
if (val.length > 2) { if (val.length > 2) {
throw new Error("Unexpected extra options " + JSON.stringify(val.slice(2)) + throw new Error(
" passed to preset."); "Unexpected extra options " +
JSON.stringify(val.slice(2)) +
" passed to preset.",
);
} }
return val; return val;
@ -160,14 +177,19 @@ function run(task) {
if (!execCode || actualCode) { if (!execCode || actualCode) {
result = babel.transform(actualCode, getOpts(actual)); result = babel.transform(actualCode, getOpts(actual));
if ( if (
!expect.code && result.code && !opts.throws && fs.statSync(path.dirname(expect.loc)).isDirectory() && !expect.code &&
result.code &&
!opts.throws &&
fs.statSync(path.dirname(expect.loc)).isDirectory() &&
!process.env.CI !process.env.CI
) { ) {
console.log(`New test file created: ${expect.loc}`); console.log(`New test file created: ${expect.loc}`);
fs.writeFileSync(expect.loc, result.code); fs.writeFileSync(expect.loc, result.code);
} else { } else {
actualCode = result.code.trim(); actualCode = result.code.trim();
chai.expect(actualCode).to.be.equal(expectCode, actual.loc + " !== " + expect.loc); chai
.expect(actualCode)
.to.be.equal(expectCode, actual.loc + " !== " + expect.loc);
} }
} }
@ -182,7 +204,9 @@ function run(task) {
const actual = mapping.original; const actual = mapping.original;
const expect = consumer.originalPositionFor(mapping.generated); const expect = consumer.originalPositionFor(mapping.generated);
chai.expect({ line: expect.line, column: expect.column }).to.deep.equal(actual); chai
.expect({ line: expect.line, column: expect.column })
.to.deep.equal(actual);
}); });
} }
@ -205,10 +229,17 @@ export default function (
describe(name + "/" + testSuite.title, function() { describe(name + "/" + testSuite.title, function() {
for (const task of testSuite.tests) { for (const task of testSuite.tests) {
if (includes(suiteOpts.ignoreTasks, task.title) || if (
includes(suiteOpts.ignoreTasks, testSuite.title + "/" + task.title)) continue; includes(suiteOpts.ignoreTasks, task.title) ||
includes(suiteOpts.ignoreTasks, testSuite.title + "/" + task.title)
) {
continue;
}
it(task.title, !task.disabled && function () { it(
task.title,
!task.disabled &&
function() {
function runTask() { function runTask() {
run(task); run(task);
} }
@ -233,7 +264,9 @@ export default function (
delete task.options.throws; delete task.options.throws;
assert.throws(runTask, function(err) { assert.throws(runTask, function(err) {
return throwMsg === true || err.message.indexOf(throwMsg) >= 0; return (
throwMsg === true || err.message.indexOf(throwMsg) >= 0
);
}); });
} else { } else {
if (task.exec.code) { if (task.exec.code) {
@ -245,7 +278,8 @@ export default function (
runTask(); runTask();
} }
} }
}); },
);
} }
}); });
} }

View File

@ -359,7 +359,6 @@ helpers.get = template(`
}); });
`); `);
helpers.inherits = template(` helpers.inherits = template(`
(function (subClass, superClass) { (function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) { if (typeof superClass !== "function" && superClass !== null) {
@ -395,7 +394,6 @@ helpers.instanceof = template(`
}); });
`); `);
helpers.interopRequireDefault = template(` helpers.interopRequireDefault = template(`
(function (obj) { (function (obj) {
return obj && obj.__esModule ? obj : { default: obj }; return obj && obj.__esModule ? obj : { default: obj };

View File

@ -8,7 +8,7 @@ export function get(name) {
} }
export const list = Object.keys(helpers) export const list = Object.keys(helpers)
.map((name) => name.replace(/^_/, "")) .map(name => name.replace(/^_/, ""))
.filter((name) => name !== "__esModule"); .filter(name => name !== "__esModule");
export default get; export default get;

View File

@ -8,38 +8,55 @@ import * as util from "util";
*/ */
export const MESSAGES = { export const MESSAGES = {
tailCallReassignmentDeopt: "Function reference has been reassigned, so it will probably be dereferenced, therefore we can't optimise this with confidence", tailCallReassignmentDeopt:
"Function reference has been reassigned, so it will probably be dereferenced, therefore we can't optimise this with confidence",
classesIllegalBareSuper: "Illegal use of bare super", classesIllegalBareSuper: "Illegal use of bare super",
classesIllegalSuperCall: "Direct super call is illegal in non-constructor, use super.$1() instead", classesIllegalSuperCall:
"Direct super call is illegal in non-constructor, use super.$1() instead",
scopeDuplicateDeclaration: "Duplicate declaration $1", scopeDuplicateDeclaration: "Duplicate declaration $1",
settersNoRest: "Setters aren't allowed to have a rest", settersNoRest: "Setters aren't allowed to have a rest",
noAssignmentsInForHead: "No assignments allowed in for-in/of head", noAssignmentsInForHead: "No assignments allowed in for-in/of head",
expectedMemberExpressionOrIdentifier: "Expected type MemberExpression or Identifier", expectedMemberExpressionOrIdentifier:
invalidParentForThisNode: "We don't know how to handle this node within the current parent - please open an issue", "Expected type MemberExpression or Identifier",
invalidParentForThisNode:
"We don't know how to handle this node within the current parent - please open an issue",
readOnly: "$1 is read-only", readOnly: "$1 is read-only",
unknownForHead: "Unknown node type $1 in ForStatement", unknownForHead: "Unknown node type $1 in ForStatement",
didYouMean: "Did you mean $1?", didYouMean: "Did you mean $1?",
codeGeneratorDeopt: "Note: The code generator has deoptimised the styling of $1 as it exceeds the max of $2.", codeGeneratorDeopt:
missingTemplatesDirectory: "no templates directory - this is most likely the result of a broken `npm publish`. Please report to https://github.com/babel/babel/issues", "Note: The code generator has deoptimised the styling of $1 as it exceeds the max of $2.",
missingTemplatesDirectory:
"no templates directory - this is most likely the result of a broken `npm publish`. Please report to https://github.com/babel/babel/issues",
unsupportedOutputType: "Unsupported output type $1", unsupportedOutputType: "Unsupported output type $1",
illegalMethodName: "Illegal method name $1", illegalMethodName: "Illegal method name $1",
lostTrackNodePath: "We lost track of this node's position, likely because the AST was directly manipulated", lostTrackNodePath:
"We lost track of this node's position, likely because the AST was directly manipulated",
modulesIllegalExportName: "Illegal export $1", modulesIllegalExportName: "Illegal export $1",
modulesDuplicateDeclarations: "Duplicate module declarations with the same source but in different scopes", modulesDuplicateDeclarations:
"Duplicate module declarations with the same source but in different scopes",
undeclaredVariable: "Reference to undeclared variable $1", undeclaredVariable: "Reference to undeclared variable $1",
undeclaredVariableType: "Referencing a type alias outside of a type annotation", undeclaredVariableType:
undeclaredVariableSuggestion: "Reference to undeclared variable $1 - did you mean $2?", "Referencing a type alias outside of a type annotation",
undeclaredVariableSuggestion:
"Reference to undeclared variable $1 - did you mean $2?",
traverseNeedsParent: "You must pass a scope and parentPath unless traversing a Program/File. Instead of that you tried to traverse a $1 node without passing scope and parentPath.", traverseNeedsParent:
traverseVerifyRootFunction: "You passed `traverse()` a function when it expected a visitor object, are you sure you didn't mean `{ enter: Function }`?", "You must pass a scope and parentPath unless traversing a Program/File. Instead of that you tried to traverse a $1 node without passing scope and parentPath.",
traverseVerifyVisitorProperty: "You passed `traverse()` a visitor object with the property $1 that has the invalid property $2", traverseVerifyRootFunction:
traverseVerifyNodeType: "You gave us a visitor for the node type $1 but it's not a valid type", "You passed `traverse()` a function when it expected a visitor object, are you sure you didn't mean `{ enter: Function }`?",
traverseVerifyVisitorProperty:
"You passed `traverse()` a visitor object with the property $1 that has the invalid property $2",
traverseVerifyNodeType:
"You gave us a visitor for the node type $1 but it's not a valid type",
pluginNotObject: "Plugin $2 specified in $1 was expected to return an object when invoked but returned $3", pluginNotObject:
pluginNotFunction: "Plugin $2 specified in $1 was expected to return a function but returned $3", "Plugin $2 specified in $1 was expected to return an object when invoked but returned $3",
pluginUnknown: "Unknown plugin $1 specified in $2 at $3, attempted to resolve relative to $4", pluginNotFunction:
"Plugin $2 specified in $1 was expected to return a function but returned $3",
pluginUnknown:
"Unknown plugin $1 specified in $2 at $3, attempted to resolve relative to $4",
pluginInvalidProperty: "Plugin $1 provided an invalid property of $2", pluginInvalidProperty: "Plugin $1 provided an invalid property of $2",
}; };

View File

@ -12,7 +12,10 @@ export default function ({ types: t }) {
const callee = state.addHelper("asyncGeneratorDelegate"); const callee = state.addHelper("asyncGeneratorDelegate");
node.argument = t.callExpression(callee, [ node.argument = t.callExpression(callee, [
t.callExpression(state.addHelper("asyncIterator"), [node.argument]), t.callExpression(state.addHelper("asyncIterator"), [node.argument]),
t.memberExpression(state.addHelper("asyncGenerator"), t.identifier("await")), t.memberExpression(
state.addHelper("asyncGenerator"),
t.identifier("await"),
),
]); ]);
}, },
}; };
@ -27,9 +30,13 @@ export default function ({ types: t }) {
remapAsyncToGenerator(path, state.file, { remapAsyncToGenerator(path, state.file, {
wrapAsync: t.memberExpression( wrapAsync: t.memberExpression(
state.addHelper("asyncGenerator"), t.identifier("wrap")), state.addHelper("asyncGenerator"),
t.identifier("wrap"),
),
wrapAwait: t.memberExpression( wrapAwait: t.memberExpression(
state.addHelper("asyncGenerator"), t.identifier("await")), state.addHelper("asyncGenerator"),
t.identifier("await"),
),
}); });
}, },
}, },

View File

@ -29,14 +29,20 @@ export default function ({ types: t }) {
}); });
`); `);
const buildClassPropertySpec = (ref, { key, value, computed }) => buildObjectDefineProperty({ const buildClassPropertySpec = (ref, { key, value, computed }) =>
buildObjectDefineProperty({
REF: ref, REF: ref,
KEY: (t.isIdentifier(key) && !computed) ? t.stringLiteral(key.name) : key, KEY: t.isIdentifier(key) && !computed ? t.stringLiteral(key.name) : key,
VALUE: value ? value : t.identifier("undefined"), VALUE: value ? value : t.identifier("undefined"),
}); });
const buildClassPropertyNonSpec = (ref, { key, value, computed }) => t.expressionStatement( const buildClassPropertyNonSpec = (ref, { key, value, computed }) =>
t.assignmentExpression("=", t.memberExpression(ref, key, computed || t.isLiteral(key)), value) t.expressionStatement(
t.assignmentExpression(
"=",
t.memberExpression(ref, key, computed || t.isLiteral(key)),
value,
),
); );
return { return {
@ -44,8 +50,9 @@ export default function ({ types: t }) {
visitor: { visitor: {
Class(path, state) { Class(path, state) {
const buildClassProperty = state.opts.spec ? buildClassPropertySpec : const buildClassProperty = state.opts.spec
buildClassPropertyNonSpec; ? buildClassPropertySpec
: buildClassPropertyNonSpec;
const isDerived = !!path.node.superClass; const isDerived = !!path.node.superClass;
let constructor; let constructor;
const props = []; const props = [];
@ -67,7 +74,8 @@ export default function ({ types: t }) {
if (path.isClassExpression() || !path.node.id) { if (path.isClassExpression() || !path.node.id) {
nameFunction(path); nameFunction(path);
ref = path.scope.generateUidIdentifier("class"); ref = path.scope.generateUidIdentifier("class");
} else { // path.isClassDeclaration() && path.node.id } else {
// path.isClassDeclaration() && path.node.id
ref = path.node.id; ref = path.node.id;
} }
@ -93,17 +101,20 @@ export default function ({ types: t }) {
if (instanceBody.length) { if (instanceBody.length) {
if (!constructor) { if (!constructor) {
const newConstructor = t.classMethod("constructor", t.identifier("constructor"), [], const newConstructor = t.classMethod(
t.blockStatement([])); "constructor",
t.identifier("constructor"),
[],
t.blockStatement([]),
);
if (isDerived) { if (isDerived) {
newConstructor.params = [t.restElement(t.identifier("args"))]; newConstructor.params = [t.restElement(t.identifier("args"))];
newConstructor.body.body.push( newConstructor.body.body.push(
t.returnStatement( t.returnStatement(
t.callExpression( t.callExpression(t.super(), [
t.super(), t.spreadElement(t.identifier("args")),
[t.spreadElement(t.identifier("args"))] ]),
) ),
)
); );
} }
[constructor] = body.unshiftContainer("body", newConstructor); [constructor] = body.unshiftContainer("body", newConstructor);
@ -120,19 +131,29 @@ export default function ({ types: t }) {
} }
if (collisionState.collision) { if (collisionState.collision) {
const initialisePropsRef = path.scope.generateUidIdentifier("initialiseProps"); const initialisePropsRef = path.scope.generateUidIdentifier(
"initialiseProps",
);
nodes.push(t.variableDeclaration("var", [ nodes.push(
t.variableDeclaration("var", [
t.variableDeclarator( t.variableDeclarator(
initialisePropsRef, initialisePropsRef,
t.functionExpression(null, [], t.blockStatement(instanceBody)) t.functionExpression(
null,
[],
t.blockStatement(instanceBody),
), ),
])); ),
]),
);
instanceBody = [ instanceBody = [
t.expressionStatement( t.expressionStatement(
t.callExpression(t.memberExpression(initialisePropsRef, t.identifier("call")), [ t.callExpression(
t.thisExpression()]) t.memberExpression(initialisePropsRef, t.identifier("call")),
[t.thisExpression()],
),
), ),
]; ];
} }
@ -159,7 +180,8 @@ export default function ({ types: t }) {
if (path.isClassExpression()) { if (path.isClassExpression()) {
path.scope.push({ id: ref }); path.scope.push({ id: ref });
path.replaceWith(t.assignmentExpression("=", ref, path.node)); path.replaceWith(t.assignmentExpression("=", ref, path.node));
} else { // path.isClassDeclaration() } else {
// path.isClassDeclaration()
if (!path.node.id) { if (!path.node.id) {
path.node.id = ref; path.node.id = ref;
} }
@ -177,7 +199,7 @@ export default function ({ types: t }) {
const body = classExp.get("body"); const body = classExp.get("body");
const members = body.get("body"); const members = body.get("body");
if (members.some((member) => member.isClassProperty())) { if (members.some(member => member.isClassProperty())) {
path.ensureBlock(); path.ensureBlock();
} }
}, },

View File

@ -15,7 +15,6 @@ const buildGetDescriptor = template(`
Object.getOwnPropertyDescriptor(TARGET, PROPERTY); Object.getOwnPropertyDescriptor(TARGET, PROPERTY);
`); `);
const buildGetObjectInitializer = template(` const buildGetObjectInitializer = template(`
(TEMP = Object.getOwnPropertyDescriptor(TARGET, PROPERTY), (TEMP = TEMP ? TEMP.value : undefined), { (TEMP = Object.getOwnPropertyDescriptor(TARGET, PROPERTY), (TEMP = TEMP ? TEMP.value : undefined), {
enumerable: true, enumerable: true,
@ -88,7 +87,9 @@ export default function({ types: t }) {
*/ */
function ensureApplyDecoratedDescriptorHelper(path, state) { function ensureApplyDecoratedDescriptorHelper(path, state) {
if (!state.applyDecoratedDescriptor) { if (!state.applyDecoratedDescriptor) {
state.applyDecoratedDescriptor = path.scope.generateUidIdentifier("applyDecoratedDescriptor"); state.applyDecoratedDescriptor = path.scope.generateUidIdentifier(
"applyDecoratedDescriptor",
);
const helper = buildApplyDecoratedDescriptor({ const helper = buildApplyDecoratedDescriptor({
NAME: state.applyDecoratedDescriptor, NAME: state.applyDecoratedDescriptor,
}); });
@ -103,7 +104,9 @@ export default function({ types: t }) {
*/ */
function ensureInitializerDefineProp(path, state) { function ensureInitializerDefineProp(path, state) {
if (!state.initializerDefineProp) { if (!state.initializerDefineProp) {
state.initializerDefineProp = path.scope.generateUidIdentifier("initDefineProp"); state.initializerDefineProp = path.scope.generateUidIdentifier(
"initDefineProp",
);
const helper = buildInitializerDefineProperty({ const helper = buildInitializerDefineProperty({
NAME: state.initializerDefineProp, NAME: state.initializerDefineProp,
}); });
@ -119,7 +122,9 @@ export default function({ types: t }) {
*/ */
function ensureInitializerWarning(path, state) { function ensureInitializerWarning(path, state) {
if (!state.initializerWarningHelper) { if (!state.initializerWarningHelper) {
state.initializerWarningHelper = path.scope.generateUidIdentifier("initializerWarningHelper"); state.initializerWarningHelper = path.scope.generateUidIdentifier(
"initializerWarningHelper",
);
const helper = buildInitializerWarningHelper({ const helper = buildInitializerWarningHelper({
NAME: state.initializerWarningHelper, NAME: state.initializerWarningHelper,
}); });
@ -135,20 +140,29 @@ export default function({ types: t }) {
*/ */
function applyEnsureOrdering(path) { function applyEnsureOrdering(path) {
// TODO: This should probably also hoist computed properties. // TODO: This should probably also hoist computed properties.
const decorators = ( const decorators = (path.isClass()
path.isClass()
? [path].concat(path.get("body.body")) ? [path].concat(path.get("body.body"))
: path.get("properties") : path.get("properties")).reduce(
).reduce((acc, prop) => acc.concat(prop.node.decorators || []), []); (acc, prop) => acc.concat(prop.node.decorators || []),
[],
);
const identDecorators = decorators.filter((decorator) => !t.isIdentifier(decorator.expression)); const identDecorators = decorators.filter(
decorator => !t.isIdentifier(decorator.expression),
);
if (identDecorators.length === 0) return; if (identDecorators.length === 0) return;
return t.sequenceExpression(identDecorators.map((decorator) => { return t.sequenceExpression(
identDecorators
.map(decorator => {
const expression = decorator.expression; const expression = decorator.expression;
const id = decorator.expression = path.scope.generateDeclaredUidIdentifier("dec"); const id = (decorator.expression = path.scope.generateDeclaredUidIdentifier(
"dec",
));
return t.assignmentExpression("=", id, expression); return t.assignmentExpression("=", id, expression);
}).concat([path.node])); })
.concat([path.node]),
);
} }
/** /**
@ -164,7 +178,7 @@ export default function({ types: t }) {
const name = classPath.scope.generateDeclaredUidIdentifier("class"); const name = classPath.scope.generateDeclaredUidIdentifier("class");
return decorators return decorators
.map((dec) => dec.expression) .map(dec => dec.expression)
.reverse() .reverse()
.reduce(function(acc, decorator) { .reduce(function(acc, decorator) {
return buildClassDecorator({ return buildClassDecorator({
@ -207,7 +221,9 @@ export default function({ types: t }) {
* A helper to pull out property decorators into a sequence expression. * A helper to pull out property decorators into a sequence expression.
*/ */
function applyTargetDecorators(path, state, decoratedProps) { function applyTargetDecorators(path, state, decoratedProps) {
const name = path.scope.generateDeclaredUidIdentifier(path.isClass() ? "class" : "obj"); const name = path.scope.generateDeclaredUidIdentifier(
path.isClass() ? "class" : "obj",
);
const exprs = decoratedProps.reduce(function(acc, node) { const exprs = decoratedProps.reduce(function(acc, node) {
const decorators = node.decorators || []; const decorators = node.decorators || [];
@ -216,36 +232,58 @@ export default function({ types: t }) {
if (decorators.length === 0) return acc; if (decorators.length === 0) return acc;
if (node.computed) { if (node.computed) {
throw path.buildCodeFrameError("Computed method/property decorators are not yet supported."); throw path.buildCodeFrameError(
"Computed method/property decorators are not yet supported.",
);
} }
const property = t.isLiteral(node.key) ? node.key : t.stringLiteral(node.key.name); const property = t.isLiteral(node.key)
? node.key
: t.stringLiteral(node.key.name);
const target = (path.isClass() && !node.static) ? buildClassPrototype({ const target =
path.isClass() && !node.static
? buildClassPrototype({
CLASS_REF: name, CLASS_REF: name,
}).expression : name; }).expression
: name;
if (t.isClassProperty(node, { static: false })) { if (t.isClassProperty(node, { static: false })) {
const descriptor = path.scope.generateDeclaredUidIdentifier("descriptor"); const descriptor = path.scope.generateDeclaredUidIdentifier(
"descriptor",
const initializer = node.value ?
t.functionExpression(null, [], t.blockStatement([t.returnStatement(node.value)])) :
t.nullLiteral();
node.value = t.callExpression(
ensureInitializerWarning(path, state), [descriptor, t.thisExpression()]
); );
const initializer = node.value
? t.functionExpression(
null,
[],
t.blockStatement([t.returnStatement(node.value)]),
)
: t.nullLiteral();
node.value = t.callExpression(ensureInitializerWarning(path, state), [
descriptor,
t.thisExpression(),
]);
acc = acc.concat([ acc = acc.concat([
t.assignmentExpression( t.assignmentExpression(
"=", descriptor, t.callExpression(ensureApplyDecoratedDescriptorHelper(path, state), [ "=",
descriptor,
t.callExpression(
ensureApplyDecoratedDescriptorHelper(path, state),
[
target, target,
property, property,
t.arrayExpression(decorators.map((dec) => dec.expression)), t.arrayExpression(decorators.map(dec => dec.expression)),
t.objectExpression([ t.objectExpression([
t.objectProperty(t.identifier("enumerable"), t.booleanLiteral(true)), t.objectProperty(
t.identifier("enumerable"),
t.booleanLiteral(true),
),
t.objectProperty(t.identifier("initializer"), initializer), t.objectProperty(t.identifier("initializer"), initializer),
]), ]),
]) ],
),
), ),
]); ]);
} else { } else {
@ -253,21 +291,20 @@ export default function({ types: t }) {
t.callExpression(ensureApplyDecoratedDescriptorHelper(path, state), [ t.callExpression(ensureApplyDecoratedDescriptorHelper(path, state), [
target, target,
property, property,
t.arrayExpression(decorators.map((dec) => dec.expression)), t.arrayExpression(decorators.map(dec => dec.expression)),
(
t.isObjectProperty(node) || t.isObjectProperty(node) ||
t.isClassProperty(node, { static: true })) ? t.isClassProperty(node, { static: true })
buildGetObjectInitializer({ ? buildGetObjectInitializer({
TEMP: path.scope.generateDeclaredUidIdentifier("init"), TEMP: path.scope.generateDeclaredUidIdentifier("init"),
TARGET: target, TARGET: target,
PROPERTY: property, PROPERTY: property,
}).expression : buildGetDescriptor({ }).expression
: buildGetDescriptor({
TARGET: target, TARGET: target,
PROPERTY: property, PROPERTY: property,
} }).expression,
).expression,
target, target,
]) ]),
); );
} }
@ -289,35 +326,42 @@ export default function({ types: t }) {
if (!path.get("declaration").isClassDeclaration()) return; if (!path.get("declaration").isClassDeclaration()) return;
const { node } = path; const { node } = path;
const ref = node.declaration.id || path.scope.generateUidIdentifier("default"); const ref =
node.declaration.id || path.scope.generateUidIdentifier("default");
node.declaration.id = ref; node.declaration.id = ref;
// Split the class declaration and the export into two separate statements. // Split the class declaration and the export into two separate statements.
path.replaceWith(node.declaration); path.replaceWith(node.declaration);
path.insertAfter(t.exportNamedDeclaration(null, [t.exportSpecifier(ref, t.identifier("default"))])); path.insertAfter(
t.exportNamedDeclaration(null, [
t.exportSpecifier(ref, t.identifier("default")),
]),
);
}, },
ClassDeclaration(path) { ClassDeclaration(path) {
const { node } = path; const { node } = path;
const ref = node.id || path.scope.generateUidIdentifier("class"); const ref = node.id || path.scope.generateUidIdentifier("class");
path.replaceWith(t.variableDeclaration("let", [ path.replaceWith(
t.variableDeclaration("let", [
t.variableDeclarator(ref, t.toExpression(node)), t.variableDeclarator(ref, t.toExpression(node)),
])); ]),
);
}, },
ClassExpression(path, state) { ClassExpression(path, state) {
// Create a replacement for the class node if there is one. We do one pass to replace classes with // Create a replacement for the class node if there is one. We do one pass to replace classes with
// class decorators, and a second pass to process method decorators. // class decorators, and a second pass to process method decorators.
const decoratedClass = ( const decoratedClass =
applyEnsureOrdering(path) || applyEnsureOrdering(path) ||
applyClassDecorators(path, state) || applyClassDecorators(path, state) ||
applyMethodDecorators(path, state) applyMethodDecorators(path, state);
);
if (decoratedClass) path.replaceWith(decoratedClass); if (decoratedClass) path.replaceWith(decoratedClass);
}, },
ObjectExpression(path, state) { ObjectExpression(path, state) {
const decoratedObject = applyEnsureOrdering(path) || applyObjectDecorators(path, state); const decoratedObject =
applyEnsureOrdering(path) || applyObjectDecorators(path, state);
if (decoratedObject) path.replaceWith(decoratedObject); if (decoratedObject) path.replaceWith(decoratedObject);
}, },
@ -328,14 +372,22 @@ export default function({ types: t }) {
if (!path.get("left").isMemberExpression()) return; if (!path.get("left").isMemberExpression()) return;
if (!path.get("left.property").isIdentifier()) return; if (!path.get("left.property").isIdentifier()) return;
if (!path.get("right").isCallExpression()) return; if (!path.get("right").isCallExpression()) return;
if (!path.get("right.callee").isIdentifier({ name: state.initializerWarningHelper.name })) return; if (
!path
.get("right.callee")
.isIdentifier({ name: state.initializerWarningHelper.name })
) {
return;
}
path.replaceWith(t.callExpression(ensureInitializerDefineProp(path, state), [ path.replaceWith(
t.callExpression(ensureInitializerDefineProp(path, state), [
path.get("left.object").node, path.get("left.object").node,
t.stringLiteral(path.get("left.property").node.name), t.stringLiteral(path.get("left.property").node.name),
path.get("right.arguments")[0].node, path.get("right.arguments")[0].node,
path.get("right.arguments")[1].node, path.get("right.arguments")[1].node,
])); ]),
);
}, },
}, },
}; };

View File

@ -5,7 +5,10 @@ import type NodePath from "babel-traverse";
export default function() { export default function() {
return { return {
visitor: { visitor: {
ArrowFunctionExpression(path: NodePath<BabelNodeArrowFunctionExpression>, state: Object) { ArrowFunctionExpression(
path: NodePath<BabelNodeArrowFunctionExpression>,
state: Object,
) {
// In some conversion cases, it may have already been converted to a function while this callback // In some conversion cases, it may have already been converted to a function while this callback
// was queued up. // was queued up.
if (!path.isArrowFunctionExpression()) return; if (!path.isArrowFunctionExpression()) return;

View File

@ -24,7 +24,10 @@ export default function ({ types: t }) {
visitor: { visitor: {
BlockStatement(path) { BlockStatement(path) {
const { node, parent } = path; const { node, parent } = path;
if (t.isFunction(parent, { body: node }) || t.isExportDeclaration(parent)) { if (
t.isFunction(parent, { body: node }) ||
t.isExportDeclaration(parent)
) {
return; return;
} }

View File

@ -44,20 +44,38 @@ export default function () {
Loop(path, file) { Loop(path, file) {
const { node, parent, scope } = path; const { node, parent, scope } = path;
t.ensureBlock(node); t.ensureBlock(node);
const blockScoping = new BlockScoping(path, path.get("body"), parent, scope, file); const blockScoping = new BlockScoping(
path,
path.get("body"),
parent,
scope,
file,
);
const replace = blockScoping.run(); const replace = blockScoping.run();
if (replace) path.replaceWith(replace); if (replace) path.replaceWith(replace);
}, },
CatchClause(path, file) { CatchClause(path, file) {
const { parent, scope } = path; const { parent, scope } = path;
const blockScoping = new BlockScoping(null, path.get("body"), parent, scope, file); const blockScoping = new BlockScoping(
null,
path.get("body"),
parent,
scope,
file,
);
blockScoping.run(); blockScoping.run();
}, },
"BlockStatement|SwitchStatement|Program"(path, file) { "BlockStatement|SwitchStatement|Program"(path, file) {
if (!ignoreBlock(path)) { if (!ignoreBlock(path)) {
const blockScoping = new BlockScoping(null, path, path.parent, path.scope, file); const blockScoping = new BlockScoping(
null,
path,
path.parent,
path.scope,
file,
);
blockScoping.run(); blockScoping.run();
} }
}, },
@ -80,7 +98,13 @@ function isBlockScoped(node) {
return true; return true;
} }
function convertBlockScopedToVar(path, node, parent, scope, moveBindingsToParent = false) { function convertBlockScopedToVar(
path,
node,
parent,
scope,
moveBindingsToParent = false,
) {
if (!node) { if (!node) {
node = path.node; node = path.node;
} }
@ -111,7 +135,8 @@ function isVar(node) {
return t.isVariableDeclaration(node, { kind: "var" }) && !isBlockScoped(node); return t.isVariableDeclaration(node, { kind: "var" }) && !isBlockScoped(node);
} }
const letReferenceBlockVisitor = traverse.visitors.merge([{ const letReferenceBlockVisitor = traverse.visitors.merge([
{
Loop: { Loop: {
enter(path, state) { enter(path, state) {
state.loopDepth++; state.loopDepth++;
@ -129,9 +154,12 @@ const letReferenceBlockVisitor = traverse.visitors.merge([{
} }
return path.skip(); return path.skip();
}, },
}, tdzVisitor]); },
tdzVisitor,
]);
const letReferenceFunctionVisitor = traverse.visitors.merge([{ const letReferenceFunctionVisitor = traverse.visitors.merge([
{
ReferencedIdentifier(path, state) { ReferencedIdentifier(path, state) {
const ref = state.letReferences[path.node.name]; const ref = state.letReferences[path.node.name];
@ -145,7 +173,9 @@ const letReferenceFunctionVisitor = traverse.visitors.merge([{
state.closurify = true; state.closurify = true;
}, },
}, tdzVisitor]); },
tdzVisitor,
]);
const hoistVarDeclarationsVisitor = { const hoistVarDeclarationsVisitor = {
enter(path, self) { enter(path, self) {
@ -166,7 +196,9 @@ const hoistVarDeclarationsVisitor = {
node.left = node.left.declarations[0].id; node.left = node.left.declarations[0].id;
} }
} else if (isVar(node, parent)) { } else if (isVar(node, parent)) {
path.replaceWithMultiple(self.pushDeclar(node).map((expr) => t.expressionStatement(expr))); path.replaceWithMultiple(
self.pushDeclar(node).map(expr => t.expressionStatement(expr)),
);
} else if (path.isFunction()) { } else if (path.isFunction()) {
return path.skip(); return path.skip();
} }
@ -184,7 +216,12 @@ const continuationVisitor = {
if (path.isAssignmentExpression() || path.isUpdateExpression()) { if (path.isAssignmentExpression() || path.isUpdateExpression()) {
const bindings = path.getBindingIdentifiers(); const bindings = path.getBindingIdentifiers();
for (const name in bindings) { for (const name in bindings) {
if (state.outsideReferences[name] !== path.scope.getBindingIdentifier(name)) continue; if (
state.outsideReferences[name] !==
path.scope.getBindingIdentifier(name)
) {
continue;
}
state.reassignments[name] = true; state.reassignments[name] = true;
} }
} }
@ -252,7 +289,10 @@ const loopVisitor = {
if (path.isReturnStatement()) { if (path.isReturnStatement()) {
state.hasReturn = true; state.hasReturn = true;
replace = t.objectExpression([ replace = t.objectExpression([
t.objectProperty(t.identifier("v"), node.argument || scope.buildUndefinedNode()), t.objectProperty(
t.identifier("v"),
node.argument || scope.buildUndefinedNode(),
),
]); ]);
} }
@ -266,7 +306,13 @@ const loopVisitor = {
}; };
class BlockScoping { class BlockScoping {
constructor(loopPath?: NodePath, blockPath: NodePath, parent: Object, scope: Scope, file: File) { constructor(
loopPath?: NodePath,
blockPath: NodePath,
parent: Object,
scope: Scope,
file: File,
) {
this.parent = parent; this.parent = parent;
this.scope = scope; this.scope = scope;
this.file = file; this.file = file;
@ -281,7 +327,8 @@ class BlockScoping {
if (loopPath) { if (loopPath) {
this.loopParent = loopPath.parent; this.loopParent = loopPath.parent;
this.loopLabel = t.isLabeledStatement(this.loopParent) && this.loopParent.label; this.loopLabel =
t.isLabeledStatement(this.loopParent) && this.loopParent.label;
this.loopPath = loopPath; this.loopPath = loopPath;
this.loop = loopPath.node; this.loop = loopPath.node;
} }
@ -360,11 +407,13 @@ class BlockScoping {
// The same identifier might have been bound separately in the block scope and // The same identifier might have been bound separately in the block scope and
// the enclosing scope (e.g. loop or catch statement), so we should handle both // the enclosing scope (e.g. loop or catch statement), so we should handle both
// individually // individually
if (scope.hasOwnBinding(key)) if (scope.hasOwnBinding(key)) {
{scope.rename(ref.name);} scope.rename(ref.name);
}
if (this.blockPath.scope.hasOwnBinding(key)) if (this.blockPath.scope.hasOwnBinding(key)) {
{this.blockPath.scope.rename(ref.name);} this.blockPath.scope.rename(ref.name);
}
} }
} }
} }
@ -373,7 +422,7 @@ class BlockScoping {
if (this.file.opts.throwIfClosureRequired) { if (this.file.opts.throwIfClosureRequired) {
throw this.blockPath.buildCodeFrameError( throw this.blockPath.buildCodeFrameError(
"Compiling let/const in this block would add a closure " + "Compiling let/const in this block would add a closure " +
"(throwIfClosureRequired)." "(throwIfClosureRequired).",
); );
} }
const block = this.block; const block = this.block;
@ -385,7 +434,10 @@ class BlockScoping {
for (const name in outsideRefs) { for (const name in outsideRefs) {
const id = outsideRefs[name]; const id = outsideRefs[name];
if (this.scope.hasGlobal(id.name) || this.scope.parentHasBinding(id.name)) { if (
this.scope.hasGlobal(id.name) ||
this.scope.parentHasBinding(id.name)
) {
delete outsideRefs[id.name]; delete outsideRefs[id.name];
delete this.letReferences[id.name]; delete this.letReferences[id.name];
@ -411,8 +463,11 @@ class BlockScoping {
const isSwitch = this.blockPath.isSwitchStatement(); const isSwitch = this.blockPath.isSwitchStatement();
// build the closure that we're going to wrap the block with, possible wrapping switch(){} // build the closure that we're going to wrap the block with, possible wrapping switch(){}
const fn = t.functionExpression(null, params, const fn = t.functionExpression(
t.blockStatement(isSwitch ? [block] : block.body)); null,
params,
t.blockStatement(isSwitch ? [block] : block.body),
);
// continuation // continuation
this.addContinuations(fn); this.addContinuations(fn);
@ -421,7 +476,12 @@ class BlockScoping {
let basePath = ".callee"; let basePath = ".callee";
// handle generators // handle generators
const hasYield = traverse.hasType(fn.body, this.scope, "YieldExpression", t.FUNCTION_TYPES); const hasYield = traverse.hasType(
fn.body,
this.scope,
"YieldExpression",
t.FUNCTION_TYPES,
);
if (hasYield) { if (hasYield) {
fn.generator = true; fn.generator = true;
call = t.yieldExpression(call, true); call = t.yieldExpression(call, true);
@ -429,7 +489,12 @@ class BlockScoping {
} }
// handlers async functions // handlers async functions
const hasAsync = traverse.hasType(fn.body, this.scope, "AwaitExpression", t.FUNCTION_TYPES); const hasAsync = traverse.hasType(
fn.body,
this.scope,
"AwaitExpression",
t.FUNCTION_TYPES,
);
if (hasAsync) { if (hasAsync) {
fn.async = true; fn.async = true;
call = t.awaitExpression(call); call = t.awaitExpression(call);
@ -441,9 +506,9 @@ class BlockScoping {
if (this.has.hasReturn || this.has.hasBreakContinue) { if (this.has.hasReturn || this.has.hasBreakContinue) {
const ret = this.scope.generateUidIdentifier("ret"); const ret = this.scope.generateUidIdentifier("ret");
this.body.push(t.variableDeclaration("var", [ this.body.push(
t.variableDeclarator(ret, call), t.variableDeclaration("var", [t.variableDeclarator(ret, call)]),
])); );
placeholderPath = "declarations.0.init" + basePath; placeholderPath = "declarations.0.init" + basePath;
index = this.body.length - 1; index = this.body.length - 1;
@ -471,9 +536,9 @@ class BlockScoping {
let fnPath; let fnPath;
if (this.loop) { if (this.loop) {
const ref = this.scope.generateUidIdentifier("loop"); const ref = this.scope.generateUidIdentifier("loop");
const p = this.loopPath.insertBefore(t.variableDeclaration("var", [ const p = this.loopPath.insertBefore(
t.variableDeclarator(ref, fn), t.variableDeclaration("var", [t.variableDeclarator(ref, fn)]),
])); );
placeholder.replaceWith(ref); placeholder.replaceWith(ref);
fnPath = p[0].get("declarations.0.init"); fnPath = p[0].get("declarations.0.init");
@ -512,7 +577,9 @@ class BlockScoping {
this.scope.rename(param.name, newParam.name, fn); this.scope.rename(param.name, newParam.name, fn);
// assign outer reference as it's been modified internally and needs to be retained // assign outer reference as it's been modified internally and needs to be retained
fn.body.body.push(t.expressionStatement(t.assignmentExpression("=", param, newParam))); fn.body.body.push(
t.expressionStatement(t.assignmentExpression("=", param, newParam)),
);
} }
} }
@ -531,7 +598,11 @@ class BlockScoping {
const addDeclarationsFromChild = (path, node) => { const addDeclarationsFromChild = (path, node) => {
node = node || path.node; node = node || path.node;
if (t.isClassDeclaration(node) || t.isFunctionDeclaration(node) || isBlockScoped(node)) { if (
t.isClassDeclaration(node) ||
t.isFunctionDeclaration(node) ||
isBlockScoped(node)
) {
if (isBlockScoped(node)) { if (isBlockScoped(node)) {
convertBlockScopedToVar(path, node, block, this.scope); convertBlockScopedToVar(path, node, block, this.scope);
} }
@ -585,7 +656,7 @@ class BlockScoping {
}; };
const loopOrFunctionParent = this.blockPath.find( const loopOrFunctionParent = this.blockPath.find(
(path) => path.isLoop() || path.isFunction() path => path.isLoop() || path.isFunction(),
); );
if (loopOrFunctionParent && loopOrFunctionParent.isLoop()) { if (loopOrFunctionParent && loopOrFunctionParent.isLoop()) {
// There is a loop ancestor closer than the closest function, so we // There is a loop ancestor closer than the closest function, so we
@ -686,18 +757,20 @@ class BlockScoping {
if (cases.length === 1) { if (cases.length === 1) {
const single = cases[0]; const single = cases[0];
body.push(t.ifStatement( body.push(
t.ifStatement(
t.binaryExpression("===", ret, single.test), t.binaryExpression("===", ret, single.test),
single.consequent[0] single.consequent[0],
)); ),
);
} else { } else {
if (this.loop) { if (this.loop) {
// https://github.com/babel/babel/issues/998 // https://github.com/babel/babel/issues/998
for (let i = 0; i < cases.length; i++) { for (let i = 0; i < cases.length; i++) {
const caseConsequent = cases[i].consequent[0]; const caseConsequent = cases[i].consequent[0];
if (t.isBreakStatement(caseConsequent) && !caseConsequent.label) { if (t.isBreakStatement(caseConsequent) && !caseConsequent.label) {
caseConsequent.label = this.loopLabel = this.loopLabel || caseConsequent.label = this.loopLabel =
this.scope.generateUidIdentifier("loop"); this.loopLabel || this.scope.generateUidIdentifier("loop");
} }
} }
} }

View File

@ -13,10 +13,11 @@ function getTDZStatus(refPath, bindingPath) {
} }
function buildTDZAssert(node, file) { function buildTDZAssert(node, file) {
return t.callExpression( return t.callExpression(file.addHelper("temporalRef"), [
file.addHelper("temporalRef"), node,
[node, t.stringLiteral(node.name), file.addHelper("temporalUndefined")] t.stringLiteral(node.name),
); file.addHelper("temporalUndefined"),
]);
} }
function isReference(node, scope, state) { function isReference(node, scope, state) {
@ -56,12 +57,18 @@ export const visitor = {
path.replaceWith(assert); path.replaceWith(assert);
} }
} else if (status === "outside") { } else if (status === "outside") {
path.replaceWith(t.throwStatement(t.inherits( path.replaceWith(
t.throwStatement(
t.inherits(
t.newExpression(t.identifier("ReferenceError"), [ t.newExpression(t.identifier("ReferenceError"), [
t.stringLiteral(`${node.name} is not defined - temporal dead zone`), t.stringLiteral(
`${node.name} is not defined - temporal dead zone`,
),
]), ]),
node node,
))); ),
),
);
} }
}, },

View File

@ -12,15 +12,17 @@ export default function ({ types: t }) {
if (!path.get("declaration").isClassDeclaration()) return; if (!path.get("declaration").isClassDeclaration()) return;
const { node } = path; const { node } = path;
const ref = node.declaration.id || path.scope.generateUidIdentifier("class"); const ref =
node.declaration.id || path.scope.generateUidIdentifier("class");
node.declaration.id = ref; node.declaration.id = ref;
// Split the class declaration and the export into two separate statements. // Split the class declaration and the export into two separate statements.
path.replaceWith(node.declaration); path.replaceWith(node.declaration);
path.insertAfter(t.exportNamedDeclaration( path.insertAfter(
null, t.exportNamedDeclaration(null, [
[t.exportSpecifier(ref, t.identifier("default"))] t.exportSpecifier(ref, t.identifier("default")),
)); ]),
);
}, },
ClassDeclaration(path) { ClassDeclaration(path) {
@ -28,9 +30,11 @@ export default function ({ types: t }) {
const ref = node.id || path.scope.generateUidIdentifier("class"); const ref = node.id || path.scope.generateUidIdentifier("class");
path.replaceWith(t.variableDeclaration("let", [ path.replaceWith(
t.variableDeclaration("let", [
t.variableDeclarator(ref, t.toExpression(node)), t.variableDeclarator(ref, t.toExpression(node)),
])); ]),
);
}, },
ClassExpression(path, state) { ClassExpression(path, state) {
@ -47,7 +51,10 @@ export default function ({ types: t }) {
path.replaceWith(new Constructor(path, state.file).run()); path.replaceWith(new Constructor(path, state.file).run());
if (path.isCallExpression() && path.get("callee").isArrowFunctionExpression()) { if (
path.isCallExpression() &&
path.get("callee").isArrowFunctionExpression()
) {
path.get("callee").arrowFunctionToExpression(); path.get("callee").arrowFunctionToExpression();
} }
}, },

View File

@ -1,7 +1,10 @@
import type { Scope } from "babel-traverse"; import type { Scope } from "babel-traverse";
import * as t from "babel-types"; import * as t from "babel-types";
export default function (decorators: Array<Object>, scope: Scope): Array<Object> { export default function(
decorators: Array<Object>,
scope: Scope,
): Array<Object> {
for (const decorator of decorators) { for (const decorator of decorators) {
const expression = decorator.expression; const expression = decorator.expression;
if (!t.isMemberExpression(expression)) continue; if (!t.isMemberExpression(expression)) continue;
@ -18,13 +21,15 @@ export default function (decorators: Array<Object>, scope: Scope): Array<Object>
ref = expression.object; ref = expression.object;
} }
nodes.push(t.callExpression( nodes.push(
t.callExpression(
t.memberExpression( t.memberExpression(
t.memberExpression(ref, expression.property, expression.computed), t.memberExpression(ref, expression.property, expression.computed),
t.identifier("bind") t.identifier("bind"),
), ),
[ref] [ref],
)); ),
);
if (nodes.length === 1) { if (nodes.length === 1) {
decorator.expression = nodes[0]; decorator.expression = nodes[0];

View File

@ -13,10 +13,22 @@ export default class LooseClassTransformer extends VanillaTransformer {
// use assignments instead of define properties for loose classes // use assignments instead of define properties for loose classes
let classRef = this.classRef; let classRef = this.classRef;
if (!node.static) classRef = t.memberExpression(classRef, t.identifier("prototype")); if (!node.static) {
const methodName = t.memberExpression(classRef, node.key, node.computed || t.isLiteral(node.key)); classRef = t.memberExpression(classRef, t.identifier("prototype"));
}
const methodName = t.memberExpression(
classRef,
node.key,
node.computed || t.isLiteral(node.key),
);
let func = t.functionExpression(null, node.params, node.body, node.generator, node.async); let func = t.functionExpression(
null,
node.params,
node.body,
node.generator,
node.async,
);
func.returnType = node.returnType; func.returnType = node.returnType;
const key = t.toComputedKey(node, node.key); const key = t.toComputedKey(node, node.key);
if (t.isStringLiteral(key)) { if (t.isStringLiteral(key)) {
@ -27,7 +39,9 @@ export default class LooseClassTransformer extends VanillaTransformer {
}); });
} }
const expr = t.expressionStatement(t.assignmentExpression("=", methodName, func)); const expr = t.expressionStatement(
t.assignmentExpression("=", methodName, func),
);
t.inheritsComments(expr, node); t.inheritsComments(expr, node);
this.body.push(expr); this.body.push(expr);
return true; return true;

View File

@ -22,14 +22,20 @@ const noMethodVisitor = {
}, },
}; };
const verifyConstructorVisitor = visitors.merge([noMethodVisitor, { const verifyConstructorVisitor = visitors.merge([
noMethodVisitor,
{
MemberExpression: { MemberExpression: {
exit(path) { exit(path) {
const objectPath = path.get("object"); const objectPath = path.get("object");
if (this.isDerived && !this.hasBareSuper && objectPath.isSuper()) { if (this.isDerived && !this.hasBareSuper && objectPath.isSuper()) {
const hasArrowFunctionParent = path.findParent((p) => p.isArrowFunctionExpression()); const hasArrowFunctionParent = path.findParent(p =>
p.isArrowFunctionExpression(),
);
if (!hasArrowFunctionParent) { if (!hasArrowFunctionParent) {
throw objectPath.buildCodeFrameError("'super.*' is not allowed before super()"); throw objectPath.buildCodeFrameError(
"'super.*' is not allowed before super()",
);
} }
} }
}, },
@ -41,7 +47,9 @@ const verifyConstructorVisitor = visitors.merge([noMethodVisitor, {
this.hasBareSuper = true; this.hasBareSuper = true;
if (!this.isDerived) { if (!this.isDerived) {
throw path.buildCodeFrameError("super() is only allowed in a derived constructor"); throw path.buildCodeFrameError(
"super() is only allowed in a derived constructor",
);
} }
} }
}, },
@ -49,20 +57,26 @@ const verifyConstructorVisitor = visitors.merge([noMethodVisitor, {
ThisExpression(path) { ThisExpression(path) {
if (this.isDerived && !this.hasBareSuper) { if (this.isDerived && !this.hasBareSuper) {
const fn = path.find((p) => p.isFunction()); const fn = path.find(p => p.isFunction());
if (!fn || !fn.isArrowFunctionExpression()) { if (!fn || !fn.isArrowFunctionExpression()) {
throw path.buildCodeFrameError("'this' is not allowed before super()"); throw path.buildCodeFrameError(
"'this' is not allowed before super()",
);
} }
} }
}, },
}]); },
]);
const findThisesVisitor = visitors.merge([noMethodVisitor, { const findThisesVisitor = visitors.merge([
noMethodVisitor,
{
ThisExpression(path) { ThisExpression(path) {
this.superThises.push(path); this.superThises.push(path);
}, },
}]); },
]);
export default class ClassTransformer { export default class ClassTransformer {
constructor(path: NodePath, file) { constructor(path: NodePath, file) {
@ -92,8 +106,9 @@ export default class ClassTransformer {
this.classId = this.node.id; this.classId = this.node.id;
// this is the name of the binding that will **always** reference the class we've constructed // this is the name of the binding that will **always** reference the class we've constructed
this.classRef = this.node.id ? t.identifier(this.node.id.name) : this.classRef = this.node.id
this.scope.generateUidIdentifier("class"); ? t.identifier(this.node.id.name)
: this.scope.generateUidIdentifier("class");
this.superName = this.node.superClass || t.identifier("Function"); this.superName = this.node.superClass || t.identifier("Function");
this.isDerived = !!this.node.superClass; this.isDerived = !!this.node.superClass;
@ -106,7 +121,7 @@ export default class ClassTransformer {
// //
const constructorBody = this.constructorBody = t.blockStatement([]); const constructorBody = (this.constructorBody = t.blockStatement([]));
this.constructor = this.buildConstructor(); this.constructor = this.buildConstructor();
// //
@ -129,15 +144,17 @@ export default class ClassTransformer {
// make sure this class isn't directly called (with A() instead new A()) // make sure this class isn't directly called (with A() instead new A())
if (!this.isLoose) { if (!this.isLoose) {
constructorBody.body.unshift(t.expressionStatement(t.callExpression( constructorBody.body.unshift(
file.addHelper("classCallCheck"), [ t.expressionStatement(
t.callExpression(file.addHelper("classCallCheck"), [
t.thisExpression(), t.thisExpression(),
this.classRef, this.classRef,
] ]),
))); ),
);
} }
body = body.concat(this.staticPropBody.map((fn) => fn(this.classRef))); body = body.concat(this.staticPropBody.map(fn => fn(this.classRef)));
if (this.classId) { if (this.classId) {
// named class with only a constructor // named class with only a constructor
@ -147,7 +164,10 @@ export default class ClassTransformer {
// //
body.push(t.returnStatement(this.classRef)); body.push(t.returnStatement(this.classRef));
const container = t.arrowFunctionExpression(closureParams, t.blockStatement(body)); const container = t.arrowFunctionExpression(
closureParams,
t.blockStatement(body),
);
return t.callExpression(container, closureArgs); return t.callExpression(container, closureArgs);
} }
@ -201,12 +221,12 @@ export default class ClassTransformer {
body = t.blockStatement([]); body = t.blockStatement([]);
} }
this.path.get("body").unshiftContainer("body", t.classMethod( this.path
"constructor", .get("body")
t.identifier("constructor"), .unshiftContainer(
params, "body",
body t.classMethod("constructor", t.identifier("constructor"), params, body),
)); );
} }
buildBody() { buildBody() {
@ -216,7 +236,9 @@ export default class ClassTransformer {
if (this.userConstructor) { if (this.userConstructor) {
const constructorBody = this.constructorBody; const constructorBody = this.constructorBody;
constructorBody.body = constructorBody.body.concat(this.userConstructor.body.body); constructorBody.body = constructorBody.body.concat(
this.userConstructor.body.body,
);
t.inherits(this.constructor, this.userConstructor); t.inherits(this.constructor, this.userConstructor);
t.inherits(constructorBody, this.userConstructor.body); t.inherits(constructorBody, this.userConstructor.body);
} }
@ -236,7 +258,8 @@ export default class ClassTransformer {
if (node.decorators) { if (node.decorators) {
throw path.buildCodeFrameError( throw path.buildCodeFrameError(
"Method has decorators, put the decorator plugin before the classes one."); "Method has decorators, put the decorator plugin before the classes one.",
);
} }
if (t.isClassMethod(node)) { if (t.isClassMethod(node)) {
@ -246,11 +269,14 @@ export default class ClassTransformer {
path.traverse(verifyConstructorVisitor, this); path.traverse(verifyConstructorVisitor, this);
if (!this.hasBareSuper && this.isDerived) { if (!this.hasBareSuper && this.isDerived) {
throw path.buildCodeFrameError("missing super() call in constructor"); throw path.buildCodeFrameError(
"missing super() call in constructor",
);
} }
} }
const replaceSupers = new ReplaceSupers({ const replaceSupers = new ReplaceSupers(
{
forceSuperMemoisation: isConstructor, forceSuperMemoisation: isConstructor,
methodPath: path, methodPath: path,
methodNode: node, methodNode: node,
@ -260,7 +286,9 @@ export default class ClassTransformer {
isLoose: this.isLoose, isLoose: this.isLoose,
scope: this.scope, scope: this.scope,
file: this.file, file: this.file,
}, true); },
true,
);
replaceSupers.replace(); replaceSupers.replace();
@ -298,8 +326,12 @@ export default class ClassTransformer {
} }
if (instanceProps || staticProps) { if (instanceProps || staticProps) {
if (instanceProps) instanceProps = defineMap.toComputedObjectFromClass(instanceProps); if (instanceProps) {
if (staticProps) staticProps = defineMap.toComputedObjectFromClass(staticProps); instanceProps = defineMap.toComputedObjectFromClass(instanceProps);
}
if (staticProps) {
staticProps = defineMap.toComputedObjectFromClass(staticProps);
}
const nullNode = t.nullLiteral(); const nullNode = t.nullLiteral();
@ -330,10 +362,11 @@ export default class ClassTransformer {
} }
args = args.slice(0, lastNonNullIndex + 1); args = args.slice(0, lastNonNullIndex + 1);
body.push(
body.push(t.expressionStatement( t.expressionStatement(
t.callExpression(this.file.addHelper("createClass"), args) t.callExpression(this.file.addHelper("createClass"), args),
)); ),
);
} }
this.clearDescriptors(); this.clearDescriptors();
@ -353,13 +386,21 @@ export default class ClassTransformer {
if ( if (
bareSuperNode.arguments.length === 2 && bareSuperNode.arguments.length === 2 &&
t.isSpreadElement(bareSuperNode.arguments[1]) && t.isSpreadElement(bareSuperNode.arguments[1]) &&
t.isIdentifier(bareSuperNode.arguments[1].argument, { name: "arguments" }) t.isIdentifier(bareSuperNode.arguments[1].argument, {
name: "arguments",
})
) { ) {
// special case single arguments spread // special case single arguments spread
bareSuperNode.arguments[1] = bareSuperNode.arguments[1].argument; bareSuperNode.arguments[1] = bareSuperNode.arguments[1].argument;
bareSuperNode.callee = t.memberExpression(superRef, t.identifier("apply")); bareSuperNode.callee = t.memberExpression(
superRef,
t.identifier("apply"),
);
} else { } else {
bareSuperNode.callee = t.memberExpression(superRef, t.identifier("call")); bareSuperNode.callee = t.memberExpression(
superRef,
t.identifier("call"),
);
} }
} else { } else {
bareSuperNode = optimiseCall( bareSuperNode = optimiseCall(
@ -367,12 +408,15 @@ export default class ClassTransformer {
"||", "||",
t.memberExpression(this.classRef, t.identifier("__proto__")), t.memberExpression(this.classRef, t.identifier("__proto__")),
t.callExpression( t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")), t.memberExpression(
[this.classRef] t.identifier("Object"),
) t.identifier("getPrototypeOf"),
),
[this.classRef],
),
), ),
t.thisExpression(), t.thisExpression(),
bareSuperNode.arguments bareSuperNode.arguments,
); );
} }
@ -383,11 +427,11 @@ export default class ClassTransformer {
} else { } else {
call = t.callExpression( call = t.callExpression(
this.file.addHelper("possibleConstructorReturn"), this.file.addHelper("possibleConstructorReturn"),
[t.thisExpression(), bareSuperNode] [t.thisExpression(), bareSuperNode],
); );
} }
const bareSuperAfter = this.bareSuperAfter.map((fn) => fn(thisRef)); const bareSuperAfter = this.bareSuperAfter.map(fn => fn(thisRef));
if ( if (
bareSuper.parentPath.isExpressionStatement() && bareSuper.parentPath.isExpressionStatement() &&
@ -409,14 +453,11 @@ export default class ClassTransformer {
bareSuper.parentPath.replaceWith(t.returnStatement(call)); bareSuper.parentPath.replaceWith(t.returnStatement(call));
} else { } else {
bareSuper.replaceWithMultiple([ bareSuper.replaceWithMultiple([
t.variableDeclaration("var", [ t.variableDeclaration("var", [t.variableDeclarator(thisRef, call)]),
t.variableDeclarator(thisRef, call),
]),
...bareSuperAfter, ...bareSuperAfter,
t.expressionStatement(thisRef), t.expressionStatement(thisRef),
]); ]);
} }
} }
verifyConstructor() { verifyConstructor() {
@ -457,13 +498,16 @@ export default class ClassTransformer {
let wrapReturn; let wrapReturn;
if (this.isLoose) { if (this.isLoose) {
wrapReturn = (returnArg) => { wrapReturn = returnArg => {
return returnArg ? t.logicalExpression("||", returnArg, thisRef) : thisRef; return returnArg
? t.logicalExpression("||", returnArg, thisRef)
: thisRef;
}; };
} else { } else {
wrapReturn = (returnArg) => t.callExpression( wrapReturn = returnArg =>
t.callExpression(
this.file.addHelper("possibleConstructorReturn"), this.file.addHelper("possibleConstructorReturn"),
[thisRef].concat(returnArg || []) [thisRef].concat(returnArg || []),
); );
} }
@ -471,14 +515,18 @@ export default class ClassTransformer {
// return // return
const bodyPaths = body.get("body"); const bodyPaths = body.get("body");
if (bodyPaths.length && !bodyPaths.pop().isReturnStatement()) { if (bodyPaths.length && !bodyPaths.pop().isReturnStatement()) {
body.pushContainer("body", t.returnStatement( body.pushContainer(
guaranteedSuperBeforeFinish ? thisRef : wrapReturn())); "body",
t.returnStatement(guaranteedSuperBeforeFinish ? thisRef : wrapReturn()),
);
} }
for (const returnPath of this.superReturns) { for (const returnPath of this.superReturns) {
if (returnPath.node.argument) { if (returnPath.node.argument) {
const ref = returnPath.scope.generateDeclaredUidIdentifier("ret"); const ref = returnPath.scope.generateDeclaredUidIdentifier("ret");
returnPath.get("argument").replaceWithMultiple([ returnPath
.get("argument")
.replaceWithMultiple([
t.assignmentExpression("=", ref, returnPath.node.argument), t.assignmentExpression("=", ref, returnPath.node.argument),
wrapReturn(ref), wrapReturn(ref),
]); ]);
@ -510,7 +558,11 @@ export default class ClassTransformer {
* Replace the constructor body of our class. * Replace the constructor body of our class.
*/ */
pushConstructor(replaceSupers, method: { type: "ClassMethod" }, path: NodePath) { pushConstructor(
replaceSupers,
method: { type: "ClassMethod" },
path: NodePath,
) {
this.bareSupers = replaceSupers.bareSupers; this.bareSupers = replaceSupers.bareSupers;
this.superReturns = replaceSupers.returns; this.superReturns = replaceSupers.returns;
@ -561,9 +613,15 @@ export default class ClassTransformer {
// Unshift to ensure that the constructor inheritance is set up before // Unshift to ensure that the constructor inheritance is set up before
// any properties can be assigned to the prototype. // any properties can be assigned to the prototype.
this.pushedInherits = true; this.pushedInherits = true;
this.body.unshift(t.expressionStatement(t.callExpression( this.body.unshift(
this.isLoose ? this.file.addHelper("inheritsLoose") : this.file.addHelper("inherits"), t.expressionStatement(
[this.classRef, this.superName] t.callExpression(
))); this.isLoose
? this.file.addHelper("inheritsLoose")
: this.file.addHelper("inherits"),
[this.classRef, this.superName],
),
),
);
} }
} }

View File

@ -8,7 +8,13 @@ export default function ({ types: t, template }) {
if (t.isObjectProperty(prop)) { if (t.isObjectProperty(prop)) {
return prop.value; return prop.value;
} else if (t.isObjectMethod(prop)) { } else if (t.isObjectMethod(prop)) {
return t.functionExpression(null, prop.params, prop.body, prop.generator, prop.async); return t.functionExpression(
null,
prop.params,
prop.body,
prop.generator,
prop.async,
);
} }
} }
@ -16,31 +22,44 @@ export default function ({ types: t, template }) {
if (prop.kind === "get" && prop.kind === "set") { if (prop.kind === "get" && prop.kind === "set") {
pushMutatorDefine(objId, prop, body); pushMutatorDefine(objId, prop, body);
} else { } else {
body.push(t.expressionStatement( body.push(
t.expressionStatement(
t.assignmentExpression( t.assignmentExpression(
"=", "=",
t.memberExpression(objId, prop.key, prop.computed || t.isLiteral(prop.key)), t.memberExpression(
getValue(prop) objId,
) prop.key,
)); prop.computed || t.isLiteral(prop.key),
),
getValue(prop),
),
),
);
} }
} }
function pushMutatorDefine({ objId, body, getMutatorId, scope }, prop) { function pushMutatorDefine({ objId, body, getMutatorId, scope }, prop) {
let key = !prop.computed && t.isIdentifier(prop.key) ? t.stringLiteral(prop.key.name) : prop.key; let key =
!prop.computed && t.isIdentifier(prop.key)
? t.stringLiteral(prop.key.name)
: prop.key;
const maybeMemoise = scope.maybeGenerateMemoised(key); const maybeMemoise = scope.maybeGenerateMemoised(key);
if (maybeMemoise) { if (maybeMemoise) {
body.push(t.expressionStatement(t.assignmentExpression("=", maybeMemoise, key))); body.push(
t.expressionStatement(t.assignmentExpression("=", maybeMemoise, key)),
);
key = maybeMemoise; key = maybeMemoise;
} }
body.push(...buildMutatorMapAssign({ body.push(
...buildMutatorMapAssign({
MUTATOR_MAP_REF: getMutatorId(), MUTATOR_MAP_REF: getMutatorId(),
KEY: key, KEY: key,
VALUE: getValue(prop), VALUE: getValue(prop),
KIND: t.identifier(prop.kind), KIND: t.identifier(prop.kind),
})); }),
);
} }
function loose(info) { function loose(info) {
@ -71,13 +90,15 @@ export default function ({ types: t, template }) {
getValue(prop), getValue(prop),
]); ]);
} else { } else {
body.push(t.expressionStatement( body.push(
t.expressionStatement(
t.callExpression(state.addHelper("defineProperty"), [ t.callExpression(state.addHelper("defineProperty"), [
objId, objId,
key, key,
getValue(prop), getValue(prop),
]) ]),
)); ),
);
} }
} }
} }
@ -118,9 +139,11 @@ export default function ({ types: t, template }) {
const initPropExpression = t.objectExpression(initProps); const initPropExpression = t.objectExpression(initProps);
const body = []; const body = [];
body.push(t.variableDeclaration("var", [ body.push(
t.variableDeclaration("var", [
t.variableDeclarator(objId, initPropExpression), t.variableDeclarator(objId, initPropExpression),
])); ]),
);
let callback = spec; let callback = spec;
if (state.opts.loose) callback = loose; if (state.opts.loose) callback = loose;
@ -131,9 +154,11 @@ export default function ({ types: t, template }) {
if (!mutatorRef) { if (!mutatorRef) {
mutatorRef = scope.generateUidIdentifier("mutatorMap"); mutatorRef = scope.generateUidIdentifier("mutatorMap");
body.push(t.variableDeclaration("var", [ body.push(
t.variableDeclaration("var", [
t.variableDeclarator(mutatorRef, t.objectExpression([])), t.variableDeclarator(mutatorRef, t.objectExpression([])),
])); ]),
);
} }
return mutatorRef; return mutatorRef;
@ -150,10 +175,14 @@ export default function ({ types: t, template }) {
}); });
if (mutatorRef) { if (mutatorRef) {
body.push(t.expressionStatement(t.callExpression( body.push(
t.expressionStatement(
t.callExpression(
state.addHelper("defineEnumerableProperties"), state.addHelper("defineEnumerableProperties"),
[objId, mutatorRef] [objId, mutatorRef],
))); ),
),
);
} }
if (single) { if (single) {

View File

@ -1,5 +1,4 @@
export default function({ types: t }) { export default function({ types: t }) {
/** /**
* Test if a VariableDeclaration's declarations contains any Patterns. * Test if a VariableDeclaration's declarations contains any Patterns.
*/ */
@ -86,7 +85,10 @@ export default function ({ types: t }) {
} }
toArray(node, count) { toArray(node, count) {
if (this.file.opts.loose || (t.isIdentifier(node) && this.arrays[node.name])) { if (
this.file.opts.loose ||
(t.isIdentifier(node) && this.arrays[node.name])
) {
return node; return node;
} else { } else {
return this.scope.toArray(node, count); return this.scope.toArray(node, count);
@ -97,7 +99,9 @@ export default function ({ types: t }) {
// we need to assign the current value of the assignment to avoid evaluating // we need to assign the current value of the assignment to avoid evaluating
// it more than once // it more than once
const tempValueRef = this.scope.generateUidIdentifierBasedOnNode(valueRef); const tempValueRef = this.scope.generateUidIdentifierBasedOnNode(
valueRef,
);
const declar = t.variableDeclaration("var", [ const declar = t.variableDeclaration("var", [
t.variableDeclarator(tempValueRef, valueRef), t.variableDeclarator(tempValueRef, valueRef),
@ -110,13 +114,13 @@ export default function ({ types: t }) {
const tempConditional = t.conditionalExpression( const tempConditional = t.conditionalExpression(
t.binaryExpression("===", tempValueRef, t.identifier("undefined")), t.binaryExpression("===", tempValueRef, t.identifier("undefined")),
pattern.right, pattern.right,
tempValueRef tempValueRef,
); );
const left = pattern.left; const left = pattern.left;
if (t.isPattern(left)) { if (t.isPattern(left)) {
const tempValueDefault = t.expressionStatement( const tempValueDefault = t.expressionStatement(
t.assignmentExpression("=", tempValueRef, tempConditional) t.assignmentExpression("=", tempValueRef, tempConditional),
); );
tempValueDefault._blockHoist = this.blockHoist; tempValueDefault._blockHoist = this.blockHoist;
@ -143,7 +147,9 @@ export default function ({ types: t }) {
if (t.isRestElement(prop)) continue; if (t.isRestElement(prop)) continue;
let key = prop.key; let key = prop.key;
if (t.isIdentifier(key) && !prop.computed) key = t.stringLiteral(prop.key.name); if (t.isIdentifier(key) && !prop.computed) {
key = t.stringLiteral(prop.key.name);
}
keys.push(key); keys.push(key);
} }
@ -152,7 +158,9 @@ export default function ({ types: t }) {
// //
const value = t.callExpression( const value = t.callExpression(
this.file.addHelper("objectWithoutProperties"), [objRef, keys]); this.file.addHelper("objectWithoutProperties"),
[objRef, keys],
);
this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value)); this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value));
} }
@ -173,9 +181,13 @@ export default function ({ types: t }) {
// https://github.com/babel/babel/issues/681 // https://github.com/babel/babel/issues/681
if (!pattern.properties.length) { if (!pattern.properties.length) {
this.nodes.push(t.expressionStatement( this.nodes.push(
t.callExpression(this.file.addHelper("objectDestructuringEmpty"), [objRef]) t.expressionStatement(
)); t.callExpression(this.file.addHelper("objectDestructuringEmpty"), [
objRef,
]),
),
);
} }
// if we have more than one properties in this pattern and the objectRef is a // if we have more than one properties in this pattern and the objectRef is a
@ -207,7 +219,9 @@ export default function ({ types: t }) {
// pattern has less elements than the array and doesn't have a rest so some // pattern has less elements than the array and doesn't have a rest so some
// elements wont be evaluated // elements wont be evaluated
if (pattern.elements.length > arr.elements.length) return; if (pattern.elements.length > arr.elements.length) return;
if (pattern.elements.length < arr.elements.length && !hasRest(pattern)) return false; if (pattern.elements.length < arr.elements.length && !hasRest(pattern)) {
return false;
}
for (const elem of (pattern.elements: Array)) { for (const elem of (pattern.elements: Array)) {
// deopt on holes // deopt on holes
@ -293,8 +307,10 @@ export default function ({ types: t }) {
if (t.isRestElement(elem)) { if (t.isRestElement(elem)) {
elemRef = this.toArray(arrayRef); elemRef = this.toArray(arrayRef);
elemRef = t.callExpression(t.memberExpression(elemRef, t.identifier("slice")), elemRef = t.callExpression(
[t.numericLiteral(i)]); t.memberExpression(elemRef, t.identifier("slice")),
[t.numericLiteral(i)],
);
// set the element to the rest element argument since we've dealt with it // set the element to the rest element argument since we've dealt with it
// being a rest already // being a rest already
@ -327,7 +343,6 @@ export default function ({ types: t }) {
} }
} }
return { return {
visitor: { visitor: {
ExportNamedDeclaration(path) { ExportNamedDeclaration(path) {
@ -364,9 +379,9 @@ export default function ({ types: t }) {
path.ensureBlock(); path.ensureBlock();
node.body.body.unshift(t.variableDeclaration("var", [ node.body.body.unshift(
t.variableDeclarator(left, temp), t.variableDeclaration("var", [t.variableDeclarator(left, temp)]),
])); );
return; return;
} }
@ -432,12 +447,17 @@ export default function ({ types: t }) {
}); });
let ref; let ref;
if (path.isCompletionRecord() || !path.parentPath.isExpressionStatement()) { if (
path.isCompletionRecord() ||
!path.parentPath.isExpressionStatement()
) {
ref = scope.generateUidIdentifierBasedOnNode(node.right, "ref"); ref = scope.generateUidIdentifierBasedOnNode(node.right, "ref");
nodes.push(t.variableDeclaration("var", [ nodes.push(
t.variableDeclaration("var", [
t.variableDeclarator(ref, node.right), t.variableDeclarator(ref, node.right),
])); ]),
);
if (t.isArrayExpression(node.right)) { if (t.isArrayExpression(node.right)) {
destructuring.arrays[ref.name] = true; destructuring.arrays[ref.name] = true;
@ -486,15 +506,23 @@ export default function ({ types: t }) {
t.inherits(nodes[nodes.length - 1], declar); t.inherits(nodes[nodes.length - 1], declar);
} }
} else { } else {
nodes.push(t.inherits( nodes.push(
destructuring.buildVariableAssignment(declar.id, declar.init), declar)); t.inherits(
destructuring.buildVariableAssignment(declar.id, declar.init),
declar,
),
);
} }
} }
const nodesOut = []; const nodesOut = [];
for (const node of nodes) { for (const node of nodes) {
const tail = nodesOut[nodesOut.length - 1]; const tail = nodesOut[nodesOut.length - 1];
if (tail && t.isVariableDeclaration(tail) && t.isVariableDeclaration(node)) { if (
tail &&
t.isVariableDeclaration(tail) &&
t.isVariableDeclaration(node)
) {
// Create a single compound declarations // Create a single compound declarations
tail.declarations.push(...node.declarations); tail.declarations.push(...node.declarations);
} else { } else {

View File

@ -12,7 +12,9 @@ export default function() {
visitor: { visitor: {
ObjectExpression(path) { ObjectExpression(path) {
const { node } = path; const { node } = path;
const plainProps = node.properties.filter((prop) => !t.isSpreadElement(prop) && !prop.computed); const plainProps = node.properties.filter(
prop => !t.isSpreadElement(prop) && !prop.computed,
);
// A property is a duplicate key if: // A property is a duplicate key if:
// * the property is a data property, and is preceeded by a data, // * the property is a data property, and is preceeded by a data,
@ -43,7 +45,11 @@ export default function() {
alreadySeenSetters[name] = true; alreadySeenSetters[name] = true;
break; break;
default: default:
if (alreadySeenData[name] || alreadySeenGetters[name] || alreadySeenSetters[name]) { if (
alreadySeenData[name] ||
alreadySeenGetters[name] ||
alreadySeenSetters[name]
) {
isDuplicate = true; isDuplicate = true;
} }
alreadySeenData[name] = true; alreadySeenData[name] = true;

View File

@ -57,9 +57,9 @@ export default function ({ messages, template, types: t }) {
if (!t.isIdentifier(right) || !scope.hasBinding(right.name)) { if (!t.isIdentifier(right) || !scope.hasBinding(right.name)) {
const uid = scope.generateUidIdentifier("arr"); const uid = scope.generateUidIdentifier("arr");
nodes.push(t.variableDeclaration("var", [ nodes.push(
t.variableDeclarator(uid, right), t.variableDeclaration("var", [t.variableDeclarator(uid, right)]),
])); );
right = uid; right = uid;
} }
@ -81,8 +81,11 @@ export default function ({ messages, template, types: t }) {
left.declarations[0].init = iterationValue; left.declarations[0].init = iterationValue;
loop.body.body.unshift(left); loop.body.body.unshift(left);
} else { } else {
loop.body.body.unshift(t.expressionStatement( loop.body.body.unshift(
t.assignmentExpression("=", left, iterationValue))); t.expressionStatement(
t.assignmentExpression("=", left, iterationValue),
),
);
} }
if (path.parentPath.isLabeledStatement()) { if (path.parentPath.isLabeledStatement()) {
@ -111,19 +114,18 @@ export default function ({ messages, template, types: t }) {
} else if (right.isIdentifier() && right.isPure()) { } else if (right.isIdentifier() && right.isPure()) {
const binding = path.scope.getBinding(right.node.name); const binding = path.scope.getBinding(right.node.name);
return optimize(path, binding.path.get("init")); return optimize(path, binding.path.get("init"));
} else if (right.isCallExpression() && ( } else if (
isArrayFrom(right.get("callee").node) || right.isCallExpression() &&
(isArrayFrom(right.get("callee").node) ||
isObjectKeys(right.get("callee").node) || isObjectKeys(right.get("callee").node) ||
isObjectValues(right.get("callee").node) || isObjectValues(right.get("callee").node) ||
isObjectEntries(right.get("callee").node) isObjectEntries(right.get("callee").node))
)
) { ) {
const initPath = right === path.get("right") ? path : right.find((p) => p.isStatement()); const initPath =
right === path.get("right") ? path : right.find(p => p.isStatement());
const uid = path.scope.generateUidIdentifierBasedOnNode(right.node); const uid = path.scope.generateUidIdentifierBasedOnNode(right.node);
initPath.insertBefore( initPath.insertBefore(
t.variableDeclaration("const", [ t.variableDeclaration("const", [t.variableDeclarator(uid, right.node)]),
t.variableDeclarator(uid, right.node),
])
); );
right.replaceWith(uid); right.replaceWith(uid);
return replaceWithArray(path); return replaceWithArray(path);
@ -176,7 +178,11 @@ export default function ({ messages, template, types: t }) {
const { left } = node; const { left } = node;
let declar, id; let declar, id;
if (t.isIdentifier(left) || t.isPattern(left) || t.isMemberExpression(left)) { if (
t.isIdentifier(left) ||
t.isPattern(left) ||
t.isMemberExpression(left)
) {
// for (i of test), for ({ i } of test) // for (i of test), for ({ i } of test)
id = left; id = left;
} else if (t.isVariableDeclaration(left)) { } else if (t.isVariableDeclaration(left)) {
@ -186,7 +192,10 @@ export default function ({ messages, template, types: t }) {
t.variableDeclarator(left.declarations[0].id, id), t.variableDeclarator(left.declarations[0].id, id),
]); ]);
} else { } else {
throw file.buildCodeFrameError(left, messages.get("unknownForHead", left.type)); throw file.buildCodeFrameError(
left,
messages.get("unknownForHead", left.type),
);
} }
const iteratorKey = scope.generateUidIdentifier("iterator"); const iteratorKey = scope.generateUidIdentifier("iterator");
@ -230,16 +239,25 @@ export default function ({ messages, template, types: t }) {
const stepKey = scope.generateUidIdentifier("step"); const stepKey = scope.generateUidIdentifier("step");
const stepValue = t.memberExpression(stepKey, t.identifier("value")); const stepValue = t.memberExpression(stepKey, t.identifier("value"));
if (t.isIdentifier(left) || t.isPattern(left) || t.isMemberExpression(left)) { if (
t.isIdentifier(left) ||
t.isPattern(left) ||
t.isMemberExpression(left)
) {
// for (i of test), for ({ i } of test) // for (i of test), for ({ i } of test)
declar = t.expressionStatement(t.assignmentExpression("=", left, stepValue)); declar = t.expressionStatement(
t.assignmentExpression("=", left, stepValue),
);
} else if (t.isVariableDeclaration(left)) { } else if (t.isVariableDeclaration(left)) {
// for (let i of test) // for (let i of test)
declar = t.variableDeclaration(left.kind, [ declar = t.variableDeclaration(left.kind, [
t.variableDeclarator(left.declarations[0].id, stepValue), t.variableDeclarator(left.declarations[0].id, stepValue),
]); ]);
} else { } else {
throw file.buildCodeFrameError(left, messages.get("unknownForHead", left.type)); throw file.buildCodeFrameError(
left,
messages.get("unknownForHead", left.type),
);
} }
// //
@ -248,7 +266,9 @@ export default function ({ messages, template, types: t }) {
const template = buildForOf({ const template = buildForOf({
ITERATOR_HAD_ERROR_KEY: scope.generateUidIdentifier("didIteratorError"), ITERATOR_HAD_ERROR_KEY: scope.generateUidIdentifier("didIteratorError"),
ITERATOR_COMPLETION: scope.generateUidIdentifier("iteratorNormalCompletion"), ITERATOR_COMPLETION: scope.generateUidIdentifier(
"iteratorNormalCompletion",
),
ITERATOR_ERROR_KEY: scope.generateUidIdentifier("iteratorError"), ITERATOR_ERROR_KEY: scope.generateUidIdentifier("iteratorError"),
ITERATOR_KEY: iteratorKey, ITERATOR_KEY: iteratorKey,
STEP_KEY: stepKey, STEP_KEY: stepKey,

View File

@ -4,7 +4,12 @@ export default function ({ types: t }) {
BinaryExpression(path) { BinaryExpression(path) {
const { node } = path; const { node } = path;
if (node.operator === "instanceof") { if (node.operator === "instanceof") {
path.replaceWith(t.callExpression(this.addHelper("instanceof"), [node.left, node.right])); path.replaceWith(
t.callExpression(this.addHelper("instanceof"), [
node.left,
node.right,
]),
);
} }
}, },
}, },

View File

@ -63,7 +63,9 @@ export default function ({ types: t }) {
CallExpression(path) { CallExpression(path) {
if (!isValidRequireCall(path)) return; if (!isValidRequireCall(path)) return;
const source = path.node.arguments[0]; const source = path.node.arguments[0];
const ref = path.scope.generateUidIdentifier(basename(source.value, extname(source.value))); const ref = path.scope.generateUidIdentifier(
basename(source.value, extname(source.value)),
);
this.sources.push([ref, source, true]); this.sources.push([ref, source, true]);
path.remove(); path.remove();
}, },
@ -126,11 +128,13 @@ export default function ({ types: t }) {
factory.expression.body.directives = node.directives; factory.expression.body.directives = node.directives;
node.directives = []; node.directives = [];
node.body = [buildDefine({ node.body = [
buildDefine({
MODULE_NAME: moduleName, MODULE_NAME: moduleName,
SOURCES: sources, SOURCES: sources,
FACTORY: factory, FACTORY: factory,
})]; }),
];
}, },
}, },
}, },

View File

@ -42,8 +42,13 @@ const buildExportAll = template(`
}); });
`); `);
const THIS_BREAK_KEYS = ["FunctionExpression", "FunctionDeclaration", "ClassProperty", const THIS_BREAK_KEYS = [
"ClassMethod", "ObjectMethod"]; "FunctionExpression",
"FunctionDeclaration",
"ClassProperty",
"ClassMethod",
"ObjectMethod",
];
export default function() { export default function() {
const REASSIGN_REMAP_SKIP = Symbol(); const REASSIGN_REMAP_SKIP = Symbol();
@ -61,8 +66,12 @@ export default function () {
path.replaceWith(t.sequenceExpression([t.numericLiteral(0), remap])); path.replaceWith(t.sequenceExpression([t.numericLiteral(0), remap]));
} else if (path.isJSXIdentifier() && t.isMemberExpression(remap)) { } else if (path.isJSXIdentifier() && t.isMemberExpression(remap)) {
const { object, property } = remap; const { object, property } = remap;
path.replaceWith(t.JSXMemberExpression(t.JSXIdentifier(object.name), path.replaceWith(
t.JSXIdentifier(property.name))); t.JSXMemberExpression(
t.JSXIdentifier(object.name),
t.JSXIdentifier(property.name),
),
);
} else { } else {
path.replaceWith(remap); path.replaceWith(remap);
} }
@ -104,9 +113,17 @@ export default function () {
// redeclared in this scope // redeclared in this scope
if (this.scope.getBinding(name) !== path.scope.getBinding(name)) return; if (this.scope.getBinding(name) !== path.scope.getBinding(name)) return;
const node = t.assignmentExpression(path.node.operator[0] + "=", arg.node, t.numericLiteral(1)); const node = t.assignmentExpression(
path.node.operator[0] + "=",
arg.node,
t.numericLiteral(1),
);
if ((path.parentPath.isExpressionStatement() && !path.isCompletionRecord()) || path.node.prefix) { if (
(path.parentPath.isExpressionStatement() &&
!path.isCompletionRecord()) ||
path.node.prefix
) {
path.replaceWith(node); path.replaceWith(node);
this.requeueInParent(path); this.requeueInParent(path);
return; return;
@ -118,7 +135,8 @@ export default function () {
let operator; let operator;
if (path.node.operator === "--") { if (path.node.operator === "--") {
operator = "+"; operator = "+";
} else { // "++" } else {
// "++"
operator = "-"; operator = "-";
} }
nodes.push(t.binaryExpression(operator, arg.node, t.numericLiteral(1))); nodes.push(t.binaryExpression(operator, arg.node, t.numericLiteral(1)));
@ -139,7 +157,7 @@ export default function () {
if ( if (
state.opts.allowTopLevelThis !== true && state.opts.allowTopLevelThis !== true &&
!path.findParent((path) => THIS_BREAK_KEYS.indexOf(path.type) >= 0) !path.findParent(path => THIS_BREAK_KEYS.indexOf(path.type) >= 0)
) { ) {
path.replaceWith(t.identifier("undefined")); path.replaceWith(t.identifier("undefined"));
} }
@ -177,12 +195,15 @@ export default function () {
const cached = requires[source]; const cached = requires[source];
if (cached) return cached; if (cached) return cached;
const ref = path.scope.generateUidIdentifier(basename(source, extname(source))); const ref = path.scope.generateUidIdentifier(
basename(source, extname(source)),
);
const varDecl = t.variableDeclaration("var", [ const varDecl = t.variableDeclaration("var", [
t.variableDeclarator(ref, buildRequire( t.variableDeclarator(
t.stringLiteral(source) ref,
).expression), buildRequire(t.stringLiteral(source)).expression,
),
]); ]);
// Copy location from the original import statement for sourcemap // Copy location from the original import statement for sourcemap
@ -197,7 +218,7 @@ export default function () {
topNodes.push(varDecl); topNodes.push(varDecl);
return requires[source] = ref; return (requires[source] = ref);
} }
function addTo(obj, key, arr) { function addTo(obj, key, arr) {
@ -209,11 +230,16 @@ export default function () {
if (path.isExportDeclaration()) { if (path.isExportDeclaration()) {
hasExports = true; hasExports = true;
const specifiers = [].concat(path.get("declaration"), path.get("specifiers")); const specifiers = [].concat(
path.get("declaration"),
path.get("specifiers"),
);
for (const specifier of specifiers) { for (const specifier of specifiers) {
const ids = specifier.getBindingIdentifiers(); const ids = specifier.getBindingIdentifiers();
if (ids.__esModule) { if (ids.__esModule) {
throw specifier.buildCodeFrameError("Illegal export \"__esModule\""); throw specifier.buildCodeFrameError(
'Illegal export "__esModule"',
);
} }
} }
} }
@ -233,7 +259,7 @@ export default function () {
if (typeof path.node._blockHoist === "number") { if (typeof path.node._blockHoist === "number") {
importsEntry.maxBlockHoist = Math.max( importsEntry.maxBlockHoist = Math.max(
path.node._blockHoist, path.node._blockHoist,
importsEntry.maxBlockHoist importsEntry.maxBlockHoist,
); );
} }
@ -250,7 +276,12 @@ export default function () {
topNodes.push(buildExportsAssignment(defNode, id)); topNodes.push(buildExportsAssignment(defNode, id));
path.replaceWith(declaration.node); path.replaceWith(declaration.node);
} else { } else {
topNodes.push(buildExportsAssignment(defNode, t.toExpression(declaration.node))); topNodes.push(
buildExportsAssignment(
defNode,
t.toExpression(declaration.node),
),
);
path.remove(); path.remove();
} }
} else if (declaration.isClassDeclaration()) { } else if (declaration.isClassDeclaration()) {
@ -263,7 +294,12 @@ export default function () {
buildExportsAssignment(defNode, id), buildExportsAssignment(defNode, id),
]); ]);
} else { } else {
path.replaceWith(buildExportsAssignment(defNode, t.toExpression(declaration.node))); path.replaceWith(
buildExportsAssignment(
defNode,
t.toExpression(declaration.node),
),
);
// Manualy re-queue `export default class {}` expressions so that the ES3 transform // Manualy re-queue `export default class {}` expressions so that the ES3 transform
// has an opportunity to convert them. Ideally this would happen automatically from the // has an opportunity to convert them. Ideally this would happen automatically from the
@ -271,7 +307,12 @@ export default function () {
path.parentPath.requeue(path.get("expression.left")); path.parentPath.requeue(path.get("expression.left"));
} }
} else { } else {
path.replaceWith(buildExportsAssignment(t.identifier("default"), declaration.node)); path.replaceWith(
buildExportsAssignment(
t.identifier("default"),
declaration.node,
),
);
// Manualy re-queue `export default foo;` expressions so that the ES3 transform // Manualy re-queue `export default foo;` expressions so that the ES3 transform
// has an opportunity to convert them. Ideally this would happen automatically from the // has an opportunity to convert them. Ideally this would happen automatically from the
@ -306,7 +347,9 @@ export default function () {
if (id.isIdentifier()) { if (id.isIdentifier()) {
addTo(exports, id.node.name, id.node); addTo(exports, id.node.name, id.node);
init.replaceWith(buildExportsAssignment(id.node, init.node).expression); init.replaceWith(
buildExportsAssignment(id.node, init.node).expression,
);
nonHoistedExportNames[id.node.name] = true; nonHoistedExportNames[id.node.name] = true;
} else if (id.isObjectPattern()) { } else if (id.isObjectPattern()) {
for (let i = 0; i < id.node.properties.length; i++) { for (let i = 0; i < id.node.properties.length; i++) {
@ -318,7 +361,9 @@ export default function () {
propValue = prop.argument; propValue = prop.argument;
} }
addTo(exports, propValue.name, propValue); addTo(exports, propValue.name, propValue);
exportsToInsert.push(buildExportsAssignment(propValue, propValue)); exportsToInsert.push(
buildExportsAssignment(propValue, propValue),
);
nonHoistedExportNames[propValue.name] = true; nonHoistedExportNames[propValue.name] = true;
} }
} else if (id.isArrayPattern() && id.node.elements) { } else if (id.isArrayPattern() && id.node.elements) {
@ -332,7 +377,9 @@ export default function () {
} }
const name = elem.name; const name = elem.name;
addTo(exports, name, elem); addTo(exports, name, elem);
exportsToInsert.push(buildExportsAssignment(elem, elem)); exportsToInsert.push(
buildExportsAssignment(elem, elem),
);
nonHoistedExportNames[name] = true; nonHoistedExportNames[name] = true;
} }
} }
@ -356,15 +403,25 @@ export default function () {
// todo // todo
} else if (specifier.isExportSpecifier()) { } else if (specifier.isExportSpecifier()) {
if (!noInterop && specifier.node.local.name === "default") { if (!noInterop && specifier.node.local.name === "default") {
topNodes.push(buildExportsFrom(t.stringLiteral(specifier.node.exported.name), topNodes.push(
buildExportsFrom(
t.stringLiteral(specifier.node.exported.name),
t.memberExpression( t.memberExpression(
t.callExpression(this.addHelper("interopRequireDefault"), [ref]), t.callExpression(
specifier.node.local this.addHelper("interopRequireDefault"),
) [ref],
)); ),
specifier.node.local,
),
),
);
} else { } else {
topNodes.push(buildExportsFrom(t.stringLiteral(specifier.node.exported.name), topNodes.push(
t.memberExpression(ref, specifier.node.local))); buildExportsFrom(
t.stringLiteral(specifier.node.exported.name),
t.memberExpression(ref, specifier.node.local),
),
);
} }
nonHoistedExportNames[specifier.node.exported.name] = true; nonHoistedExportNames[specifier.node.exported.name] = true;
} }
@ -372,16 +429,28 @@ export default function () {
} else { } else {
for (const specifier of specifiers) { for (const specifier of specifiers) {
if (specifier.isExportSpecifier()) { if (specifier.isExportSpecifier()) {
addTo(exports, specifier.node.local.name, specifier.node.exported); addTo(
exports,
specifier.node.local.name,
specifier.node.exported,
);
nonHoistedExportNames[specifier.node.exported.name] = true; nonHoistedExportNames[specifier.node.exported.name] = true;
nodes.push(buildExportsAssignment(specifier.node.exported, specifier.node.local)); nodes.push(
buildExportsAssignment(
specifier.node.exported,
specifier.node.local,
),
);
} }
} }
} }
path.replaceWithMultiple(nodes); path.replaceWithMultiple(nodes);
} else if (path.isExportAllDeclaration()) { } else if (path.isExportAllDeclaration()) {
const exportNode = buildExportAll({ const exportNode = buildExportAll({
OBJECT: addRequire(path.node.source.value, path.node._blockHoist), OBJECT: addRequire(
path.node.source.value,
path.node._blockHoist,
),
}); });
exportNode.loc = path.node.loc; exportNode.loc = path.node.loc;
topNodes.push(exportNode); topNodes.push(exportNode);
@ -407,8 +476,8 @@ export default function () {
specifier.local, specifier.local,
t.callExpression( t.callExpression(
this.addHelper("interopRequireWildcard"), this.addHelper("interopRequireWildcard"),
[uid] [uid],
) ),
), ),
]); ]);
@ -420,7 +489,10 @@ export default function () {
} }
wildcard = specifier.local; wildcard = specifier.local;
} else if (t.isImportDefaultSpecifier(specifier)) { } else if (t.isImportDefaultSpecifier(specifier)) {
specifiers[i] = t.importSpecifier(specifier.local, t.identifier("default")); specifiers[i] = t.importSpecifier(
specifier.local,
t.identifier("default"),
);
} }
} }
@ -431,14 +503,16 @@ export default function () {
if (wildcard) { if (wildcard) {
target = wildcard; target = wildcard;
} else if (!noInterop) { } else if (!noInterop) {
target = wildcard = path.scope.generateUidIdentifier(uid.name); target = wildcard = path.scope.generateUidIdentifier(
uid.name,
);
const varDecl = t.variableDeclaration("var", [ const varDecl = t.variableDeclaration("var", [
t.variableDeclarator( t.variableDeclarator(
target, target,
t.callExpression( t.callExpression(
this.addHelper("interopRequireDefault"), this.addHelper("interopRequireDefault"),
[uid] [uid],
) ),
), ),
]); ]);
@ -449,8 +523,10 @@ export default function () {
topNodes.push(varDecl); topNodes.push(varDecl);
} }
} }
remaps[specifier.local.name] = t.memberExpression(target, remaps[specifier.local.name] = t.memberExpression(
t.cloneWithoutLoc(specifier.imported)); target,
t.cloneWithoutLoc(specifier.imported),
);
} }
} }
} else { } else {
@ -462,25 +538,29 @@ export default function () {
} }
if (hasImports && Object.keys(nonHoistedExportNames).length) { if (hasImports && Object.keys(nonHoistedExportNames).length) {
// avoid creating too long of export assignment to prevent stack overflow // avoid creating too long of export assignment to prevent stack overflow
const maxHoistedExportsNodeAssignmentLength = 100; const maxHoistedExportsNodeAssignmentLength = 100;
const nonHoistedExportNamesArr = Object.keys(nonHoistedExportNames); const nonHoistedExportNamesArr = Object.keys(nonHoistedExportNames);
for ( for (
let currentExportsNodeAssignmentLength = 0; let currentExportsNodeAssignmentLength = 0;
currentExportsNodeAssignmentLength < nonHoistedExportNamesArr.length; currentExportsNodeAssignmentLength <
nonHoistedExportNamesArr.length;
currentExportsNodeAssignmentLength += maxHoistedExportsNodeAssignmentLength currentExportsNodeAssignmentLength += maxHoistedExportsNodeAssignmentLength
) { ) {
const nonHoistedExportNamesChunk = nonHoistedExportNamesArr.slice( const nonHoistedExportNamesChunk = nonHoistedExportNamesArr.slice(
currentExportsNodeAssignmentLength, currentExportsNodeAssignmentLength,
currentExportsNodeAssignmentLength + maxHoistedExportsNodeAssignmentLength); currentExportsNodeAssignmentLength +
maxHoistedExportsNodeAssignmentLength,
);
let hoistedExportsNode = t.identifier("undefined"); let hoistedExportsNode = t.identifier("undefined");
nonHoistedExportNamesChunk.forEach(function(name) { nonHoistedExportNamesChunk.forEach(function(name) {
hoistedExportsNode = buildExportsAssignment(t.identifier(name), hoistedExportsNode) hoistedExportsNode = buildExportsAssignment(
.expression; t.identifier(name),
hoistedExportsNode,
).expression;
}); });
const node = t.expressionStatement(hoistedExportsNode); const node = t.expressionStatement(hoistedExportsNode);
@ -493,7 +573,9 @@ export default function () {
// add __esModule declaration if this file has any exports // add __esModule declaration if this file has any exports
if (hasExports && !strict) { if (hasExports && !strict) {
let buildTemplate = buildExportsModuleDeclaration; let buildTemplate = buildExportsModuleDeclaration;
if (this.opts.loose) buildTemplate = buildLooseExportsModuleDeclaration; if (this.opts.loose) {
buildTemplate = buildLooseExportsModuleDeclaration;
}
const declar = buildTemplate(); const declar = buildTemplate();
declar._blockHoist = 3; declar._blockHoist = 3;
@ -506,7 +588,7 @@ export default function () {
remaps, remaps,
scope, scope,
exports, exports,
requeueInParent: (newPath) => path.requeue(newPath), requeueInParent: newPath => path.requeue(newPath),
}); });
}, },
}, },

View File

@ -3,7 +3,7 @@ const babel = require("babel-core");
const vm = require("vm"); const vm = require("vm");
test("Re-export doesn't overwrite __esModule flag", function() { test("Re-export doesn't overwrite __esModule flag", function() {
let code = "export * from \"./dep\";"; let code = 'export * from "./dep";';
const depStub = { const depStub = {
__esModule: false, __esModule: false,
}; };
@ -20,10 +20,8 @@ test("Re-export doesn't overwrite __esModule flag", function () {
context.exports = context.module.exports; context.exports = context.module.exports;
code = babel.transform(code, { code = babel.transform(code, {
"plugins": [ plugins: [[require("../"), { loose: true }]],
[require("../"), { loose: true }], ast: false,
],
"ast": false,
}).code; }).code;
vm.runInNewContext(code, context); vm.runInNewContext(code, context);
@ -32,6 +30,6 @@ test("Re-export doesn't overwrite __esModule flag", function () {
assert.equal( assert.equal(
context.exports.__esModule, context.exports.__esModule,
true, true,
"Expected exports.__esModule === true" "Expected exports.__esModule === true",
); );
}); });

View File

@ -20,7 +20,6 @@ const buildExportAll = template(`
} }
`); `);
const TYPE_IMPORT = "Import"; const TYPE_IMPORT = "Import";
export default function({ types: t }) { export default function({ types: t }) {
@ -49,20 +48,22 @@ export default function ({ types: t }) {
// in order to ensure the same update expression value // in order to ensure the same update expression value
let isPostUpdateExpression = path.isUpdateExpression() && !node.prefix; let isPostUpdateExpression = path.isUpdateExpression() && !node.prefix;
if (isPostUpdateExpression) { if (isPostUpdateExpression) {
if (node.operator === "++") if (node.operator === "++") {
{node = t.binaryExpression("+", node.argument, t.numericLiteral(1));} node = t.binaryExpression("+", node.argument, t.numericLiteral(1));
else if (node.operator === "--") } else if (node.operator === "--") {
{node = t.binaryExpression("-", node.argument, t.numericLiteral(1));} node = t.binaryExpression("-", node.argument, t.numericLiteral(1));
else } else {
{isPostUpdateExpression = false;} isPostUpdateExpression = false;
}
} }
for (const exportedName of exportedNames) { for (const exportedName of exportedNames) {
node = this.buildCall(exportedName, node).expression; node = this.buildCall(exportedName, node).expression;
} }
if (isPostUpdateExpression) if (isPostUpdateExpression) {
{node = t.sequenceExpression([node, path.node]);} node = t.sequenceExpression([node, path.node]);
}
path.replaceWith(node); path.replaceWith(node);
}, },
@ -70,18 +71,26 @@ export default function ({ types: t }) {
return { return {
visitor: { visitor: {
CallExpression(path, state) { CallExpression(path, state) {
if (path.node.callee.type === TYPE_IMPORT) { if (path.node.callee.type === TYPE_IMPORT) {
const contextIdent = state.contextIdent; const contextIdent = state.contextIdent;
path.replaceWith(t.callExpression(t.memberExpression(contextIdent, t.identifier("import")), path.replaceWith(
path.node.arguments)); t.callExpression(
t.memberExpression(contextIdent, t.identifier("import")),
path.node.arguments,
),
);
} }
}, },
ReferencedIdentifier(path, state) { ReferencedIdentifier(path, state) {
if (path.node.name == "__moduleName" && !path.scope.hasBinding("__moduleName")) { if (
path.replaceWith(t.memberExpression(state.contextIdent, t.identifier("id"))); path.node.name == "__moduleName" &&
!path.scope.hasBinding("__moduleName")
) {
path.replaceWith(
t.memberExpression(state.contextIdent, t.identifier("id")),
);
} }
}, },
@ -115,14 +124,16 @@ export default function ({ types: t }) {
} }
}); });
if (!module) { if (!module) {
modules.push(module = { key: source, imports: [], exports: [] }); modules.push(
(module = { key: source, imports: [], exports: [] }),
);
} }
module[key] = module[key].concat(specifiers); module[key] = module[key].concat(specifiers);
} }
function buildExportCall(name, val) { function buildExportCall(name, val) {
return t.expressionStatement( return t.expressionStatement(
t.callExpression(exportIdent, [t.stringLiteral(name), val]) t.callExpression(exportIdent, [t.stringLiteral(name), val]),
); );
} }
@ -154,7 +165,10 @@ export default function ({ types: t }) {
path.remove(); path.remove();
} else if (path.isExportDefaultDeclaration()) { } else if (path.isExportDefaultDeclaration()) {
const declar = path.get("declaration"); const declar = path.get("declaration");
if (declar.isClassDeclaration() || declar.isFunctionDeclaration()) { if (
declar.isClassDeclaration() ||
declar.isFunctionDeclaration()
) {
const id = declar.node.id; const id = declar.node.id;
const nodes = []; const nodes = [];
@ -163,7 +177,9 @@ export default function ({ types: t }) {
nodes.push(buildExportCall("default", id)); nodes.push(buildExportCall("default", id));
addExportName(id.name, "default"); addExportName(id.name, "default");
} else { } else {
nodes.push(buildExportCall("default", t.toExpression(declar.node))); nodes.push(
buildExportCall("default", t.toExpression(declar.node)),
);
} }
if (!canHoist || declar.isClassDeclaration()) { if (!canHoist || declar.isClassDeclaration()) {
@ -212,8 +228,16 @@ export default function ({ types: t }) {
const nodes = []; const nodes = [];
for (const specifier of specifiers) { for (const specifier of specifiers) {
nodes.push(buildExportCall(specifier.exported.name, specifier.local)); nodes.push(
addExportName(specifier.local.name, specifier.exported.name); buildExportCall(
specifier.exported.name,
specifier.local,
),
);
addExportName(
specifier.local.name,
specifier.exported.name,
);
} }
path.replaceWithMultiple(nodes); path.replaceWithMultiple(nodes);
@ -229,59 +253,97 @@ export default function ({ types: t }) {
for (let specifier of specifiers.imports) { for (let specifier of specifiers.imports) {
if (t.isImportNamespaceSpecifier(specifier)) { if (t.isImportNamespaceSpecifier(specifier)) {
setterBody.push(t.expressionStatement(t.assignmentExpression("=", specifier.local, target))); setterBody.push(
t.expressionStatement(
t.assignmentExpression("=", specifier.local, target),
),
);
} else if (t.isImportDefaultSpecifier(specifier)) { } else if (t.isImportDefaultSpecifier(specifier)) {
specifier = t.importSpecifier(specifier.local, t.identifier("default")); specifier = t.importSpecifier(
specifier.local,
t.identifier("default"),
);
} }
if (t.isImportSpecifier(specifier)) { if (t.isImportSpecifier(specifier)) {
setterBody.push(t.expressionStatement(t.assignmentExpression("=", specifier.local, setterBody.push(
t.memberExpression(target, specifier.imported)))); t.expressionStatement(
t.assignmentExpression(
"=",
specifier.local,
t.memberExpression(target, specifier.imported),
),
),
);
} }
} }
if (specifiers.exports.length) { if (specifiers.exports.length) {
const exportObjRef = path.scope.generateUidIdentifier("exportObj"); const exportObjRef = path.scope.generateUidIdentifier(
"exportObj",
);
setterBody.push(t.variableDeclaration("var", [ setterBody.push(
t.variableDeclaration("var", [
t.variableDeclarator(exportObjRef, t.objectExpression([])), t.variableDeclarator(exportObjRef, t.objectExpression([])),
])); ]),
);
for (const node of specifiers.exports) { for (const node of specifiers.exports) {
if (t.isExportAllDeclaration(node)) { if (t.isExportAllDeclaration(node)) {
setterBody.push(buildExportAll({ setterBody.push(
buildExportAll({
KEY: path.scope.generateUidIdentifier("key"), KEY: path.scope.generateUidIdentifier("key"),
EXPORT_OBJ: exportObjRef, EXPORT_OBJ: exportObjRef,
TARGET: target, TARGET: target,
})); }),
);
} else if (t.isExportSpecifier(node)) { } else if (t.isExportSpecifier(node)) {
setterBody.push(t.expressionStatement( setterBody.push(
t.assignmentExpression("=", t.memberExpression(exportObjRef, node.exported), t.expressionStatement(
t.memberExpression(target, node.local)) t.assignmentExpression(
)); "=",
t.memberExpression(exportObjRef, node.exported),
t.memberExpression(target, node.local),
),
),
);
} else { } else {
// todo // todo
} }
} }
setterBody.push(t.expressionStatement(t.callExpression(exportIdent, [exportObjRef]))); setterBody.push(
t.expressionStatement(
t.callExpression(exportIdent, [exportObjRef]),
),
);
} }
sources.push(t.stringLiteral(specifiers.key)); sources.push(t.stringLiteral(specifiers.key));
setters.push(t.functionExpression(null, [target], t.blockStatement(setterBody))); setters.push(
t.functionExpression(
null,
[target],
t.blockStatement(setterBody),
),
);
}); });
let moduleName = this.getModuleName(); let moduleName = this.getModuleName();
if (moduleName) moduleName = t.stringLiteral(moduleName); if (moduleName) moduleName = t.stringLiteral(moduleName);
if (canHoist) { if (canHoist) {
hoistVariables(path, (id) => variableIds.push(id)); hoistVariables(path, id => variableIds.push(id));
} }
if (variableIds.length) { if (variableIds.length) {
beforeBody.unshift(t.variableDeclaration("var", beforeBody.unshift(
variableIds.map((id) => t.variableDeclarator(id)))); t.variableDeclaration(
"var",
variableIds.map(id => t.variableDeclarator(id)),
),
);
} }
path.traverse(reassignmentVisitor, { path.traverse(reassignmentVisitor, {
@ -297,7 +359,9 @@ export default function ({ types: t }) {
path.node.body = [ path.node.body = [
buildTemplate({ buildTemplate({
SYSTEM_REGISTER: t.memberExpression( SYSTEM_REGISTER: t.memberExpression(
t.identifier(state.opts.systemGlobal || "System"), t.identifier("register")), t.identifier(state.opts.systemGlobal || "System"),
t.identifier("register"),
),
BEFORE_BODY: beforeBody, BEFORE_BODY: beforeBody,
MODULE_NAME: moduleName, MODULE_NAME: moduleName,
SETTERS: setters, SETTERS: setters,

View File

@ -59,7 +59,7 @@ export default function ({ types: t }) {
const func = call.arguments[1]; const func = call.arguments[1];
const browserGlobals = state.opts.globals || {}; const browserGlobals = state.opts.globals || {};
const commonArgs = amdArgs.elements.map((arg) => { const commonArgs = amdArgs.elements.map(arg => {
if (arg.value === "module" || arg.value === "exports") { if (arg.value === "module" || arg.value === "exports") {
return t.identifier(arg.value); return t.identifier(arg.value);
} else { } else {
@ -67,30 +67,39 @@ export default function ({ types: t }) {
} }
}); });
const browserArgs = amdArgs.elements.map((arg) => { const browserArgs = amdArgs.elements.map(arg => {
if (arg.value === "module") { if (arg.value === "module") {
return t.identifier("mod"); return t.identifier("mod");
} else if (arg.value === "exports") { } else if (arg.value === "exports") {
return t.memberExpression(t.identifier("mod"), t.identifier("exports")); return t.memberExpression(
t.identifier("mod"),
t.identifier("exports"),
);
} else { } else {
let memberExpression; let memberExpression;
if (state.opts.exactGlobals) { if (state.opts.exactGlobals) {
const globalRef = browserGlobals[arg.value]; const globalRef = browserGlobals[arg.value];
if (globalRef) { if (globalRef) {
memberExpression = globalRef.split(".").reduce( memberExpression = globalRef
(accum, curr) => t.memberExpression(accum, t.identifier(curr)), t.identifier("global") .split(".")
.reduce(
(accum, curr) =>
t.memberExpression(accum, t.identifier(curr)),
t.identifier("global"),
); );
} else { } else {
memberExpression = t.memberExpression( memberExpression = t.memberExpression(
t.identifier("global"), t.identifier(t.toIdentifier(arg.value)) t.identifier("global"),
t.identifier(t.toIdentifier(arg.value)),
); );
} }
} else { } else {
const requireName = basename(arg.value, extname(arg.value)); const requireName = basename(arg.value, extname(arg.value));
const globalName = browserGlobals[requireName] || requireName; const globalName = browserGlobals[requireName] || requireName;
memberExpression = t.memberExpression( memberExpression = t.memberExpression(
t.identifier("global"), t.identifier(t.toIdentifier(globalName)) t.identifier("global"),
t.identifier(t.toIdentifier(globalName)),
); );
} }
@ -98,10 +107,15 @@ export default function ({ types: t }) {
} }
}); });
const moduleNameOrBasename = moduleName ? moduleName.value : const moduleNameOrBasename = moduleName
basename(this.file.opts.filename, extname(this.file.opts.filename)); ? moduleName.value
: basename(
this.file.opts.filename,
extname(this.file.opts.filename),
);
let globalToAssign = t.memberExpression( let globalToAssign = t.memberExpression(
t.identifier("global"), t.identifier(t.toIdentifier(moduleNameOrBasename)) t.identifier("global"),
t.identifier(t.toIdentifier(moduleNameOrBasename)),
); );
let prerequisiteAssignments = null; let prerequisiteAssignments = null;
@ -113,7 +127,9 @@ export default function ({ types: t }) {
const members = globalName.split("."); const members = globalName.split(".");
globalToAssign = members.slice(1).reduce((accum, curr) => { globalToAssign = members.slice(1).reduce((accum, curr) => {
prerequisiteAssignments.push(buildPrerequisiteAssignment({ GLOBAL_REFERENCE: accum })); prerequisiteAssignments.push(
buildPrerequisiteAssignment({ GLOBAL_REFERENCE: accum }),
);
return t.memberExpression(accum, t.identifier(curr)); return t.memberExpression(accum, t.identifier(curr));
}, t.memberExpression(t.identifier("global"), t.identifier(members[0]))); }, t.memberExpression(t.identifier("global"), t.identifier(members[0])));
} }
@ -125,13 +141,15 @@ export default function ({ types: t }) {
GLOBAL_TO_ASSIGN: globalToAssign, GLOBAL_TO_ASSIGN: globalToAssign,
}); });
last.replaceWith(buildWrapper({ last.replaceWith(
buildWrapper({
MODULE_NAME: moduleName, MODULE_NAME: moduleName,
AMD_ARGUMENTS: amdArgs, AMD_ARGUMENTS: amdArgs,
COMMON_ARGUMENTS: commonArgs, COMMON_ARGUMENTS: commonArgs,
GLOBAL_EXPORT: globalExport, GLOBAL_EXPORT: globalExport,
FUNC: func, FUNC: func,
})); }),
);
}, },
}, },
}, },

View File

@ -18,15 +18,22 @@ export default function ({ types: t }) {
visitor: { visitor: {
ObjectExpression(path, state) { ObjectExpression(path, state) {
let objectRef; let objectRef;
const getObjectRef = () => objectRef = objectRef || path.scope.generateUidIdentifier("obj"); const getObjectRef = () =>
(objectRef = objectRef || path.scope.generateUidIdentifier("obj"));
path.get("properties").forEach((propertyPath) => { path.get("properties").forEach(propertyPath => {
if (!propertyPath.isMethod()) return; if (!propertyPath.isMethod()) return;
const propPaths: Array = path.get("properties"); const propPaths: Array = path.get("properties");
for (let propPath of propPaths) { for (let propPath of propPaths) {
if (propPath.isObjectProperty()) propPath = propPath.get("value"); if (propPath.isObjectProperty()) propPath = propPath.get("value");
replacePropertySuper(propPath, propPath.node, path.scope, getObjectRef, state); replacePropertySuper(
propPath,
propPath.node,
path.scope,
getObjectRef,
state,
);
} }
}); });

View File

@ -7,7 +7,8 @@ import * as rest from "./rest";
export default function() { export default function() {
return { return {
visitor: visitors.merge([{ visitor: visitors.merge([
{
ArrowFunctionExpression(path) { ArrowFunctionExpression(path) {
// In some conversion cases, it may have already been converted to a function while this callback // In some conversion cases, it may have already been converted to a function while this callback
// was queued up. // was queued up.
@ -22,6 +23,10 @@ export default function () {
} }
} }
}, },
}, destructuring.visitor, rest.visitor, def.visitor]), },
destructuring.visitor,
rest.visitor,
def.visitor,
]),
}; };
} }

View File

@ -86,37 +86,28 @@ const memberExpressionOptimisationVisitor = {
if (parentPath.isMemberExpression({ object: node })) { if (parentPath.isMemberExpression({ object: node })) {
const grandparentPath = parentPath.parentPath; const grandparentPath = parentPath.parentPath;
const argsOptEligible = !state.deopted && !( const argsOptEligible =
// ex: `args[0] = "whatever"` !state.deopted &&
!// ex: `args[0] = "whatever"`
( (
grandparentPath.isAssignmentExpression() && (grandparentPath.isAssignmentExpression() &&
parentPath.node === grandparentPath.node.left parentPath.node === grandparentPath.node.left) ||
) ||
// ex: `[args[0]] = ["whatever"]` // ex: `[args[0]] = ["whatever"]`
grandparentPath.isLVal() || grandparentPath.isLVal() ||
// ex: `for (rest[0] in this)` // ex: `for (rest[0] in this)`
// ex: `for (rest[0] of this)` // ex: `for (rest[0] of this)`
grandparentPath.isForXStatement() || grandparentPath.isForXStatement() ||
// ex: `++args[0]` // ex: `++args[0]`
// ex: `args[0]--` // ex: `args[0]--`
grandparentPath.isUpdateExpression() || grandparentPath.isUpdateExpression() ||
// ex: `delete args[0]` // ex: `delete args[0]`
grandparentPath.isUnaryExpression({ operator: "delete" }) || grandparentPath.isUnaryExpression({ operator: "delete" }) ||
// ex: `args[0]()` // ex: `args[0]()`
// ex: `new args[0]()` // ex: `new args[0]()`
// ex: `new args[0]` // ex: `new args[0]`
( ((grandparentPath.isCallExpression() ||
( grandparentPath.isNewExpression()) &&
grandparentPath.isCallExpression() || parentPath.node === grandparentPath.node.callee)
grandparentPath.isNewExpression()
) &&
parentPath.node === grandparentPath.node.callee
)
); );
if (argsOptEligible) { if (argsOptEligible) {
@ -127,9 +118,8 @@ const memberExpressionOptimisationVisitor = {
state.candidates.push({ cause: "indexGetter", path }); state.candidates.push({ cause: "indexGetter", path });
return; return;
} }
} } else if (parentPath.node.property.name === "length") {
// args.length // args.length
else if (parentPath.node.property.name === "length") {
state.candidates.push({ cause: "lengthGetter", path }); state.candidates.push({ cause: "lengthGetter", path });
return; return;
} }
@ -177,32 +167,42 @@ function optimiseIndexGetter(path, argsId, offset) {
// Avoid unnecessary '+ 0' // Avoid unnecessary '+ 0'
index = path.parent.property; index = path.parent.property;
} else { } else {
index = t.binaryExpression("+", path.parent.property, t.numericLiteral(offset)); index = t.binaryExpression(
"+",
path.parent.property,
t.numericLiteral(offset),
);
} }
const { scope } = path; const { scope } = path;
if (!scope.isPure(index)) { if (!scope.isPure(index)) {
const temp = scope.generateUidIdentifierBasedOnNode(index); const temp = scope.generateUidIdentifierBasedOnNode(index);
scope.push({ id: temp, kind: "var" }); scope.push({ id: temp, kind: "var" });
path.parentPath.replaceWith(restIndexImpure({ path.parentPath.replaceWith(
restIndexImpure({
ARGUMENTS: argsId, ARGUMENTS: argsId,
INDEX: index, INDEX: index,
REF: temp, REF: temp,
})); }),
);
} else { } else {
path.parentPath.replaceWith(restIndex({ path.parentPath.replaceWith(
restIndex({
ARGUMENTS: argsId, ARGUMENTS: argsId,
INDEX: index, INDEX: index,
})); }),
);
} }
} }
function optimiseLengthGetter(path, argsId, offset) { function optimiseLengthGetter(path, argsId, offset) {
if (offset) { if (offset) {
path.parentPath.replaceWith(restLength({ path.parentPath.replaceWith(
restLength({
ARGUMENTS: argsId, ARGUMENTS: argsId,
OFFSET: t.numericLiteral(offset), OFFSET: t.numericLiteral(offset),
})); }),
);
} else { } else {
path.replaceWith(argsId); path.replaceWith(argsId);
} }
@ -266,7 +266,7 @@ export const visitor = {
} }
state.references = state.references.concat( state.references = state.references.concat(
state.candidates.map(({ path }) => path) state.candidates.map(({ path }) => path),
); );
const start = t.numericLiteral(node.params.length); const start = t.numericLiteral(node.params.length);
@ -290,7 +290,7 @@ export const visitor = {
arrLen = t.conditionalExpression( arrLen = t.conditionalExpression(
t.binaryExpression(">", len, start), t.binaryExpression(">", len, start),
t.binaryExpression("-", len, start), t.binaryExpression("-", len, start),
t.numericLiteral(0) t.numericLiteral(0),
); );
} }
@ -311,10 +311,12 @@ export const visitor = {
// perform allocation at the lowest common ancestor of all references // perform allocation at the lowest common ancestor of all references
loop._blockHoist = 1; loop._blockHoist = 1;
let target = path.getEarliestCommonAncestorFrom(state.references).getStatementParent(); let target = path
.getEarliestCommonAncestorFrom(state.references)
.getStatementParent();
// don't perform the allocation inside a loop // don't perform the allocation inside a loop
target.findParent((path) => { target.findParent(path => {
if (path.isLoop()) { if (path.isLoop()) {
target = path; target = path;
} else { } else {

View File

@ -6,14 +6,16 @@ export default function () {
ObjectMethod(path) { ObjectMethod(path) {
const { node } = path; const { node } = path;
if (node.kind === "method") { if (node.kind === "method") {
const func = t.functionExpression(null, node.params, node.body, node.generator, node.async); const func = t.functionExpression(
null,
node.params,
node.body,
node.generator,
node.async,
);
func.returnType = node.returnType; func.returnType = node.returnType;
path.replaceWith(t.objectProperty( path.replaceWith(t.objectProperty(node.key, func, node.computed));
node.key,
func,
node.computed
));
} }
}, },

View File

@ -1,6 +1,9 @@
export default function({ types: t }) { export default function({ types: t }) {
function getSpreadLiteral(spread, scope, state) { function getSpreadLiteral(spread, scope, state) {
if (state.opts.loose && !t.isIdentifier(spread.argument, { name: "arguments" })) { if (
state.opts.loose &&
!t.isIdentifier(spread.argument, { name: "arguments" })
) {
return spread.argument; return spread.argument;
} else { } else {
return scope.toArray(spread.argument, true); return scope.toArray(spread.argument, true);
@ -55,7 +58,12 @@ export default function ({ types: t }) {
first = t.arrayExpression([]); first = t.arrayExpression([]);
} }
path.replaceWith(t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes)); path.replaceWith(
t.callExpression(
t.memberExpression(first, t.identifier("concat")),
nodes,
),
);
}, },
CallExpression(path, state) { CallExpression(path, state) {
@ -80,7 +88,12 @@ export default function ({ types: t }) {
const first = nodes.shift(); const first = nodes.shift();
if (nodes.length) { if (nodes.length) {
node.arguments.push(t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes)); node.arguments.push(
t.callExpression(
t.memberExpression(first, t.identifier("concat")),
nodes,
),
);
} else { } else {
node.arguments.push(first); node.arguments.push(first);
} }
@ -116,10 +129,13 @@ export default function ({ types: t }) {
const context = t.arrayExpression([t.nullLiteral()]); const context = t.arrayExpression([t.nullLiteral()]);
args = t.callExpression(
t.memberExpression(context, t.identifier("concat")),
nodes,
);
args = t.callExpression(t.memberExpression(context, t.identifier("concat")), nodes); path.replaceWith(
t.newExpression(
path.replaceWith(t.newExpression(
t.callExpression( t.callExpression(
t.memberExpression( t.memberExpression(
t.memberExpression( t.memberExpression(
@ -127,14 +143,15 @@ export default function ({ types: t }) {
t.identifier("Function"), t.identifier("Function"),
t.identifier("prototype"), t.identifier("prototype"),
), ),
t.identifier("bind") t.identifier("bind"),
), ),
t.identifier("apply") t.identifier("apply"),
), ),
[node.callee, args] [node.callee, args],
), ),
[] [],
)); ),
);
}, },
}, },
}; };

View File

@ -8,10 +8,12 @@ export default function () {
const { node } = path; const { node } = path;
if (!regex.is(node, "y")) return; if (!regex.is(node, "y")) return;
path.replaceWith(t.newExpression(t.identifier("RegExp"), [ path.replaceWith(
t.newExpression(t.identifier("RegExp"), [
t.stringLiteral(node.pattern), t.stringLiteral(node.pattern),
t.stringLiteral(node.flags), t.stringLiteral(node.flags),
])); ]),
);
}, },
}, },
}; };

View File

@ -1,5 +1,4 @@
export default function({ types: t }) { export default function({ types: t }) {
function buildConcatCallExressions(items) { function buildConcatCallExressions(items) {
let avail = true; let avail = true;
return items.reduce(function(left, right) { return items.reduce(function(left, right) {
@ -15,7 +14,7 @@ export default function ({ types: t }) {
} }
return t.callExpression( return t.callExpression(
t.memberExpression(left, t.identifier("concat")), t.memberExpression(left, t.identifier("concat")),
[right] [right],
); );
}); });
} }
@ -23,7 +22,6 @@ export default function ({ types: t }) {
return { return {
visitor: { visitor: {
TaggedTemplateExpression(path, state) { TaggedTemplateExpression(path, state) {
const { node } = path; const { node } = path;
const { quasi } = node; const { quasi } = node;
@ -32,7 +30,8 @@ export default function ({ types: t }) {
for (const elem of (quasi.quasis: Array)) { for (const elem of (quasi.quasis: Array)) {
const { raw, cooked } = elem.value; const { raw, cooked } = elem.value;
const value = cooked == null const value =
cooked == null
? path.scope.buildUndefinedNode() ? path.scope.buildUndefinedNode()
: t.stringLiteral(cooked); : t.stringLiteral(cooked);
@ -46,7 +45,7 @@ export default function ({ types: t }) {
const templateObject = state.file.addTemplateObject( const templateObject = state.file.addTemplateObject(
templateName, templateName,
t.arrayExpression(strings), t.arrayExpression(strings),
t.arrayExpression(raws) t.arrayExpression(raws),
); );
const args = [templateObject].concat(quasi.expressions); const args = [templateObject].concat(quasi.expressions);
@ -75,7 +74,8 @@ export default function ({ types: t }) {
// since `+` is left-to-right associative // since `+` is left-to-right associative
// ensure the first node is a string if first/second isn't // ensure the first node is a string if first/second isn't
const considerSecondNode = state.opts.spec || !t.isStringLiteral(nodes[1]); const considerSecondNode =
state.opts.spec || !t.isStringLiteral(nodes[1]);
if (!t.isStringLiteral(nodes[0]) && considerSecondNode) { if (!t.isStringLiteral(nodes[0]) && considerSecondNode) {
nodes.unshift(t.stringLiteral("")); nodes.unshift(t.stringLiteral(""));
} }

View File

@ -14,7 +14,7 @@ export default function ({ types: t }) {
UnaryExpression(path) { UnaryExpression(path) {
const { node, parent } = path; const { node, parent } = path;
if (node[IGNORE]) return; if (node[IGNORE]) return;
if (path.find((path) => path.node && !!path.node._generated)) return; if (path.find(path => path.node && !!path.node._generated)) return;
if ( if (
path.parentPath.isBinaryExpression() && path.parentPath.isBinaryExpression() &&
@ -24,7 +24,8 @@ export default function ({ types: t }) {
// need to handle symbols // need to handle symbols
const opposite = path.getOpposite(); const opposite = path.getOpposite();
if ( if (
opposite.isLiteral() && opposite.node.value !== "symbol" && opposite.isLiteral() &&
opposite.node.value !== "symbol" &&
opposite.node.value !== "object" opposite.node.value !== "object"
) { ) {
return; return;
@ -32,16 +33,20 @@ export default function ({ types: t }) {
} }
if (node.operator === "typeof") { if (node.operator === "typeof") {
const call = t.callExpression(this.addHelper("typeof"), [node.argument]); const call = t.callExpression(this.addHelper("typeof"), [
node.argument,
]);
if (path.get("argument").isIdentifier()) { if (path.get("argument").isIdentifier()) {
const undefLiteral = t.stringLiteral("undefined"); const undefLiteral = t.stringLiteral("undefined");
const unary = t.unaryExpression("typeof", node.argument); const unary = t.unaryExpression("typeof", node.argument);
unary[IGNORE] = true; unary[IGNORE] = true;
path.replaceWith(t.conditionalExpression( path.replaceWith(
t.conditionalExpression(
t.binaryExpression("===", unary, undefLiteral), t.binaryExpression("===", unary, undefLiteral),
undefLiteral, undefLiteral,
call call,
)); ),
);
} else { } else {
path.replaceWith(call); path.replaceWith(call);
} }

View File

@ -4,7 +4,11 @@ export default function ({ types: t }) {
MemberExpression: { MemberExpression: {
exit({ node }) { exit({ node }) {
const prop = node.property; const prop = node.property;
if (!node.computed && t.isIdentifier(prop) && !t.isValidIdentifier(prop.name)) { if (
!node.computed &&
t.isIdentifier(prop) &&
!t.isValidIdentifier(prop.name)
) {
// foo.default -> foo["default"] // foo.default -> foo["default"]
node.property = t.stringLiteral(prop.name); node.property = t.stringLiteral(prop.name);
node.computed = true; node.computed = true;

View File

@ -4,7 +4,11 @@ export default function ({ types: t }) {
ObjectProperty: { ObjectProperty: {
exit({ node }) { exit({ node }) {
const key = node.key; const key = node.key;
if (!node.computed && t.isIdentifier(key) && !t.isValidIdentifier(key.name)) { if (
!node.computed &&
t.isIdentifier(key) &&
!t.isValidIdentifier(key.name)
) {
// default: "bar" -> "default": "bar" // default: "bar" -> "default": "bar"
node.key = t.stringLiteral(key.name); node.key = t.stringLiteral(key.name);
} }

View File

@ -25,10 +25,15 @@ export default function ({ types: t }) {
} }
}); });
path.replaceWith(t.callExpression( path.replaceWith(
t.memberExpression(t.identifier("Object"), t.identifier("defineProperties")), t.callExpression(
[node, defineMap.toDefineObject(mutatorMap)] t.memberExpression(
)); t.identifier("Object"),
t.identifier("defineProperties"),
),
[node, defineMap.toDefineObject(mutatorMap)],
),
);
}, },
}, },
}; };

View File

@ -2,7 +2,10 @@ export default function ({ parse, traverse }) {
return { return {
visitor: { visitor: {
CallExpression(path) { CallExpression(path) {
if (path.get("callee").isIdentifier({ name: "eval" }) && path.node.arguments.length === 1) { if (
path.get("callee").isIdentifier({ name: "eval" }) &&
path.node.arguments.length === 1
) {
const evaluate = path.get("arguments")[0].evaluate(); const evaluate = path.get("arguments")[0].evaluate();
if (!evaluate.confident) return; if (!evaluate.confident) return;

View File

@ -9,7 +9,10 @@ export default function ({ types: t }) {
operator: "**", operator: "**",
build(left, right) { build(left, right) {
return t.callExpression(t.memberExpression(t.identifier("Math"), t.identifier("pow")), [left, right]); return t.callExpression(
t.memberExpression(t.identifier("Math"), t.identifier("pow")),
[left, right],
);
}, },
}), }),
}; };

Some files were not shown because too many files have changed in this diff Show More