Skip to content

Commit

Permalink
Transform parameters after transforming generators
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Oct 26, 2022
1 parent 745eacc commit bc8915c
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 62 deletions.
24 changes: 12 additions & 12 deletions packages/babel-compat-data/data/plugin-bugfixes.json
Expand Up @@ -120,18 +120,6 @@
"samsung": "13",
"electron": "8.0"
},
"transform-parameters": {
"chrome": "49",
"opera": "36",
"edge": "15",
"firefox": "53",
"safari": "10",
"node": "6",
"deno": "1",
"ios": "10",
"samsung": "5",
"electron": "0.37"
},
"transform-async-to-generator": {
"chrome": "55",
"opera": "42",
Expand Down Expand Up @@ -179,5 +167,17 @@
"ios": "10",
"samsung": "5",
"electron": "0.37"
},
"transform-parameters": {
"chrome": "49",
"opera": "36",
"edge": "15",
"firefox": "53",
"safari": "10",
"node": "6",
"deno": "1",
"ios": "10",
"samsung": "5",
"electron": "0.37"
}
}
20 changes: 10 additions & 10 deletions packages/babel-compat-data/data/plugins.json
Expand Up @@ -233,16 +233,6 @@
"samsung": "9",
"electron": "3.0"
},
"transform-parameters": {
"chrome": "49",
"opera": "36",
"edge": "18",
"firefox": "53",
"node": "6",
"deno": "1",
"samsung": "5",
"electron": "0.37"
},
"transform-async-generator-functions": {
"chrome": "63",
"opera": "50",
Expand Down Expand Up @@ -608,6 +598,16 @@
"samsung": "5",
"electron": "1.1"
},
"transform-parameters": {
"chrome": "49",
"opera": "36",
"edge": "18",
"firefox": "53",
"node": "6",
"deno": "1",
"samsung": "5",
"electron": "0.37"
},
"transform-member-expression-literals": {
"chrome": "7",
"opera": "12",
Expand Down
26 changes: 11 additions & 15 deletions packages/babel-compat-data/scripts/data/plugin-features.js
Expand Up @@ -9,20 +9,6 @@ const es5 = {
"transform-reserved-words": "Miscellaneous / Unreserved words",
};

// https://github.com/babel/babel/issues/11278
// transform-parameters should run before object-rest-spread
const es2015Parameter = {
"transform-parameters": {
features: [
"default function parameters",
"rest parameters",
"destructuring, parameters / aliased defaults, arrow function",
"destructuring, parameters / shorthand defaults, arrow function",
"destructuring, parameters / duplicate identifier",
],
},
};

const es2015 = {
"transform-template-literals": {
features: ["template literals"],
Expand Down Expand Up @@ -113,6 +99,17 @@ const es2015 = {
"transform-regenerator": {
features: ["generators"],
},
// transform-parameters must be _after_ transform-regenertor
// https://github.com/babel/babel/issues/15012
"transform-parameters": {
features: [
"default function parameters",
"rest parameters",
"destructuring, parameters / aliased defaults, arrow function",
"destructuring, parameters / shorthand defaults, arrow function",
"destructuring, parameters / duplicate identifier",
],
},
};

const es2016 = {
Expand Down Expand Up @@ -178,7 +175,6 @@ module.exports = Object.assign(
es2021,
es2020,
es2019,
es2015Parameter,
es2018,
es2017,
es2016,
Expand Down
70 changes: 45 additions & 25 deletions packages/babel-plugin-transform-parameters/src/index.ts
@@ -1,3 +1,5 @@
import type { types as t } from "@babel/core";
import type { NodePath } from "@babel/traverse";
import { declare } from "@babel/helper-plugin-utils";
import convertFunctionParams from "./params";
import convertFunctionRest from "./rest";
Expand All @@ -15,35 +17,53 @@ export default declare((api, options: Options) => {
// Todo(BABEL 8): Consider default it to false
const noNewArrows = (api.assumption("noNewArrows") ?? true) as boolean;

function transformParameters(path: NodePath<t.Function>) {
if (
path.isArrowFunctionExpression() &&
path
.get("params")
.some(param => param.isRestElement() || param.isAssignmentPattern())
) {
// default/rest visitors require access to `arguments`, so it cannot be an arrow
path.arrowFunctionToExpression({ noNewArrows });

// In some cases arrowFunctionToExpression replaces the function with a wrapper.
// Return early; the wrapped function will be visited later in the AST traversal.
if (!path.isFunctionExpression()) return false;
}

const convertedRest = convertFunctionRest(path);
const convertedParams = convertFunctionParams(path, ignoreFunctionLength);

if (convertedRest || convertedParams) {
// Manually reprocess this scope to ensure that the moved params are updated.
path.scope.crawl();
return true;
}
return false;
}

const isAsyncOrGenerator = ({ node }: NodePath<t.Function>) =>
node.async || node.generator;

return {
name: "transform-parameters",

visitor: {
Function(path) {
if (
path.isArrowFunctionExpression() &&
path
.get("params")
.some(param => param.isRestElement() || param.isAssignmentPattern())
) {
// default/rest visitors require access to `arguments`, so it cannot be an arrow
path.arrowFunctionToExpression({ noNewArrows });

// In some cases arrowFunctionToExpression replaces the function with a wrapper.
// Return early; the wrapped function will be visited later in the AST traversal.
if (!path.isFunctionExpression()) return;
}

const convertedRest = convertFunctionRest(path);
const convertedParams = convertFunctionParams(
path,
ignoreFunctionLength,
);

if (convertedRest || convertedParams) {
// Manually reprocess this scope to ensure that the moved params are updated.
path.scope.crawl();
}
Function: {
enter(path) {
if (!isAsyncOrGenerator(path)) transformParameters(path);
},
// We need to transform async/generator functions in `exit`,
// to avoid transforming parameters before that regenerator
// runs: https://github.com/babel/babel/issues/15012
// However, we still transform classic functions in `enter`,
// to avoid unnecessarily requeueing them.
exit(path) {
if (isAsyncOrGenerator(path)) {
if (transformParameters(path)) path.requeue();
}
},
},
},
};
Expand Down
@@ -0,0 +1,13 @@
function* f([]) {}

expect(() => f()).toThrow();

let called = false;
let run = false;
function* g(x = (called = true)) {
run = true;
}

g();
expect(called).toBe(true);
expect(run).toBe(false);
@@ -0,0 +1,3 @@
function* f([]) {}

function* g(x = fn()) {}
@@ -0,0 +1,3 @@
{
"presets": ["env"]
}
@@ -0,0 +1,26 @@
var _marked = /*#__PURE__*/babelHelpers.regeneratorRuntime().mark(f),
_marked2 = /*#__PURE__*/babelHelpers.regeneratorRuntime().mark(g);
function f(_ref) {
var _ref2 = babelHelpers.toArray(_ref);
return babelHelpers.regeneratorRuntime().wrap(function f$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
case "end":
return _context.stop();
}
}
}, _marked);
}
function g() {
var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : fn();
return babelHelpers.regeneratorRuntime().wrap(function g$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
case "end":
return _context2.stop();
}
}
}, _marked2);
}

0 comments on commit bc8915c

Please sign in to comment.