From 0f60d42fdf391d72031c9d01fb81aaeea84a3929 Mon Sep 17 00:00:00 2001 From: Diogo Franco Date: Thu, 28 Dec 2017 17:02:54 +0900 Subject: [PATCH] Avoid adding #__PURE__ annotation to .bind(this)() expressions (#7043) * Avoid adding #__PURE__ annotation to .bind(this)() expressions Fixes the #__PURE__ annotation getting added to (async () => {})() IIFEs when the arrow function transform is running with spec: true. * Return false instead of undefined * Fix indentation in json files * Add one more case to the async-iife fixtures --- .../src/index.js | 32 +++++++- .../actual.js | 4 + .../expected.js | 74 +++++++++++++++++++ .../options.json | 8 ++ .../async-iife-with-regenerator/actual.js | 4 + .../async-iife-with-regenerator/expected.js | 70 ++++++++++++++++++ .../async-iife-with-regenerator/options.json | 8 ++ .../async-to-generator/async-iife/actual.js | 1 + .../async-to-generator/async-iife/expected.js | 5 ++ 9 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/actual.js create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/expected.js create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/options.json create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator/actual.js create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator/expected.js create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator/options.json diff --git a/packages/babel-helper-remap-async-to-generator/src/index.js b/packages/babel-helper-remap-async-to-generator/src/index.js index 4e00df8d49..29fb3d6552 100644 --- a/packages/babel-helper-remap-async-to-generator/src/index.js +++ b/packages/babel-helper-remap-async-to-generator/src/index.js @@ -68,7 +68,7 @@ export default function(path: NodePath, file: Object, helpers: Object) { wrapAwait: helpers.wrapAwait, }); - const isIIFE = path.parentPath.isCallExpression({ callee: path.node }); + const isIIFE = checkIsIIFE(path); path.node.async = false; path.node.generator = true; @@ -84,4 +84,34 @@ export default function(path: NodePath, file: Object, helpers: Object) { if (!isProperty && !isIIFE && path.isExpression()) { annotateAsPure(path); } + + function checkIsIIFE(path: NodePath) { + if (path.parentPath.isCallExpression({ callee: path.node })) { + return true; + } + + // try to catch calls to Function#bind, as emitted by arrowFunctionToExpression in spec mode + // this may also catch .bind(this) written by users, but does it matter? 🤔 + const { parentPath } = path; + if ( + parentPath.isMemberExpression() && + t.isIdentifier(parentPath.node.property, { name: "bind" }) + ) { + const { parentPath: bindCall } = parentPath; + + // (function () { ... }).bind(this)() + + return ( + // first, check if the .bind is actually being called + bindCall.isCallExpression() && + // and whether its sole argument is 'this' + bindCall.node.arguments.length === 1 && + t.isThisExpression(bindCall.node.arguments[0]) && + // and whether the result of the .bind(this) is being called + bindCall.parentPath.isCallExpression({ callee: bindCall.node }) + ); + } + + return false; + } } diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/actual.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/actual.js new file mode 100644 index 0000000000..21f2cd9050 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/actual.js @@ -0,0 +1,4 @@ +(async function() { await 'ok' })(); +(async () => { await 'ok' })(); +(async function notIIFE() { await 'ok' }); +(async () => { await 'not iife' }); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/expected.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/expected.js new file mode 100644 index 0000000000..d036604c88 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/expected.js @@ -0,0 +1,74 @@ +var _this = this; + +babelHelpers.asyncToGenerator( +/*#__PURE__*/ +regeneratorRuntime.mark(function _callee() { + return regeneratorRuntime.wrap(function _callee$(_context) { + while (1) switch (_context.prev = _context.next) { + case 0: + _context.next = 2; + return 'ok'; + + case 2: + case "end": + return _context.stop(); + } + }, _callee, this); +}))(); +babelHelpers.asyncToGenerator( +/*#__PURE__*/ +regeneratorRuntime.mark(function _callee2() { + return regeneratorRuntime.wrap(function _callee2$(_context2) { + while (1) switch (_context2.prev = _context2.next) { + case 0: + babelHelpers.newArrowCheck(this, _this); + _context2.next = 3; + return 'ok'; + + case 3: + case "end": + return _context2.stop(); + } + }, _callee2, this); +})).bind(this)(); + +/*#__PURE__*/ +(function () { + var _notIIFE = babelHelpers.asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee3() { + return regeneratorRuntime.wrap(function _callee3$(_context3) { + while (1) switch (_context3.prev = _context3.next) { + case 0: + _context3.next = 2; + return 'ok'; + + case 2: + case "end": + return _context3.stop(); + } + }, _callee3, this); + })); + + return function notIIFE() { + return _notIIFE.apply(this, arguments); + }; +})(); + +/*#__PURE__*/ +babelHelpers.asyncToGenerator( +/*#__PURE__*/ +regeneratorRuntime.mark(function _callee4() { + return regeneratorRuntime.wrap(function _callee4$(_context4) { + while (1) switch (_context4.prev = _context4.next) { + case 0: + babelHelpers.newArrowCheck(this, _this); + _context4.next = 3; + return 'not iife'; + + case 3: + case "end": + return _context4.stop(); + } + }, _callee4, this); +})).bind(this); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/options.json b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/options.json new file mode 100644 index 0000000000..6eae662831 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + ["transform-arrow-functions", { "spec": true }], + "transform-regenerator", + "transform-async-to-generator", + "external-helpers" + ] +} diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator/actual.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator/actual.js new file mode 100644 index 0000000000..21f2cd9050 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator/actual.js @@ -0,0 +1,4 @@ +(async function() { await 'ok' })(); +(async () => { await 'ok' })(); +(async function notIIFE() { await 'ok' }); +(async () => { await 'not iife' }); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator/expected.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator/expected.js new file mode 100644 index 0000000000..5cc5472121 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator/expected.js @@ -0,0 +1,70 @@ +babelHelpers.asyncToGenerator( +/*#__PURE__*/ +regeneratorRuntime.mark(function _callee() { + return regeneratorRuntime.wrap(function _callee$(_context) { + while (1) switch (_context.prev = _context.next) { + case 0: + _context.next = 2; + return 'ok'; + + case 2: + case "end": + return _context.stop(); + } + }, _callee, this); +}))(); +babelHelpers.asyncToGenerator( +/*#__PURE__*/ +regeneratorRuntime.mark(function _callee2() { + return regeneratorRuntime.wrap(function _callee2$(_context2) { + while (1) switch (_context2.prev = _context2.next) { + case 0: + _context2.next = 2; + return 'ok'; + + case 2: + case "end": + return _context2.stop(); + } + }, _callee2, this); +}))(); + +/*#__PURE__*/ +(function () { + var _notIIFE = babelHelpers.asyncToGenerator( + /*#__PURE__*/ + regeneratorRuntime.mark(function _callee3() { + return regeneratorRuntime.wrap(function _callee3$(_context3) { + while (1) switch (_context3.prev = _context3.next) { + case 0: + _context3.next = 2; + return 'ok'; + + case 2: + case "end": + return _context3.stop(); + } + }, _callee3, this); + })); + + return function notIIFE() { + return _notIIFE.apply(this, arguments); + }; +})(); + +/*#__PURE__*/ +babelHelpers.asyncToGenerator( +/*#__PURE__*/ +regeneratorRuntime.mark(function _callee4() { + return regeneratorRuntime.wrap(function _callee4$(_context4) { + while (1) switch (_context4.prev = _context4.next) { + case 0: + _context4.next = 2; + return 'not iife'; + + case 2: + case "end": + return _context4.stop(); + } + }, _callee4, this); +})); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator/options.json b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator/options.json new file mode 100644 index 0000000000..d924af2adf --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + "transform-arrow-functions", + "transform-regenerator", + "transform-async-to-generator", + "external-helpers" + ] +} diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife/actual.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife/actual.js index de46a88e2e..21f2cd9050 100644 --- a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife/actual.js +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife/actual.js @@ -1,3 +1,4 @@ (async function() { await 'ok' })(); (async () => { await 'ok' })(); (async function notIIFE() { await 'ok' }); +(async () => { await 'not iife' }); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife/expected.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife/expected.js index edc4094abe..293c2722a5 100644 --- a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife/expected.js +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife/expected.js @@ -15,3 +15,8 @@ babelHelpers.asyncToGenerator(function* () { return _notIIFE.apply(this, arguments); }; })(); + +/*#__PURE__*/ +babelHelpers.asyncToGenerator(function* () { + yield 'not iife'; +});