New issue

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

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

Already on GitHub? Sign in to your account

Release 1.3.3 #7033

Merged
merged 135 commits into from Jun 10, 2016
Commits
Jump to file or symbol
Failed to load files and symbols.
+85 −40
Diff settings

Always

Just for now

Viewing a subset of changes. View all

Support .babelrc presets and plugins.

In addition to package.json files with "babel" sections, BabelCompiler now
supports .babelrc files, though in both cases only the "presets" and
"plugins" fields are respected. If a .babelrc file is found, package.json
files are ignored.

Additional presets and plugins are now *prepended* to the original
babelOptions.{presets,plugins} lists, so that the custom plugins have a
chance to handle syntax differently than babel-preset-meteor would.

The inputFile.getPackageJson method has been replaced by a more general
method, inputFile.findControlFile.

Fixes #6351.
  • Loading branch information...
benjamn committed May 20, 2016
commit 49a60f155b64e00a5f3e879540ce4be7bbb74691
@@ -5,10 +5,13 @@
*/
BabelCompiler = function BabelCompiler(extraFeatures) {
this.extraFeatures = extraFeatures;
this._babelrcCache = Object.create(null);
};
var BCp = BabelCompiler.prototype;
var excludedFileExtensionPattern = /\.es5\.js$/i;
var fs = Npm.require("fs");
var hasOwn = Object.prototype.hasOwnProperty;
var strictModulesPluginFactory =
Npm.require("babel-plugin-transform-es2015-modules-commonjs");
@@ -84,7 +87,7 @@ BCp.processFilesForTarget = function (inputFiles) {
babelOptions.plugins.push(babelModulesPlugin);
}
inferExtraBabelOptions(inputFile, babelOptions);
self.inferExtraBabelOptions(inputFile, babelOptions);
babelOptions.sourceMap = true;
babelOptions.filename =
@@ -133,28 +136,64 @@ function profile(name, func) {
}
};
function inferExtraBabelOptions(inputFile, babelOptions) {
const pkgJson =
inputFile.require &&
inputFile.getPathInPackage &&
inputFile.getPackageJson();
BCp.inferExtraBabelOptions = function (inputFile, babelOptions) {
if (! inputFile.require ||
! inputFile.findControlFile) {
return false;
}
return (
// If a .babelrc exists, it takes precedence over package.json.
this._inferFromBabelRc(inputFile, babelOptions) ||
this._inferFromPackageJson(inputFile, babelOptions)
);
};
BCp._inferFromBabelRc = function (inputFile, babelOptions) {
var babelrcPath = inputFile.findControlFile(".babelrc");
if (babelrcPath) {
if (! hasOwn.call(this._babelrcCache, babelrcPath)) {
this._babelrcCache[babelrcPath] =
JSON.parse(fs.readFileSync(babelrcPath));
}
if (! pkgJson || ! pkgJson.babel) {
return;
return this._inferHelper(
inputFile,
babelOptions,
this._babelrcCache[babelrcPath]
);
}
};
function infer(listName, prefix) {
const list = pkgJson.babel[listName];
if (! Array.isArray(list)) {
return;
BCp._inferFromPackageJson = function (inputFile, babelOptions) {
var pkgJsonPath = inputFile.findControlFile(".babelrc");

This comment has been minimized.

@abernix

abernix May 21, 2016

Member

Was this meant to be .babelrc or package.json?

@abernix

abernix May 21, 2016

Member

Was this meant to be .babelrc or package.json?

if (pkgJsonPath) {
if (! hasOwn.call(this._babelrcCache, pkgJsonPath)) {
this._babelrcCache[pkgJsonPath] =
JSON.parse(fs.readFileSync(pkgJsonPath)).babel || null;
}
function addPrefix(id) {
return isTopLevel ? prefix + id : id;
return this._inferHelper(
inputFile,
babelOptions,
this._babelrcCache[pkgJsonPath]
);
}
};
BCp._inferHelper = function (inputFile, babelOptions, babelrc) {
if (! babelrc) {
return false;
}
function infer(listName, prefix) {
var list = babelrc[listName];
if (! Array.isArray(list) || list.length === 0) {
return;
}
function req(id) {
const isTopLevel = "./".indexOf(id.charAt(0)) < 0;
var isTopLevel = "./".indexOf(id.charAt(0)) < 0;
if (isTopLevel) {
// If the identifier is top-level, it will be prefixed with
// "babel-plugin-" or "babel-preset-". If the identifier is not
@@ -166,17 +205,27 @@ function inferExtraBabelOptions(inputFile, babelOptions) {
return inputFile.require(id);
}
list.forEach(function (item) {
list.forEach(function (item, i) {
if (typeof item === "string") {
item = req(item);
} else if (Array.isArray(item) &&
typeof item[0] === "string") {
item = item.slice(); // defensive copy
item[0] = req(item[0]);
}
babelOptions[listName].push(item);
list[i] = item;
});
// PREPEND additional plugins to the existing babelOptions[listName]
// list, so that they have a chance to handle syntax differently than
// babel-preset-meteor normally would.
var target = babelOptions[listName] || [];
target.unshift.apply(target, list);
babelOptions[listName] = target;
}
infer("presets", "babel-preset-");
infer("plugins", "babel-plugin-");
}
return true;
};
@@ -204,10 +204,9 @@ class InputFile extends buildPluginModule.InputFile {
// document.
this._resourceSlot = resourceSlot;
// This `false` means we haven't read the package.json file governing
// this InputFile yet. Once we read it, this cached value will be
// either an object or null (meaning there was no package.json file).
this._packageJson = false;
// Map from control file names (e.g. package.json, .babelrc) to
// absolute paths, or null to indicate absence.
this._controlFileCache = Object.create(null);
// Map from imported module identifier strings (possibly relative) to
// fully require.resolve'd module identifiers.
@@ -257,43 +256,40 @@ class InputFile extends buildPluginModule.InputFile {
return self._resourceSlot.inputResource.fileOptions || {};
}
getPackageJson() {
if (typeof this._packageJson === "object") {
// Note that this._packageJson could be either an actual object or
// null at this point, which may be the first time I've ever been
// glad that typeof null === "object".
return this._packageJson;
// Search ancestor directories for control files (e.g. package.json,
// .babelrc), and return the absolute path of the first one found, or
// null if the search failed.
findControlFile(basename) {
let absPath = this._controlFileCache[basename];
if (typeof absPath === "string") {
return absPath;
}
const sourceRoot = this._resourceSlot.packageSourceBatch.sourceRoot;
if (! _.isString(sourceRoot)) {
return this._packageJson = null;
return this._controlFileCache[basename] = null;
}
let dir = files.pathDirname(this.getPathInPackage());
while (true) {
const pkgJsonId = files.convertToPosixPath(
files.pathJoin(sourceRoot, dir, "package.json"));
absPath = files.pathJoin(sourceRoot, dir, basename);
try {
// The require function will cache results across the process.
return this._packageJson = require(pkgJsonId);
} catch (e) {
if (e.code !== "MODULE_NOT_FOUND") {
throw e;
}
const stat = files.statOrNull(absPath);
if (stat && stat.isFile()) {
return this._controlFileCache[basename] = absPath;
}
if (files.pathBasename(dir) === "node_modules") {
return this._packageJson = null;
// The search for control files should not escape node_modules.
return this._controlFileCache[basename] = null;
}
let parentDir = files.pathDirname(dir);
if (parentDir === dir) break;
dir = parentDir;
}
return this._packageJson = null;
return this._controlFileCache[basename] = null;
}
resolve(id) {
ProTip! Use n and p to navigate between commits in a pull request.