Skip to content

Commit

Permalink
fix: Throw error when compiling super() in arrow functions with def…
Browse files Browse the repository at this point in the history
…ault / rest parameters (#15163)

* Fix: Throw when super in arrow with default / rest

* Add allowInsertArrowWithRest and improve throw

* Update packages/babel-traverse/src/path/conversion.ts

Co-authored-by: Huáng Jùnliàng <jlhwung@gmail.com>

Co-authored-by: Huáng Jùnliàng <jlhwung@gmail.com>
  • Loading branch information
SuperSodaSea and JLHwung committed Nov 22, 2022
1 parent 871fd5e commit e7405b9
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 3 deletions.
@@ -0,0 +1,6 @@
class Bar extends Foo {
constructor() {
let f = () => super();
f();
}
}
@@ -0,0 +1,4 @@
{
"plugins": ["transform-arrow-functions"],
"throws": "When using '@babel/plugin-transform-arrow-functions', it's not possible to compile `super()` in an arrow function without compiling classes.\nPlease add '@babel/plugin-transform-classes' to your Babel configuration."
}
@@ -0,0 +1,6 @@
class Bar extends Foo {
constructor() {
let f = () => super.x;
f();
}
}
@@ -0,0 +1,4 @@
{
"plugins": ["transform-arrow-functions"],
"throws": "When using '@babel/plugin-transform-arrow-functions', it's not possible to compile `super.prop` in an arrow function without compiling classes.\nPlease add '@babel/plugin-transform-classes' to your Babel configuration."
}
5 changes: 4 additions & 1 deletion packages/babel-plugin-transform-parameters/src/index.ts
Expand Up @@ -27,7 +27,10 @@ export default declare((api, options: Options) => {
.some(param => param.isRestElement() || param.isAssignmentPattern())
) {
// default/rest visitors require access to `arguments`, so it cannot be an arrow
path.arrowFunctionToExpression({ noNewArrows });
path.arrowFunctionToExpression({
allowInsertArrowWithRest: false,
noNewArrows,
});

// In some cases arrowFunctionToExpression replaces the function with a wrapper.
// Return early; the wrapped function will be visited later in the AST traversal.
Expand Down
@@ -0,0 +1,6 @@
class Bar extends Foo {
constructor() {
let f = (x = super()) => x;
f();
}
}
@@ -0,0 +1,4 @@
{
"plugins": ["transform-parameters"],
"throws": "When using '@babel/plugin-transform-parameters', it's not possible to compile `super()` in an arrow function with default or rest parameters without compiling classes.\nPlease add '@babel/plugin-transform-classes' to your Babel configuration."
}
@@ -0,0 +1,6 @@
class Bar extends Foo {
constructor() {
let f = (...args) => super(...args);
f();
}
}
@@ -0,0 +1,4 @@
{
"plugins": ["transform-parameters"],
"throws": "When using '@babel/plugin-transform-parameters', it's not possible to compile `super()` in an arrow function with default or rest parameters without compiling classes.\nPlease add '@babel/plugin-transform-classes' to your Babel configuration."
}
20 changes: 18 additions & 2 deletions packages/babel-traverse/src/path/conversion.ts
Expand Up @@ -149,12 +149,14 @@ export function arrowFunctionToExpression(
this: NodePath<t.ArrowFunctionExpression>,
{
allowInsertArrow = true,
allowInsertArrowWithRest = allowInsertArrow,
/** @deprecated Use `noNewArrows` instead */
specCompliant = false,
// TODO(Babel 8): Consider defaulting to `false` for spec compliancy
noNewArrows = !specCompliant,
}: {
allowInsertArrow?: boolean | void;
allowInsertArrowWithRest?: boolean | void;
specCompliant?: boolean | void;
noNewArrows?: boolean;
} = {},
Expand All @@ -169,6 +171,7 @@ export function arrowFunctionToExpression(
this,
noNewArrows,
allowInsertArrow,
allowInsertArrowWithRest,
);

// @ts-expect-error TS requires explicit fn type annotation
Expand Down Expand Up @@ -240,6 +243,7 @@ function hoistFunctionEnvironment(
// TODO(Babel 8): Consider defaulting to `false` for spec compliancy
noNewArrows: boolean | void = true,
allowInsertArrow: boolean | void = true,
allowInsertArrowWithRest: boolean | void = true,
): { thisBinding: string; fnPath: NodePath<t.Function> } {
let arrowParent;
let thisEnvFn: NodePath<t.Function> = fnPath.findParent(p => {
Expand Down Expand Up @@ -286,7 +290,17 @@ function hoistFunctionEnvironment(
if (inConstructor && superCalls.length > 0) {
if (!allowInsertArrow) {
throw superCalls[0].buildCodeFrameError(
"Unable to handle nested super() usage in arrow",
"When using '@babel/plugin-transform-arrow-functions', " +
"it's not possible to compile `super()` in an arrow function without compiling classes.\n" +
"Please add '@babel/plugin-transform-classes' to your Babel configuration.",
);
}
if (!allowInsertArrowWithRest) {
// preset-env with target `since 2017` enables `transform-parameters` without `transform-classes`.
throw superCalls[0].buildCodeFrameError(
"When using '@babel/plugin-transform-parameters', " +
"it's not possible to compile `super()` in an arrow function with default or rest parameters without compiling classes.\n" +
"Please add '@babel/plugin-transform-classes' to your Babel configuration.",
);
}
const allSuperCalls: NodePath<t.CallExpression>[] = [];
Expand Down Expand Up @@ -345,7 +359,9 @@ function hoistFunctionEnvironment(
if (superProps.length > 0) {
if (!allowInsertArrow) {
throw superProps[0].buildCodeFrameError(
"Unable to handle nested super.prop usage",
"When using '@babel/plugin-transform-arrow-functions', " +
"it's not possible to compile `super.prop` in an arrow function without compiling classes.\n" +
"Please add '@babel/plugin-transform-classes' to your Babel configuration.",
);
}

Expand Down

0 comments on commit e7405b9

Please sign in to comment.