mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Add Debug.Frame.prototype.older.
This commit is contained in:
parent
03415943ee
commit
5dc65a5a16
52
js/src/jit-test/tests/debug/Frame-identity-03.js
Normal file
52
js/src/jit-test/tests/debug/Frame-identity-03.js
Normal file
@ -0,0 +1,52 @@
|
||||
// |jit-test| debug
|
||||
// Test that we create new Debug.Frames and reuse old ones correctly with recursion.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
g.debuggeeGlobal = this;
|
||||
g.eval("(" + function () {
|
||||
function id(f) {
|
||||
return ("id" in f) ? f.id : (f.id = nextid++);
|
||||
}
|
||||
|
||||
var dbg = new Debug(debuggeeGlobal);
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (frame) {
|
||||
var a = [];
|
||||
for (; frame; frame = frame.older)
|
||||
a.push(frame);
|
||||
var s = '';
|
||||
while (a.length)
|
||||
s += id(a.pop());
|
||||
results.push(s);
|
||||
}
|
||||
};
|
||||
} + ")();");
|
||||
|
||||
function cons(a, b) {
|
||||
debugger;
|
||||
return [a, b];
|
||||
}
|
||||
|
||||
function tree(n) {
|
||||
if (n < 2)
|
||||
return n;
|
||||
return cons(tree(n - 1), tree(n - 2));
|
||||
}
|
||||
|
||||
g.eval("results = []; nextid = 0;");
|
||||
debugger;
|
||||
assertEq(g.results.join(","), "0");
|
||||
assertEq(g.nextid, 1);
|
||||
|
||||
g.eval("results = [];");
|
||||
tree(2);
|
||||
assertEq(g.results.join(","), "012"); // 0=global, 1=tree, 2=cons
|
||||
|
||||
g.eval("results = []; nextid = 1;");
|
||||
tree(3);
|
||||
assertEq(g.results.join(","), "0123,014"); //0=global, 1=tree(3), 2=tree(2), 3=cons, 4=cons
|
||||
|
||||
g.eval("results = []; nextid = 1;");
|
||||
tree(4);
|
||||
// 0=global, 1=tree(4), 2=tree(3), 3=tree(2), 4=cons, tree(1), 5=cons, 6=tree(2), 7=cons, 8=cons
|
||||
assertEq(g.results.join(","), "01234,0125,0167,018");
|
25
js/src/jit-test/tests/debug/Frame-older-01.js
Normal file
25
js/src/jit-test/tests/debug/Frame-older-01.js
Normal file
@ -0,0 +1,25 @@
|
||||
// |jit-test| debug
|
||||
// Basic call chain.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
g.debuggeeGlobal = this;
|
||||
g.result = null;
|
||||
g.eval("(" + function () {
|
||||
var dbg = new Debug(debuggeeGlobal);
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (frame) {
|
||||
var a = [];
|
||||
assertEq(frame === frame.older, false);
|
||||
for (; frame; frame = frame.older)
|
||||
a.push(frame.type === 'call' ? frame.callee.name : frame.type);
|
||||
a.reverse();
|
||||
result = a.join(", ");
|
||||
}
|
||||
};
|
||||
} + ")();");
|
||||
|
||||
function first() { return second(); }
|
||||
function second() { return eval("third()"); }
|
||||
function third() { debugger; }
|
||||
first();
|
||||
assertEq(g.result, "global, first, second, eval, third");
|
@ -149,9 +149,22 @@ Debug::init()
|
||||
return frames.init() && objects.init();
|
||||
}
|
||||
|
||||
JS_STATIC_ASSERT(uintN(JSSLOT_DEBUGFRAME_OWNER) == uintN(JSSLOT_DEBUGOBJECT_OWNER));
|
||||
|
||||
Debug *
|
||||
Debug::fromChildJSObject(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->clasp == &DebugFrame_class ||
|
||||
obj->clasp == &DebugObject_class ||
|
||||
obj->clasp == &DebugFunction_class);
|
||||
JSObject *dbgobj = &obj->getReservedSlot(JSSLOT_DEBUGOBJECT_OWNER).toObject();
|
||||
return fromJSObject(dbgobj);
|
||||
}
|
||||
|
||||
bool
|
||||
Debug::getScriptFrame(JSContext *cx, StackFrame *fp, Value *vp)
|
||||
{
|
||||
JS_ASSERT(fp->isScriptFrame());
|
||||
FrameMap::AddPtr p = frames.lookupForAdd(fp);
|
||||
if (!p) {
|
||||
// Create script frame. First copy the arguments.
|
||||
@ -734,28 +747,12 @@ DebugFrame_getType(JSContext *cx, uintN argc, Value *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_STATIC_ASSERT(uintN(JSSLOT_DEBUGFRAME_OWNER) == uintN(JSSLOT_DEBUGOBJECT_OWNER));
|
||||
|
||||
static JSBool
|
||||
DebugChild_wrapDebuggeeValue(JSContext *cx, JSObject *frameobj, Value *vp)
|
||||
{
|
||||
// This uses JSSLOT_DEBUGOBJECT_OWNER, but it will work for any object that
|
||||
// has a pointer to the owning Debug object in reserved slot 0.
|
||||
JSObject *dbgobj = &frameobj->getReservedSlot(JSSLOT_DEBUGOBJECT_OWNER).toObject();
|
||||
Debug *dbg = Debug::fromJSObject(dbgobj);
|
||||
if (!dbg->wrapDebuggeeValue(cx, vp)) {
|
||||
vp->setUndefined();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
DebugFrame_getCallee(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
THIS_FRAME(cx, vp, "get callee", thisobj, fp);
|
||||
*vp = (fp->isFunctionFrame() && !fp->isEvalFrame()) ? fp->calleev() : NullValue();
|
||||
return DebugChild_wrapDebuggeeValue(cx, thisobj, vp);
|
||||
return Debug::fromChildJSObject(thisobj)->wrapDebuggeeValue(cx, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -779,7 +776,19 @@ DebugFrame_getThis(JSContext *cx, uintN argc, Value *vp)
|
||||
*vp = fp->thisValue();
|
||||
ac.leave();
|
||||
}
|
||||
return DebugChild_wrapDebuggeeValue(cx, thisobj, vp);
|
||||
return Debug::fromChildJSObject(thisobj)->wrapDebuggeeValue(cx, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
DebugFrame_getOlder(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
THIS_FRAME(cx, vp, "get this", thisobj, thisfp);
|
||||
for (StackFrame *fp = thisfp->prev(); fp; fp = fp->prev()) {
|
||||
if (!fp->isDummyFrame())
|
||||
return Debug::fromChildJSObject(thisobj)->getScriptFrame(cx, fp, vp);
|
||||
}
|
||||
vp->setNull();
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
@ -811,11 +820,12 @@ DebugFrame_construct(JSContext *cx, uintN argc, Value *vp)
|
||||
|
||||
static JSPropertySpec DebugFrame_properties[] = {
|
||||
JS_PSG("type", DebugFrame_getType, 0),
|
||||
JS_PSG("this", DebugFrame_getThis, 0),
|
||||
JS_PSG("older", DebugFrame_getOlder, 0),
|
||||
JS_PSG("live", DebugFrame_getLive, 0),
|
||||
JS_PSG("callee", DebugFrame_getCallee, 0),
|
||||
JS_PSG("generator", DebugFrame_getGenerator, 0),
|
||||
JS_PSG("this", DebugFrame_getThis, 0),
|
||||
JS_PSG("arguments", DebugFrame_getArguments, 0),
|
||||
JS_PSG("live", DebugFrame_getLive, 0),
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
@ -922,7 +932,7 @@ DebugFunction_getName(JSContext *cx, uintN argc, Value *vp)
|
||||
THIS_DEBUGFUNCTION_REFERENT(cx, vp, "get name", funobj);
|
||||
if (JSString *name = funobj->getFunctionPrivate()->atom) {
|
||||
vp->setString(name);
|
||||
return DebugChild_wrapDebuggeeValue(cx, &vp[1].toObject(), vp);
|
||||
return Debug::fromChildJSObject(&vp[1].toObject())->wrapDebuggeeValue(cx, vp);
|
||||
}
|
||||
vp->setNull();
|
||||
return true;
|
||||
|
@ -92,7 +92,6 @@ class Debug {
|
||||
|
||||
inline bool hasAnyLiveHooks() const;
|
||||
|
||||
bool getScriptFrame(JSContext *cx, StackFrame *fp, Value *vp);
|
||||
static void slowPathLeaveStackFrame(JSContext *cx);
|
||||
|
||||
inline bool observesDebuggerStatement() const;
|
||||
@ -104,8 +103,10 @@ class Debug {
|
||||
bool init();
|
||||
inline JSObject *toJSObject() const;
|
||||
static inline Debug *fromJSObject(JSObject *obj);
|
||||
static Debug *fromChildJSObject(JSObject *obj);
|
||||
|
||||
/*********************************** Methods for interaction with the GC. */
|
||||
|
||||
// Methods for interaction with the GC.
|
||||
//
|
||||
// A Debug object is live if:
|
||||
// * the Debug JSObject is live (Debug::trace handles this case); OR
|
||||
@ -131,6 +132,8 @@ class Debug {
|
||||
static inline void leaveStackFrame(JSContext *cx);
|
||||
static inline JSTrapStatus onDebuggerStatement(JSContext *cx, js::Value *vp);
|
||||
|
||||
/**************************************** Functions for use by jsdbg.cpp. */
|
||||
|
||||
// Precondition: *vp is a value from a debuggee compartment and cx is in
|
||||
// the debugger's compartment.
|
||||
//
|
||||
@ -151,6 +154,8 @@ class Debug {
|
||||
//
|
||||
bool unwrapDebuggeeValue(JSContext *cx, Value *vp);
|
||||
|
||||
// Store the Debug.Frame object for the frame fp in *vp.
|
||||
bool getScriptFrame(JSContext *cx, StackFrame *fp, Value *vp);
|
||||
};
|
||||
|
||||
bool
|
||||
|
Loading…
Reference in New Issue
Block a user