@@ -258,144 +258,152 @@ private class JQueryChainedElement extends DOM::Element, InvokeExpr {
258258}
259259
260260/**
261- * A model of a URL request made using the `jQuery.ajax` .
261+ * Classes and predicates for modelling `ClientRequest`s in JQuery .
262262 */
263- private class JQueryAjaxCall extends ClientRequest:: Range {
264- JQueryAjaxCall ( ) { this = jquery ( ) .getAMemberCall ( "ajax" ) }
263+ private module JQueryClientRequest {
264+ /**
265+ * A model of a URL request made using the `jQuery.ajax`.
266+ */
267+ private class JQueryAjaxCall extends ClientRequest:: Range {
268+ JQueryAjaxCall ( ) { this = jquery ( ) .getAMemberCall ( "ajax" ) }
265269
266- override DataFlow:: Node getUrl ( ) {
267- result = getArgument ( 0 ) and not exists ( getOptionArgument ( 0 , _) )
268- or
269- result = getOptionArgument ( [ 0 .. 1 ] , "url" )
270- }
270+ override DataFlow:: Node getUrl ( ) {
271+ result = getArgument ( 0 ) and not exists ( getOptionArgument ( 0 , _) )
272+ or
273+ result = getOptionArgument ( [ 0 .. 1 ] , "url" )
274+ }
271275
272- override DataFlow:: Node getHost ( ) { none ( ) }
276+ override DataFlow:: Node getHost ( ) { none ( ) }
273277
274- override DataFlow:: Node getADataNode ( ) { result = getOptionArgument ( [ 0 .. 1 ] , "data" ) }
278+ override DataFlow:: Node getADataNode ( ) { result = getOptionArgument ( [ 0 .. 1 ] , "data" ) }
275279
276- private string getResponseType ( ) {
277- getOptionArgument ( [ 0 .. 1 ] , "dataType" ) .mayHaveStringValue ( result )
278- }
280+ private string getResponseType ( ) {
281+ getOptionArgument ( [ 0 .. 1 ] , "dataType" ) .mayHaveStringValue ( result )
282+ }
279283
280- override DataFlow:: Node getAResponseDataNode ( string responseType , boolean promise ) {
281- (
282- responseType = getResponseType ( )
283- or
284- not exists ( getResponseType ( ) ) and responseType = ""
285- ) and
286- promise = false and
287- (
288- result =
289- getOptionArgument ( [ 0 .. 1 ] , "success" )
290- .getALocalSource ( )
291- .( DataFlow:: FunctionNode )
292- .getParameter ( 0 )
293- or
294- result =
295- getAResponseNodeFromAnXHRObject ( getOptionArgument ( [ 0 .. 1 ] ,
296- any ( string method | method = "error" or method = "complete" ) )
284+ override DataFlow:: Node getAResponseDataNode ( string responseType , boolean promise ) {
285+ (
286+ responseType = getResponseType ( )
287+ or
288+ not exists ( getResponseType ( ) ) and responseType = ""
289+ ) and
290+ promise = false and
291+ (
292+ result =
293+ getOptionArgument ( [ 0 .. 1 ] , "success" )
297294 .getALocalSource ( )
298295 .( DataFlow:: FunctionNode )
299- .getParameter ( 0 ) )
300- or
301- result = getAnAjaxCallbackDataNode ( this )
302- or
303- result = getAResponseNodeFromAnXHRObject ( getAnXHRObject ( this ) )
304- )
296+ .getParameter ( 0 )
297+ or
298+ result =
299+ getAResponseNodeFromAnXHRObject ( getOptionArgument ( [ 0 .. 1 ] ,
300+ any ( string method | method = "error" or method = "complete" ) )
301+ .getALocalSource ( )
302+ .( DataFlow:: FunctionNode )
303+ .getParameter ( 0 ) )
304+ or
305+ result = getAnAjaxCallbackDataNode ( this )
306+ or
307+ result = getAResponseNodeFromAnXHRObject ( getAnXHRObject ( this ) )
308+ )
309+ }
305310 }
306- }
307-
308- /**
309- * Gets the response data node from a call to a jqXHR Object.
310- */
311- DataFlow:: Node getAnAjaxCallbackDataNode ( ClientRequest:: Range request ) {
312- result =
313- request .getAMemberCall ( any ( string s | s = "done" or s = "then" ) ) .getCallback ( 0 ) .getParameter ( 0 )
314- }
315-
316- /**
317- * Gets the `jqXHR` object from a call to `fail` on the result from an ajax call (`request`).
318- */
319- DataFlow:: SourceNode getAnXHRObject ( ClientRequest:: Range request ) {
320- result = request .getAMemberCall ( "fail" ) .getCallback ( 0 ) .getParameter ( 0 )
321- }
322311
323- /**
324- * Gets a node refering to the response contained in an `jqXHR` object (`obj`).
325- */
326- DataFlow:: SourceNode getAResponseNodeFromAnXHRObject ( DataFlow:: SourceNode obj ) {
327- result =
328- obj
329- .getAPropertyRead ( any ( string s |
330- s = "responseText" or
331- s = "responseXML"
332- ) )
333- }
312+ /**
313+ * Gets a response data node from a call to a method on jqXHR Object.
314+ */
315+ private DataFlow:: Node getAnAjaxCallbackDataNode ( ClientRequest:: Range request ) {
316+ result =
317+ request
318+ .getAMemberCall ( any ( string s | s = "done" or s = "then" ) )
319+ .getCallback ( 0 )
320+ .getParameter ( 0 )
321+ }
334322
335- /**
336- * A model of a URL request made using a `jQuery.ajax` shorthand.
337- * E.g. `jQuery.getJSON`, `jQuery.post` etc.
338- * See: https://api.jquery.com/category/ajax/shorthand-methods/.
339- *
340- * The method signatures:
341- * jQuery.get( url [, data ] [, success ] [, dataType ] )
342- * jQuery.getJSON( url [, data ] [, success ] )
343- * jQuery.getScript( url [, success ] )
344- * jQuery.post( url [, data ] [, success ] [, dataType ] )
345- * .load( url [, data ] [, complete ] )
346- */
347- private class JQueryAjaxShortHand extends ClientRequest:: Range {
348- string name ;
323+ /**
324+ * Gets a `jqXHR` object from a call to the `fail(..)` method on jqXHR Object.
325+ */
326+ private DataFlow:: SourceNode getAnXHRObject ( ClientRequest:: Range request ) {
327+ result = request .getAMemberCall ( "fail" ) .getCallback ( 0 ) .getParameter ( 0 )
328+ }
349329
350- JQueryAjaxShortHand ( ) {
351- (
352- name = "get" or
353- name = "getJSON" or
354- name = "getScript" or
355- name = "post"
356- ) and
357- this = jquery ( ) .getAMemberCall ( name )
358- or
359- name = "load" and
360- this = JQuery:: objectRef ( ) .getAMethodCall ( name )
330+ /**
331+ * Gets a node refering to the response contained in an `jqXHR` object.
332+ */
333+ private DataFlow:: SourceNode getAResponseNodeFromAnXHRObject ( DataFlow:: SourceNode obj ) {
334+ result =
335+ obj
336+ .getAPropertyRead ( any ( string s |
337+ s = "responseText" or
338+ s = "responseXML"
339+ ) )
361340 }
362341
363- override DataFlow:: Node getUrl ( ) { result = getArgument ( 0 ) }
342+ /**
343+ * A model of a URL request made using a `jQuery.ajax` shorthand.
344+ * E.g. `jQuery.getJSON`, `jQuery.post` etc.
345+ * See: https://api.jquery.com/category/ajax/shorthand-methods/.
346+ *
347+ * Models the following method signatures:
348+ * - `jQuery.get( url [, data ] [, success ] [, dataType ] )`
349+ * - `jQuery.getJSON( url [, data ] [, success ] )`
350+ * - `jQuery.getScript( url [, success ] )`
351+ * - `jQuery.post( url [, data ] [, success ] [, dataType ] )`
352+ * - `.load( url [, data ] [, complete ] )`
353+ */
354+ private class JQueryAjaxShortHand extends ClientRequest:: Range {
355+ string name ;
364356
365- override DataFlow:: Node getHost ( ) { none ( ) }
357+ JQueryAjaxShortHand ( ) {
358+ (
359+ name = "get" or
360+ name = "getJSON" or
361+ name = "getScript" or
362+ name = "post"
363+ ) and
364+ this = jquery ( ) .getAMemberCall ( name )
365+ or
366+ name = "load" and
367+ this = JQuery:: objectRef ( ) .getAMethodCall ( name )
368+ }
366369
367- override DataFlow:: Node getADataNode ( ) {
368- result = getArgument ( 1 ) and
369- not name = "getScript" and // doesn't have a data-node.
370- not result .getALocalSource ( ) instanceof DataFlow:: FunctionNode // looks like the success callback.
371- }
370+ override DataFlow:: Node getUrl ( ) { result = getArgument ( 0 ) }
372371
373- string getResponseType ( ) {
374- ( name = "get" or name = "post" ) and
375- getLastArgument ( ) .mayHaveStringValue ( result ) and
376- getNumArgument ( ) > 1
377- or
378- name = "getJSON" and result = "json"
379- or
380- ( name = "getScript" or name = "load" ) and
381- result = "text"
382- }
372+ override DataFlow:: Node getHost ( ) { none ( ) }
383373
384- override DataFlow:: Node getAResponseDataNode ( string responseType , boolean promise ) {
385- (
386- responseType = getResponseType ( )
387- or
388- not exists ( getResponseType ( ) ) and responseType = ""
389- ) and
390- promise = false and
391- (
392- // one of the two last arguments
393- result = getCallback ( [ getNumArgument ( ) - 2 .. getNumArgument ( ) - 1 ] ) . getParameter ( 0 )
374+ override DataFlow:: Node getADataNode ( ) {
375+ result = getArgument ( 1 ) and
376+ not name = "getScript" and // doesn't have a data-node.
377+ not result . getALocalSource ( ) instanceof DataFlow :: FunctionNode // looks like the success callback.
378+ }
379+
380+ private string getResponseType ( ) {
381+ ( name = "get" or name = "post" ) and
382+ getLastArgument ( ) . mayHaveStringValue ( result ) and
383+ getNumArgument ( ) > 1
394384 or
395- result = getAnAjaxCallbackDataNode ( this )
385+ name = "getJSON" and result = "json"
396386 or
397- result = getAResponseNodeFromAnXHRObject ( getAnXHRObject ( this ) )
398- )
387+ ( name = "getScript" or name = "load" ) and
388+ result = "text"
389+ }
390+
391+ override DataFlow:: Node getAResponseDataNode ( string responseType , boolean promise ) {
392+ (
393+ responseType = getResponseType ( )
394+ or
395+ not exists ( getResponseType ( ) ) and responseType = ""
396+ ) and
397+ promise = false and
398+ (
399+ // one of the two last arguments
400+ result = getCallback ( [ getNumArgument ( ) - 2 .. getNumArgument ( ) - 1 ] ) .getParameter ( 0 )
401+ or
402+ result = getAnAjaxCallbackDataNode ( this )
403+ or
404+ result = getAResponseNodeFromAnXHRObject ( getAnXHRObject ( this ) )
405+ )
406+ }
399407 }
400408}
401409
0 commit comments