@@ -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,8 @@ module API {
15791613 /** Gets the edge label for the receiver. */
15801614 LabelReceiver receiver ( ) { any ( ) }
15811615
1616+ LabelSpreadArgument spreadArgument ( int i ) { result .getIndex ( ) = i }
1617+
15821618 /** Gets the `return` edge label. */
15831619 LabelReturn return ( ) { any ( ) }
15841620
@@ -1628,6 +1664,7 @@ module API {
16281664 } or
16291665 MkLabelReceiver ( ) or
16301666 MkLabelReturn ( ) or
1667+ MkLabelSpreadArgument ( int index ) { index = [ 0 .. 10 ] } or
16311668 MkLabelDecoratedClass ( ) or
16321669 MkLabelDecoratedMember ( ) or
16331670 MkLabelDecoratedParameter ( ) or
@@ -1743,6 +1780,18 @@ module API {
17431780 override string toString ( ) { result = "getReceiver()" }
17441781 }
17451782
1783+ /** A label representing an array passed as a spread argument at a given index. */
1784+ class LabelSpreadArgument extends ApiLabel , MkLabelSpreadArgument {
1785+ private int index ;
1786+
1787+ LabelSpreadArgument ( ) { this = MkLabelSpreadArgument ( index ) }
1788+
1789+ /** The argument index at which the spread argument appears. */
1790+ int getIndex ( ) { result = index }
1791+
1792+ override string toString ( ) { result = "getSpreadArgument(" + index + ")" }
1793+ }
1794+
17461795 /** A label for a function that is a wrapper around another function. */
17471796 class LabelForwardingFunction extends ApiLabel , MkLabelForwardingFunction {
17481797 override string toString ( ) { result = "getForwardingFunction()" }
0 commit comments