Bug 967718 - Observe script and frame observance rules in Debugger more systematically. (r=jimb)

This commit is contained in:
Shu-yu Guo 2014-02-11 12:05:19 -08:00
parent 8e92ad5678
commit 234c6a1c8a
4 changed files with 50 additions and 24 deletions

View File

@ -0,0 +1,15 @@
var g = newGlobal();
var dbg = new Debugger(g);
var visibleFrames = 0;
dbg.onEnterFrame = function (frame) {
print("> " + frame.script.url);
visibleFrames++;
}
g.eval("(" + function iife() {
[1].forEach(function noop() {});
for (let x of [1]) {}
} + ")()");
// 1 for eval, 1 for iife(), 1 for noop()
assertEq(visibleFrames, 3);

View File

@ -521,9 +521,11 @@ Debugger::slowPathOnEnterFrame(JSContext *cx, AbstractFramePtr frame, MutableHan
if (GlobalObject::DebuggerVector *debuggers = global->getDebuggers()) {
for (Debugger **p = debuggers->begin(); p != debuggers->end(); p++) {
Debugger *dbg = *p;
JS_ASSERT(dbg->observesFrame(frame));
if (dbg->observesEnterFrame() && !triggered.append(ObjectValue(*dbg->toJSObject())))
if (dbg->observesFrame(frame) && dbg->observesEnterFrame() &&
!triggered.append(ObjectValue(*dbg->toJSObject())))
{
return JSTRAP_ERROR;
}
}
}
@ -1097,13 +1099,14 @@ Debugger::dispatchHook(JSContext *cx, MutableHandleValue vp, Hook which)
}
static bool
AddNewScriptRecipients(GlobalObject::DebuggerVector *src, AutoValueVector *dest)
AddNewScriptRecipients(GlobalObject::DebuggerVector *src, HandleScript script,
AutoValueVector *dest)
{
bool wasEmpty = dest->length() == 0;
for (Debugger **p = src->begin(); p != src->end(); p++) {
Debugger *dbg = *p;
Value v = ObjectValue(*dbg->toJSObject());
if (dbg->observesNewScript() &&
if (dbg->observesScript(script) && dbg->observesNewScript() &&
(wasEmpty || Find(dest->begin(), dest->end(), v) == dest->end()) &&
!dest->append(v))
{
@ -1116,9 +1119,6 @@ AddNewScriptRecipients(GlobalObject::DebuggerVector *src, AutoValueVector *dest)
void
Debugger::slowPathOnNewScript(JSContext *cx, HandleScript script, GlobalObject *compileAndGoGlobal_)
{
if (script->selfHosted())
return;
Rooted<GlobalObject*> compileAndGoGlobal(cx, compileAndGoGlobal_);
JS_ASSERT(script->compileAndGo() == !!compileAndGoGlobal);
@ -1132,13 +1132,13 @@ Debugger::slowPathOnNewScript(JSContext *cx, HandleScript script, GlobalObject *
AutoValueVector triggered(cx);
if (script->compileAndGo()) {
if (GlobalObject::DebuggerVector *debuggers = compileAndGoGlobal->getDebuggers()) {
if (!AddNewScriptRecipients(debuggers, &triggered))
if (!AddNewScriptRecipients(debuggers, script, &triggered))
return;
}
} else {
GlobalObjectSet &debuggees = script->compartment()->getDebuggees();
for (GlobalObjectSet::Range r = debuggees.all(); !r.empty(); r.popFront()) {
if (!AddNewScriptRecipients(r.front()->getDebuggers(), &triggered))
if (!AddNewScriptRecipients(r.front()->getDebuggers(), script, &triggered))
return;
}
}
@ -3513,7 +3513,7 @@ DebuggerScript_getLineOffsets(JSContext *cx, unsigned argc, Value *vp)
bool
Debugger::observesFrame(AbstractFramePtr frame) const
{
return observesGlobal(&frame.script()->global());
return observesScript(frame.script());
}
bool
@ -3521,7 +3521,8 @@ Debugger::observesScript(JSScript *script) const
{
if (!enabled)
return false;
return observesGlobal(&script->global()) && !script->selfHosted();
return observesGlobal(&script->global()) && (!script->selfHosted() ||
SelfHostedFramesVisible());
}
/* static */ bool

View File

@ -1222,10 +1222,17 @@ ScriptFrameIter::frameSlotValue(size_t index) const
#endif
#ifdef DEBUG
/* static */
bool NonBuiltinScriptFrameIter::includeSelfhostedFrames() {
static char* env = getenv("MOZ_SHOW_ALL_JS_FRAMES");
return (bool)env;
bool
js::SelfHostedFramesVisible()
{
static bool checked = false;
static bool visible = false;
if (!checked) {
checked = true;
char *env = getenv("MOZ_SHOW_ALL_JS_FRAMES");
visible = !!env;
}
return visible;
}
#endif

View File

@ -1592,21 +1592,24 @@ class ScriptFrameIter
inline void ionForEachCanonicalActualArg(JSContext *cx, Op op);
};
#ifdef DEBUG
bool SelfHostedFramesVisible();
#else
static inline bool
SelfHostedFramesVisible()
{
return false;
}
#endif
/* A filtering of the ScriptFrameIter to only stop at non-self-hosted scripts. */
class NonBuiltinScriptFrameIter : public ScriptFrameIter
{
#ifdef DEBUG
static bool includeSelfhostedFrames();
#else
static bool includeSelfhostedFrames() {
return false;
}
#endif
void settle() {
if (!includeSelfhostedFrames())
if (!SelfHostedFramesVisible()) {
while (!done() && script()->selfHosted())
ScriptFrameIter::operator++();
}
}
public: