diff --git a/src/asyncify.ts b/src/asyncify.ts index 802e6e9..74e0a53 100644 --- a/src/asyncify.ts +++ b/src/asyncify.ts @@ -8,9 +8,10 @@ import unwindPromiseChain from './util/unwindPromiseChain' import finalCleanup from './util/finalCleanup' import codeLength from './util/codeLength' import babelBugWorkarounds from './util/babelBugWorkarounds' +import isGetterOrSetter from './util/isGetterOrSetter' function asyncifyFunction(path: NodePath): void { - if (returnsOrAwaitsPromises(path)) { + if (returnsOrAwaitsPromises(path) && !isGetterOrSetter(path)) { path.node.async = true } const chains = findPromiseChains(path) diff --git a/src/util/isGetterOrSetter.ts b/src/util/isGetterOrSetter.ts new file mode 100644 index 0000000..84b9e4d --- /dev/null +++ b/src/util/isGetterOrSetter.ts @@ -0,0 +1,12 @@ +import * as t from '@babel/types' +import { NodePath } from '@babel/traverse' + +export default function isGetterOrSetter( + path: NodePath | null +): boolean { + return ( + path !== null && + (path.isObjectMethod() || path.isClassMethod()) && + (path.node.kind === 'get' || path.node.kind === 'set') + ) +} diff --git a/src/util/shouldIgnoreChain.ts b/src/util/shouldIgnoreChain.ts index 26eb641..4a6db36 100644 --- a/src/util/shouldIgnoreChain.ts +++ b/src/util/shouldIgnoreChain.ts @@ -5,6 +5,7 @@ import iterateChain from './iterateChain' import getThenHandler from './getThenHandler' import getCatchHandler from './getCatchHandler' import getFinallyHandler from './getFinallyHandler' +import isGetterOrSetter from './isGetterOrSetter' function chainLength(path: NodePath): number { let length = 0 @@ -36,9 +37,10 @@ export default function shouldIgnoreChain( ): boolean { const { parentPath } = path if ( - !parentPath.isReturnStatement() && - !parentPath.isAwaitExpression() && - !parentPath.isFunction() + (!parentPath.isReturnStatement() && + !parentPath.isAwaitExpression() && + !parentPath.isFunction()) || + isGetterOrSetter(path.getFunctionParent()) ) { if (chainLength(path) <= 2 && !hasComplexHandlers(path)) return true } diff --git a/src/util/unwindPromiseChain.ts b/src/util/unwindPromiseChain.ts index 44a9ab7..fc0ebaf 100644 --- a/src/util/unwindPromiseChain.ts +++ b/src/util/unwindPromiseChain.ts @@ -9,14 +9,16 @@ import { unwindThen } from './unwindThen' import unwindFinally from './unwindFinally' import parentStatement from './parentStatement' import replaceWithImmediatelyInvokedAsyncArrowFunction from './replaceWithImmediatelyInvokedAsyncArrowFunction' +import isGetterOrSetter from './isGetterOrSetter' export default function unwindPromiseChain( path: NodePath ): void { if ( - !path.parentPath.isAwaitExpression() && - !path.parentPath.isReturnStatement() && - !path.parentPath.isFunction() + (!path.parentPath.isAwaitExpression() && + !path.parentPath.isReturnStatement() && + !path.parentPath.isFunction()) || + isGetterOrSetter(path.getFunctionParent()) ) { path = replaceWithImmediatelyInvokedAsyncArrowFunction(path)[1] } diff --git a/test/fixtures/bugs_GetterAndSetterCannotBeAsync.ts b/test/fixtures/bugs_GetterAndSetterCannotBeAsync.ts new file mode 100644 index 0000000..75614d6 --- /dev/null +++ b/test/fixtures/bugs_GetterAndSetterCannotBeAsync.ts @@ -0,0 +1,47 @@ +export const input = ` +class A { + method() {return p.then(x => f(x))} + get prop() {return p.then(x => f(x))} + set prop(val) {return p.then(x => f(x))} + get longchain() {return p.then(x => f(x)).then(y => g(y)).then(z => h(z))} +} +const obj = { + method() {return p.then(x => f(x))}, + get prop() {return p.then(x => f(x))}, + set prop(val) {return p.then(x => f(x))} +}; +` +export const expected = ` +class A { + async method() { + const x = await p; + return f(x); + } + get prop() { + return p.then(x => f(x)) + } + set prop(val) { + return p.then(x => f(x)) + } + get longchain() { + return (async () => { + const x = await p + const y = await f(x) + const z = await g(y) + return await h(z) + })() + } +} +const obj = { + async method() { + const x = await p; + return f(x); + }, + get prop() { + return p.then(x => f(x)) + }, + set prop(val) { + return p.then(x => f(x)) + } +}; +`