michael@0: // We detect and stop the runaway recursion caused by making onEnterFrame a michael@0: // wrapper of a debuggee function. michael@0: michael@0: // This is all a bit silly. In any reasonable design, both debugger re-entry michael@0: // (the second onEnterFrame invocation) and debuggee re-entry (the call to g.f michael@0: // from within the debugger, not via a Debugger invocation function) would raise michael@0: // errors immediately. We have plans to do so, but in the mean time, we settle michael@0: // for at least detecting the recursion. michael@0: michael@0: load(libdir + 'asserts.js'); michael@0: michael@0: var g = newGlobal(); michael@0: g.eval("function f(frame) { n++; return 42; }"); michael@0: g.n = 0; michael@0: michael@0: var dbg = Debugger(); michael@0: var gw = dbg.addDebuggee(g); michael@0: michael@0: // Register the debuggee function as the onEnterFrame handler. When we first michael@0: // call or eval in the debuggee: michael@0: // michael@0: // - The onEnterFrame call reporting that frame's creation is itself an event michael@0: // that must be reported, so we call onEnterFrame again. michael@0: // michael@0: // - SpiderMonkey detects the out-of-control recursion, and generates a "too michael@0: // much recursion" InternalError in the youngest onEnterFrame call. michael@0: // michael@0: // - We don't catch it, so the onEnterFrame handler call itself throws. michael@0: // michael@0: // - Since the Debugger doesn't have an uncaughtExceptionHook (it can't; such a michael@0: // hook would itself raise a "too much recursion" exception), Spidermonkey michael@0: // reports the exception immediately and terminates the debuggee --- which is michael@0: // the next-older onEnterFrame call. michael@0: // michael@0: // - This termination propagates all the way out to the initial attempt to michael@0: // create a frame in the debuggee. michael@0: dbg.onEnterFrame = g.f; michael@0: michael@0: // Get a Debugger.Object instance referring to f. michael@0: var debuggeeF = gw.makeDebuggeeValue(g.f); michael@0: michael@0: // Using f.call allows us to catch the termination. michael@0: assertEq(debuggeeF.call(), null); michael@0: michael@0: // We should never actually begin execution of the function. michael@0: assertEq(g.n, 0); michael@0: michael@0: // When an error is reported, the shell usually exits with a nonzero exit code. michael@0: // If we get here, the test passed, so override that behavior. michael@0: quit(0);