Closed Bug 332104 Opened 14 years ago Closed 11 years ago

recursion thwarts arguments.callee.caller

Categories

(Core :: JavaScript Engine, defect)

defect
Not set

Tracking

()

RESOLVED WONTFIX

People

(Reporter: danswer, Unassigned)

Details

User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1
Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1

Within a function it's possible to find the entire stack of functions calling the given one by doing something like:
function getStack() {
  var aStack = [arguments.callee];    // self
  while (aStack[0].caller) aStack.unshift(aStack[0].caller);
  return aStack;
}

However, if any function on up this chain (including the current one), was called recursively, then this approach fails, since .caller points to the function object and not the activation object (so .caller will keep returning the recursed function).

There used to be a .__caller__ (mentioned in Bug 65683) that pointed to the activation object, but that was let go as a security precaution.

However, there is a simple way to achieve the ability to get the complete stack trace if we allow arguments.__parent__ to point to the arguments object of the calling function (activation object).  That way, the following revised function would yeild the stack (without recursion related problems) at the same time avoiding a pointer to the activation object (As a side benefit, relying on .caller is no longer necessary).

function getStack2() {
  var oArg = arguments;
  var aStack = [oArg.callee];    // self
  while (oArg=oArg.__parent__) aStack.unshift(oArg.callee);
  return aStack;
}

Csaba Gabor from Vienna


Reproducible: Always

Steps to Reproduce:
function foo(lev) {
  if (arguments.length) return getStack();
  else return foo(1); }
function bar() {
  alert (foo().join("; ")); }
foo();

Actual Results:  
Mozilla eventually asks me if I want to stop the current unresponsive script as it may be busy or unresponsive (or recursing ad infinitum).


Expected Results:  
If I use getStack2, I should get a stack trace showing bar, foo twice, and then getStack2.


There is a __parent__ on function objects pointing (I think) to where they live.  So maybe __parent__ is not the best name to use.
(In reply to comment #0)
> However, if any function on up this chain (including the current one), was
> called recursively, then this approach fails, since .caller points to the
> function object and not the activation object 

caller never points to the activation object, only to a function object; arguments.callee points to a function object.

> (so .caller will keep returning
> the recursed function).

This follows from the fact that only function objects are reflected.

> There used to be a .__caller__ (mentioned in Bug 65683) that pointed to the
> activation object, but that was let go as a security precaution.
> 
> However, there is a simple way to achieve the ability to get the complete stack
> trace if we allow arguments.__parent__ to point to the arguments object of the
> calling function (activation object).  That way, the following revised function
> would yeild the stack (without recursion related problems) at the same time
> avoiding a pointer to the activation object (As a side benefit, relying on
> .caller is no longer necessary).

The reason __caller__ was removed would apply here too.  But, we could try to secure the boundaries of the trust model against this new connection point.

> There is a __parent__ on function objects pointing (I think) to where they
> live.  So maybe __parent__ is not the best name to use.

Right, __parent__ in SpiderMonkey is what ECMA-262 Edition 3 calls [[Scope]] on function objects, but it is universal.

The bad news is that we are not going to hack yet more non-standard reflection APIs into SpiderMonkey.

The good news is that ECMA TG1 is busy working on Edition 4, and part of that (still not a done deal) is stack reflection.

This bug should be WONTFIXed, it's not INVALID but it is not going to be "fixed".  Instead we are going to implement the Edition 4 draft, once it has stabilized.
 
/be
Status: UNCONFIRMED → NEW
Ever confirmed: true
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → WONTFIX
(In reply to comment #1)
> 
> The bad news is that we are not going to hack yet more non-standard reflection
> APIs into SpiderMonkey.
> 

Assuming this is still true.
You need to log in before you can comment on or make changes to this bug.