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
This commit is contained in:
Diogo Franco 2017-12-28 17:02:54 +09:00 committed by GitHub
parent 7d798952d2
commit 0f60d42fdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 205 additions and 1 deletions

View File

@ -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;
}
}

View File

@ -0,0 +1,4 @@
(async function() { await 'ok' })();
(async () => { await 'ok' })();
(async function notIIFE() { await 'ok' });
(async () => { await 'not iife' });

View File

@ -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);

View File

@ -0,0 +1,8 @@
{
"plugins": [
["transform-arrow-functions", { "spec": true }],
"transform-regenerator",
"transform-async-to-generator",
"external-helpers"
]
}

View File

@ -0,0 +1,4 @@
(async function() { await 'ok' })();
(async () => { await 'ok' })();
(async function notIIFE() { await 'ok' });
(async () => { await 'not iife' });

View File

@ -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);
}));

View File

@ -0,0 +1,8 @@
{
"plugins": [
"transform-arrow-functions",
"transform-regenerator",
"transform-async-to-generator",
"external-helpers"
]
}

View File

@ -1,3 +1,4 @@
(async function() { await 'ok' })();
(async () => { await 'ok' })();
(async function notIIFE() { await 'ok' });
(async () => { await 'not iife' });

View File

@ -15,3 +15,8 @@ babelHelpers.asyncToGenerator(function* () {
return _notIIFE.apply(this, arguments);
};
})();
/*#__PURE__*/
babelHelpers.asyncToGenerator(function* () {
yield 'not iife';
});