@@ -1236,6 +1236,129 @@ module ClassNode {
1236
1236
func instanceof AbstractCallable // the join-order goes bad if `func` has type `AbstractFunction`.
1237
1237
}
1238
1238
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
+
1239
1362
/**
1240
1363
* A function definition, targeted by a `new`-call or with prototype manipulation, seen as a `ClassNode` instance.
1241
1364
* Or An ES6 class as a `ClassNode` instance.
0 commit comments