Merge branch '7.0' into fix-require-debug

This commit is contained in:
Sven SAULEAU
2017-03-11 12:17:04 +01:00
703 changed files with 14486 additions and 6482 deletions

View File

@@ -1,112 +0,0 @@
/* eslint max-len: 0 */
/* eslint no-new-func: 0 */
import { transform } from "./node";
export {
File,
options,
buildExternalHelpers,
template,
version,
util,
messages,
types,
traverse,
OptionManager,
Plugin,
Pipeline,
analyse,
transform,
transformFromAst,
transformFile,
transformFileSync
} from "./node";
export function run(code: string, opts: Object = {}): any {
return new Function(transform(code, opts).code)();
}
export function load(url: string, callback: Function, opts: Object = {}, hold?: boolean) {
opts.filename = opts.filename || url;
let xhr = global.ActiveXObject ? new global.ActiveXObject("Microsoft.XMLHTTP") : new global.XMLHttpRequest();
xhr.open("GET", url, true);
if ("overrideMimeType" in xhr) xhr.overrideMimeType("text/plain");
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return;
let status = xhr.status;
if (status === 0 || status === 200) {
let param = [xhr.responseText, opts];
if (!hold) run(param);
if (callback) callback(param);
} else {
throw new Error(`Could not load ${url}`);
}
};
xhr.send(null);
}
function runScripts() {
let scripts: Array<Array<any> | Object> = [];
let types = ["text/ecmascript-6", "text/6to5", "text/babel", "module"];
let index = 0;
/**
* Transform and execute script. Ensures correct load order.
*/
function exec() {
let param = scripts[index];
if (param instanceof Array) {
run(param, index);
index++;
exec();
}
}
/**
* Load, transform, and execute all scripts.
*/
function run(script: Object, i: number) {
let opts = {};
if (script.src) {
load(script.src, function (param) {
scripts[i] = param;
exec();
}, opts, true);
} else {
opts.filename = "embedded";
scripts[i] = [script.innerHTML, opts];
}
}
// Collect scripts with Babel `types`.
let _scripts = global.document.getElementsByTagName("script");
for (let i = 0; i < _scripts.length; ++i) {
let _script = _scripts[i];
if (types.indexOf(_script.type) >= 0) scripts.push(_script);
}
for (let i = 0; i < scripts.length; i++) {
run(scripts[i], i);
}
exec();
}
/**
* Register load event to transform and execute scripts.
*/
if (global.addEventListener) {
global.addEventListener("DOMContentLoaded", runScripts, false);
} else if (global.attachEvent) {
global.attachEvent("onload", runScripts);
}

View File

@@ -0,0 +1,3 @@
export default function getPossiblePluginNames(pluginName: string): Array<string> {
return [`babel-plugin-${pluginName}`, pluginName];
}

View File

@@ -0,0 +1,13 @@
export default function getPossiblePresetNames(presetName: string): Array<string> {
const possibleNames = [`babel-preset-${presetName}`, presetName];
// trying to resolve @organization shortcat
// @foo/es2015 -> @foo/babel-preset-es2015
const matches = presetName.match(/^(@[^/]+)\/(.+)$/);
if (matches) {
const [, orgName, presetPath] = matches;
possibleNames.push(`${orgName}/babel-preset-${presetPath}`);
}
return possibleNames;
}

View File

@@ -5,9 +5,9 @@ export default function (dest?: Object, src?: Object): ?Object {
return mergeWith(dest, src, function (a, b) {
if (b && Array.isArray(a)) {
let newArray = b.slice(0);
const newArray = b.slice(0);
for (let item of a) {
for (const item of a) {
if (newArray.indexOf(item) < 0) {
newArray.push(item);
}

View File

@@ -0,0 +1,5 @@
import resolve from "./resolve";
export default function resolveFromPossibleNames(possibleNames: Array<string>, dirname: string): ?string {
return possibleNames.reduce((accum, curr) => accum || resolve(curr, dirname), null);
}

View File

@@ -0,0 +1,6 @@
import resolveFromPossibleNames from "./resolve-from-possible-names";
import getPossiblePluginNames from "./get-possible-plugin-names";
export default function resolvePlugin(pluginName: string, dirname: string = process.cwd()): ?string {
return resolveFromPossibleNames(getPossiblePluginNames(pluginName), dirname);
}

View File

@@ -0,0 +1,6 @@
import resolveFromPossibleNames from "./resolve-from-possible-names";
import getPossiblePresetNames from "./get-possible-preset-names";
export default function resolvePreset(presetName: string, dirname: string = process.cwd()): ?string {
return resolveFromPossibleNames(getPossiblePresetNames(presetName), dirname);
}

View File

@@ -1,33 +1,8 @@
import Module from "module";
import path from "path";
let relativeModules = {};
import resolve from "resolve";
export default function (loc: string, relative: string = process.cwd()): ?string {
// we're in the browser, probably
if (typeof Module === "object") return null;
let relativeMod = relativeModules[relative];
if (!relativeMod) {
relativeMod = new Module;
// We need to define an id and filename on our "fake" relative` module so that
// Node knows what "." means in the case of us trying to resolve a plugin
// such as "./myPlugins/somePlugin.js". If we don't specify id and filename here,
// Node presumes "." is process.cwd(), not our relative path.
// Since this fake module is never "loaded", we don't have to worry about mutating
// any global Node module cache state here.
let filename = path.join(relative, ".babelrc");
relativeMod.id = filename;
relativeMod.filename = filename;
relativeMod.paths = Module._nodeModulePaths(relative);
relativeModules[relative] = relativeMod;
}
try {
return Module._resolveFilename(loc, relativeMod);
return resolve.sync(loc, { basedir: relative });
} catch (err) {
return null;
}

View File

@@ -1,13 +1,14 @@
import isFunction from "lodash/isFunction";
import fs from "fs";
export { default as File } from "../transformation/file";
export { default as options } from "../transformation/file/options/config";
export { default as buildExternalHelpers } from "../tools/build-external-helpers";
export { default as File } from "./transformation/file";
export { default as options } from "./transformation/file/options/config";
export { default as buildExternalHelpers } from "./tools/build-external-helpers";
export { default as template } from "babel-template";
export { version } from "../../package";
export { default as resolvePlugin } from "./helpers/resolve-plugin";
export { default as resolvePreset } from "./helpers/resolve-preset";
export { version } from "../package";
import * as util from "../util";
import * as util from "./util";
export { util };
import * as messages from "babel-messages";
@@ -19,23 +20,18 @@ export { t as types };
import traverse from "babel-traverse";
export { traverse };
import OptionManager from "../transformation/file/options/option-manager";
import OptionManager from "./transformation/file/options/option-manager";
export { OptionManager };
export function Plugin(alias) {
throw new Error(`The (${alias}) Babel 5 plugin is being run with Babel 6.`);
}
import Pipeline from "../transformation/pipeline";
export { Pipeline };
let pipeline = new Pipeline;
export let analyse = pipeline.analyse.bind(pipeline);
export let transform = pipeline.transform.bind(pipeline);
export let transformFromAst = pipeline.transformFromAst.bind(pipeline);
import { transform, analyse, transformFromAst } from "./transformation/pipeline";
export { transform, analyse, transformFromAst };
export function transformFile(filename: string, opts?: Object, callback: Function) {
if (isFunction(opts)) {
if (typeof opts === "function") {
callback = opts;
opts = {};
}

View File

@@ -1,22 +1,24 @@
export default class Store extends Map {
export default class Store {
constructor() {
super();
this.dynamicData = {};
this._map = new Map();
this._map.dynamicData = {};
}
dynamicData: Object;
setDynamic(key, fn) {
this.dynamicData[key] = fn;
this._map.dynamicData[key] = fn;
}
set(key: string, val) {
this._map.set(key, val);
}
get(key: string): any {
if (this.has(key)) {
return super.get(key);
if (this._map.has(key)) {
return this._map.get(key);
} else {
if (Object.prototype.hasOwnProperty.call(this.dynamicData, key)) {
let val = this.dynamicData[key]();
this.set(key, val);
if (Object.prototype.hasOwnProperty.call(this._map.dynamicData, key)) {
const val = this._map.dynamicData[key]();
this._map.set(key, val);
return val;
}
}

View File

@@ -1,13 +1,10 @@
/* eslint max-len: 0 */
import * as helpers from "babel-helpers";
import generator from "babel-generator";
import * as messages from "babel-messages";
import template from "babel-template";
import each from "lodash/each";
import * as t from "babel-types";
let buildUmdWrapper = template(`
const buildUmdWrapper = template(`
(function (root, factory) {
if (typeof define === "function" && define.amd) {
define(AMD_ARGUMENTS, factory);
@@ -22,15 +19,17 @@ let buildUmdWrapper = template(`
`);
function buildGlobal(namespace, builder) {
let body = [];
let container = t.functionExpression(null, [t.identifier("global")], t.blockStatement(body));
let tree = t.program([t.expressionStatement(t.callExpression(container, [helpers.get("selfGlobal")]))]);
const body = [];
const container = t.functionExpression(null, [t.identifier("global")], t.blockStatement(body));
const tree = t.program([
t.expressionStatement(t.callExpression(container, [helpers.get("selfGlobal")]))]);
body.push(t.variableDeclaration("var", [
t.variableDeclarator(
namespace,
t.assignmentExpression("=", t.memberExpression(t.identifier("global"), namespace), t.objectExpression([]))
)
t.assignmentExpression("=", t.memberExpression(t.identifier("global"), namespace),
t.objectExpression([]))
),
]));
builder(body);
@@ -39,9 +38,9 @@ function buildGlobal(namespace, builder) {
}
function buildUmd(namespace, builder) {
let body = [];
const body = [];
body.push(t.variableDeclaration("var", [
t.variableDeclarator(namespace, t.identifier("global"))
t.variableDeclarator(namespace, t.identifier("global")),
]));
builder(body);
@@ -49,23 +48,23 @@ function buildUmd(namespace, builder) {
return t.program([
buildUmdWrapper({
FACTORY_PARAMETERS: t.identifier("global"),
BROWSER_ARGUMENTS: t.assignmentExpression(
BROWSER_ARGUMENTS: t.assignmentExpression(
"=",
t.memberExpression(t.identifier("root"), namespace),
t.objectExpression([])
),
COMMON_ARGUMENTS: t.identifier("exports"),
AMD_ARGUMENTS: t.arrayExpression([t.stringLiteral("exports")]),
FACTORY_BODY: body,
UMD_ROOT: t.identifier("this")
})
COMMON_ARGUMENTS: t.identifier("exports"),
AMD_ARGUMENTS: t.arrayExpression([t.stringLiteral("exports")]),
FACTORY_BODY: body,
UMD_ROOT: t.identifier("this"),
}),
]);
}
function buildVar(namespace, builder) {
let body = [];
const body = [];
body.push(t.variableDeclaration("var", [
t.variableDeclarator(namespace, t.objectExpression([]))
t.variableDeclarator(namespace, t.objectExpression([])),
]));
builder(body);
body.push(t.expressionStatement(namespace));
@@ -73,10 +72,10 @@ function buildVar(namespace, builder) {
}
function buildHelpers(body, namespace, whitelist) {
each(helpers.list, function (name) {
helpers.list.forEach(function (name) {
if (whitelist && whitelist.indexOf(name) < 0) return;
let key = t.identifier(name);
const key = t.identifier(name);
body.push(t.expressionStatement(
t.assignmentExpression("=", t.memberExpression(namespace, key), helpers.get(name))
));
@@ -86,18 +85,18 @@ export default function (
whitelist?: Array<string>,
outputType: "global" | "umd" | "var" = "global",
) {
let namespace = t.identifier("babelHelpers");
const namespace = t.identifier("babelHelpers");
let builder = function (body) {
const builder = function (body) {
return buildHelpers(body, namespace, whitelist);
};
let tree;
let build = {
const build = {
global: buildGlobal,
umd: buildUmd,
var: buildVar,
umd: buildUmd,
var: buildVar,
}[outputType];
if (build) {

View File

@@ -1,11 +1,9 @@
/* global BabelFileResult, BabelParserOptions, BabelFileMetadata */
/* eslint max-len: 0 */
import getHelper from "babel-helpers";
import * as metadataVisitor from "./metadata";
import convertSourceMap from "convert-source-map";
import OptionManager from "./options/option-manager";
import type Pipeline from "../pipeline";
import PluginPass from "../plugin-pass";
import { NodePath, Hub, Scope } from "babel-traverse";
import sourceMap from "source-map";
@@ -16,7 +14,7 @@ import traverse from "babel-traverse";
import Logger from "./logger";
import Store from "../../store";
import { parse } from "babylon";
import * as util from "../../util";
import * as util from "../../util";
import path from "path";
import * as t from "babel-types";
@@ -29,50 +27,48 @@ const shebangRegex = /^#!.*/;
const INTERNAL_PLUGINS = [
[blockHoistPlugin],
[shadowFunctionsPlugin]
[shadowFunctionsPlugin],
];
let errorVisitor = {
const errorVisitor = {
enter(path, state) {
let loc = path.node.loc;
const loc = path.node.loc;
if (loc) {
state.loc = loc;
path.stop();
}
}
},
};
export default class File extends Store {
constructor(opts: Object = {}, pipeline: Pipeline) {
constructor(opts: Object = {}) {
super();
this.pipeline = pipeline;
this.log = new Logger(this, opts.filename || "unknown");
this.log = new Logger(this, opts.filename || "unknown");
this.opts = this.initOptions(opts);
opts = this.initOptions(opts);
let passes = [];
if (opts.plugins) passes.push(opts.plugins);
// With "passPerPreset" enabled there may still be presets in the options.
if (opts.presets) passes = passes.concat(opts.presets.map((preset) => preset.plugins).filter(Boolean));
this.pluginPasses = passes;
this.opts = opts;
this.parserOpts = {
sourceType: this.opts.sourceType,
sourceType: this.opts.sourceType,
sourceFileName: this.opts.filename,
plugins: []
plugins: [],
};
this.pluginVisitors = [];
this.pluginPasses = [];
// Plugins for top-level options.
this.buildPluginsForOptions(this.opts);
// If we are in the "pass per preset" mode, build
// also plugins for each preset.
if (this.opts.passPerPreset) {
// All the "per preset" options are inherited from the main options.
this.perPresetOpts = [];
this.opts.presets.forEach((presetOpts) => {
let perPresetOpts = Object.assign(Object.create(this.opts), presetOpts);
this.perPresetOpts.push(perPresetOpts);
this.buildPluginsForOptions(perPresetOpts);
});
for (const pluginPairs of passes) {
for (const [ plugin ] of pluginPairs) {
if (plugin.manipulateOptions) {
plugin.manipulateOptions(opts, this.parserOpts, this);
}
}
}
this.metadata = {
@@ -82,21 +78,21 @@ export default class File extends Store {
imports: [],
exports: {
exported: [],
specifiers: []
}
}
specifiers: [],
},
},
};
this.dynamicImportTypes = {};
this.dynamicImportIds = {};
this.dynamicImports = [];
this.declarations = {};
this.usedHelpers = {};
this.dynamicImportIds = {};
this.dynamicImports = [];
this.declarations = {};
this.usedHelpers = {};
this.path = null;
this.ast = {};
this.ast = {};
this.code = "";
this.code = "";
this.shebang = "";
this.hub = new Hub(this);
@@ -104,9 +100,7 @@ export default class File extends Store {
static helpers: Array<string>;
pluginVisitors: Array<Object>;
pluginPasses: Array<PluginPass>;
pipeline: Pipeline;
pluginPasses: Array<Array<[Plugin, Object]>>;
parserOpts: BabelParserOptions;
log: Logger;
opts: Object;
@@ -125,7 +119,7 @@ export default class File extends Store {
getMetadata() {
let has = false;
for (let node of (this.ast.program.body: Array<Object>)) {
for (const node of (this.ast.program.body: Array<Object>)) {
if (t.isModuleDeclaration(node)) {
has = true;
break;
@@ -137,7 +131,7 @@ export default class File extends Store {
}
initOptions(opts) {
opts = new OptionManager(this.log, this.pipeline).init(opts);
opts = this.log.wrap(() => new OptionManager().init(opts));
if (opts.inputSourceMap) {
opts.sourceMaps = true;
@@ -154,54 +148,29 @@ export default class File extends Store {
if (opts.only) opts.only = util.arrayify(opts.only, util.regexify);
defaults(opts, {
moduleRoot: opts.sourceRoot
moduleRoot: opts.sourceRoot,
});
defaults(opts, {
sourceRoot: opts.moduleRoot
sourceRoot: opts.moduleRoot,
});
defaults(opts, {
filenameRelative: opts.filename
filenameRelative: opts.filename,
});
let basenameRelative = path.basename(opts.filenameRelative);
const basenameRelative = path.basename(opts.filenameRelative);
defaults(opts, {
sourceFileName: basenameRelative,
sourceMapTarget: basenameRelative
sourceFileName: basenameRelative,
sourceMapTarget: basenameRelative,
});
return opts;
}
buildPluginsForOptions(opts) {
if (!Array.isArray(opts.plugins)) {
return;
}
let plugins: Array<[PluginPass, Object]> = opts.plugins.concat(INTERNAL_PLUGINS);
let currentPluginVisitors = [];
let currentPluginPasses = [];
// init plugins!
for (let ref of plugins) {
let [plugin, pluginOpts] = ref; // todo: fix - can't embed in loop head because of flow bug
currentPluginVisitors.push(plugin.visitor);
currentPluginPasses.push(new PluginPass(this, plugin, pluginOpts));
if (plugin.manipulateOptions) {
plugin.manipulateOptions(opts, this.parserOpts, this);
}
}
this.pluginVisitors.push(currentPluginVisitors);
this.pluginPasses.push(currentPluginPasses);
}
getModuleName(): ?string {
let opts = this.opts;
const opts = this.opts;
if (!opts.moduleIds) {
return null;
}
@@ -224,7 +193,7 @@ export default class File extends Store {
if (opts.sourceRoot != null) {
// remove sourceRoot from filename
let sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "\/?");
const sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "\/?");
filenameRelative = filenameRelative.replace(sourceRootRegEx, "");
}
@@ -245,20 +214,20 @@ export default class File extends Store {
}
resolveModuleSource(source: string): string {
let resolveModuleSource = this.opts.resolveModuleSource;
const resolveModuleSource = this.opts.resolveModuleSource;
if (resolveModuleSource) source = resolveModuleSource(source, this.opts.filename);
return source;
}
addImport(source: string, imported: string, name?: string = imported): Object {
let alias = `${source}:${imported}`;
const alias = `${source}:${imported}`;
let id = this.dynamicImportIds[alias];
if (!id) {
source = this.resolveModuleSource(source);
id = this.dynamicImportIds[alias] = this.scope.generateUidIdentifier(name);
let specifiers = [];
const specifiers = [];
if (imported === "*") {
specifiers.push(t.importNamespaceSpecifier(id));
@@ -268,7 +237,7 @@ export default class File extends Store {
specifiers.push(t.importSpecifier(id, t.identifier(imported)));
}
let declar = t.importDeclaration(specifiers, t.stringLiteral(source));
const declar = t.importDeclaration(specifiers, t.stringLiteral(source));
declar._blockHoist = 3;
this.path.unshiftContainer("body", declar);
@@ -278,7 +247,7 @@ export default class File extends Store {
}
addHelper(name: string): Object {
let declar = this.declarations[name];
const declar = this.declarations[name];
if (declar) return declar;
if (!this.usedHelpers[name]) {
@@ -286,17 +255,17 @@ export default class File extends Store {
this.usedHelpers[name] = true;
}
let generator = this.get("helperGenerator");
let runtime = this.get("helpersNamespace");
const generator = this.get("helperGenerator");
const runtime = this.get("helpersNamespace");
if (generator) {
let res = generator(name);
const res = generator(name);
if (res) return res;
} else if (runtime) {
return t.memberExpression(runtime, t.identifier(name));
}
let ref = getHelper(name);
let uid = this.declarations[name] = this.scope.generateUidIdentifier(name);
const ref = getHelper(name);
const uid = this.declarations[name] = this.scope.generateUidIdentifier(name);
if (t.isFunctionExpression(ref) && !ref.id) {
ref.body._compact = true;
@@ -309,7 +278,7 @@ export default class File extends Store {
this.scope.push({
id: uid,
init: ref,
unique: true
unique: true,
});
}
@@ -323,31 +292,31 @@ export default class File extends Store {
): Object {
// Generate a unique name based on the string literals so we dedupe
// identical strings used in the program.
let stringIds = raw.elements.map(function(string) {
const stringIds = raw.elements.map(function(string) {
return string.value;
});
let name = `${helperName}_${raw.elements.length}_${stringIds.join(",")}`;
const name = `${helperName}_${raw.elements.length}_${stringIds.join(",")}`;
let declar = this.declarations[name];
const declar = this.declarations[name];
if (declar) return declar;
let uid = this.declarations[name] = this.scope.generateUidIdentifier("templateObject");
const uid = this.declarations[name] = this.scope.generateUidIdentifier("templateObject");
let helperId = this.addHelper(helperName);
let init = t.callExpression(helperId, [strings, raw]);
const helperId = this.addHelper(helperName);
const init = t.callExpression(helperId, [strings, raw]);
init._compact = true;
this.scope.push({
id: uid,
init: init,
_blockHoist: 1.9 // This ensures that we don't fail if not using function expression helpers
_blockHoist: 1.9, // This ensures that we don't fail if not using function expression helpers
});
return uid;
}
buildCodeFrameError(node: Object, msg: string, Error: typeof Error = SyntaxError): Error {
let loc = node && (node.loc || node._loc);
const loc = node && (node.loc || node._loc);
let err = new Error(msg);
const err = new Error(msg);
if (loc) {
err.loc = loc.start;
@@ -367,26 +336,26 @@ export default class File extends Store {
}
mergeSourceMap(map: Object) {
let inputMap = this.opts.inputSourceMap;
const inputMap = this.opts.inputSourceMap;
if (inputMap) {
let inputMapConsumer = new sourceMap.SourceMapConsumer(inputMap);
let outputMapConsumer = new sourceMap.SourceMapConsumer(map);
const inputMapConsumer = new sourceMap.SourceMapConsumer(inputMap);
const outputMapConsumer = new sourceMap.SourceMapConsumer(map);
let mergedGenerator = new sourceMap.SourceMapGenerator({
const mergedGenerator = new sourceMap.SourceMapGenerator({
file: inputMapConsumer.file,
sourceRoot: inputMapConsumer.sourceRoot
sourceRoot: inputMapConsumer.sourceRoot,
});
// This assumes the output map always has a single source, since Babel always compiles a single source file to a
// single output file.
// This assumes the output map always has a single source, since Babel always compiles a
// single source file to a single output file.
const source = outputMapConsumer.sources[0];
inputMapConsumer.eachMapping(function (mapping) {
const generatedPosition = outputMapConsumer.generatedPositionFor({
line: mapping.generatedLine,
column: mapping.generatedColumn,
source: source
source: source,
});
if (generatedPosition.column != null) {
mergedGenerator.addMapping({
@@ -394,15 +363,15 @@ export default class File extends Store {
original: mapping.source == null ? null : {
line: mapping.originalLine,
column: mapping.originalColumn
column: mapping.originalColumn,
},
generated: generatedPosition
generated: generatedPosition,
});
}
});
let mergedMap = mergedGenerator.toJSON();
const mergedMap = mergedGenerator.toJSON();
inputMap.mappings = mergedMap.mappings;
return inputMap;
} else {
@@ -419,12 +388,13 @@ export default class File extends Store {
if (parserOpts.parser) {
if (typeof parserOpts.parser === "string") {
let dirname = path.dirname(this.opts.filename) || process.cwd();
let parser = resolve(parserOpts.parser, dirname);
const dirname = path.dirname(this.opts.filename) || process.cwd();
const parser = resolve(parserOpts.parser, dirname);
if (parser) {
parseCode = require(parser).parse;
} else {
throw new Error(`Couldn't find parser ${parserOpts.parser} with "parse" method relative to directory ${dirname}`);
throw new Error(`Couldn't find parser ${parserOpts.parser} with "parse" method ` +
`relative to directory ${dirname}`);
}
} else {
parseCode = parserOpts.parser;
@@ -433,13 +403,13 @@ export default class File extends Store {
parserOpts.parser = {
parse(source) {
return parse(source, parserOpts);
}
},
};
}
}
this.log.debug("Parse start");
let ast = parseCode(code, parserOpts || this.parserOpts);
const ast = parseCode(code, parserOpts || this.parserOpts);
this.log.debug("Parse stop");
return ast;
}
@@ -450,10 +420,10 @@ export default class File extends Store {
parentPath: null,
parent: ast,
container: ast,
key: "program"
key: "program",
}).setContext();
this.scope = this.path.scope;
this.ast = ast;
this.ast = ast;
this.getMetadata();
}
@@ -464,19 +434,25 @@ export default class File extends Store {
}
transform(): BabelFileResult {
// In the "pass per preset" mode, we have grouped passes.
// Otherwise, there is only one plain pluginPasses array.
for (let i = 0; i < this.pluginPasses.length; i++) {
const pluginPasses = this.pluginPasses[i];
this.call("pre", pluginPasses);
for (const pluginPairs of this.pluginPasses) {
const passes = [];
const visitors = [];
for (const [ plugin, pluginOpts ] of pluginPairs.concat(INTERNAL_PLUGINS)) {
const pass = new PluginPass(this, plugin, pluginOpts);
passes.push(pass);
visitors.push(plugin.visitor);
}
this.call("pre", passes);
this.log.debug("Start transform traverse");
// merge all plugin visitors into a single visitor
let visitor = traverse.visitors.merge(this.pluginVisitors[i], pluginPasses, this.opts.wrapPluginVisitorMethod);
const visitor = traverse.visitors.merge(visitors, passes, this.opts.wrapPluginVisitorMethod);
traverse(this.ast, visitor, this.scope);
this.log.debug("End transform traverse");
this.call("post", pluginPasses);
this.call("post", passes);
}
return this.generate();
@@ -500,7 +476,7 @@ export default class File extends Store {
let message = err.message = `${this.opts.filename}: ${err.message}`;
let loc = err.loc;
const loc = err.loc;
if (loc) {
err.codeFrame = codeFrame(code, loc.line, loc.column + 1, this.opts);
message += "\n" + err.codeFrame;
@@ -513,7 +489,7 @@ export default class File extends Store {
}
if (err.stack) {
let newStack = err.stack.replace(err.message, message);
const newStack = err.stack.replace(err.message, message);
err.stack = newStack;
}
@@ -529,28 +505,28 @@ export default class File extends Store {
parseCode() {
this.parseShebang();
let ast = this.parse(this.code);
const ast = this.parse(this.code);
this.addAst(ast);
}
shouldIgnore() {
let opts = this.opts;
const opts = this.opts;
return util.shouldIgnore(opts.filename, opts.ignore, opts.only);
}
call(key: "pre" | "post", pluginPasses: Array<PluginPass>) {
for (let pass of pluginPasses) {
let plugin = pass.plugin;
let fn = plugin[key];
for (const pass of pluginPasses) {
const plugin = pass.plugin;
const fn = plugin[key];
if (fn) fn.call(pass, this);
}
}
parseInputSourceMap(code: string): string {
let opts = this.opts;
const opts = this.opts;
if (opts.inputSourceMap !== false) {
let inputMap = convertSourceMap.fromSource(code);
const inputMap = convertSourceMap.fromSource(code);
if (inputMap) {
opts.inputSourceMap = inputMap.toObject();
code = convertSourceMap.removeComments(code);
@@ -561,7 +537,7 @@ export default class File extends Store {
}
parseShebang() {
let shebangMatch = shebangRegex.exec(this.code);
const shebangMatch = shebangRegex.exec(this.code);
if (shebangMatch) {
this.shebang = shebangMatch[0];
this.code = this.code.replace(shebangRegex, "");
@@ -569,13 +545,13 @@ export default class File extends Store {
}
makeResult({ code, map, ast, ignored }: BabelFileResult): BabelFileResult {
let result = {
const result = {
metadata: null,
options: this.opts,
ignored: !!ignored,
code: null,
ast: null,
map: map || null
options: this.opts,
ignored: !!ignored,
code: null,
ast: null,
map: map || null,
};
if (this.opts.code) {
@@ -594,10 +570,10 @@ export default class File extends Store {
}
generate(): BabelFileResult {
let opts = this.opts;
let ast = this.ast;
const opts = this.opts;
const ast = this.ast;
let result: BabelFileResult = { ast };
const result: BabelFileResult = { ast };
if (!opts.code) return this.makeResult(result);
let gen = generate;
@@ -605,21 +581,23 @@ export default class File extends Store {
gen = opts.generatorOpts.generator;
if (typeof gen === "string") {
let dirname = path.dirname(this.opts.filename) || process.cwd();
let generator = resolve(gen, dirname);
const dirname = path.dirname(this.opts.filename) || process.cwd();
const generator = resolve(gen, dirname);
if (generator) {
gen = require(generator).print;
} else {
throw new Error(`Couldn't find generator ${gen} with "print" method relative to directory ${dirname}`);
throw new Error(`Couldn't find generator ${gen} with "print" method relative ` +
`to directory ${dirname}`);
}
}
}
this.log.debug("Generation start");
let _result = gen(ast, opts.generatorOpts ? Object.assign(opts, opts.generatorOpts) : opts, this.code);
const _result = gen(ast, opts.generatorOpts ? Object.assign(opts, opts.generatorOpts) : opts,
this.code);
result.code = _result.code;
result.map = _result.map;
result.map = _result.map;
this.log.debug("Generation end");

View File

@@ -1,15 +1,15 @@
import type File from "./index";
import buildDebug from "debug";
let verboseDebug = buildDebug("babel:verbose");
let generalDebug = buildDebug("babel");
const verboseDebug = buildDebug("babel:verbose");
const generalDebug = buildDebug("babel");
let seenDeprecatedMessages = [];
const seenDeprecatedMessages = [];
export default class Logger {
constructor(file: File, filename: string) {
this.filename = filename;
this.file = file;
this.file = file;
}
filename: string;
@@ -21,6 +21,15 @@ export default class Logger {
return parts;
}
wrap<T>(callback: () => T): T {
try {
return callback();
} catch (e) {
e.message = this._buildMessage(e.message);
throw e;
}
}
warn(msg: string) {
console.warn(this._buildMessage(msg));
}

View File

@@ -1,45 +1,45 @@
import * as t from "babel-types";
export let ModuleDeclaration = {
export const ModuleDeclaration = {
enter(path, file) {
let { node } = path;
const { node } = path;
if (node.source) {
node.source.value = file.resolveModuleSource(node.source.value);
}
}
},
};
export let ImportDeclaration = {
export const ImportDeclaration = {
exit(path, file) {
let { node } = path;
const { node } = path;
let specifiers = [];
let imported = [];
const specifiers = [];
const imported = [];
file.metadata.modules.imports.push({
source: node.source.value,
imported,
specifiers
specifiers,
});
for (let specifier of (path.get("specifiers"): Array<Object>)) {
let local = specifier.node.local.name;
for (const specifier of (path.get("specifiers"): Array<Object>)) {
const local = specifier.node.local.name;
if (specifier.isImportDefaultSpecifier()) {
imported.push("default");
specifiers.push({
kind: "named",
imported: "default",
local
local,
});
}
if (specifier.isImportSpecifier()) {
let importedName = specifier.node.imported.name;
const importedName = specifier.node.imported.name;
imported.push(importedName);
specifiers.push({
kind: "named",
imported: importedName,
local
local,
});
}
@@ -47,38 +47,38 @@ export let ImportDeclaration = {
imported.push("*");
specifiers.push({
kind: "namespace",
local
local,
});
}
}
}
},
};
export function ExportDeclaration(path, file) {
let { node } = path;
const { node } = path;
let source = node.source ? node.source.value : null;
let exports = file.metadata.modules.exports;
const source = node.source ? node.source.value : null;
const exports = file.metadata.modules.exports;
// export function foo() {}
// export let foo = "bar";
let declar = path.get("declaration");
const declar = path.get("declaration");
if (declar.isStatement()) {
let bindings = declar.getBindingIdentifiers();
const bindings = declar.getBindingIdentifiers();
for (let name in bindings) {
for (const name in bindings) {
exports.exported.push(name);
exports.specifiers.push({
kind: "local",
local: name,
exported: path.isExportDefaultDeclaration() ? "default" : name
exported: path.isExportDefaultDeclaration() ? "default" : name,
});
}
}
if (path.isExportNamedDeclaration() && node.specifiers) {
for (let specifier of (node.specifiers: Array<Object>)) {
let exported = specifier.exported.name;
for (const specifier of (node.specifiers: Array<Object>)) {
const exported = specifier.exported.name;
exports.exported.push(exported);
// export foo from "bar";
@@ -87,7 +87,7 @@ export function ExportDeclaration(path, file) {
kind: "external",
local: exported,
exported,
source
source,
});
}
@@ -96,11 +96,11 @@ export function ExportDeclaration(path, file) {
exports.specifiers.push({
kind: "external-namespace",
exported,
source
source,
});
}
let local = specifier.local;
const local = specifier.local;
if (!local) continue;
// export { foo } from "bar";
@@ -110,7 +110,7 @@ export function ExportDeclaration(path, file) {
kind: "external",
local: local.name,
exported,
source
source,
});
}
@@ -120,7 +120,7 @@ export function ExportDeclaration(path, file) {
exports.specifiers.push({
kind: "local",
local: local.name,
exported
exported,
});
}
}
@@ -130,7 +130,7 @@ export function ExportDeclaration(path, file) {
if (path.isExportAllDeclaration()) {
exports.specifiers.push({
kind: "external-all",
source
source,
});
}
}

View File

@@ -1,20 +1,18 @@
import type Logger from "../logger";
import resolve from "../../../helpers/resolve";
import json5 from "json5";
import isAbsolute from "path-is-absolute";
import path from "path";
import fs from "fs";
let existsCache = {};
let jsonCache = {};
const existsCache = {};
const jsonCache = {};
const BABELRC_FILENAME = ".babelrc";
const BABELRC_JS_FILENAME = ".babelrc.js";
const PACKAGE_FILENAME = "package.json";
const BABELIGNORE_FILENAME = ".babelignore";
const BABELRC_FILENAME = ".babelrc";
const PACKAGE_FILENAME = "package.json";
function exists(filename) {
let cached = existsCache[filename];
const cached = existsCache[filename];
if (cached == null) {
return existsCache[filename] = fs.existsSync(filename);
} else {
@@ -22,9 +20,9 @@ function exists(filename) {
}
}
export default function buildConfigChain(opts: Object = {}, log?: Logger) {
let filename = opts.filename;
let builder = new ConfigChainBuilder(log);
export default function buildConfigChain(opts: Object = {}) {
const filename = opts.filename;
const builder = new ConfigChainBuilder();
// resolve all .babelrc files
if (opts.babelrc !== false) {
@@ -34,23 +32,27 @@ export default function buildConfigChain(opts: Object = {}, log?: Logger) {
builder.mergeConfig({
options: opts,
alias: "base",
dirname: filename && path.dirname(filename)
dirname: filename && path.dirname(filename),
});
return builder.configs;
}
class ConfigChainBuilder {
constructor(log?: Logger) {
constructor() {
this.resolvedConfigs = [];
this.configs = [];
this.log = log;
}
findConfigs(loc) {
errorMultipleConfigs(loc1: string, loc2: string) {
throw new Error(`Multiple configuration files found. Please remove one:\n- ${
loc1}\n- ${loc2}`);
}
findConfigs(loc: string) {
if (!loc) return;
if (!isAbsolute(loc)) {
if (!path.isAbsolute(loc)) {
loc = path.join(process.cwd(), loc);
}
@@ -59,20 +61,31 @@ class ConfigChainBuilder {
while (loc !== (loc = path.dirname(loc))) {
if (!foundConfig) {
let configLoc = path.join(loc, BABELRC_FILENAME);
if (exists(configLoc)) {
this.addConfig(configLoc);
foundConfig = true;
}
const configLoc = path.join(loc, BABELRC_FILENAME);
const configJSLoc = path.join(loc, BABELRC_JS_FILENAME);
const pkgLoc = path.join(loc, PACKAGE_FILENAME);
const configLocs = [configLoc, configJSLoc, pkgLoc];
const foundConfigs = configLocs.reduce((arr, config) => {
if (exists(config)) {
const configAdded = config === pkgLoc
? this.addConfig(config, "babel", JSON)
: this.addConfig(config);
let pkgLoc = path.join(loc, PACKAGE_FILENAME);
if (!foundConfig && exists(pkgLoc)) {
foundConfig = this.addConfig(pkgLoc, "babel", JSON);
}
if (configAdded && arr.length) {
this.errorMultipleConfigs(arr.pop(), config);
}
arr.push(config);
}
return arr;
}, []);
foundConfig = !!foundConfigs.length;
}
if (!foundIgnore) {
let ignoreLoc = path.join(loc, BABELIGNORE_FILENAME);
const ignoreLoc = path.join(loc, BABELIGNORE_FILENAME);
if (exists(ignoreLoc)) {
this.addIgnoreConfig(ignoreLoc);
foundIgnore = true;
@@ -83,8 +96,8 @@ class ConfigChainBuilder {
}
}
addIgnoreConfig(loc) {
let file = fs.readFileSync(loc, "utf8");
addIgnoreConfig(loc: string) {
const file = fs.readFileSync(loc, "utf8");
let lines = file.split("\n");
lines = lines
@@ -95,7 +108,7 @@ class ConfigChainBuilder {
this.mergeConfig({
options: { ignore: lines },
alias: loc,
dirname: path.dirname(loc)
dirname: path.dirname(loc),
});
}
}
@@ -107,21 +120,41 @@ class ConfigChainBuilder {
this.resolvedConfigs.push(loc);
let content = fs.readFileSync(loc, "utf8");
let options;
if (path.extname(loc) === ".js") {
try {
const configModule = require(loc);
options = configModule && configModule.__esModule ? configModule.default : configModule;
} catch (err) {
err.message = `${loc}: Error while loading config - ${err.message}`;
throw err;
}
try {
options = jsonCache[content] = jsonCache[content] || json.parse(content);
if (key) options = options[key];
} catch (err) {
err.message = `${loc}: Error while parsing JSON - ${err.message}`;
throw err;
if (!options || typeof options !== "object") {
throw new Error("Configuration should be an exported JavaScript object.");
}
} else {
const content = fs.readFileSync(loc, "utf8");
try {
options = jsonCache[content] = jsonCache[content] || json.parse(content);
} catch (err) {
err.message = `${loc}: Error while parsing JSON - ${err.message}`;
throw err;
}
}
if (key) {
if (!options[key]) {
return false;
}
options = options[key];
}
this.mergeConfig({
options,
alias: loc,
dirname: path.dirname(loc)
dirname: path.dirname(loc),
});
return !!options;
@@ -131,7 +164,7 @@ class ConfigChainBuilder {
options,
alias,
loc,
dirname
dirname,
}) {
if (!options) {
return false;
@@ -144,11 +177,11 @@ class ConfigChainBuilder {
// add extends clause
if (options.extends) {
let extendsLoc = resolve(options.extends, dirname);
const extendsLoc = resolve(options.extends, dirname);
if (extendsLoc) {
this.addConfig(extendsLoc);
} else {
if (this.log) this.log.error(`Couldn't resolve extends clause of ${options.extends} in ${alias}`);
throw new Error(`Couldn't resolve extends clause of ${options.extends} in ${alias}`);
}
delete options.extends;
}
@@ -157,12 +190,12 @@ class ConfigChainBuilder {
options,
alias,
loc,
dirname
dirname,
});
// env
let envOpts;
let envKey = process.env.BABEL_ENV || process.env.NODE_ENV || "development";
const envKey = process.env.BABEL_ENV || process.env.NODE_ENV || "development";
if (options.env) {
envOpts = options.env[envKey];
delete options.env;
@@ -171,7 +204,7 @@ class ConfigChainBuilder {
this.mergeConfig({
options: envOpts,
alias: `${alias}.env.${envKey}`,
dirname: dirname
dirname: dirname,
});
}
}

View File

@@ -1,195 +1,195 @@
/* eslint max-len: 0 */
/* eslint max-len: "off" */
module.exports = {
export default {
filename: {
type: "filename",
description: "filename to use when reading from stdin - this will be used in source-maps, errors etc",
default: "unknown",
shorthand: "f"
shorthand: "f",
},
filenameRelative: {
hidden: true,
type: "string"
type: "string",
},
inputSourceMap: {
hidden: true
hidden: true,
},
env: {
hidden: true,
default: {}
default: {},
},
mode: {
description: "",
hidden: true
hidden: true,
},
retainLines: {
type: "boolean",
default: false,
description: "retain line numbers - will result in really ugly code"
description: "retain line numbers - will result in really ugly code",
},
highlightCode: {
description: "enable/disable ANSI syntax highlighting of code frames (on by default)",
type: "boolean",
default: true
default: true,
},
suppressDeprecationMessages: {
type: "boolean",
default: false,
hidden: true
hidden: true,
},
presets: {
type: "list",
description: "",
default: []
default: [],
},
plugins: {
type: "list",
default: [],
description: ""
description: "",
},
ignore: {
type: "list",
description: "list of glob paths to **not** compile",
default: []
default: [],
},
only: {
type: "list",
description: "list of glob paths to **only** compile"
description: "list of glob paths to **only** compile",
},
code: {
hidden: true,
default: true,
type: "boolean"
type: "boolean",
},
metadata: {
hidden: true,
default: true,
type: "boolean"
type: "boolean",
},
ast: {
hidden: true,
default: true,
type: "boolean"
type: "boolean",
},
extends: {
type: "string",
hidden: true
hidden: true,
},
comments: {
type: "boolean",
default: true,
description: "write comments to generated output (true by default)"
description: "write comments to generated output (true by default)",
},
shouldPrintComment: {
hidden: true,
description: "optional callback to control whether a comment should be inserted, when this is used the comments option is ignored"
description: "optional callback to control whether a comment should be inserted, when this is used the comments option is ignored",
},
wrapPluginVisitorMethod: {
hidden: true,
description: "optional callback to wrap all visitor methods"
description: "optional callback to wrap all visitor methods",
},
compact: {
type: "booleanString",
default: "auto",
description: "do not include superfluous whitespace characters and line terminators [true|false|auto]"
description: "do not include superfluous whitespace characters and line terminators [true|false|auto]",
},
minified: {
type: "boolean",
default: false,
description: "save as much bytes when printing [true|false]"
description: "save as much bytes when printing [true|false]",
},
sourceMap: {
alias: "sourceMaps",
hidden: true
hidden: true,
},
sourceMaps: {
type: "booleanString",
description: "[true|false|inline]",
default: false,
shorthand: "s"
shorthand: "s",
},
sourceMapTarget: {
type: "string",
description: "set `file` on returned source map"
description: "set `file` on returned source map",
},
sourceFileName: {
type: "string",
description: "set `sources[0]` on returned source map"
description: "set `sources[0]` on returned source map",
},
sourceRoot: {
type: "filename",
description: "the root from which all sources are relative"
description: "the root from which all sources are relative",
},
babelrc: {
description: "Whether or not to look up .babelrc and .babelignore files",
type: "boolean",
default: true
default: true,
},
sourceType: {
description: "",
default: "module"
default: "module",
},
auxiliaryCommentBefore: {
type: "string",
description: "print a comment before any injected non-user code"
description: "print a comment before any injected non-user code",
},
auxiliaryCommentAfter: {
type: "string",
description: "print a comment after any injected non-user code"
description: "print a comment after any injected non-user code",
},
resolveModuleSource: {
hidden: true
hidden: true,
},
getModuleId: {
hidden: true
hidden: true,
},
moduleRoot: {
type: "filename",
description: "optional prefix for the AMD module formatter that will be prepend to the filename on module definitions"
description: "optional prefix for the AMD module formatter that will be prepend to the filename on module definitions",
},
moduleIds: {
type: "boolean",
default: false,
shorthand: "M",
description: "insert an explicit id for modules"
description: "insert an explicit id for modules",
},
moduleId: {
description: "specify a custom name for module ids",
type: "string"
type: "string",
},
passPerPreset: {
@@ -202,12 +202,12 @@ module.exports = {
// Deprecate top level parserOpts
parserOpts: {
description: "Options to pass into the parser, or to change parsers (parserOpts.parser)",
default: false
default: false,
},
// Deprecate top level generatorOpts
generatorOpts: {
description: "Options to pass into the generator, or to change generators (generatorOpts.generator)",
default: false
}
default: false,
},
};

View File

@@ -4,7 +4,7 @@ import config from "./config";
export { config };
export function normaliseOptions(options: Object = {}): Object {
for (let key in options) {
for (const key in options) {
let val = options[key];
if (val == null) continue;
@@ -12,7 +12,7 @@ export function normaliseOptions(options: Object = {}): Object {
if (opt && opt.alias) opt = config[opt.alias];
if (!opt) continue;
let parser = parsers[opt.type];
const parser = parsers[opt.type];
if (parser) val = parser(val);
options[key] = val;

View File

@@ -1,11 +1,9 @@
/* eslint max-len: 0 */
import * as context from "../../../api/node";
import type Logger from "../logger";
import * as context from "../../../index";
import Plugin from "../../plugin";
import * as messages from "babel-messages";
import { normaliseOptions } from "./index";
import resolve from "../../../helpers/resolve";
import resolvePlugin from "../../../helpers/resolve-plugin";
import resolvePreset from "../../../helpers/resolve-preset";
import cloneDeepWith from "lodash/cloneDeepWith";
import clone from "lodash/clone";
import merge from "../../../helpers/merge";
@@ -36,15 +34,13 @@ type MergeOptions = {
};
export default class OptionManager {
constructor(log?: Logger) {
constructor() {
this.resolvedConfigs = [];
this.options = OptionManager.createBareOptions();
this.log = log;
}
resolvedConfigs: Array<string>;
options: Object;
log: ?Logger;
static memoisedPlugins: Array<{
container: Function;
@@ -52,7 +48,7 @@ export default class OptionManager {
}>;
static memoisePluginContainer(fn, loc, i, alias) {
for (let cache of (OptionManager.memoisedPlugins: Array<Object>)) {
for (const cache of (OptionManager.memoisedPlugins: Array<Object>)) {
if (cache.container === fn) return cache.plugin;
}
@@ -65,10 +61,10 @@ export default class OptionManager {
}
if (typeof obj === "object") {
let plugin = new Plugin(obj, alias);
const plugin = new Plugin(obj, alias);
OptionManager.memoisedPlugins.push({
container: fn,
plugin: plugin
plugin: plugin,
});
return plugin;
} else {
@@ -77,10 +73,10 @@ export default class OptionManager {
}
static createBareOptions() {
let opts = {};
const opts = {};
for (let key in config) {
let opt = config[key];
for (const key in config) {
const opt = config[key];
opts[key] = clone(opt.default);
}
@@ -119,11 +115,11 @@ export default class OptionManager {
plugin = val;
}
let alias = typeof plugin === "string" ? plugin : `${loc}$${i}`;
const alias = typeof plugin === "string" ? plugin : `${loc}$${i}`;
// allow plugins to be specified as strings
if (typeof plugin === "string") {
let pluginLoc = resolve(`babel-plugin-${plugin}`, dirname) || resolve(plugin, dirname);
const pluginLoc = resolvePlugin(plugin, dirname);
if (pluginLoc) {
plugin = require(pluginLoc);
} else {
@@ -152,18 +148,18 @@ export default class OptionManager {
extending: extendingOpts,
alias,
loc,
dirname
dirname,
}: MergeOptions) {
alias = alias || "foreign";
if (!rawOpts) return;
//
if (typeof rawOpts !== "object" || Array.isArray(rawOpts)) {
this.log.error(`Invalid options type for ${alias}`, TypeError);
throw new TypeError(`Invalid options type for ${alias}`);
}
//
let opts = cloneDeepWith(rawOpts, (val) => {
const opts = cloneDeepWith(rawOpts, (val) => {
if (val instanceof Plugin) {
return val;
}
@@ -173,18 +169,18 @@ export default class OptionManager {
dirname = dirname || process.cwd();
loc = loc || alias;
for (let key in opts) {
let option = config[key];
for (const key in opts) {
const option = config[key];
// check for an unknown option
if (!option && this.log) {
if (!option) {
if (removed[key]) {
this.log.error(`Using removed Babel 5 option: ${alias}.${key} - ${removed[key].message}`, ReferenceError);
throw new ReferenceError(`Using removed Babel 5 option: ${alias}.${key} - ${removed[key].message}`);
} else {
let unknownOptErr = `Unknown option: ${alias}.${key}. Check out http://babeljs.io/docs/usage/options/ for more information about options.`;
let presetConfigErr = "A common cause of this error is the presence of a configuration options object without the corresponding preset name. Example:\n\nInvalid:\n `{ presets: [{option: value}] }`\nValid:\n `{ presets: [['presetName', {option: value}]] }`\n\nFor more detailed information on preset configuration, please see http://babeljs.io/docs/plugins/#pluginpresets-options.";
// 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.`;
this.log.error(`${unknownOptErr}\n\n${presetConfigErr}`, ReferenceError);
throw new ReferenceError(unknownOptErr);
}
}
}
@@ -208,7 +204,7 @@ export default class OptionManager {
extending: preset,
alias: presetLoc,
loc: presetLoc,
dirname: dirname
dirname: dirname,
});
});
} else {
@@ -238,7 +234,7 @@ export default class OptionManager {
options: presetOpts,
alias: presetLoc,
loc: presetLoc,
dirname: path.dirname(presetLoc || "")
dirname: path.dirname(presetLoc || ""),
});
});
}
@@ -248,89 +244,77 @@ export default class OptionManager {
* or a module name to require.
*/
resolvePresets(presets: Array<string | Object>, dirname: string, onResolve?) {
return presets.map((val) => {
return presets.map((preset) => {
let options;
if (Array.isArray(val)) {
if (val.length > 2) {
throw new Error(`Unexpected extra options ${JSON.stringify(val.slice(2))} passed to preset.`);
if (Array.isArray(preset)) {
if (preset.length > 2) {
throw new Error(`Unexpected extra options ${JSON.stringify(preset.slice(2))} passed to preset.`);
}
[val, options] = val;
[preset, options] = preset;
}
let presetLoc;
try {
if (typeof val === "string") {
presetLoc = resolve(`babel-preset-${val}`, dirname) || resolve(val, dirname);
// trying to resolve @organization shortcat
// @foo/es2015 -> @foo/babel-preset-es2015
if (!presetLoc) {
let matches = val.match(/^(@[^/]+)\/(.+)$/);
if (matches) {
let [, orgName, presetPath] = matches;
val = `${orgName}/babel-preset-${presetPath}`;
presetLoc = resolve(val, dirname);
}
}
if (typeof preset === "string") {
presetLoc = resolvePreset(preset, dirname);
if (!presetLoc) {
throw new Error(`Couldn't find preset ${JSON.stringify(val)} relative to directory ` +
throw new Error(`Couldn't find preset ${JSON.stringify(preset)} relative to directory ` +
JSON.stringify(dirname));
}
val = require(presetLoc);
}
const resolvedPreset = this.loadPreset(presetLoc || preset, options, { dirname });
// If the imported preset is a transpiled ES2015 module
if (typeof val === "object" && val.__esModule) {
// Try to grab the default export.
if (val.default) {
val = val.default;
} else {
// If there is no default export we treat all named exports as options
// and just remove the __esModule. This is to support presets that have been
// exporting named exports in the past, although we definitely want presets to
// only use the default export (with either an object or a function)
const { __esModule, ...rest } = val; // eslint-disable-line no-unused-vars
val = rest;
}
}
if (onResolve) onResolve(resolvedPreset, presetLoc);
// For compatibility with babel-core < 6.13.x, allow presets to export an object with a
// a 'buildPreset' function that will return the preset itself, while still exporting a
// simple object (rather than a function), for supporting old Babel versions.
if (typeof val === "object" && val.buildPreset) val = val.buildPreset;
if (typeof val !== "function" && options !== undefined) {
throw new Error(`Options ${JSON.stringify(options)} passed to ` +
(presetLoc || "a preset") + " which does not accept options.");
}
if (typeof val === "function") val = val(context, options);
if (typeof val !== "object") {
throw new Error(`Unsupported preset format: ${val}.`);
}
onResolve && onResolve(val, presetLoc);
return resolvedPreset;
} catch (e) {
if (presetLoc) {
e.message += ` (While processing preset: ${JSON.stringify(presetLoc)})`;
}
throw e;
}
return val;
});
}
normaliseOptions() {
let opts = this.options;
/**
* Tries to load one preset. The input is either the module name of the preset,
* a function, or an object
*/
loadPreset(preset, options, meta) {
let presetFactory = preset;
if (typeof presetFactory === "string") {
presetFactory = require(presetFactory);
}
for (let key in config) {
let option = config[key];
let val = opts[key];
if (typeof presetFactory === "object" && presetFactory.__esModule) {
if (presetFactory.default) {
presetFactory = presetFactory.default;
} else {
throw new Error("Preset must export a default export when using ES6 modules.");
}
}
// Allow simple object exports
if (typeof presetFactory === "object") {
return presetFactory;
}
if (typeof presetFactory !== "function") {
// eslint-disable-next-line max-len
throw new Error(`Unsupported preset format: ${typeof presetFactory}. Expected preset to return a function.`);
}
return presetFactory(context, options, meta);
}
normaliseOptions() {
const opts = this.options;
for (const key in config) {
const option = config[key];
const val = opts[key];
// optional
if (!val && option.optional) continue;
@@ -345,7 +329,7 @@ export default class OptionManager {
}
init(opts: Object = {}): Object {
for (let config of buildConfigChain(opts, this.log)) {
for (const config of buildConfigChain(opts)) {
this.mergeOptions(config);
}

View File

@@ -1,7 +1,7 @@
import slash from "slash";
import * as util from "../../../util";
export let filename = slash;
export const filename = slash;
export function boolean(val: any): boolean {
return !!val;

View File

@@ -1,35 +1,35 @@
/* eslint max-len: 0 */
/* eslint max-len: "off" */
module.exports = {
export default {
"auxiliaryComment": {
"message": "Use `auxiliaryCommentBefore` or `auxiliaryCommentAfter`"
"message": "Use `auxiliaryCommentBefore` or `auxiliaryCommentAfter`",
},
"blacklist": {
"message": "Put the specific transforms you want in the `plugins` option"
"message": "Put the specific transforms you want in the `plugins` option",
},
"breakConfig": {
"message": "This is not a necessary option in Babel 6"
"message": "This is not a necessary option in Babel 6",
},
"experimental": {
"message": "Put the specific transforms you want in the `plugins` option"
"message": "Put the specific transforms you want in the `plugins` option",
},
"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": {
"message": ""
"message": "",
},
"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": {
// "message": ""
// },
"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": {
"message": "Not required anymore as this is enabled by default"
"message": "Not required anymore as this is enabled by default",
},
"modules": {
"message": "Use the corresponding module transform plugin in the `plugins` option. Check out http://babeljs.io/docs/plugins/#modules",
@@ -38,15 +38,15 @@ module.exports = {
"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": {
"message": "Put the specific transforms you want in the `plugins` option"
"message": "Put the specific transforms you want in the `plugins` option",
},
"sourceMapName": {
"message": "Use the `sourceMapTarget` option"
"message": "Use the `sourceMapTarget` option",
},
"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": {
"message": "Put the specific transforms you want in the `plugins` option"
}
"message": "Put the specific transforms you want in the `plugins` option",
},
};

View File

@@ -20,7 +20,7 @@ export default new Plugin({
exit({ node }) {
let hasChange = false;
for (let i = 0; i < node.body.length; i++) {
let bodyNode = node.body[i];
const bodyNode = node.body[i];
if (bodyNode && bodyNode._blockHoist != null) {
hasChange = true;
break;
@@ -36,7 +36,7 @@ export default new Plugin({
// Higher priorities should move toward the top.
return -1 * priority;
});
}
}
}
},
},
},
});

View File

@@ -7,12 +7,12 @@ const superVisitor = {
CallExpression(path) {
if (!path.get("callee").isSuper()) return;
const {node} = path;
const { node } = path;
if (node[SUPER_THIS_BOUND]) return;
node[SUPER_THIS_BOUND] = true;
path.replaceWith(t.assignmentExpression("=", this.id, node));
}
},
};
export default new Plugin({
@@ -27,8 +27,8 @@ export default new Plugin({
if (path.node.name === "arguments") {
remap(path, "arguments");
}
}
}
},
},
});
function shouldShadow(path, shadowPath) {
@@ -41,10 +41,10 @@ function shouldShadow(path, shadowPath) {
function remap(path, key) {
// ensure that we're shadowed
let shadowPath = path.inShadow(key);
const shadowPath = path.inShadow(key);
if (!shouldShadow(path, shadowPath)) return;
let shadowFunction = path.node._shadowedFunctionLiteral;
const shadowFunction = path.node._shadowedFunctionLiteral;
let currentFunction;
let passedShadowFunction = false;
@@ -91,17 +91,17 @@ function remap(path, key) {
// binding since arrow function syntax already does that.
if (!passedShadowFunction) return;
let cached = fnPath.getData(key);
const cached = fnPath.getData(key);
if (cached) return path.replaceWith(cached);
let id = path.scope.generateUidIdentifier(key);
const id = path.scope.generateUidIdentifier(key);
fnPath.setData(key, id);
let classPath = fnPath.findParent((p) => p.isClass());
let hasSuperClass = !!(classPath && classPath.node && classPath.node.superClass);
const classPath = fnPath.findParent((p) => p.isClass());
const hasSuperClass = !!(classPath && classPath.node && classPath.node.superClass);
if (key === "this" && fnPath.isMethod({kind: "constructor"}) && hasSuperClass) {
if (key === "this" && fnPath.isMethod({ kind: "constructor" }) && hasSuperClass) {
fnPath.scope.push({ id });
fnPath.traverse(superVisitor, { id });

View File

@@ -3,48 +3,31 @@ import normalizeAst from "../helpers/normalize-ast";
import Plugin from "./plugin";
import File from "./file";
export default class Pipeline {
lint(code: string, opts?: Object = {}): BabelFileResult {
opts.code = false;
opts.mode = "lint";
return this.transform(code, opts);
}
pretransform(code: string, opts?: Object): BabelFileResult {
let file = new File(opts, this);
return file.wrap(code, function () {
file.addCode(code);
file.parseCode(code);
return file;
});
}
transform(code: string, opts?: Object): BabelFileResult {
let file = new File(opts, this);
return file.wrap(code, function () {
file.addCode(code);
file.parseCode(code);
return file.transform();
});
}
analyse(code: string, opts: Object = {}, visitor?: Object): ?BabelFileMetadata {
opts.code = false;
if (visitor) {
opts.plugins = opts.plugins || [];
opts.plugins.push(new Plugin({ visitor }));
}
return this.transform(code, opts).metadata;
}
transformFromAst(ast: Object, code: string, opts: Object): BabelFileResult {
ast = normalizeAst(ast);
let file = new File(opts, this);
return file.wrap(code, function () {
file.addCode(code);
file.addAst(ast);
return file.transform();
});
export function analyse(code: string, opts: Object = {}, visitor?: Object): ?BabelFileMetadata {
opts.code = false;
if (visitor) {
opts.plugins = opts.plugins || [];
opts.plugins.push(new Plugin({ visitor }));
}
return transform(code, opts).metadata;
}
export function transform(code: string, opts?: Object): BabelFileResult {
const file = new File(opts);
return file.wrap(code, function () {
file.addCode(code);
file.parseCode(code);
return file.transform();
});
}
export function transformFromAst(ast: Object, code: string, opts: Object): BabelFileResult {
ast = normalizeAst(ast);
const file = new File(opts);
return file.wrap(code, function () {
file.addCode(code);
file.addAst(ast);
return file.transform();
});
}

View File

@@ -6,9 +6,9 @@ export default class PluginPass extends Store {
constructor(file: File, plugin: Plugin, options: Object = {}) {
super();
this.plugin = plugin;
this.key = plugin.key;
this.file = file;
this.opts = options;
this.key = plugin.key;
this.file = file;
this.opts = options;
}
key: string;

View File

@@ -1,10 +1,7 @@
/* eslint max-len: 0 */
import OptionManager from "./file/options/option-manager";
import * as messages from "babel-messages";
import Store from "../store";
import traverse from "babel-traverse";
import assign from "lodash/assign";
import clone from "lodash/clone";
const GLOBAL_VISITOR_PROPS = ["enter", "exit"];
@@ -14,13 +11,13 @@ export default class Plugin extends Store {
super();
this.initialized = false;
this.raw = assign({}, plugin);
this.key = this.take("name") || key;
this.raw = Object.assign({}, plugin);
this.key = this.take("name") || key;
this.manipulateOptions = this.take("manipulateOptions");
this.post = this.take("post");
this.pre = this.take("pre");
this.visitor = this.normaliseVisitor(clone(this.take("visitor")) || {});
this.post = this.take("post");
this.pre = this.take("pre");
this.visitor = this.normaliseVisitor(clone(this.take("visitor")) || {});
}
initialized: boolean;
@@ -31,7 +28,7 @@ export default class Plugin extends Store {
visitor: Object;
take(key) {
let val = this.raw[key];
const val = this.raw[key];
delete this.raw[key];
return val;
}
@@ -40,13 +37,13 @@ export default class Plugin extends Store {
if (!target[key]) return this[key];
if (!this[key]) return target[key];
let fns: Array<?Function> = [target[key], this[key]];
const fns: Array<?Function> = [target[key], this[key]];
return function (...args) {
let val;
for (let fn of fns) {
for (const fn of fns) {
if (fn) {
let ret = fn.apply(this, args);
const ret = fn.apply(this, args);
if (ret != null) val = ret;
}
}
@@ -77,15 +74,16 @@ export default class Plugin extends Store {
this.maybeInherit(loc);
for (let key in this.raw) {
for (const key in this.raw) {
throw new Error(messages.get("pluginInvalidProperty", loc, i, key));
}
}
normaliseVisitor(visitor: Object): Object {
for (let key of GLOBAL_VISITOR_PROPS) {
for (const key of GLOBAL_VISITOR_PROPS) {
if (visitor[key]) {
throw new Error("Plugins aren't allowed to specify catch-all enter/exit handlers. Please target individual nodes.");
throw new Error("Plugins aren't allowed to specify catch-all enter/exit handlers. " +
"Please target individual nodes.");
}
}

View File

@@ -1,9 +1,7 @@
import escapeRegExp from "lodash/escapeRegExp";
import startsWith from "lodash/startsWith";
import isBoolean from "lodash/isBoolean";
import minimatch from "minimatch";
import includes from "lodash/includes";
import isString from "lodash/isString";
import isRegExp from "lodash/isRegExp";
import path from "path";
import slash from "slash";
@@ -15,8 +13,8 @@ export { inherits, inspect } from "util";
*/
export function canCompile(filename: string, altExts?: Array<string>): boolean {
let exts = altExts || canCompile.EXTENSIONS;
let ext = path.extname(filename);
const exts = altExts || canCompile.EXTENSIONS;
const ext = path.extname(filename);
return includes(exts, ext);
}
@@ -63,7 +61,7 @@ export function regexify(val: any): RegExp {
if (startsWith(val, "./") || startsWith(val, "*/")) val = val.slice(2);
if (startsWith(val, "**/")) val = val.slice(3);
let regex = minimatch.makeRe(val, { nocase: true });
const regex = minimatch.makeRe(val, { nocase: true });
return new RegExp(regex.source.slice(1, -1), "i");
}
@@ -80,8 +78,8 @@ export function regexify(val: any): RegExp {
export function arrayify(val: any, mapFn?: Function): Array<any> {
if (!val) return [];
if (isBoolean(val)) return arrayify([val], mapFn);
if (isString(val)) return arrayify(list(val), mapFn);
if (typeof val === "boolean") return arrayify([val], mapFn);
if (typeof val === "string") return arrayify(list(val), mapFn);
if (Array.isArray(val)) {
if (mapFn) val = val.map(mapFn);
@@ -119,12 +117,12 @@ export function shouldIgnore(
filename = filename.replace(/\\/g, "/");
if (only) {
for (let pattern of only) {
for (const pattern of only) {
if (_shouldIgnore(pattern, filename)) return false;
}
return true;
} else if (ignore.length) {
for (let pattern of ignore) {
for (const pattern of ignore) {
if (_shouldIgnore(pattern, filename)) return true;
}
}