From 94958cf9ff173830fbed66cf4b4158c51df1df7c Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 17 Aug 2009 09:21:03 +0200 Subject: Fix the QScriptContext::argumentsObject and QScriptContext::argument for js functions On js functions, if the number of arguments is different from the number of expected arguments, they are located in different place in the stackframe. We need to call the JSC functions that take that into account. Test is the backtrace test Reviewed-by: Kent Hansen --- src/script/api/qscriptcontext.cpp | 21 ++++++---- tests/auto/qscriptcontext/tst_qscriptcontext.cpp | 53 +++++++++++++++++++++--- 2 files changed, 62 insertions(+), 12 deletions(-) diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp index 229c8ab..118b551 100644 --- a/src/script/api/qscriptcontext.cpp +++ b/src/script/api/qscriptcontext.cpp @@ -273,9 +273,8 @@ QScriptValue QScriptContext::argument(int index) const return QScriptValue(); if (index >= argumentCount()) return QScriptValue(QScriptValue::UndefinedValue); - JSC::Register* thisRegister = frame->registers() - JSC::RegisterFile::CallFrameHeaderSize - frame->argumentCount(); - ++index; //skip the 'this' object - return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(thisRegister[index].jsValue()); + QScriptValue v = argumentsObject().property(index); + return v; } /*! @@ -306,15 +305,23 @@ QScriptValue QScriptContext::callee() const QScriptValue QScriptContext::argumentsObject() const { JSC::CallFrame *frame = const_cast(QScriptEnginePrivate::frameForContext(this)); - if (frame == frame->lexicalGlobalObject()->globalExec()) { - //global context doesn't have any argument, return an empty object + + if (frame == frame->lexicalGlobalObject()->globalExec() || frame->callerFrame()->hasHostCallFrameFlag()) { + // or context doesn't have arguments. return an empty object return QScriptEnginePrivate::get(QScript::scriptEngineFromExec(frame))->newObject(); } - Q_ASSERT(frame->argumentCount() > 0); //we need at least 'this' otherwise we'll crash later + + //for a js function + if (frame->codeBlock() && frame->callee()) { + JSC::JSValue result = frame->interpreter()->retrieveArguments(frame, JSC::asFunction(frame->callee())); + return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result); + } + + //for a native function if (!frame->optionalCalleeArguments()) { + Q_ASSERT(frame->argumentCount() > 0); //we need at least 'this' otherwise we'll crash later JSC::Arguments* arguments = new (&frame->globalData())JSC::Arguments(frame, JSC::Arguments::NoParameters); frame->setCalleeArguments(arguments); - frame[JSC::RegisterFile::ArgumentsRegister] = arguments; } return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(frame->optionalCalleeArguments()); } diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index e5d26a3..a0c56ed 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -565,11 +565,6 @@ void tst_QScriptContext::backtrace_data() QTest::addColumn("expectedbacktrace"); { - QStringList expected; - expected << "(123) at -1" - << "foo([object Object], [object global]) at testfile:2" //### object instead of 'hello' - << "() at testfile:4"; - QString source( "function foo() {\n" " return bt(123);\n" @@ -577,6 +572,12 @@ void tst_QScriptContext::backtrace_data() "foo('hello', { })\n" "var r = 0;"); + QStringList expected; + expected << "(123) at -1" + << "foo('hello', [object Object]) at testfile:2" + << "() at testfile:4"; + + QTest::newRow("simple") << source << expected; } @@ -639,6 +640,48 @@ void tst_QScriptContext::backtrace_data() QTest::newRow("closure") << source << expected; } + + { + QStringList expected; + QString source = QString( + "var o = new Object;\n" + "o.foo = function plop() {\n" + " return eval(\"%1\");\n" + "}\n" + "o.foo('hello', 456)\n" + ).arg("\\n \\n bt('hey'); \\n"); + + expected << "('hey') at -1" + << "() at 3" + //### line number should be 3 but the line number information is not kept for eval call + << "plop('hello', 456) at testfile:-1" + << "() at testfile:5"; + + QTest::newRow("eval in member") << source << expected; + } + + { + QString source( + "function foo(a) {\n" + " return bt(123);\n" + "}\n" + "function bar() {\n" + " var v = foo('arg', 4);\n" + " return v;\n" + "}\n" + "bar('hello', { });\n"); + + QStringList expected; + expected << "(123) at -1" + << "foo(a = 'arg', 4) at testfile:2" + << "bar('hello', [object Object]) at testfile:5" + << "() at testfile:8"; + + + QTest::newRow("two function") << source << expected; + } + + } -- cgit v0.12