@@ -318,6 +318,11 @@ module API {
318318 Node getParameter ( int i ) {
319319 Stages:: ApiStage:: ref ( ) and
320320 result = this .getASuccessor ( Label:: parameter ( i ) )
321+ or
322+ exists ( int spreadIndex , string arrayProp |
323+ result = this .getASuccessor ( Label:: spreadArgument ( spreadIndex ) ) .getMember ( arrayProp ) and
324+ i = spreadIndex + arrayProp .toInt ( )
325+ )
321326 }
322327
323328 /**
@@ -860,6 +865,15 @@ module API {
860865 .getStaticMember ( name , DataFlow:: MemberKind:: getter ( ) )
861866 .getAReturn ( )
862867 )
868+ or
869+ exists ( Function fun , DataFlow:: InvokeNode invoke , int argIndex , Parameter rest |
870+ fun .getRestParameter ( ) = rest and
871+ rest .flow ( ) = pred and
872+ invoke .getACallee ( ) = fun and
873+ invoke .getArgument ( argIndex ) = rhs and
874+ argIndex >= rest .getIndex ( ) and
875+ lbl = Label:: member ( ( argIndex - rest .getIndex ( ) ) .toString ( ) )
876+ )
863877 )
864878 or
865879 exists ( DataFlow:: ClassNode cls , string name |
@@ -888,6 +902,11 @@ module API {
888902 i = - 1 and lbl = Label:: receiver ( )
889903 )
890904 or
905+ exists ( int i |
906+ spreadArgumentPassing ( base , i , rhs ) and
907+ lbl = Label:: spreadArgument ( i )
908+ )
909+ or
891910 exists ( DataFlow:: SourceNode src , DataFlow:: PropWrite pw |
892911 use ( base , src ) and pw = trackUseNode ( src ) .getAPropertyWrite ( ) and rhs = pw .getRhs ( )
893912 |
@@ -931,6 +950,21 @@ module API {
931950 )
932951 }
933952
953+ pragma [ nomagic]
954+ private int firstSpreadIndex ( InvokeExpr expr ) {
955+ result = min ( int i | expr .getArgument ( i ) instanceof SpreadElement )
956+ }
957+
958+ private predicate spreadArgumentPassing ( TApiNode base , int i , DataFlow:: Node spreadArray ) {
959+ exists ( DataFlow:: Node use , DataFlow:: SourceNode pred , int bound , InvokeExpr invoke |
960+ use ( base , use ) and
961+ pred = trackUseNode ( use , _, bound , "" ) and
962+ invoke = pred .getAnInvocation ( ) .asExpr ( ) and
963+ i = firstSpreadIndex ( invoke ) and
964+ spreadArray = invoke .getArgument ( i - bound ) .( SpreadElement ) .getOperand ( ) .flow ( )
965+ )
966+ }
967+
934968 /**
935969 * Holds if `rhs` is the right-hand side of a definition of node `nd`.
936970 */
@@ -1579,6 +1613,9 @@ module API {
15791613 /** Gets the edge label for the receiver. */
15801614 LabelReceiver receiver ( ) { any ( ) }
15811615
1616+ /** Gets the edge label for a spread argument passed at index `i`. */
1617+ LabelSpreadArgument spreadArgument ( int i ) { result .getIndex ( ) = i }
1618+
15821619 /** Gets the `return` edge label. */
15831620 LabelReturn return ( ) { any ( ) }
15841621
@@ -1628,6 +1665,7 @@ module API {
16281665 } or
16291666 MkLabelReceiver ( ) or
16301667 MkLabelReturn ( ) or
1668+ MkLabelSpreadArgument ( int index ) { index = [ 0 .. 10 ] } or
16311669 MkLabelDecoratedClass ( ) or
16321670 MkLabelDecoratedMember ( ) or
16331671 MkLabelDecoratedParameter ( ) or
@@ -1743,6 +1781,18 @@ module API {
17431781 override string toString ( ) { result = "getReceiver()" }
17441782 }
17451783
1784+ /** A label representing an array passed as a spread argument at a given index. */
1785+ class LabelSpreadArgument extends ApiLabel , MkLabelSpreadArgument {
1786+ private int index ;
1787+
1788+ LabelSpreadArgument ( ) { this = MkLabelSpreadArgument ( index ) }
1789+
1790+ /** The argument index at which the spread argument appears. */
1791+ int getIndex ( ) { result = index }
1792+
1793+ override string toString ( ) { result = "getSpreadArgument(" + index + ")" }
1794+ }
1795+
17461796 /** A label for a function that is a wrapper around another function. */
17471797 class LabelForwardingFunction extends ApiLabel , MkLabelForwardingFunction {
17481798 override string toString ( ) { result = "getForwardingFunction()" }
0 commit comments