@@ -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