4

JavaScript (browser): I want to find out how deep the stack is. Basically, I want to know how many lines would be printed if I would call console.trace(). But I don't want to call console.trace() (and then count lines in the console window), I just want to 'have' that number of lines in a variable which I can then store to get some kind of performance statistics. Here is an example.

function StackTest(limit){
    this.inc = -1;
    this.limit = limit;
}
StackTest.prototype.test = function(n){
    //console.log(n);
    if (n>this.limit){
        console.trace();
        return [n, this.inc];
    }
    this.inc += 2;
    return this.test(n + this.inc);
}
test899 = new StackTest(899);
document.body.innerHTML = test899.test(0);

Above dummy code sums up odd numbers (which generates the sequence of square numbers), until the sum exceeds a given limit, here 899. So, we compute 1 + 3 + 5 + ... + 59 = 900; 900 is the first square exceeding our limit of 899.

The stack depth (for the innermost return) is 30 (as we summed up 30 numbers, namely the odd numbers below 60), and console.trace() will print out 30 lines (to be more exact, 30 lines referring to the last line of our test function)

I want this 30, but I don't want to call console.trace(). Neither do I want to modify my code and put in manual counters. Neither do I want anything specific to the dummy example (like depth = (1+this.inc)/2 or depth=Math.ceil(Math.sqrt(this.limit))); I want a generic way to get the 30 programmatically.

Is that possible?

I should mention: One thing which does not work: generating (not throwing, just creating) an Error with e = new Error('blah'), then doing e.stack, then doing .split('\n') on that to see how many lines there are. The reason this does not work is that the Error stack is 'cut down' to only the topmost couple of lines/frames of the 'real' stack. If there would be something like e.fullStack, that would give me what I want. If error objects as the above have the information I want, then I was unable to find it there.

UPDATE

one more thing which does not work: Error.captureStackTrace, taken from accepted answer to this question. It's 'cut down' also, and therefore, this really shouldn't be the accepted answer!!!

CLARIFICATION

What I'm doing is analyzing/comparing various performance measures of various algorithms. Among the performance measures are run time, space requirements, and stack depth (which is, kind of, a special case of 'space requirements'). The measures are graphed with the problem size on the horizontal axis, and run time etc vertically. To be able to construct graphs like this, obviously, it helps to have functions which do programmatically what otherwise would be done via debugger / console tools.

Please, please spare me with dull lectures about how I allegedly advocate some weirdo programming style, and other far-fetched assumptions on how I write code, just to construct an hallucinated argument for why I "don't need" and/or "shouldn't want" what I'm asking for. More angry rant (very optional)

If you have a rational argument against the existence of the feature, such as security concerns, different story, obviously.

mathheadinclouds
  • 3,507
  • 2
  • 27
  • 37
  • one more thing which *does not* work: using the 'old-fashioned' `arguments.callee.caller` thing in a loop. If the same function occurs twice in the stack trace, you'll get the exact same function (`===`) again in your chain, rather than some object representing the function (and the different arguments). Thus, if you're doing a while loop until `.caller.caller.caller.caller....` gives null, that will give you an infinite loop. – mathheadinclouds Jul 07 '20 at 06:02
  • 1
    I don't think there's a way. That's a thing that your code can't and *shouldn't* have access to (functions shouldn't rely on what have called them)... You'll have to stick to counters. – FZs Jul 07 '20 at 06:05
  • related: https://stackoverflow.com/questions/147891/javascript-exception-stack-trace?noredirect=1&lq=1 – mathheadinclouds Jul 07 '20 at 06:13
  • related: https://stackoverflow.com/questions/591857/how-can-i-get-a-javascript-stack-trace-when-i-throw-an-exception – mathheadinclouds Jul 07 '20 at 06:13
  • @FZs: the whole point of functions is to depend on *arguments* = 'what have called them'; what you want to say (as I understand it), is not that functions shouldn't have arguments - it's that functions shouldn't have *hidden* arguments - that is something making a programming language less readable, we agree. That you should see in the head-only portion of the function (i.e. line 1) what the arguments are. And the stack trace is (if used) a hidden argument. All true. But now, JavaScript *already* violates this. With the `this` object, which is nothing other than a hidden argument. – mathheadinclouds Jul 07 '20 at 11:02
  • @FZs (continued) and the available portion of the stack trace (what (new Error()).stack or Error.getStackTrace give you) violate it (the principle that function shouldn't have hidden arguments) some more. So if it's already violated, why try to make a half baked infeasible attempt to half-save it. I do not get the point. Also, this is more a "nice to have thing" than something "essential". My legitimate code analysis concerns are much more "essential", IMHO. – mathheadinclouds Jul 07 '20 at 11:06
  • 1
    I agree with those. However, I still don't think there's a way. (and I assume `new Error().stack` and alike exist to allow providing meaningful information *to the developer*, not to be used by the program after applying crazy regexes on them...) – FZs Jul 07 '20 at 17:10
  • "*The stack depth is 30. I want this 30*" - why? The stack depth should not matter at all. If it *does* matter for your code, then you should change it to explicitly pass through a counter. – Bergi Jul 08 '20 at 13:56
  • For debugging, you can just view the stack at a `debugger` breakpoint, or when you use call tracing you will be able to see the height of the flame graph. You would not put anything in your code for that, it's all just done by the tooling. – Bergi Jul 08 '20 at 14:35
  • @mathheadinclouds The deep equality thing has nothing to do with recursion or depth. One needs an algorithm which does not follow cyclical references, you don't do that by checking recursion depth. For checking whether your assumptions are correct, you just debug your code - whether with `console.trace()` or breakpoints is your call. – Bergi Jul 08 '20 at 14:47
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/217466/discussion-between-mathheadinclouds-and-bergi). – mathheadinclouds Jul 08 '20 at 14:49

0 Answers0