Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/asyncify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<t.Function>): void {
if (returnsOrAwaitsPromises(path)) {
if (returnsOrAwaitsPromises(path) && !isGetterOrSetter(path)) {
path.node.async = true
}
const chains = findPromiseChains(path)
Expand Down
12 changes: 12 additions & 0 deletions src/util/isGetterOrSetter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as t from '@babel/types'
import { NodePath } from '@babel/traverse'

export default function isGetterOrSetter(
path: NodePath<t.Function> | null
): boolean {
return (
path !== null &&
(path.isObjectMethod() || path.isClassMethod()) &&
(path.node.kind === 'get' || path.node.kind === 'set')
)
}
8 changes: 5 additions & 3 deletions src/util/shouldIgnoreChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<t.CallExpression>): number {
let length = 0
Expand Down Expand Up @@ -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
}
Expand Down
8 changes: 5 additions & 3 deletions src/util/unwindPromiseChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<t.CallExpression>
): 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]
}
Expand Down
47 changes: 47 additions & 0 deletions test/fixtures/bugs_GetterAndSetterCannotBeAsync.ts
Original file line number Diff line number Diff line change
@@ -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))
}
};
`