@@ -347,6 +347,46 @@ module API {
347347 result = this .getASuccessor ( Label:: promisedError ( ) )
348348 }
349349
350+ /**
351+ * Gets a node representing a function that is a wrapper around the function represented by this node.
352+ *
353+ * Concretely, a function that forwards all its parameters to a call to `f` and returns the result of that call
354+ * is considered a wrapper around `f`.
355+ *
356+ * Examples:
357+ * ```js
358+ * function f(x) {
359+ * return g(x); // f = g.getForwardingFunction()
360+ * }
361+ *
362+ * function doExec(x) {
363+ * console.log(x);
364+ * return exec(x); // doExec = exec.getForwardingFunction()
365+ * }
366+ *
367+ * function doEither(x, y) {
368+ * if (x > y) {
369+ * return foo(x, y); // doEither = foo.getForwardingFunction()
370+ * } else {
371+ * return bar(x, y); // doEither = bar.getForwardingFunction()
372+ * }
373+ * }
374+ *
375+ * function wrapWithLogging(f) {
376+ * return (x) => {
377+ * console.log(x);
378+ * return f(x); // f.getForwardingFunction() = anonymous arrow function
379+ * }
380+ * }
381+ * wrapWithLogging(g); // g.getForwardingFunction() = wrapWithLogging(g)
382+ * ```
383+ */
384+ cached
385+ Node getForwardingFunction ( ) {
386+ Stages:: ApiStage:: ref ( ) and
387+ result = this .getASuccessor ( Label:: forwardingFunction ( ) )
388+ }
389+
350390 /**
351391 * Gets any class that has this value as a decorator.
352392 *
@@ -901,6 +941,9 @@ module API {
901941 or
902942 lbl = Label:: return ( ) and
903943 ref = pred .getAnInvocation ( )
944+ or
945+ lbl = Label:: forwardingFunction ( ) and
946+ DataFlow:: functionForwardingStep ( pred .getALocalUse ( ) , ref )
904947 )
905948 or
906949 exists ( DataFlow:: Node def , DataFlow:: FunctionNode fn |
@@ -1431,6 +1474,9 @@ module API {
14311474 /** Gets the `return` edge label. */
14321475 LabelReturn return ( ) { any ( ) }
14331476
1477+ /** Gets the label representing a function wrapper that forwards to an underlying function. */
1478+ LabelForwardingFunction forwardingFunction ( ) { any ( ) }
1479+
14341480 /** Gets the `promised` edge label connecting a promise to its contained value. */
14351481 LabelPromised promised ( ) { any ( ) }
14361482
@@ -1483,6 +1529,7 @@ module API {
14831529 MkLabelDecoratedClass ( ) or
14841530 MkLabelDecoratedMember ( ) or
14851531 MkLabelDecoratedParameter ( ) or
1532+ MkLabelForwardingFunction ( ) or
14861533 MkLabelEntryPoint ( API:: EntryPoint e )
14871534
14881535 /** A label for an entry-point. */
@@ -1566,6 +1613,11 @@ module API {
15661613 override string toString ( ) { result = "getReceiver()" }
15671614 }
15681615
1616+ /** A label for a function that is a wrapper around another function. */
1617+ class LabelForwardingFunction extends ApiLabel , MkLabelForwardingFunction {
1618+ override string toString ( ) { result = "getForwardingFunction()" }
1619+ }
1620+
15691621 /** A label for a class decorated by the current value. */
15701622 class LabelDecoratedClass extends ApiLabel , MkLabelDecoratedClass {
15711623 override string toString ( ) { result = "getADecoratedClass()" }
0 commit comments