JS: Add support for Promise.try

This commit is contained in:
Asger F
2025-09-05 12:45:12 +02:00
parent 45eff3dac8
commit ee78b7dc96
3 changed files with 62 additions and 0 deletions

View File

@@ -49,3 +49,10 @@ string getAnArrayContent() {
// Values stored at an unknown index
result = "ArrayElement[?]"
}
/**
* Gets an argument position up to a certain limit.
*
* This can be used to generate flow summaries that should preserve such positions.
*/
int getAnArgumentPosition() { result = [0 .. 10] }

View File

@@ -368,3 +368,29 @@ private class PromiseWithResolversLike extends SummarizedCallable {
)
}
}
class PromiseTry extends DataFlow::SummarizedCallable {
PromiseTry() { this = "Promise.try()" }
override DataFlow::CallNode getACallSimple() {
result = promiseConstructorRef().getAMemberCall(["try", "attempt"])
or
result = DataFlow::moduleImport(["p-try", "es6-promise-try"]).getACall()
}
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
preservesValue = true and
(
exists(int i | i = getAnArgumentPosition() |
input = "Argument[" + (i + 1) + "]" and
output = "Argument[0].Parameter[" + i + "]"
)
or
input = "Argument[0].ReturnValue" and
output = "ReturnValue.Awaited"
or
input = "Argument[0].ReturnValue[exception]" and
output = "ReturnValue.Awaited[error]"
)
}
}

View File

@@ -0,0 +1,29 @@
async function t1() {
const promise = Promise.try(() => {
return source('try.1');
});
sink(await promise); // $ hasValueFlow=try.1
}
async function t2() {
const promise = Promise.try((x) => {
return x
}, source('try.2'));
sink(await promise); // $ hasValueFlow=try.2
}
async function t3() {
const promise = Promise.try((x) => {
throw x;
}, source('try.3'));
promise.catch(err => {
sink(err); // $ hasValueFlow=try.3
});
}
async function t4() {
const promise = Promise.try((x, y) => {
return y;
}, source('try.4.1'), source('try.4.2'));
sink(await promise); // $ hasValueFlow=try.4.2
}