From f7906352b21b0634745094f7bb7966d5f6941192 Mon Sep 17 00:00:00 2001
From: Olivier Goffart <ogoffart@trolltech.com>
Date: Wed, 9 Sep 2009 08:48:34 +0200
Subject: Fix the bactkrace in the QScript Debugger

This patch remove the 'fake' context  that appears in the debugger
backtrace when there is a break point in the global context.

This problem never appeared in the tests because the
QScriptContext::backtrace has always at least two items in the backtrace
as it needs the native 'bt' function to be called.

Changed QScriptEnginePrivate::contextForFrame to skip the fake frame
(instead of QScriptContext::parentContext). So we never have a QScriptContext
pointing to that frame.

The changes in QScriptContextInfo are for retreiving the right filename
information for the global context when the global context is on top.

Reviewed-by: Kent Hansen
---
 src/script/api/qscriptcontext.cpp     |  7 +------
 src/script/api/qscriptcontextinfo.cpp | 20 ++++++++++----------
 src/script/api/qscriptengine.cpp      |  5 +++++
 3 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp
index 7a09d91..2ca6d26 100644
--- a/src/script/api/qscriptcontext.cpp
+++ b/src/script/api/qscriptcontext.cpp
@@ -374,12 +374,7 @@ QScriptContext *QScriptContext::parentContext() const
 {
     const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
     JSC::CallFrame *callerFrame = frame->callerFrame()->removeHostCallFrameFlag();
-    if (callerFrame && callerFrame->callerFrame()->hasHostCallFrameFlag()
-        && callerFrame->callerFrame()->removeHostCallFrameFlag() == QScript::scriptEngineFromExec(frame)->globalExec()) {
-        //skip the "fake" context created in Interpreter::execute.
-        callerFrame = callerFrame->callerFrame()->removeHostCallFrameFlag();
-    }
-    return reinterpret_cast<QScriptContext *>(callerFrame);
+    return QScriptEnginePrivate::contextForFrame(callerFrame);
 }
 
 /*!
diff --git a/src/script/api/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp
index c22a465..1be76a9 100644
--- a/src/script/api/qscriptcontextinfo.cpp
+++ b/src/script/api/qscriptcontextinfo.cpp
@@ -162,16 +162,19 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte
     // Get the line number:
 
     //We need to know the context directly up in the backtrace, in order to get the line number, and adjust the global context
-    QScriptContext *rewindContext = context->engine()->currentContext();
-    if (rewindContext != context) {  //ignore top context (native function)
+    JSC::CallFrame *rewindContext = QScriptEnginePrivate::get(context->engine())->currentFrame;
+    if (QScriptEnginePrivate::contextForFrame(rewindContext) == context) {  //top context
+        frame = rewindContext; //for retreiving the global context's "fake" frame
+        // An agent might have provided the line number.
+        lineNumber = QScript::scriptEngineFromExec(frame)->agentLineNumber;
+    } else {
         // rewind the stack from the top in order to find the frame from the caller where the returnPC is stored
-        while (rewindContext && rewindContext->parentContext() != context)
-            rewindContext = rewindContext->parentContext();
+        while (rewindContext && QScriptEnginePrivate::contextForFrame(rewindContext->callerFrame()->removeHostCallFrameFlag()) != context)
+            rewindContext = rewindContext->callerFrame()->removeHostCallFrameFlag();
         if (rewindContext) {
-            JSC::ExecState *aboveFrame = QScriptEnginePrivate::frameForContext(rewindContext);
-            frame = aboveFrame->callerFrame()->removeHostCallFrameFlag(); //it will be different for the global context.
+            frame = rewindContext->callerFrame()->removeHostCallFrameFlag(); //for retreiving the global context's "fake" frame
 
-            JSC::Instruction *returnPC = aboveFrame->returnPC();
+            JSC::Instruction *returnPC = rewindContext->returnPC();
             JSC::CodeBlock *codeBlock = frame->codeBlock();
             if (returnPC && codeBlock) {
 #if ENABLE(JIT)
@@ -183,9 +186,6 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte
                 lineNumber = codeBlock->lineNumberForBytecodeOffset(const_cast<JSC::ExecState *>(frame), bytecodeOffset);
             }
         }
-    } else {
-        // An agent might have provided the line number.
-        lineNumber = QScript::scriptEngineFromExec(frame)->agentLineNumber;
     }
 
     // Get the filename and the scriptId:
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index 6dc10d6..087e49c 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -985,6 +985,11 @@ void QScriptEnginePrivate::setDefaultPrototype(int metaTypeId, JSC::JSValue prot
 
 QScriptContext *QScriptEnginePrivate::contextForFrame(JSC::ExecState *frame)
 {
+    if (frame && frame->callerFrame()->hasHostCallFrameFlag()
+        && frame->callerFrame()->removeHostCallFrameFlag() == QScript::scriptEngineFromExec(frame)->globalExec()) {
+        //skip the "fake" context created in Interpreter::execute.
+        frame = frame->callerFrame()->removeHostCallFrameFlag();
+    }
     return reinterpret_cast<QScriptContext *>(frame);
 }
 
-- 
cgit v0.12