diff --git a/packages/babel-core/src/transformation/file/options/build-config-chain.js b/packages/babel-core/src/transformation/file/options/build-config-chain.js index 5542072f69..5902d4c16e 100644 --- a/packages/babel-core/src/transformation/file/options/build-config-chain.js +++ b/packages/babel-core/src/transformation/file/options/build-config-chain.js @@ -1,4 +1,3 @@ - import type Logger from "../logger"; import resolve from "../../../helpers/resolve"; import json5 from "json5"; @@ -8,9 +7,10 @@ import fs from "fs"; const existsCache = {}; const jsonCache = {}; -const BABELIGNORE_FILENAME = ".babelignore"; const BABELRC_FILENAME = ".babelrc"; +const BABELRC_JS_FILENAME = ".babelrc.js"; const PACKAGE_FILENAME = "package.json"; +const BABELIGNORE_FILENAME = ".babelignore"; function exists(filename) { const cached = existsCache[filename]; @@ -46,7 +46,12 @@ class ConfigChainBuilder { 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 (!path.isAbsolute(loc)) { @@ -59,15 +64,26 @@ class ConfigChainBuilder { while (loc !== (loc = path.dirname(loc))) { if (!foundConfig) { const configLoc = path.join(loc, BABELRC_FILENAME); - if (exists(configLoc)) { - this.addConfig(configLoc); - foundConfig = true; - } - + const configJSLoc = path.join(loc, BABELRC_JS_FILENAME); const pkgLoc = path.join(loc, PACKAGE_FILENAME); - if (!foundConfig && exists(pkgLoc)) { - foundConfig = this.addConfig(pkgLoc, "babel", JSON); - } + 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); + + if (configAdded && arr.length) { + this.errorMultipleConfigs(arr.pop(), config); + } + + arr.push(config); + } + + return arr; + }, []); + + foundConfig = !!foundConfigs.length; } if (!foundIgnore) { @@ -82,7 +98,7 @@ class ConfigChainBuilder { } } - addIgnoreConfig(loc) { + addIgnoreConfig(loc: string) { const file = fs.readFileSync(loc, "utf8"); let lines = file.split("\n"); @@ -106,15 +122,35 @@ class ConfigChainBuilder { this.resolvedConfigs.push(loc); - const 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({ diff --git a/packages/babel-core/test/config-chain.js b/packages/babel-core/test/config-chain.js index 5032973e7d..f317eca7d8 100644 --- a/packages/babel-core/test/config-chain.js +++ b/packages/babel-core/test/config-chain.js @@ -294,4 +294,253 @@ describe("buildConfigChain", function () { assert.deepEqual(chain, expected); }); + + it("js-config", function () { + const chain = buildConfigChain({ + filename: fixture("js-config", "src.js"), + }); + + const expected = [ + { + options: { + plugins: [ + "foo", + "bar", + ], + }, + alias: fixture("js-config", ".babelrc.js"), + loc: fixture("js-config", ".babelrc.js"), + dirname: fixture("js-config"), + }, + { + options: { + ignore: [ + "root-ignore", + ], + }, + alias: fixture(".babelignore"), + loc: fixture(".babelignore"), + dirname: fixture(), + }, + { + options: { + filename: fixture("js-config", "src.js"), + }, + alias: "base", + loc: "base", + dirname: fixture("js-config"), + }, + ]; + + assert.deepEqual(chain, expected); + }); + + it("js-config-default - should read transpiled export default", function () { + const chain = buildConfigChain({ + filename: fixture("js-config-default", "src.js"), + }); + + const expected = [ + { + options: { + plugins: [ + "foo", + "bar", + ], + }, + alias: fixture("js-config-default", ".babelrc.js"), + loc: fixture("js-config-default", ".babelrc.js"), + dirname: fixture("js-config-default"), + }, + { + options: { + ignore: [ + "root-ignore", + ], + }, + alias: fixture(".babelignore"), + loc: fixture(".babelignore"), + dirname: fixture(), + }, + { + options: { + filename: fixture("js-config-default", "src.js"), + }, + alias: "base", + loc: "base", + dirname: fixture("js-config-default"), + }, + ]; + + assert.deepEqual(chain, expected); + }); + it("js-config-extended", function () { + const chain = buildConfigChain({ + filename: fixture("js-config-extended", "src.js"), + }); + + const expected = [ + { + options: { + plugins: [ + "extended", + ], + }, + alias: fixture("extended.babelrc.json"), + loc: fixture("extended.babelrc.json"), + dirname: fixture(), + }, + { + options: { + plugins: [ + "foo", + "bar", + ], + }, + alias: fixture("js-config-extended", ".babelrc.js"), + loc: fixture("js-config-extended", ".babelrc.js"), + dirname: fixture("js-config-extended"), + }, + { + options: { + ignore: [ + "root-ignore", + ], + }, + alias: fixture(".babelignore"), + loc: fixture(".babelignore"), + dirname: fixture(), + }, + { + options: { + filename: fixture("js-config-extended", "src.js"), + }, + alias: "base", + loc: "base", + dirname: fixture("js-config-extended"), + }, + ]; + + assert.deepEqual(chain, expected); + }); + + it("json-pkg-config-no-babel - should not throw if" + + " package.json doesn't contain a `babel` field", function () { + const chain = buildConfigChain({ + filename: fixture("json-pkg-config-no-babel", "src.js"), + }); + + const expected = [ + { + options: { + plugins: [ + "json", + ], + }, + alias: fixture("json-pkg-config-no-babel", ".babelrc"), + loc: fixture("json-pkg-config-no-babel", ".babelrc"), + dirname: fixture("json-pkg-config-no-babel"), + }, + { + options: { + ignore: [ + "root-ignore", + ], + }, + alias: fixture(".babelignore"), + loc: fixture(".babelignore"), + dirname: fixture(), + }, + { + options: { + filename: fixture("json-pkg-config-no-babel", "src.js"), + }, + alias: "base", + loc: "base", + dirname: fixture("json-pkg-config-no-babel"), + }, + ]; + + assert.deepEqual(chain, expected); + }); + + it("js-json-config - should throw an error if both a .babelrc" + + " and a .babelrc.js are present", function () { + assert.throws( + function () { + buildConfigChain({ + filename: fixture("js-json-config", "src.js"), + }); + }, + /Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*\.babelrc\.js/ + ); + }); + + it("js-pkg-config - should throw an error if both a .babelrc.js" + + " and a package.json with a babel field are present", function () { + assert.throws( + function () { + buildConfigChain({ + filename: fixture("js-pkg-config", "src.js"), + }); + }, + /Multiple configuration files found\.(.|\n)*\.babelrc\.js(.|\n)*package\.json/ + ); + }); + + it("json-pkg-config - should throw an error if both a .babelrc" + + " and a package.json with a babel field are present", function () { + assert.throws( + function () { + buildConfigChain({ + filename: fixture("json-pkg-config", "src.js"), + }); + }, + /Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*package\.json/ + ); + }); + + it("js-config-error", function () { + assert.throws( + function () { + buildConfigChain({ + filename: fixture("js-config-error", "src.js"), + }); + }, + /Error while loading config/ + ); + }); + + it("js-config-error2", function () { + assert.throws( + function () { + buildConfigChain({ + filename: fixture("js-config-error2", "src.js"), + }); + }, + /Configuration should be an exported JavaScript object/ + ); + }); + + it("js-config-error3", function () { + assert.throws( + function () { + buildConfigChain({ + filename: fixture("js-config-error3", "src.js"), + }); + }, + /Configuration should be an exported JavaScript object/ + ); + }); + + it("json-config-error", function () { + assert.throws( + function () { + buildConfigChain({ + filename: fixture("json-config-error", "src.js"), + }); + }, + /Error while parsing JSON/ + ); + }); }); diff --git a/packages/babel-core/test/fixtures/config/js-config-default/.babelrc.js b/packages/babel-core/test/fixtures/config/js-config-default/.babelrc.js new file mode 100644 index 0000000000..de5f1c0244 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-config-default/.babelrc.js @@ -0,0 +1,10 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +var plugins = ["foo", "bar"]; + +exports.default = { + plugins: plugins +}; diff --git a/packages/babel-core/test/fixtures/config/js-config-default/src.js b/packages/babel-core/test/fixtures/config/js-config-default/src.js new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-config-default/src.js @@ -0,0 +1 @@ +// empty diff --git a/packages/babel-core/test/fixtures/config/js-config-error/.babelrc.js b/packages/babel-core/test/fixtures/config/js-config-error/.babelrc.js new file mode 100644 index 0000000000..d14a2b71a8 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-config-error/.babelrc.js @@ -0,0 +1,2 @@ +throw new Error("Something bad happened!"); +module.exports = {} diff --git a/packages/babel-core/test/fixtures/config/js-config-error/src.js b/packages/babel-core/test/fixtures/config/js-config-error/src.js new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-config-error/src.js @@ -0,0 +1 @@ +// empty diff --git a/packages/babel-core/test/fixtures/config/js-config-error2/.babelrc.js b/packages/babel-core/test/fixtures/config/js-config-error2/.babelrc.js new file mode 100644 index 0000000000..9dc5fc1e4a --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-config-error2/.babelrc.js @@ -0,0 +1 @@ +module.exports = ''; diff --git a/packages/babel-core/test/fixtures/config/js-config-error2/src.js b/packages/babel-core/test/fixtures/config/js-config-error2/src.js new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-config-error2/src.js @@ -0,0 +1 @@ +// empty diff --git a/packages/babel-core/test/fixtures/config/js-config-error3/.babelrc.js b/packages/babel-core/test/fixtures/config/js-config-error3/.babelrc.js new file mode 100644 index 0000000000..b894a23a24 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-config-error3/.babelrc.js @@ -0,0 +1 @@ +module.exports = null; diff --git a/packages/babel-core/test/fixtures/config/js-config-error3/src.js b/packages/babel-core/test/fixtures/config/js-config-error3/src.js new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-config-error3/src.js @@ -0,0 +1 @@ +// empty diff --git a/packages/babel-core/test/fixtures/config/js-config-extended/.babelrc.js b/packages/babel-core/test/fixtures/config/js-config-extended/.babelrc.js new file mode 100644 index 0000000000..05741c6ef8 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-config-extended/.babelrc.js @@ -0,0 +1,6 @@ +var plugins = ["foo", "bar"]; + +module.exports = { + extends: "../extended.babelrc.json", + plugins: plugins +} diff --git a/packages/babel-core/test/fixtures/config/js-config-extended/src.js b/packages/babel-core/test/fixtures/config/js-config-extended/src.js new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-config-extended/src.js @@ -0,0 +1 @@ +// empty diff --git a/packages/babel-core/test/fixtures/config/js-config/.babelrc.js b/packages/babel-core/test/fixtures/config/js-config/.babelrc.js new file mode 100644 index 0000000000..e6fa0742df --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-config/.babelrc.js @@ -0,0 +1,5 @@ +var plugins = ["foo", "bar"]; + +module.exports = { + plugins: plugins +} diff --git a/packages/babel-core/test/fixtures/config/js-config/src.js b/packages/babel-core/test/fixtures/config/js-config/src.js new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-config/src.js @@ -0,0 +1 @@ +// empty diff --git a/packages/babel-core/test/fixtures/config/js-json-config/.babelrc b/packages/babel-core/test/fixtures/config/js-json-config/.babelrc new file mode 100644 index 0000000000..c80e833d70 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-json-config/.babelrc @@ -0,0 +1,5 @@ +{ + "plugins": [ + "json" + ] +} diff --git a/packages/babel-core/test/fixtures/config/js-json-config/.babelrc.js b/packages/babel-core/test/fixtures/config/js-json-config/.babelrc.js new file mode 100644 index 0000000000..71bb3e5762 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-json-config/.babelrc.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: [ + "js" + ] +} diff --git a/packages/babel-core/test/fixtures/config/js-json-config/src.js b/packages/babel-core/test/fixtures/config/js-json-config/src.js new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-json-config/src.js @@ -0,0 +1 @@ +// empty diff --git a/packages/babel-core/test/fixtures/config/js-pkg-config/.babelrc.js b/packages/babel-core/test/fixtures/config/js-pkg-config/.babelrc.js new file mode 100644 index 0000000000..71bb3e5762 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-pkg-config/.babelrc.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: [ + "js" + ] +} diff --git a/packages/babel-core/test/fixtures/config/js-pkg-config/package.json b/packages/babel-core/test/fixtures/config/js-pkg-config/package.json new file mode 100644 index 0000000000..e25be3ecd2 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-pkg-config/package.json @@ -0,0 +1,3 @@ +{ + "babel": {} +} diff --git a/packages/babel-core/test/fixtures/config/js-pkg-config/src.js b/packages/babel-core/test/fixtures/config/js-pkg-config/src.js new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/js-pkg-config/src.js @@ -0,0 +1 @@ +// empty diff --git a/packages/babel-core/test/fixtures/config/json-config-error/.babelrc b/packages/babel-core/test/fixtures/config/json-config-error/.babelrc new file mode 100644 index 0000000000..a07fde17a3 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/json-config-error/.babelrc @@ -0,0 +1,3 @@ +{ + "bad: "json" +} diff --git a/packages/babel-core/test/fixtures/config/json-config-error/src.js b/packages/babel-core/test/fixtures/config/json-config-error/src.js new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/json-config-error/src.js @@ -0,0 +1 @@ +// empty diff --git a/packages/babel-core/test/fixtures/config/json-pkg-config-no-babel/.babelrc b/packages/babel-core/test/fixtures/config/json-pkg-config-no-babel/.babelrc new file mode 100644 index 0000000000..c80e833d70 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/json-pkg-config-no-babel/.babelrc @@ -0,0 +1,5 @@ +{ + "plugins": [ + "json" + ] +} diff --git a/packages/babel-core/test/fixtures/config/json-pkg-config-no-babel/package.json b/packages/babel-core/test/fixtures/config/json-pkg-config-no-babel/package.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/packages/babel-core/test/fixtures/config/json-pkg-config-no-babel/package.json @@ -0,0 +1 @@ +{} diff --git a/packages/babel-core/test/fixtures/config/json-pkg-config-no-babel/src.js b/packages/babel-core/test/fixtures/config/json-pkg-config-no-babel/src.js new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/json-pkg-config-no-babel/src.js @@ -0,0 +1 @@ +// empty diff --git a/packages/babel-core/test/fixtures/config/json-pkg-config/.babelrc b/packages/babel-core/test/fixtures/config/json-pkg-config/.babelrc new file mode 100644 index 0000000000..c80e833d70 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/json-pkg-config/.babelrc @@ -0,0 +1,5 @@ +{ + "plugins": [ + "json" + ] +} diff --git a/packages/babel-core/test/fixtures/config/json-pkg-config/package.json b/packages/babel-core/test/fixtures/config/json-pkg-config/package.json new file mode 100644 index 0000000000..e25be3ecd2 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/json-pkg-config/package.json @@ -0,0 +1,3 @@ +{ + "babel": {} +} diff --git a/packages/babel-core/test/fixtures/config/json-pkg-config/src.js b/packages/babel-core/test/fixtures/config/json-pkg-config/src.js new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/packages/babel-core/test/fixtures/config/json-pkg-config/src.js @@ -0,0 +1 @@ +// empty diff --git a/packages/babel-generator/src/index.js b/packages/babel-generator/src/index.js index d8fbaf2a49..5be44e2d02 100644 --- a/packages/babel-generator/src/index.js +++ b/packages/babel-generator/src/index.js @@ -10,9 +10,7 @@ import type { Format } from "./printer"; */ class Generator extends Printer { - constructor(ast, opts, code) { - opts = opts || {}; - + constructor(ast, opts = {}, code) { const tokens = ast.tokens || []; const format = normalizeOptions(code, opts, tokens); const map = opts.sourceMaps ? new SourceMap(opts, code) : null; diff --git a/packages/babel-generator/src/node/parentheses.js b/packages/babel-generator/src/node/parentheses.js index b469ef1703..0175a6312d 100644 --- a/packages/babel-generator/src/node/parentheses.js +++ b/packages/babel-generator/src/node/parentheses.js @@ -34,12 +34,8 @@ export function NullableTypeAnnotation(node: Object, parent: Object): boolean { export { NullableTypeAnnotation as FunctionTypeAnnotation }; export function UpdateExpression(node: Object, parent: Object): boolean { - if (t.isMemberExpression(parent) && parent.object === node) { - // (foo++).test() - return true; - } - - return false; + // (foo++).test() + return t.isMemberExpression(parent) && parent.object === node; } export function ObjectExpression(node: Object, parent: Object, printStack: Array): boolean { @@ -51,15 +47,11 @@ export function DoExpression(node: Object, parent: Object, printStack: Array nodePos) { - return true; - } - - // Logical expressions with the same precedence don't need parens. - if (parentPos === nodePos && parent.right === node && !t.isLogicalExpression(parent)) { + if ( + // Logical expressions with the same precedence don't need parens. + (parentPos === nodePos && parent.right === node && !t.isLogicalExpression(parent)) || + parentPos > nodePos + ) { return true; } } @@ -84,55 +75,27 @@ export function Binary(node: Object, parent: Object): boolean { } export function BinaryExpression(node: Object, parent: Object): boolean { - if (node.operator === "in") { - // let i = (1 in []); - if (t.isVariableDeclarator(parent)) { - return true; - } - - // for ((1 in []);;); - if (t.isFor(parent)) { - return true; - } - } - - return false; + // let i = (1 in []); + // for ((1 in []);;); + return node.operator === "in" && (t.isVariableDeclarator(parent) || t.isFor(parent)); } export function SequenceExpression(node: Object, parent: Object): boolean { - if (t.isForStatement(parent)) { + + if ( // Although parentheses wouldn"t hurt around sequence // expressions in the head of for loops, traditional style // dictates that e.g. i++, j++ should not be wrapped with // parentheses. - return false; - } - - if (t.isExpressionStatement(parent) && parent.expression === node) { - return false; - } - - if (t.isReturnStatement(parent)) { - return false; - } - - if (t.isThrowStatement(parent)) { - return false; - } - - if (t.isSwitchStatement(parent) && parent.discriminant === node) { - return false; - } - - if (t.isWhileStatement(parent) && parent.test === node) { - return false; - } - - if (t.isIfStatement(parent) && parent.test === node) { - return false; - } - - if (t.isForInStatement(parent) && parent.right === node) { + t.isForStatement(parent) || + t.isThrowStatement(parent) || + t.isReturnStatement(parent) || + (t.isIfStatement(parent) && parent.test === node) || + (t.isWhileStatement(parent) && parent.test === node) || + (t.isForInStatement(parent) && parent.right === node) || + (t.isSwitchStatement(parent) && parent.discriminant === node) || + (t.isExpressionStatement(parent) && parent.expression === node) + ) { return false; } @@ -158,15 +121,9 @@ export function ClassExpression(node: Object, parent: Object, printStack: Array< } export function UnaryLike(node: Object, parent: Object): boolean { - if (t.isMemberExpression(parent, { object: node })) { - return true; - } - - if (t.isCallExpression(parent, { callee: node }) || t.isNewExpression(parent, { callee: node })) { - return true; - } - - return false; + return t.isMemberExpression(parent, { object: node }) || + t.isCallExpression(parent, { callee: node }) || + t.isNewExpression(parent, { callee: node }); } export function FunctionExpression(node: Object, parent: Object, printStack: Array): boolean { @@ -189,19 +146,12 @@ export function ArrowFunctionExpression(node: Object, parent: Object): boolean { } export function ConditionalExpression(node: Object, parent: Object): boolean { - if (t.isUnaryLike(parent)) { - return true; - } - - if (t.isBinary(parent)) { - return true; - } - - if (t.isConditionalExpression(parent, { test: node })) { - return true; - } - - if (t.isAwaitExpression(parent)) { + if ( + t.isUnaryLike(parent) || + t.isBinary(parent) || + t.isConditionalExpression(parent, { test: node }) || + t.isAwaitExpression(parent) + ) { return true; } @@ -227,28 +177,23 @@ function isFirstInStatement(printStack: Array, { i--; let parent = printStack[i]; while (i > 0) { - if (t.isExpressionStatement(parent, { expression: node })) { + if ( + t.isExpressionStatement(parent, { expression: node }) || + t.isTaggedTemplateExpression(parent) || + considerDefaultExports && t.isExportDefaultDeclaration(parent, { declaration: node }) || + considerArrow && t.isArrowFunctionExpression(parent, { body: node }) + ) { return true; } - if (t.isTaggedTemplateExpression(parent)) { - return true; - } - - if (considerDefaultExports && t.isExportDefaultDeclaration(parent, { declaration: node })) { - return true; - } - - if (considerArrow && t.isArrowFunctionExpression(parent, { body: node })) { - return true; - } - - if ((t.isCallExpression(parent, { callee: node })) || - (t.isSequenceExpression(parent) && parent.expressions[0] === node) || - (t.isMemberExpression(parent, { object: node })) || - (t.isConditional(parent, { test: node })) || - (t.isBinary(parent, { left: node })) || - (t.isAssignmentExpression(parent, { left: node }))) { + if ( + t.isCallExpression(parent, { callee: node }) || + (t.isSequenceExpression(parent) && parent.expressions[0] === node) || + t.isMemberExpression(parent, { object: node }) || + t.isConditional(parent, { test: node }) || + t.isBinary(parent, { left: node }) || + t.isAssignmentExpression(parent, { left: node }) + ) { node = parent; i--; parent = printStack[i]; diff --git a/packages/babel-generator/src/printer.js b/packages/babel-generator/src/printer.js index 7a7331e06c..1941b94ace 100644 --- a/packages/babel-generator/src/printer.js +++ b/packages/babel-generator/src/printer.js @@ -332,9 +332,11 @@ export default class Printer { this._maybeAddAuxComment(this._insideAux && !oldInAux); let needsParens = n.needsParens(node, parent, this._printStack); - if (this.format.retainFunctionParens && - node.type === "FunctionExpression" && - node.extra && node.extra.parenthesized) { + if ( + this.format.retainFunctionParens && + node.type === "FunctionExpression" && + node.extra && node.extra.parenthesized + ) { needsParens = true; } if (needsParens) this.token("("); diff --git a/packages/babel-plugin-transform-object-rest-spread/README.md b/packages/babel-plugin-transform-object-rest-spread/README.md index 61c3debfff..79f2432d03 100644 --- a/packages/babel-plugin-transform-object-rest-spread/README.md +++ b/packages/babel-plugin-transform-object-rest-spread/README.md @@ -4,19 +4,22 @@ ## Example +### Rest Properties + ```js -// Rest properties let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; console.log(x); // 1 console.log(y); // 2 console.log(z); // { a: 3, b: 4 } +``` -// Spread properties +### Spread Properties + +```js let n = { x, y, ...z }; console.log(n); // { x: 1, y: 2, a: 3, b: 4 } ``` - ## Installation ```sh @@ -35,27 +38,6 @@ npm install --save-dev babel-plugin-transform-object-rest-spread } ``` -## Options - -This plugin will use babel's `extends` helper, which will polyfill `Object.assign` by default. - -* `useBuiltIns` - Do not use Babel's helper's and just transform to use the built-in method (Disabled by default). - -```json -{ - "plugins": [ - ["transform-object-rest-spread", { "useBuiltIns": true }] - ] -} -``` - -```js -// source -z = { x, ...y }; -// compiled -z = Object.assign({ x }, y); -``` - ### Via CLI ```sh @@ -70,6 +52,36 @@ require("babel-core").transform("code", { }); ``` +## Options + +### `useBuiltIns` + +`boolean`, defaults to `false`. + +By default, this plugin uses Babel's `extends` helper which polyfills `Object.assign`. Enabling this option will use `Object.assign` directly. + +**.babelrc** + +```json +{ + "plugins": [ + ["transform-object-rest-spread", { "useBuiltIns": true }] + ] +} +``` + +**In** + +```js +z = { x, ...y }; +``` + +**Out** + +```js +z = Object.assign({ x }, y); +``` + ## References * [Proposal: Object Rest/Spread Properties for ECMAScript](https://github.com/sebmarkbage/ecmascript-rest-spread)