Skip to content

Commit 2d928f2

Browse files
committed
JS: Handle contextual return type in async function
1 parent 500b034 commit 2d928f2

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,17 +151,41 @@ module TypeResolution {
151151
)
152152
}
153153

154+
bindingset[name]
155+
private predicate isPromiseTypeName(string name) {
156+
name.regexpMatch(".?(Promise|Thenable)(Like)?")
157+
}
158+
159+
private Node unwrapPromiseType(Node promiseType) {
160+
exists(GenericTypeExpr type |
161+
promiseType = type and
162+
isPromiseTypeName(type.getTypeAccess().(LocalTypeAccess).getName()) and
163+
result = type.getTypeArgument(0)
164+
)
165+
or
166+
exists(JSDocAppliedTypeExpr type |
167+
promiseType = type and
168+
isPromiseTypeName(type.getHead().(JSDocLocalTypeAccess).getName()) and
169+
result = type.getArgument(0)
170+
)
171+
}
172+
154173
private predicate contextualType(Node value, Node type) {
155174
exists(InvokeExpr call, Function target, int i |
156175
callTarget(call, target) and
157176
value = call.getArgument(i) and
158177
type = target.getParameter(i).getTypeAnnotation()
159178
)
160179
or
161-
exists(Function lambda |
162-
not lambda.isAsyncOrGenerator() and
180+
exists(Function lambda, Node returnType |
163181
value = lambda.getAReturnedExpr() and
164-
functionReturnType(lambda, type)
182+
functionReturnType(lambda, returnType)
183+
|
184+
not lambda.isAsyncOrGenerator() and
185+
type = returnType
186+
or
187+
lambda.isAsync() and
188+
type = unwrapPromiseType(returnType)
165189
)
166190
or
167191
exists(ObjectExpr object, Node objectType, Node host, string name |

javascript/ql/test/library-tests/UnderlyingTypes/contextualTypes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ function t4(): Options[] {
3838

3939
async function t5(): Promise<Options> {
4040
return {
41-
handle(req) { // $ MISSING: hasUnderlyingType='express'.Request
41+
handle(req) { // $ hasUnderlyingType='express'.Request
4242

4343
}
4444
}

0 commit comments

Comments
 (0)