Skip to content
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

Ensure expressions wrapped in parens #12082

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/babel-generator/src/node/parentheses.js
Expand Up @@ -293,7 +293,7 @@ function isFirstInStatement(
let node = printStack[i];
i--;
let parent = printStack[i];
while (i > 0) {
while (i >= 0) {
if (
t.isExpressionStatement(parent, { expression: node }) ||
(considerDefaultExports &&
Expand Down
Expand Up @@ -3,3 +3,5 @@ var foo = arr.map(v => ({
y: v.bar*2
}));
var fn = () => ({}).key;
var fn2 = () => ({});
var fn3 = () => ({a} = {});
Expand Up @@ -3,4 +3,10 @@ var foo = arr.map(v => ({
y: v.bar * 2
}));

var fn = () => ({}).key;
var fn = () => ({}).key;

var fn2 = () => ({});

var fn3 = () => ({
a
} = {});
Expand Up @@ -4,3 +4,4 @@ a = a || (a = {});

(a = b)();
(a = b)?.();
({a} = {});
Expand Up @@ -2,4 +2,7 @@
1 + (a += 2);
a = a || (a = {});
(a = b)();
(a = b)?.();
(a = b)?.();
({
a
} = {});
163 changes: 163 additions & 0 deletions packages/babel-generator/test/index.js
Expand Up @@ -494,6 +494,169 @@ describe("programmatic generation", function () {
expect(output).toBe("(number & boolean)?");
});
});

describe("object expressions", () => {
it("not wrapped in parentheses when standalone", () => {
const objectExpression = t.objectExpression([]);
const output = generate(objectExpression).code;
expect(output).toBe("{}");
});

it("wrapped in parentheses in expression statement", () => {
const expressionStatement = t.expressionStatement(t.objectExpression([]));
const output = generate(expressionStatement).code;
expect(output).toBe("({});");
});

it("wrapped in parentheses in arrow function", () => {
const arrowFunctionExpression = t.arrowFunctionExpression(
[],
t.objectExpression([]),
);
const output = generate(arrowFunctionExpression).code;
expect(output).toBe("() => ({})");
});

it("not wrapped in parentheses in conditional", () => {
const conditionalExpression = t.conditionalExpression(
t.objectExpression([]),
t.booleanLiteral(true),
t.booleanLiteral(false),
);
const output = generate(conditionalExpression).code;
expect(output).toBe("{} ? true : false");
});

it("wrapped in parentheses in conditional in expression statement", () => {
const expressionStatement = t.expressionStatement(
t.conditionalExpression(
t.objectExpression([]),
t.booleanLiteral(true),
t.booleanLiteral(false),
),
);
const output = generate(expressionStatement).code;
expect(output).toBe("({}) ? true : false;");
});

it("wrapped in parentheses in conditional in arrow function", () => {
const arrowFunctionExpression = t.arrowFunctionExpression(
[],
t.conditionalExpression(
t.objectExpression([]),
t.booleanLiteral(true),
t.booleanLiteral(false),
),
);
const output = generate(arrowFunctionExpression).code;
expect(output).toBe("() => ({}) ? true : false");
});

it("not wrapped in parentheses in binary expression", () => {
const binaryExpression = t.binaryExpression(
"+",
t.objectExpression([]),
t.numericLiteral(1),
);
const output = generate(binaryExpression).code;
expect(output).toBe("{} + 1");
});

it("wrapped in parentheses in binary expression in expression statement", () => {
const expressionStatement = t.expressionStatement(
t.binaryExpression("+", t.objectExpression([]), t.numericLiteral(1)),
);
const output = generate(expressionStatement).code;
expect(output).toBe("({}) + 1;");
});

it("wrapped in parentheses in binary expression in arrow function", () => {
const arrowFunctionExpression = t.arrowFunctionExpression(
[],
t.binaryExpression("+", t.objectExpression([]), t.numericLiteral(1)),
);
const output = generate(arrowFunctionExpression).code;
expect(output).toBe("() => ({}) + 1");
});

it("not wrapped in parentheses in sequence expression", () => {
const sequenceExpression = t.sequenceExpression([
t.objectExpression([]),
t.numericLiteral(1),
]);
const output = generate(sequenceExpression).code;
expect(output).toBe("{}, 1");
});

it("wrapped in parentheses in sequence expression in expression statement", () => {
const expressionStatement = t.expressionStatement(
t.sequenceExpression([t.objectExpression([]), t.numericLiteral(1)]),
);
const output = generate(expressionStatement).code;
expect(output).toBe("({}), 1;");
});

it("wrapped in parentheses in sequence expression in arrow function", () => {
const arrowFunctionExpression = t.arrowFunctionExpression(
[],
t.sequenceExpression([t.objectExpression([]), t.numericLiteral(1)]),
);
const output = generate(arrowFunctionExpression).code;
expect(output).toBe("() => (({}), 1)");
});
});

describe("function expressions", () => {
it("not wrapped in parentheses when standalone", () => {
const functionExpression = t.functionExpression(
null,
[],
t.blockStatement([]),
);
const output = generate(functionExpression).code;
expect(output).toBe("function () {}");
});

it("wrapped in parentheses in expression statement", () => {
const expressionStatement = t.expressionStatement(
t.functionExpression(null, [], t.blockStatement([])),
);
const output = generate(expressionStatement).code;
expect(output).toBe("(function () {});");
});

it("wrapped in parentheses in export default declaration", () => {
const exportDefaultDeclaration = t.exportDefaultDeclaration(
t.functionExpression(null, [], t.blockStatement([])),
);
const output = generate(exportDefaultDeclaration).code;
expect(output).toBe("export default (function () {});");
});
});

describe("class expressions", () => {
it("not wrapped in parentheses when standalone", () => {
const classExpression = t.classExpression(null, null, t.classBody([]));
const output = generate(classExpression).code;
expect(output).toBe("class {}");
});

it("wrapped in parentheses in expression statement", () => {
const expressionStatement = t.expressionStatement(
t.classExpression(null, null, t.classBody([])),
);
const output = generate(expressionStatement).code;
expect(output).toBe("(class {});");
});

it("wrapped in parentheses in export default declaration", () => {
const exportDefaultDeclaration = t.exportDefaultDeclaration(
t.classExpression(null, null, t.classBody([])),
);
const output = generate(exportDefaultDeclaration).code;
expect(output).toBe("export default (class {});");
});
});
});

describe("CodeGenerator", function () {
Expand Down