From 3cde4b2dce74419be439b68c1f715a78aed7d6c4 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Fri, 13 May 2011 22:08:26 -0500 Subject: [PATCH] Add Debug.prototype.getYoungestFrame. --- .../tests/debug/Debug-getYoungestFrame-01.js | 20 ++++++++++++++++ .../tests/debug/Debug-getYoungestFrame-02.js | 23 +++++++++++++++++++ js/src/jsdbg.cpp | 21 ++++++++++++++++- js/src/jsdbg.h | 17 ++++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 js/src/jit-test/tests/debug/Debug-getYoungestFrame-01.js create mode 100644 js/src/jit-test/tests/debug/Debug-getYoungestFrame-02.js diff --git a/js/src/jit-test/tests/debug/Debug-getYoungestFrame-01.js b/js/src/jit-test/tests/debug/Debug-getYoungestFrame-01.js new file mode 100644 index 00000000000..77e630ad33b --- /dev/null +++ b/js/src/jit-test/tests/debug/Debug-getYoungestFrame-01.js @@ -0,0 +1,20 @@ +// |jit-test| debug +// getYoungestFrame basics. + +load(libdir + "asserts.js"); + +var g = newGlobal('new-compartment'); +var dbg = new Debug(g); +assertEq(dbg.getYoungestFrame(), null); + +var frame; +function f() { + frame = dbg.getYoungestFrame(); + assertEq(frame instanceof Debug.Frame, true); + assertEq(frame.type, "eval"); + assertEq(frame.older, null); +} +g.h = this; +g.eval("h.f()"); +assertEq(frame.live, false); +assertThrowsInstanceOf(function () { frame.older; }, Error); diff --git a/js/src/jit-test/tests/debug/Debug-getYoungestFrame-02.js b/js/src/jit-test/tests/debug/Debug-getYoungestFrame-02.js new file mode 100644 index 00000000000..fdffa6aa401 --- /dev/null +++ b/js/src/jit-test/tests/debug/Debug-getYoungestFrame-02.js @@ -0,0 +1,23 @@ +// |jit-test| debug +// Hooks and Debug.prototype.getYoungestFrame produce the same Frame object. + +var g = newGlobal('new-compartment'); +var dbg = Debug(g); +var hits = 0; +var savedFrame, savedCallee; +dbg.hooks = { + debuggerHandler: function (frame) { + assertEq(frame, savedFrame); + assertEq(frame.live, true); + assertEq(frame.callee, savedCallee); + hits++; + } +}; +g.h = function () { + savedFrame = dbg.getYoungestFrame(); + savedCallee = savedFrame.callee; + assertEq(savedCallee.name, "f"); +}; +g.eval("function f() { h(); debugger; }"); +g.f(); +assertEq(hits, 1); diff --git a/js/src/jsdbg.cpp b/js/src/jsdbg.cpp index 2a6f3c900c9..9017adcb1a6 100644 --- a/js/src/jsdbg.cpp +++ b/js/src/jsdbg.cpp @@ -690,6 +690,20 @@ Debug::setUncaughtExceptionHook(JSContext *cx, uintN argc, Value *vp) return true; } +JSBool +Debug::getYoungestFrame(JSContext *cx, uintN argc, Value *vp) +{ + THISOBJ(cx, vp, Debug, "getYoungestFrame", thisobj, dbg); + StackFrame *fp = cx->fp(); + while (fp && !dbg->observesFrame(fp)) + fp = fp->prev(); + if (!fp) { + vp->setNull(); + return true; + } + return dbg->getScriptFrame(cx, fp, vp); +} + JSBool Debug::construct(JSContext *cx, uintN argc, Value *vp) { @@ -755,6 +769,11 @@ JSPropertySpec Debug::properties[] = { JS_PS_END }; +JSFunctionSpec Debug::methods[] = { + JS_FN("getYoungestFrame", Debug::getYoungestFrame, 0, 0), + JS_FS_END +}; + // === Debug.Frame Class DebugFrame_class = { @@ -1102,7 +1121,7 @@ JS_DefineDebugObject(JSContext *cx, JSObject *obj) JSObject *debugCtor; JSObject *debugProto = js_InitClass(cx, obj, objProto, &Debug::jsclass, Debug::construct, 1, - Debug::properties, NULL, NULL, NULL, &debugCtor); + Debug::properties, Debug::methods, NULL, NULL, &debugCtor); if (!debugProto || !debugProto->ensureClassReservedSlots(cx)) return false; diff --git a/js/src/jsdbg.h b/js/src/jsdbg.h index 825d890218e..98eb2cb0b96 100644 --- a/js/src/jsdbg.h +++ b/js/src/jsdbg.h @@ -88,8 +88,10 @@ class Debug { static JSBool setEnabled(JSContext *cx, uintN argc, Value *vp); static JSBool getUncaughtExceptionHook(JSContext *cx, uintN argc, Value *vp); static JSBool setUncaughtExceptionHook(JSContext *cx, uintN argc, Value *vp); + static JSBool getYoungestFrame(JSContext *cx, uintN argc, Value *vp); static JSBool construct(JSContext *cx, uintN argc, Value *vp); static JSPropertySpec properties[]; + static JSFunctionSpec methods[]; inline bool hasAnyLiveHooks() const; @@ -101,6 +103,9 @@ class Debug { DebugObservesMethod observesEvent, DebugHandleMethod handleEvent); + inline bool observesScope(JSObject *obj) const; + inline bool observesFrame(StackFrame *fp) const; + bool observesDebuggerStatement() const; JSTrapStatus handleDebuggerStatement(JSContext *cx, Value *vp); @@ -189,6 +194,18 @@ Debug::hasAnyLiveHooks() const return observesDebuggerStatement(); } +bool +Debug::observesScope(JSObject *obj) const +{ + return observesCompartment(obj->compartment()); +} + +bool +Debug::observesFrame(StackFrame *fp) const +{ + return observesScope(&fp->scopeChain()); +} + bool Debug::observesCompartment(JSCompartment *c) const {