Skip to content

Commit 3422bde

Browse files
author
Stephan Brandauer
committed
add functionInterfacesInFile and surroundingFunctionParameters features
1 parent 3e86076 commit 3422bde

3 files changed

Lines changed: 137 additions & 13 deletions

File tree

javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ predicate tokenFeatures(DataFlow::Node endpoint, string featureName, string feat
219219
}
220220

221221
/**
222-
* See EndpointFeauture
222+
* See EndpointFeature
223223
*/
224224
private newtype TEndpointFeature =
225225
TEnclosingFunctionName() or
@@ -234,7 +234,9 @@ private newtype TEndpointFeature =
234234
TCalleeImports() or
235235
TCalleeFlexibleAccessPath() or
236236
TInputAccessPathFromCallee() or
237-
TInputArgumentIndex()
237+
TInputArgumentIndex() or
238+
TContextFunctionInterfacesInFile() or
239+
TContextSurroundingFunctionParametersInFile()
238240

239241
/**
240242
* An implementation of an endpoint feature: produces feature names and values for used in ML.
@@ -440,6 +442,30 @@ class FileImports extends EndpointFeature, TFileImports {
440442
}
441443
}
442444

445+
/**
446+
* The feature for the function parameters of the functions that enclose an endpoint.
447+
*/
448+
class ContextSurroundingFunctionParametersInFile extends EndpointFeature,
449+
TContextSurroundingFunctionParametersInFile {
450+
override string getName() { result = "contextSurroundingFunctionParametersInFile" }
451+
452+
Function getRelevantFunction(DataFlow::Node endpoint) {
453+
result = endpoint.asExpr().getEnclosingFunction*()
454+
}
455+
456+
override string getValue(DataFlow::Node endpoint) {
457+
result =
458+
concat(string functionParameterLine, Function f |
459+
f = getRelevantFunction(endpoint) and
460+
functionParameterLine = SyntacticUtilities::getFunctionParametersFeatureComponent(f)
461+
|
462+
functionParameterLine, "\n"
463+
order by
464+
f.getLocation().getStartLine(), f.getLocation().getStartColumn()
465+
)
466+
}
467+
}
468+
443469
/**
444470
* The feature for the imports used in the callee of an invocation.
445471
*
@@ -475,6 +501,18 @@ class CalleeImports extends EndpointFeature, TCalleeImports {
475501
}
476502
}
477503

504+
/*
505+
* The feature for the interfaces of all named functions in the same file as the endpoint.
506+
*/
507+
508+
class ContextFunctionInterfacesInFile extends EndpointFeature, TContextFunctionInterfacesInFile {
509+
override string getName() { result = "contextFunctionInterfacesInFile" }
510+
511+
override string getValue(DataFlow::Node endpoint) {
512+
result = SyntacticUtilities::getFunctionInterfacesForFile(endpoint.getFile())
513+
}
514+
}
515+
478516
/**
479517
* Syntactic utilities for feature value computation.
480518
*/
@@ -484,6 +522,54 @@ private module SyntacticUtilities {
484522
result = any(Import imp | imp.getFile() = file).getImportedPath().getValue()
485523
}
486524

525+
/**
526+
* Gets the feature component for the parameters of a function.
527+
*
528+
* ```javascript
529+
* function f(a, b, c) { // will return "(a, b, c)" for this function
530+
* return a + b + c;
531+
* }
532+
*
533+
* async function g(a) { // will return "(a)" for this function
534+
* return 2*a
535+
* };
536+
*
537+
* const h = (b) => 3*b; // will return "(b)" for this function
538+
* ```
539+
*/
540+
string getFunctionParametersFeatureComponent(Function f) {
541+
result =
542+
"(" +
543+
concat(string parameter, int i |
544+
parameter = f.getParameter(i).getName()
545+
|
546+
parameter, ", " order by i
547+
) + ")"
548+
}
549+
550+
/**
551+
* Gets the function interfaces of all named functions in a file, concatenated together.
552+
*
553+
* ```javascript
554+
* // Will return: "f(a, b, c)\ng(x, y, z)\nh(u, v)" for this file.
555+
* function f(a, b, c) { ... }
556+
*
557+
* function g(x, y, z) {
558+
* function h(u, v) { ... }
559+
* ...
560+
* }
561+
*/
562+
string getFunctionInterfacesForFile(File file) {
563+
result =
564+
concat(Function func, string line |
565+
func.getFile() = file and
566+
exists(func.getName()) and
567+
line = func.getName() + getFunctionParametersFeatureComponent(func)
568+
|
569+
line, "\n" order by line
570+
)
571+
}
572+
487573
/**
488574
* Gets a property initializer value in a an object literal or one of its nested object literals.
489575
*/

javascript/ql/experimental/adaptivethreatmodeling/test/generic_feature_testing/FeatureValue.expected

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44
| test.html:2:61:2:68 | endpoint | calleeAccessPath | |
55
| test.html:2:61:2:68 | endpoint | calleeAccessPathWithStructuralInfo | |
66
| test.html:2:61:2:68 | endpoint | calleeName | item |
7+
| test.html:2:61:2:68 | endpoint | contextFunctionInterfacesInFile | |
8+
| test.html:2:61:2:68 | endpoint | contextSurroundingFunctionParametersInFile | |
79
| test.html:2:61:2:68 | endpoint | fileImports | |
810
| test.js:6:7:6:14 | endpoint | CalleeFlexibleAccessPath | f |
911
| test.js:6:7:6:14 | endpoint | InputArgumentIndex | 0 |
1012
| test.js:6:7:6:14 | endpoint | argumentIndex | 0 |
1113
| test.js:6:7:6:14 | endpoint | calleeAccessPath | lib3 |
1214
| test.js:6:7:6:14 | endpoint | calleeAccessPathWithStructuralInfo | lib3 instanceorreturn |
1315
| test.js:6:7:6:14 | endpoint | calleeApiName | lib3 |
14-
| test.js:6:7:6:14 | endpoint | calleeImports | lib3 |
16+
| test.js:6:7:6:14 | endpoint | calleeImports | ? lib3 |
1517
| test.js:6:7:6:14 | endpoint | calleeName | f |
18+
| test.js:6:7:6:14 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
19+
| test.js:6:7:6:14 | endpoint | contextSurroundingFunctionParametersInFile | () |
1620
| test.js:6:7:6:14 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
1721
| test.js:6:7:6:14 | endpoint | enclosingFunctionName | |
1822
| test.js:6:7:6:14 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -21,7 +25,9 @@
2125
| test.js:7:11:7:18 | endpoint | InputArgumentIndex | 0 |
2226
| test.js:7:11:7:18 | endpoint | calleeAccessPath | |
2327
| test.js:7:11:7:18 | endpoint | calleeAccessPathWithStructuralInfo | |
24-
| test.js:7:11:7:18 | endpoint | calleeImports | lib3 |
28+
| test.js:7:11:7:18 | endpoint | calleeImports | ? lib3 |
29+
| test.js:7:11:7:18 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
30+
| test.js:7:11:7:18 | endpoint | contextSurroundingFunctionParametersInFile | () |
2531
| test.js:7:11:7:18 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
2632
| test.js:7:11:7:18 | endpoint | enclosingFunctionName | |
2733
| test.js:7:11:7:18 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -30,7 +36,9 @@
3036
| test.js:8:15:8:22 | endpoint | InputArgumentIndex | 0 |
3137
| test.js:8:15:8:22 | endpoint | calleeAccessPath | |
3238
| test.js:8:15:8:22 | endpoint | calleeAccessPathWithStructuralInfo | |
33-
| test.js:8:15:8:22 | endpoint | calleeImports | lib3 |
39+
| test.js:8:15:8:22 | endpoint | calleeImports | ? lib3 |
40+
| test.js:8:15:8:22 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
41+
| test.js:8:15:8:22 | endpoint | contextSurroundingFunctionParametersInFile | () |
3442
| test.js:8:15:8:22 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
3543
| test.js:8:15:8:22 | endpoint | enclosingFunctionName | |
3644
| test.js:8:15:8:22 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -40,8 +48,10 @@
4048
| test.js:9:9:9:16 | endpoint | calleeAccessPath | lib2 m |
4149
| test.js:9:9:9:16 | endpoint | calleeAccessPathWithStructuralInfo | lib2 member m instanceorreturn |
4250
| test.js:9:9:9:16 | endpoint | calleeApiName | lib2 |
43-
| test.js:9:9:9:16 | endpoint | calleeImports | lib2 |
51+
| test.js:9:9:9:16 | endpoint | calleeImports | ? lib2 |
4452
| test.js:9:9:9:16 | endpoint | calleeName | m |
53+
| test.js:9:9:9:16 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
54+
| test.js:9:9:9:16 | endpoint | contextSurroundingFunctionParametersInFile | () |
4555
| test.js:9:9:9:16 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
4656
| test.js:9:9:9:16 | endpoint | enclosingFunctionName | |
4757
| test.js:9:9:9:16 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -51,7 +61,9 @@
5161
| test.js:10:13:10:20 | endpoint | InputArgumentIndex | 0 |
5262
| test.js:10:13:10:20 | endpoint | calleeAccessPath | |
5363
| test.js:10:13:10:20 | endpoint | calleeAccessPathWithStructuralInfo | |
54-
| test.js:10:13:10:20 | endpoint | calleeImports | lib2 |
64+
| test.js:10:13:10:20 | endpoint | calleeImports | ? lib2 |
65+
| test.js:10:13:10:20 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
66+
| test.js:10:13:10:20 | endpoint | contextSurroundingFunctionParametersInFile | () |
5567
| test.js:10:13:10:20 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
5668
| test.js:10:13:10:20 | endpoint | enclosingFunctionName | |
5769
| test.js:10:13:10:20 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -60,7 +72,9 @@
6072
| test.js:11:17:11:24 | endpoint | InputArgumentIndex | 0 |
6173
| test.js:11:17:11:24 | endpoint | calleeAccessPath | |
6274
| test.js:11:17:11:24 | endpoint | calleeAccessPathWithStructuralInfo | |
63-
| test.js:11:17:11:24 | endpoint | calleeImports | lib2 |
75+
| test.js:11:17:11:24 | endpoint | calleeImports | ? lib2 |
76+
| test.js:11:17:11:24 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
77+
| test.js:11:17:11:24 | endpoint | contextSurroundingFunctionParametersInFile | () |
6478
| test.js:11:17:11:24 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
6579
| test.js:11:17:11:24 | endpoint | enclosingFunctionName | |
6680
| test.js:11:17:11:24 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -69,6 +83,8 @@
6983
| test.js:12:11:12:18 | endpoint | calleeAccessPath | |
7084
| test.js:12:11:12:18 | endpoint | calleeAccessPathWithStructuralInfo | |
7185
| test.js:12:11:12:18 | endpoint | calleeImports | lib1 |
86+
| test.js:12:11:12:18 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
87+
| test.js:12:11:12:18 | endpoint | contextSurroundingFunctionParametersInFile | () |
7288
| test.js:12:11:12:18 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
7389
| test.js:12:11:12:18 | endpoint | enclosingFunctionName | |
7490
| test.js:12:11:12:18 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -78,8 +94,10 @@
7894
| test.js:13:17:13:24 | endpoint | calleeAccessPath | lib2 m m m |
7995
| test.js:13:17:13:24 | endpoint | calleeAccessPathWithStructuralInfo | lib2 member m instanceorreturn member m instanceorreturn member m instanceorreturn |
8096
| test.js:13:17:13:24 | endpoint | calleeApiName | lib2 |
81-
| test.js:13:17:13:24 | endpoint | calleeImports | lib2 |
97+
| test.js:13:17:13:24 | endpoint | calleeImports | ? lib2 |
8298
| test.js:13:17:13:24 | endpoint | calleeName | m |
99+
| test.js:13:17:13:24 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
100+
| test.js:13:17:13:24 | endpoint | contextSurroundingFunctionParametersInFile | () |
83101
| test.js:13:17:13:24 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
84102
| test.js:13:17:13:24 | endpoint | enclosingFunctionName | |
85103
| test.js:13:17:13:24 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -89,7 +107,9 @@
89107
| test.js:14:9:14:16 | endpoint | calleeAccessPath | lib3 |
90108
| test.js:14:9:14:16 | endpoint | calleeAccessPathWithStructuralInfo | lib3 instanceorreturn instanceorreturn |
91109
| test.js:14:9:14:16 | endpoint | calleeApiName | lib3 |
92-
| test.js:14:9:14:16 | endpoint | calleeImports | lib3 |
110+
| test.js:14:9:14:16 | endpoint | calleeImports | ? lib3 |
111+
| test.js:14:9:14:16 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
112+
| test.js:14:9:14:16 | endpoint | contextSurroundingFunctionParametersInFile | () |
93113
| test.js:14:9:14:16 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
94114
| test.js:14:9:14:16 | endpoint | enclosingFunctionName | |
95115
| test.js:14:9:14:16 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -99,8 +119,10 @@
99119
| test.js:15:12:15:19 | endpoint | calleeAccessPath | lib2 m |
100120
| test.js:15:12:15:19 | endpoint | calleeAccessPathWithStructuralInfo | lib2 member member m instanceorreturn |
101121
| test.js:15:12:15:19 | endpoint | calleeApiName | lib2 |
102-
| test.js:15:12:15:19 | endpoint | calleeImports | lib2 |
122+
| test.js:15:12:15:19 | endpoint | calleeImports | ? lib2 |
103123
| test.js:15:12:15:19 | endpoint | calleeName | m |
124+
| test.js:15:12:15:19 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
125+
| test.js:15:12:15:19 | endpoint | contextSurroundingFunctionParametersInFile | () |
104126
| test.js:15:12:15:19 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
105127
| test.js:15:12:15:19 | endpoint | enclosingFunctionName | |
106128
| test.js:15:12:15:19 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -110,8 +132,10 @@
110132
| test.js:16:16:16:23 | endpoint | calleeAccessPath | lib2 m p m |
111133
| test.js:16:16:16:23 | endpoint | calleeAccessPathWithStructuralInfo | lib2 member m member member p member m instanceorreturn |
112134
| test.js:16:16:16:23 | endpoint | calleeApiName | lib2 |
113-
| test.js:16:16:16:23 | endpoint | calleeImports | lib2 |
135+
| test.js:16:16:16:23 | endpoint | calleeImports | ? lib2 |
114136
| test.js:16:16:16:23 | endpoint | calleeName | m |
137+
| test.js:16:16:16:23 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
138+
| test.js:16:16:16:23 | endpoint | contextSurroundingFunctionParametersInFile | () |
115139
| test.js:16:16:16:23 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
116140
| test.js:16:16:16:23 | endpoint | enclosingFunctionName | |
117141
| test.js:16:16:16:23 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -122,6 +146,8 @@
122146
| test.js:17:15:17:22 | endpoint | calleeAccessPathWithStructuralInfo | lib1 member p instanceorreturn |
123147
| test.js:17:15:17:22 | endpoint | calleeApiName | lib1 |
124148
| test.js:17:15:17:22 | endpoint | calleeImports | lib1 |
149+
| test.js:17:15:17:22 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
150+
| test.js:17:15:17:22 | endpoint | contextSurroundingFunctionParametersInFile | () |
125151
| test.js:17:15:17:22 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
126152
| test.js:17:15:17:22 | endpoint | enclosingFunctionName | |
127153
| test.js:17:15:17:22 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -133,6 +159,8 @@
133159
| test.js:18:27:18:34 | endpoint | calleeApiName | foo |
134160
| test.js:18:27:18:34 | endpoint | calleeImports | foo |
135161
| test.js:18:27:18:34 | endpoint | calleeName | baz |
162+
| test.js:18:27:18:34 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
163+
| test.js:18:27:18:34 | endpoint | contextSurroundingFunctionParametersInFile | () |
136164
| test.js:18:27:18:34 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
137165
| test.js:18:27:18:34 | endpoint | enclosingFunctionName | |
138166
| test.js:18:27:18:34 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -144,6 +172,8 @@
144172
| test.js:20:13:20:20 | endpoint | calleeApiName | lib1 |
145173
| test.js:20:13:20:20 | endpoint | calleeImports | lib1 |
146174
| test.js:20:13:20:20 | endpoint | calleeName | bar |
175+
| test.js:20:13:20:20 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
176+
| test.js:20:13:20:20 | endpoint | contextSurroundingFunctionParametersInFile | () |
147177
| test.js:20:13:20:20 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
148178
| test.js:20:13:20:20 | endpoint | enclosingFunctionName | |
149179
| test.js:20:13:20:20 | endpoint | fileImports | foo lib1 lib2 lib3 |
@@ -152,7 +182,9 @@
152182
| test.js:22:21:22:28 | endpoint | calleeAccessPath | lib3 |
153183
| test.js:22:21:22:28 | endpoint | calleeAccessPathWithStructuralInfo | lib3 instanceorreturn |
154184
| test.js:22:21:22:28 | endpoint | calleeApiName | lib3 |
155-
| test.js:22:21:22:28 | endpoint | calleeImports | lib2 lib3 |
185+
| test.js:22:21:22:28 | endpoint | calleeImports | ? lib2 lib3 |
186+
| test.js:22:21:22:28 | endpoint | contextFunctionInterfacesInFile | f(endpoint)\nfoo()\ng()\nm() |
187+
| test.js:22:21:22:28 | endpoint | contextSurroundingFunctionParametersInFile | () |
156188
| test.js:22:21:22:28 | endpoint | enclosingFunctionBody | f endpoint f p endpoint f p q endpoint o m endpoint o m p endpoint o m p q endpoint F endpoint o m m m endpoint f endpoint o x m endpoint o m x p m endpoint p endpoint foo bar baz endpoint foo bar endpoint f f o m endpoint |
157189
| test.js:22:21:22:28 | endpoint | enclosingFunctionName | |
158190
| test.js:22:21:22:28 | endpoint | fileImports | foo lib1 lib2 lib3 |

javascript/ql/experimental/adaptivethreatmodeling/test/generic_feature_testing/test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,9 @@ const f = require('lib3');
2121
}
2222
(f() ? f : o.m)(endpoint);
2323
});
24+
25+
function f(endpoint) {}
26+
27+
const g = async () => undefined;
28+
29+
const o = { m: () => undefined }

0 commit comments

Comments
 (0)