4

I am trying to find out the name of the function that called my Google Apps Script function, by using arguments.callee.caller as in How do you find out the caller function in JavaScript?, but it seems there's no such property exported. (However, arguments.callee exists.)

How can I get that calling function's name in Google Apps Script?

As a secondary question, why isn't arguments.callee.caller there?

Community
  • 1
  • 1
timchen
  • 378
  • 3
  • 13
  • Can this help? http://stackoverflow.com/questions/10105526/google-apps-script-find-function-caller-id I'm not sure what's your purpose – bpoiss Feb 05 '13 at 17:27
  • @bpoiss - That question is dealing with the deprecated UiApp, while timchen is looking for a JavaScript-like stack trace. Not the same thing, unfortunately. – Mogsdad Mar 08 '16 at 19:49

4 Answers4

4

I made this function:

function getCaller()
{
  var stack;
  var ret = "";
    try 
    {
      throw new Error("Whoops!");
    } 
    catch (e) 
    {
      stack = e.stack;
    }
    finally
    {
      var matchArr = stack.match(/\(.*\)/g);
      if (matchArr.length > 2)
      {
        tmp = matchArr[2];
        ret = tmp.slice(1, tmp.length - 1) + "()";
      }
      return ret;
    }
}

It throws as Error() and then gets the function name from the stack trace. Try vary the '2' in matchArr[2] when using wrappers.

AtheistP3ace
  • 9,611
  • 12
  • 43
  • 43
jgrotius
  • 41
  • 2
  • You could improve this answer with some example code showing how to use it, and Logger output, say, to demonstrate what the outcome is. This sort of answer would be relevant to questions [like this one](http://stackoverflow.com/questions/35855430/get-file-id-or-type-of-google-app-a-function-was-called-from). – Mogsdad Mar 08 '16 at 19:52
  • Clever solution. I tweaked it to return the entire call-chain by defaulting `ret` to an empty array and replacing the logic inside the if with the following: `ret = matchArr.slice(2).map(function(caller) { return caller.slice(1, caller.length - 1) + "()"});` – Jon Senchyna May 04 '17 at 17:13
  • @Mogsdad Calling the proposed `getCaller()` function returns a string that contains whatever called the function you are currently in. e.g if I have the following function `function test() { console.log(getCaller()); }`, calling this function will log the caller of `test()` to the console. – Jon Senchyna May 04 '17 at 17:15
1

caller is a non-standard extension to JavaScript (that is, many browsers have it but it's not part of the EcmaScript standard) and not implemented in Apps Script.

Corey G
  • 7,754
  • 1
  • 28
  • 28
0

I made a function to get the call stack based on jgrotius's answer:

  function getCallStack()
  {
    var returnValue = "";
    var framePattern = /\sat (.+?):(\d+) \((.+?)\)/;
    try 
    {
      throw new Error('');
    } 
    catch (e) 
    {
      returnValue = e.stack
      .split('\n')
      .filter(function(frame, index) {
        return !frame.isBlank() && index > 0;
      })
      // at app/lib/debug:21 (getCaller)
      .map(function(frame) {
        var parts = frame.match(framePattern);
        return {
          file: parts[1],
          line: parseInt(parts[2]),
          func: parts[3]
        };
      });
    }
    return returnValue;
  }  
toddmo
  • 20,682
  • 14
  • 97
  • 107
0

This is my updated version of the other two proposed solutions:

const getStacktrace = () => {
  try {
    throw new Error('')
  } catch (exception) {
    // example: at getStacktrace (helper:6:11)
    const regex = /\sat (.+?) \((.+?):(\d+):(\d+)\)/

    return exception
      .stack
      .split('\n')
      .slice(1, -1)
      .filter((frame, index) => {
        return frame && index > 0
      })
      .map((frame) => {
        const parts = frame.match(regex)

        return {
          function: parts[1],
          file: parts[2],
          line: parseInt(parts[3]),
          column: parseInt(parts[4])
        }
    })
  }
}

P.S.: please not that the regex has changed and also we are ignoring the first element of the stacktrace, since it is the getStacktrace function itself.

GarouDan
  • 3,743
  • 9
  • 49
  • 75