Skip to content

Commit 5caf652

Browse files
committed
Brought back FunctionStyleClass marked as deprecated
1 parent 9bab593 commit 5caf652

File tree

1 file changed

+123
-0
lines changed
  • javascript/ql/lib/semmle/javascript/dataflow

1 file changed

+123
-0
lines changed

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

+123
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,129 @@ module ClassNode {
12361236
func instanceof AbstractCallable // the join-order goes bad if `func` has type `AbstractFunction`.
12371237
}
12381238

1239+
/**
1240+
* A function definition, targeted by a `new`-call or with prototype manipulation, seen as a `ClassNode` instance.
1241+
*/
1242+
deprecated class FunctionStyleClass extends Range, DataFlow::ValueNode {
1243+
override Function astNode;
1244+
AbstractFunction function;
1245+
1246+
FunctionStyleClass() {
1247+
function.getFunction() = astNode and
1248+
(
1249+
exists(getAFunctionValueWithPrototype(function))
1250+
or
1251+
function = any(NewNode new).getCalleeNode().analyze().getAValue()
1252+
or
1253+
exists(string name | this = AccessPath::getAnAssignmentTo(name) |
1254+
exists(getAPrototypeReferenceInFile(name, this.getFile()))
1255+
or
1256+
exists(getAnInstantiationInFile(name, this.getFile()))
1257+
)
1258+
)
1259+
}
1260+
1261+
override string getName() { result = astNode.getName() }
1262+
1263+
override string describe() { result = astNode.describe() }
1264+
1265+
override FunctionNode getConstructor() { result = this }
1266+
1267+
private PropertyAccessor getAnAccessor(MemberKind kind) {
1268+
result.getObjectExpr() = this.getAPrototypeReference().asExpr() and
1269+
(
1270+
kind = MemberKind::getter() and
1271+
result instanceof PropertyGetter
1272+
or
1273+
kind = MemberKind::setter() and
1274+
result instanceof PropertySetter
1275+
)
1276+
}
1277+
1278+
override FunctionNode getInstanceMember(string name, MemberKind kind) {
1279+
kind = MemberKind::method() and
1280+
result = this.getAPrototypeReference().getAPropertySource(name)
1281+
or
1282+
kind = MemberKind::method() and
1283+
result = this.getConstructor().getReceiver().getAPropertySource(name)
1284+
or
1285+
exists(PropertyAccessor accessor |
1286+
accessor = this.getAnAccessor(kind) and
1287+
accessor.getName() = name and
1288+
result = accessor.getInit().flow()
1289+
)
1290+
}
1291+
1292+
override FunctionNode getAnInstanceMember(MemberKind kind) {
1293+
kind = MemberKind::method() and
1294+
result = this.getAPrototypeReference().getAPropertySource()
1295+
or
1296+
kind = MemberKind::method() and
1297+
result = this.getConstructor().getReceiver().getAPropertySource()
1298+
or
1299+
exists(PropertyAccessor accessor |
1300+
accessor = this.getAnAccessor(kind) and
1301+
result = accessor.getInit().flow()
1302+
)
1303+
}
1304+
1305+
override FunctionNode getStaticMember(string name, MemberKind kind) {
1306+
kind.isMethod() and
1307+
result = this.getAPropertySource(name)
1308+
}
1309+
1310+
override FunctionNode getAStaticMember(MemberKind kind) {
1311+
kind.isMethod() and
1312+
result = this.getAPropertySource()
1313+
}
1314+
1315+
/**
1316+
* Gets a reference to the prototype of this class.
1317+
*/
1318+
DataFlow::SourceNode getAPrototypeReference() {
1319+
exists(DataFlow::SourceNode base | base = getAFunctionValueWithPrototype(function) |
1320+
result = base.getAPropertyRead("prototype")
1321+
or
1322+
result = base.getAPropertySource("prototype")
1323+
)
1324+
or
1325+
exists(string name |
1326+
this = AccessPath::getAnAssignmentTo(name) and
1327+
result = getAPrototypeReferenceInFile(name, this.getFile())
1328+
)
1329+
or
1330+
exists(ExtendCall call |
1331+
call.getDestinationOperand() = this.getAPrototypeReference() and
1332+
result = call.getASourceOperand()
1333+
)
1334+
}
1335+
1336+
override DataFlow::Node getASuperClassNode() {
1337+
// C.prototype = Object.create(D.prototype)
1338+
exists(DataFlow::InvokeNode objectCreate, DataFlow::PropRead superProto |
1339+
this.getAPropertySource("prototype") = objectCreate and
1340+
objectCreate = DataFlow::globalVarRef("Object").getAMemberCall("create") and
1341+
superProto.flowsTo(objectCreate.getArgument(0)) and
1342+
superProto.getPropertyName() = "prototype" and
1343+
result = superProto.getBase()
1344+
)
1345+
or
1346+
// C.prototype = new D()
1347+
exists(DataFlow::NewNode newCall |
1348+
this.getAPropertySource("prototype") = newCall and
1349+
result = newCall.getCalleeNode()
1350+
)
1351+
or
1352+
// util.inherits(C, D);
1353+
exists(DataFlow::CallNode inheritsCall |
1354+
inheritsCall = DataFlow::moduleMember("util", "inherits").getACall()
1355+
|
1356+
this = inheritsCall.getArgument(0).getALocalSource() and
1357+
result = inheritsCall.getArgument(1)
1358+
)
1359+
}
1360+
}
1361+
12391362
/**
12401363
* A function definition, targeted by a `new`-call or with prototype manipulation, seen as a `ClassNode` instance.
12411364
* Or An ES6 class as a `ClassNode` instance.

0 commit comments

Comments
 (0)