From 81d8292e486bce768d9af27e3510520a769c4fa8 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 11 Aug 2009 09:35:50 +0200 Subject: Fix line number and arguments in QScriptContext::toString For arguments, we always need to skip the implicit 'this' argument For line number, we walk thought the stack frames from the top to find the one above the requested one, which contains the returnPC we need. Also fixed a crash because QScriptContext::parentContext would have returned a pointer with flags inside. Reviewed-by: Kent Hansen --- src/script/api/qscriptcontext.cpp | 7 ++----- src/script/api/qscriptcontextinfo.cpp | 20 ++++++++++++++++++-- tests/auto/qscriptcontext/tst_qscriptcontext.cpp | 1 - .../qscriptcontextinfo/tst_qscriptcontextinfo.cpp | 1 - 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp index 669002d..f4b8af6 100644 --- a/src/script/api/qscriptcontext.cpp +++ b/src/script/api/qscriptcontext.cpp @@ -273,8 +273,7 @@ QScriptValue QScriptContext::argument(int index) const if (index >= argumentCount()) return QScriptValue(QScriptValue::UndefinedValue); JSC::Register* thisRegister = frame->registers() - JSC::RegisterFile::CallFrameHeaderSize - frame->argumentCount(); - if (frame->codeBlock() == 0) - ++index; // ### off-by-one issue with native functions + ++index; //skip the 'this' object return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(thisRegister[index].jsValue()); } @@ -370,9 +369,7 @@ bool QScriptContext::isCalledAsConstructor() const QScriptContext *QScriptContext::parentContext() const { const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); - JSC::CallFrame *callerFrame = frame->callerFrame(); - if (callerFrame == (JSC::CallFrame*)(1)) // ### CallFrame::noCaller() is private - return 0; + JSC::CallFrame *callerFrame = frame->callerFrame()->removeHostCallFrameFlag(); return reinterpret_cast(callerFrame); } diff --git a/src/script/api/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp index 52776e2..20b77f0 100644 --- a/src/script/api/qscriptcontextinfo.cpp +++ b/src/script/api/qscriptcontextinfo.cpp @@ -174,8 +174,6 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte for (size_t i = 0; i < body->parameterCount(); ++i) parameterNames.append(QScript::qtStringFromJSCUString(params[i].ustring())); // ### get the function name from the AST - // ### don't know the PC, since it's not stored in the frame - // lineNumber = codeBlock->expressionRangeForBytecodeOffset(...); } else if (callee && callee->isObject(&QScript::QtFunction::info)) { functionType = QScriptContextInfo::QtFunction; // ### the slot can be overloaded -- need to get the particular overload from the context @@ -192,6 +190,24 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte functionType = QScriptContextInfo::QtPropertyFunction; functionMetaIndex = static_cast(callee)->propertyIndex(); } + + // get the lineNumber: + QScriptContext *rewindContext = context->engine()->currentContext(); + if (rewindContext == context) { + //ignore native function + } 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(); + if (rewindContext) { + JSC::Instruction *returnPC = QScriptEnginePrivate::frameForContext(rewindContext)->returnPC(); + JSC::CodeBlock *codeBlock = frame->codeBlock(); + if (returnPC && codeBlock) { + lineNumber = codeBlock->lineNumberForBytecodeOffset(const_cast(frame), + returnPC - codeBlock->instructions().begin()); + } + } + } } /*! diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index a278d2c..be0b2b7 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -791,7 +791,6 @@ void tst_QScriptContext::toString() " return parentContextToString();\n" "}; foo(1, 2, 3)", "script.qs"); QVERIFY(ret.isString()); - QEXPECT_FAIL("", "", Continue); QCOMPARE(ret.toString(), QString::fromLatin1("foo (first=1, second=2, third=3) at script.qs:2")); } diff --git a/tests/auto/qscriptcontextinfo/tst_qscriptcontextinfo.cpp b/tests/auto/qscriptcontextinfo/tst_qscriptcontextinfo.cpp index 0877717..921cbd8 100644 --- a/tests/auto/qscriptcontextinfo/tst_qscriptcontextinfo.cpp +++ b/tests/auto/qscriptcontextinfo/tst_qscriptcontextinfo.cpp @@ -185,7 +185,6 @@ void tst_QScriptContextInfo::scriptFunction() QCOMPARE(info.functionType(), QScriptContextInfo::ScriptFunction); QVERIFY(info.scriptId() != -1); QCOMPARE(info.fileName(), fileName); - QEXPECT_FAIL("", "lineNumber doesn't work", Continue); QCOMPARE(info.lineNumber(), lineNumber + 1); QEXPECT_FAIL("", "columnNumber doesn't work", Continue); QCOMPARE(info.columnNumber(), 2); -- cgit v0.12