Skip to content

Commit 6a284ee

Browse files
committed
Merged ES6Class into FunctionStyleClass
1 parent 008dd3f commit 6a284ee

File tree

1 file changed

+162
-115
lines changed
  • javascript/ql/lib/semmle/javascript/dataflow

1 file changed

+162
-115
lines changed

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

Lines changed: 162 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,81 +1214,6 @@ module ClassNode {
12141214
DataFlow::Node getADecorator() { none() }
12151215
}
12161216

1217-
/**
1218-
* An ES6 class as a `ClassNode` instance.
1219-
*/
1220-
private class ES6Class extends Range, DataFlow::ValueNode {
1221-
override ClassDefinition astNode;
1222-
1223-
override string getName() { result = astNode.getName() }
1224-
1225-
override string describe() { result = astNode.describe() }
1226-
1227-
override FunctionNode getConstructor() { result = astNode.getConstructor().getBody().flow() }
1228-
1229-
override FunctionNode getInstanceMember(string name, MemberKind kind) {
1230-
exists(MethodDeclaration method |
1231-
method = astNode.getMethod(name) and
1232-
not method.isStatic() and
1233-
kind = MemberKind::of(method) and
1234-
result = method.getBody().flow()
1235-
)
1236-
or
1237-
kind = MemberKind::method() and
1238-
result = this.getConstructor().getReceiver().getAPropertySource(name)
1239-
}
1240-
1241-
override FunctionNode getAnInstanceMember(MemberKind kind) {
1242-
exists(MethodDeclaration method |
1243-
method = astNode.getAMethod() and
1244-
not method.isStatic() and
1245-
kind = MemberKind::of(method) and
1246-
result = method.getBody().flow()
1247-
)
1248-
or
1249-
kind = MemberKind::method() and
1250-
result = this.getConstructor().getReceiver().getAPropertySource()
1251-
}
1252-
1253-
override FunctionNode getStaticMember(string name, MemberKind kind) {
1254-
exists(MethodDeclaration method |
1255-
method = astNode.getMethod(name) and
1256-
method.isStatic() and
1257-
kind = MemberKind::of(method) and
1258-
result = method.getBody().flow()
1259-
)
1260-
or
1261-
kind.isMethod() and
1262-
result = this.getAPropertySource(name)
1263-
}
1264-
1265-
override FunctionNode getAStaticMember(MemberKind kind) {
1266-
exists(MethodDeclaration method |
1267-
method = astNode.getAMethod() and
1268-
method.isStatic() and
1269-
kind = MemberKind::of(method) and
1270-
result = method.getBody().flow()
1271-
)
1272-
or
1273-
kind.isMethod() and
1274-
result = this.getAPropertySource()
1275-
}
1276-
1277-
override DataFlow::Node getASuperClassNode() { result = astNode.getSuperClass().flow() }
1278-
1279-
override TypeAnnotation getFieldTypeAnnotation(string fieldName) {
1280-
exists(FieldDeclaration field |
1281-
field.getDeclaringClass() = astNode and
1282-
fieldName = field.getName() and
1283-
result = field.getTypeAnnotation()
1284-
)
1285-
}
1286-
1287-
override DataFlow::Node getADecorator() {
1288-
result = astNode.getADecorator().getExpression().flow()
1289-
}
1290-
}
1291-
12921217
private DataFlow::PropRef getAPrototypeReferenceInFile(string name, File f) {
12931218
result.getBase() = AccessPath::getAReferenceOrAssignmentTo(name) and
12941219
result.getPropertyName() = "prototype" and
@@ -1313,12 +1238,18 @@ module ClassNode {
13131238

13141239
/**
13151240
* A function definition, targeted by a `new`-call or with prototype manipulation, seen as a `ClassNode` instance.
1241+
* Or An ES6 class as a `ClassNode` instance.
13161242
*/
13171243
class FunctionStyleClass extends Range, DataFlow::ValueNode {
1318-
override Function astNode;
1244+
override AST::ValueNode astNode;
13191245
AbstractFunction function;
13201246

13211247
FunctionStyleClass() {
1248+
// ES6 class case
1249+
astNode instanceof ClassDefinition
1250+
or
1251+
// Function-style class case
1252+
astNode instanceof Function and
13221253
function.getFunction() = astNode and
13231254
(
13241255
exists(getAFunctionValueWithPrototype(function))
@@ -1333,13 +1264,30 @@ module ClassNode {
13331264
)
13341265
}
13351266

1336-
override string getName() { result = astNode.getName() }
1267+
override string getName() {
1268+
astNode instanceof ClassDefinition and result = astNode.(ClassDefinition).getName()
1269+
or
1270+
astNode instanceof Function and result = astNode.(Function).getName()
1271+
}
13371272

1338-
override string describe() { result = astNode.describe() }
1273+
override string describe() {
1274+
astNode instanceof ClassDefinition and result = astNode.(ClassDefinition).describe()
1275+
or
1276+
astNode instanceof Function and result = astNode.(Function).describe()
1277+
}
13391278

1340-
override FunctionNode getConstructor() { result = this }
1279+
override FunctionNode getConstructor() {
1280+
// For ES6 classes
1281+
astNode instanceof ClassDefinition and
1282+
result = astNode.(ClassDefinition).getConstructor().getBody().flow()
1283+
or
1284+
// For function-style classes
1285+
astNode instanceof Function and result = this
1286+
}
13411287

13421288
private PropertyAccessor getAnAccessor(MemberKind kind) {
1289+
// Only applies to function-style classes
1290+
astNode instanceof Function and
13431291
result.getObjectExpr() = this.getAPrototypeReference().asExpr() and
13441292
(
13451293
kind = MemberKind::getter() and
@@ -1351,12 +1299,41 @@ module ClassNode {
13511299
}
13521300

13531301
override FunctionNode getInstanceMember(string name, MemberKind kind) {
1302+
// ES6 class methods
1303+
exists(MethodDeclaration method |
1304+
astNode instanceof ClassDefinition and
1305+
method = astNode.(ClassDefinition).getMethod(name) and
1306+
not method.isStatic() and
1307+
kind = MemberKind::of(method) and
1308+
result = method.getBody().flow()
1309+
)
1310+
or
1311+
// ES6 class property in constructor
1312+
astNode instanceof ClassDefinition and
13541313
kind = MemberKind::method() and
1355-
result = this.getAPrototypeReference().getAPropertySource(name)
1314+
exists(ThisNode receiver |
1315+
receiver = this.getConstructor().getReceiver() and
1316+
receiver.hasPropertyWrite(name, result)
1317+
)
1318+
or
1319+
// Function-style class methods via prototype
1320+
astNode instanceof Function and
1321+
kind = MemberKind::method() and
1322+
exists(DataFlow::SourceNode proto |
1323+
proto = this.getAPrototypeReference() and
1324+
proto.hasPropertyWrite(name, result)
1325+
)
13561326
or
1327+
// Function-style class methods via constructor
1328+
astNode instanceof Function and
13571329
kind = MemberKind::method() and
1358-
result = this.getConstructor().getReceiver().getAPropertySource(name)
1330+
exists(ThisNode receiver |
1331+
receiver = this.getConstructor().getReceiver() and
1332+
receiver.hasPropertyWrite(name, result)
1333+
)
13591334
or
1335+
// Function-style class accessors
1336+
astNode instanceof Function and
13601337
exists(PropertyAccessor accessor |
13611338
accessor = this.getAnAccessor(kind) and
13621339
accessor.getName() = name and
@@ -1365,73 +1342,143 @@ module ClassNode {
13651342
}
13661343

13671344
override FunctionNode getAnInstanceMember(MemberKind kind) {
1345+
// ES6 class methods
1346+
exists(MethodDeclaration method |
1347+
astNode instanceof ClassDefinition and
1348+
method = astNode.(ClassDefinition).getAMethod() and
1349+
not method.isStatic() and
1350+
kind = MemberKind::of(method) and
1351+
result = method.getBody().flow()
1352+
)
1353+
or
1354+
// ES6 class property in constructor
1355+
astNode instanceof ClassDefinition and
1356+
kind = MemberKind::method() and
1357+
exists(ThisNode receiver |
1358+
receiver = this.getConstructor().getReceiver() and
1359+
result = receiver.getAPropertySource()
1360+
)
1361+
or
1362+
// Function-style class methods via prototype
1363+
astNode instanceof Function and
13681364
kind = MemberKind::method() and
1369-
result = this.getAPrototypeReference().getAPropertySource()
1365+
exists(DataFlow::SourceNode proto |
1366+
proto = this.getAPrototypeReference() and
1367+
result = proto.getAPropertySource()
1368+
)
13701369
or
1370+
// Function-style class methods via constructor
1371+
astNode instanceof Function and
13711372
kind = MemberKind::method() and
1372-
result = this.getConstructor().getReceiver().getAPropertySource()
1373+
exists(ThisNode receiver |
1374+
receiver = this.getConstructor().getReceiver() and
1375+
result = receiver.getAPropertySource()
1376+
)
13731377
or
1378+
// Function-style class accessors
1379+
astNode instanceof Function and
13741380
exists(PropertyAccessor accessor |
13751381
accessor = this.getAnAccessor(kind) and
13761382
result = accessor.getInit().flow()
13771383
)
13781384
}
13791385

13801386
override FunctionNode getStaticMember(string name, MemberKind kind) {
1387+
exists(MethodDeclaration method |
1388+
astNode instanceof ClassDefinition and
1389+
method = astNode.(ClassDefinition).getMethod(name) and
1390+
method.isStatic() and
1391+
kind = MemberKind::of(method) and
1392+
result = method.getBody().flow()
1393+
)
1394+
or
13811395
kind.isMethod() and
13821396
result = this.getAPropertySource(name)
13831397
}
13841398

13851399
override FunctionNode getAStaticMember(MemberKind kind) {
1400+
exists(MethodDeclaration method |
1401+
astNode instanceof ClassDefinition and
1402+
method = astNode.(ClassDefinition).getAMethod() and
1403+
method.isStatic() and
1404+
kind = MemberKind::of(method) and
1405+
result = method.getBody().flow()
1406+
)
1407+
or
13861408
kind.isMethod() and
13871409
result = this.getAPropertySource()
13881410
}
13891411

13901412
/**
13911413
* Gets a reference to the prototype of this class.
1414+
* Only applies to function-style classes.
13921415
*/
13931416
DataFlow::SourceNode getAPrototypeReference() {
1394-
exists(DataFlow::SourceNode base | base = getAFunctionValueWithPrototype(function) |
1395-
result = base.getAPropertyRead("prototype")
1417+
astNode instanceof Function and
1418+
(
1419+
exists(DataFlow::SourceNode base | base = getAFunctionValueWithPrototype(function) |
1420+
result = base.getAPropertyRead("prototype")
1421+
or
1422+
result = base.getAPropertySource("prototype")
1423+
)
13961424
or
1397-
result = base.getAPropertySource("prototype")
1398-
)
1399-
or
1400-
exists(string name |
1401-
this = AccessPath::getAnAssignmentTo(name) and
1402-
result = getAPrototypeReferenceInFile(name, this.getFile())
1403-
)
1404-
or
1405-
exists(ExtendCall call |
1406-
call.getDestinationOperand() = this.getAPrototypeReference() and
1407-
result = call.getASourceOperand()
1425+
exists(string name |
1426+
this = AccessPath::getAnAssignmentTo(name) and
1427+
result = getAPrototypeReferenceInFile(name, this.getFile())
1428+
)
1429+
or
1430+
exists(ExtendCall call |
1431+
call.getDestinationOperand() = this.getAPrototypeReference() and
1432+
result = call.getASourceOperand()
1433+
)
14081434
)
14091435
}
14101436

14111437
override DataFlow::Node getASuperClassNode() {
1412-
// C.prototype = Object.create(D.prototype)
1413-
exists(DataFlow::InvokeNode objectCreate, DataFlow::PropRead superProto |
1414-
this.getAPropertySource("prototype") = objectCreate and
1415-
objectCreate = DataFlow::globalVarRef("Object").getAMemberCall("create") and
1416-
superProto.flowsTo(objectCreate.getArgument(0)) and
1417-
superProto.getPropertyName() = "prototype" and
1418-
result = superProto.getBase()
1419-
)
1438+
// ES6 class superclass
1439+
astNode instanceof ClassDefinition and
1440+
result = astNode.(ClassDefinition).getSuperClass().flow()
14201441
or
1421-
// C.prototype = new D()
1422-
exists(DataFlow::NewNode newCall |
1423-
this.getAPropertySource("prototype") = newCall and
1424-
result = newCall.getCalleeNode()
1442+
// Function-style class superclass patterns
1443+
astNode instanceof Function and
1444+
(
1445+
// C.prototype = Object.create(D.prototype)
1446+
exists(DataFlow::InvokeNode objectCreate, DataFlow::PropRead superProto |
1447+
this.getAPropertySource("prototype") = objectCreate and
1448+
objectCreate = DataFlow::globalVarRef("Object").getAMemberCall("create") and
1449+
superProto.flowsTo(objectCreate.getArgument(0)) and
1450+
superProto.getPropertyName() = "prototype" and
1451+
result = superProto.getBase()
1452+
)
1453+
or
1454+
// C.prototype = new D()
1455+
exists(DataFlow::NewNode newCall |
1456+
this.getAPropertySource("prototype") = newCall and
1457+
result = newCall.getCalleeNode()
1458+
)
1459+
or
1460+
// util.inherits(C, D);
1461+
exists(DataFlow::CallNode inheritsCall |
1462+
inheritsCall = DataFlow::moduleMember("util", "inherits").getACall()
1463+
|
1464+
this = inheritsCall.getArgument(0).getALocalSource() and
1465+
result = inheritsCall.getArgument(1)
1466+
)
14251467
)
1426-
or
1427-
// util.inherits(C, D);
1428-
exists(DataFlow::CallNode inheritsCall |
1429-
inheritsCall = DataFlow::moduleMember("util", "inherits").getACall()
1430-
|
1431-
this = inheritsCall.getArgument(0).getALocalSource() and
1432-
result = inheritsCall.getArgument(1)
1468+
}
1469+
1470+
override TypeAnnotation getFieldTypeAnnotation(string fieldName) {
1471+
exists(FieldDeclaration field |
1472+
field.getDeclaringClass() = astNode and
1473+
fieldName = field.getName() and
1474+
result = field.getTypeAnnotation()
14331475
)
14341476
}
1477+
1478+
override DataFlow::Node getADecorator() {
1479+
astNode instanceof ClassDefinition and
1480+
result = astNode.(ClassDefinition).getADecorator().getExpression().flow()
1481+
}
14351482
}
14361483
}
14371484

0 commit comments

Comments
 (0)