Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3bf86ee

Browse files
committed
JS: Rename AdditionalPartialInvoke -> PartialInvoke::Range
1 parent d6ba966 commit 3bf86ee

3 files changed

Lines changed: 109 additions & 50 deletions

File tree

javascript/ql/src/meta/analysis-quality/CallGraphQuality.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ SourceNode nodeLeadingToInvocation() {
7676
result.flowsTo(arg)
7777
)
7878
or
79-
exists(AdditionalPartialInvokeNode invoke, Node arg |
79+
exists(PartialInvokeNode invoke, Node arg |
8080
invoke.isPartialArgument(arg, _, _) and
8181
result.flowsTo(arg)
8282
)

javascript/ql/src/semmle/javascript/dataflow/Nodes.qll

Lines changed: 107 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -983,73 +983,132 @@ module ClassNode {
983983
}
984984

985985
/**
986-
* An invocation that is modeled as a partial function application.
986+
* A data flow node that performs a partial function application.
987987
*
988-
* This contributes additional argument-passing flow edges that should be added to all data flow configurations.
988+
* Examples:
989+
* ```
990+
* fn.bind(this)
991+
* x.method.bind(x)
992+
* _.partial(fn, x, y, z)
993+
* ```
989994
*/
990-
abstract class AdditionalPartialInvokeNode extends DataFlow::InvokeNode {
995+
class PartialInvokeNode extends DataFlow::Node {
996+
PartialInvokeNode::Range range;
997+
998+
PartialInvokeNode() { this = range }
999+
9911000
/**
9921001
* Holds if `argument` is passed as argument `index` to the function in `callback`.
9931002
*/
994-
abstract predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index);
1003+
predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
1004+
range.isPartialArgument(callback, argument, index)
1005+
}
1006+
1007+
/**
1008+
* Gets a node referring to a bound version of `callback` with `boundArgs` arguments bound.
1009+
*/
1010+
DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
1011+
result = range.getBoundFunction(callback, boundArgs)
1012+
}
9951013

996-
/** Gets the data flow node referring to the bound function, if such a node exists. */
997-
DataFlow::SourceNode getBoundFunction(int boundArgs) { none() }
1014+
/**
1015+
* Gets the node holding the receiver to be passed to the bound function, if specified.
1016+
*/
1017+
DataFlow::Node getBoundReceiver() { result = range.getBoundReceiver() }
9981018
}
9991019

1000-
/**
1001-
* A partial call through the built-in `Function.prototype.bind`.
1002-
*/
1003-
private class BindPartialCall extends AdditionalPartialInvokeNode, DataFlow::MethodCallNode {
1004-
BindPartialCall() { getMethodName() = "bind" }
1020+
module PartialInvokeNode {
1021+
/**
1022+
* A data flow node that performs a partial function application.
1023+
*/
1024+
abstract class Range extends DataFlow::Node {
1025+
/**
1026+
* Holds if `argument` is passed as argument `index` to the function in `callback`.
1027+
*/
1028+
predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) { none() }
10051029

1006-
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
1007-
index >= 0 and
1008-
callback = getReceiver() and
1009-
argument = getArgument(index + 1)
1010-
}
1030+
/**
1031+
* Gets a node referring to a bound version of `callback` with `boundArgs` arguments bound.
1032+
*/
1033+
DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) { none() }
10111034

1012-
override DataFlow::SourceNode getBoundFunction(int boundArgs) {
1013-
boundArgs = getNumArgument() - 1 and
1014-
result = this
1035+
/**
1036+
* Gets the node holding the receiver to be passed to the bound function, if specified.
1037+
*/
1038+
DataFlow::Node getBoundReceiver() { none() }
10151039
}
1016-
}
10171040

1018-
/**
1019-
* A partial call through `_.partial`.
1020-
*/
1021-
private class LodashPartialCall extends AdditionalPartialInvokeNode {
1022-
LodashPartialCall() { this = LodashUnderscore::member("partial").getACall() }
1041+
/**
1042+
* A partial call through the built-in `Function.prototype.bind`.
1043+
*/
1044+
private class BindPartialCall extends PartialInvokeNode::Range, DataFlow::MethodCallNode {
1045+
BindPartialCall() { getMethodName() = "bind" }
1046+
1047+
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
1048+
index >= 0 and
1049+
callback = getReceiver() and
1050+
argument = getArgument(index + 1)
1051+
}
10231052

1024-
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
1025-
index >= 0 and
1026-
callback = getArgument(0) and
1027-
argument = getArgument(index + 1)
1028-
}
1053+
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
1054+
callback = getReceiver() and
1055+
boundArgs = getNumArgument() - 1 and
1056+
result = this
1057+
}
10291058

1030-
override DataFlow::SourceNode getBoundFunction(int boundArgs) {
1031-
boundArgs = getNumArgument() - 1 and
1032-
result = this
1059+
override DataFlow::Node getBoundReceiver() {
1060+
result = getArgument(0)
1061+
}
10331062
}
1034-
}
10351063

1036-
/**
1037-
* A partial call through `ramda.partial`.
1038-
*/
1039-
private class RamdaPartialCall extends AdditionalPartialInvokeNode {
1040-
RamdaPartialCall() { this = DataFlow::moduleMember("ramda", "partial").getACall() }
1064+
/**
1065+
* A partial call through `_.partial`.
1066+
*/
1067+
private class LodashPartialCall extends PartialInvokeNode::Range, DataFlow::CallNode {
1068+
LodashPartialCall() { this = LodashUnderscore::member("partial").getACall() }
1069+
1070+
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
1071+
index >= 0 and
1072+
callback = getArgument(0) and
1073+
argument = getArgument(index + 1)
1074+
}
10411075

1042-
private DataFlow::ArrayCreationNode getArgumentsArray() {
1043-
result.flowsTo(getArgument(1))
1076+
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
1077+
callback = getReceiver() and
1078+
boundArgs = getNumArgument() - 1 and
1079+
result = this
1080+
}
10441081
}
10451082

1046-
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
1047-
callback = getArgument(0) and
1048-
argument = getArgumentsArray().getElement(index)
1049-
}
1083+
/**
1084+
* A partial call through `ramda.partial`.
1085+
*/
1086+
private class RamdaPartialCall extends PartialInvokeNode::Range, DataFlow::CallNode {
1087+
RamdaPartialCall() { this = DataFlow::moduleMember("ramda", "partial").getACall() }
1088+
1089+
private DataFlow::ArrayCreationNode getArgumentsArray() {
1090+
result.flowsTo(getArgument(1))
1091+
}
10501092

1051-
override DataFlow::SourceNode getBoundFunction(int boundArgs) {
1052-
boundArgs = getArgumentsArray().getSize() and
1053-
result = this
1093+
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
1094+
callback = getArgument(0) and
1095+
argument = getArgumentsArray().getElement(index)
1096+
}
1097+
1098+
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
1099+
callback = getArgument(0) and
1100+
boundArgs = getArgumentsArray().getSize() and
1101+
result = this
1102+
}
10541103
}
10551104
}
1105+
1106+
/**
1107+
* DEPRECATED. Subclasses should extend `PartialInvokeNode::Range` instead,
1108+
* and predicates should use `PartialInvokeNode` instead.
1109+
*
1110+
* An invocation that is modeled as a partial function application.
1111+
*
1112+
* This contributes additional argument-passing flow edges that should be added to all data flow configurations.
1113+
*/
1114+
deprecated class AdditionalPartialInvokeNode = PartialInvokeNode::Range;

javascript/ql/src/semmle/javascript/frameworks/AsyncPackage.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ module AsyncPackage {
7070
* to the first parameter of the final callback, while `result1, result2, ...` are propagated to
7171
* the parameters of the following task.
7272
*/
73-
private class WaterfallNextTaskCall extends DataFlow::AdditionalPartialInvokeNode {
73+
private class WaterfallNextTaskCall extends DataFlow::PartialInvokeNode::Range, DataFlow::CallNode {
7474
Waterfall waterfall;
7575
int n;
7676

0 commit comments

Comments
 (0)