diff options
-rw-r--r-- | src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp | 14 | ||||
-rw-r--r-- | src/script/api/qscriptengine.cpp | 17 | ||||
-rw-r--r-- | src/script/api/qscriptengine_p.h | 3 | ||||
-rw-r--r-- | tests/auto/qscriptcontext/tst_qscriptcontext.cpp | 25 |
4 files changed, 50 insertions, 9 deletions
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp index c31216b..bfb0307 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp @@ -3071,8 +3071,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (callType == CallTypeHost) { ScopeChainNode* scopeChain = callFrame->scopeChain(); CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); +#ifdef QT_BUILD_SCRIPT_LIB //we need the returnValue to be 0 as it is used as flags + newCallFrame->init(0, vPC + 5, scopeChain, callFrame, 0, argCount, asObject(v)); +#else newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, asObject(v)); - +#endif Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; ArgList args(thisRegister + 1, argCount - 1); @@ -3225,7 +3228,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (callType == CallTypeHost) { ScopeChainNode* scopeChain = callFrame->scopeChain(); CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); +#ifdef QT_BUILD_SCRIPT_LIB //we need the returnValue to be 0 as it is used as flags + newCallFrame->init(0, vPC + 5, scopeChain, callFrame, 0, argCount, asObject(v)); +#else newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, asObject(v)); +#endif + Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; ArgList args(thisRegister + 1, argCount - 1); @@ -3501,7 +3509,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ScopeChainNode* scopeChain = callFrame->scopeChain(); CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); +#ifdef QT_BUILD_SCRIPT_LIB //we need the returnValue to be 0 as it is used as flags + newCallFrame->init(0, vPC + 7, scopeChain, callFrame, 0, argCount, asObject(v)); +#else newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, asObject(v)); +#endif JSValue returnValue; { diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 78bbf5f..b27d1be 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -2353,23 +2353,25 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV //build a frame JSC::CallFrame *newCallFrame = exec; if (callee == 0 //called from public QScriptEngine::pushContext - || exec->returnPC() == 0 || (contextFlags(exec) & NativeContext) //called from native-native call + || exec->returnPC() == 0 || (contextFlags(exec) & NativeContext) //called from native-native call || (exec->codeBlock() && exec->callee() != callee)) { //the interpreter did not build a frame for us. //We need to check if the Interpreter might have already created a frame for function called from JS. JSC::Interpreter *interp = exec->interpreter(); JSC::Register *oldEnd = interp->registerFile().end(); int argc = args.size() + 1; //add "this" JSC::Register *newEnd = oldEnd + argc + JSC::RegisterFile::CallFrameHeaderSize; - if (!interp->registerFile().grow(newEnd)) + //Without + argc + JSC::RegisterFile::CallFrameHeaderSize, it crashes. + //It seems that JSC is not consistant with the way the callframe is crated + if (!interp->registerFile().grow(newEnd + argc + JSC::RegisterFile::CallFrameHeaderSize)) return 0; //### Stack overflow - newCallFrame = JSC::CallFrame::create(oldEnd); + newCallFrame = JSC::CallFrame::create(newEnd); newCallFrame[0] = thisObject; int dst = 0; JSC::ArgList::const_iterator it; for (it = args.begin(); it != args.end(); ++it) newCallFrame[++dst] = *it; newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize; - newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags, argc, callee); + newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); } else { setContextFlags(newCallFrame, flags); #if ENABLE(JIT) @@ -2411,18 +2413,19 @@ void QScriptEngine::popContext() */ void QScriptEnginePrivate::popContext() { - bool hasScope = contextFlags(currentFrame) & HasScopeContext; - if (currentFrame->returnPC() == 0) { //normal case + uint flags = contextFlags(currentFrame); + bool hasScope = flags & HasScopeContext; + if (flags & ShouldRestoreCallFrame) { //normal case JSC::RegisterFile ®isterFile = currentFrame->interpreter()->registerFile(); JSC::Register *const newEnd = currentFrame->registers() - JSC::RegisterFile::CallFrameHeaderSize - currentFrame->argumentCount(); if (hasScope) currentFrame->scopeChain()->pop()->deref(); - currentFrame = currentFrame->callerFrame(); registerFile.shrink(newEnd); } else if(hasScope) { //the stack frame was created by the Interpreter, we don't need to rewind it. currentFrame->setScopeChain(currentFrame->scopeChain()->pop()); currentFrame->scopeChain()->deref(); } + currentFrame = currentFrame->callerFrame(); } /*! diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index c43ca61..b8b805e 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -170,7 +170,8 @@ public: enum ContextFlags { NativeContext = 1, CalledAsConstructorContext = 2, - HasScopeContext = 4 + HasScopeContext = 4, // Specifies that the is a QScriptActivationObject + ShouldRestoreCallFrame = 8 }; static uint contextFlags(JSC::ExecState *); static void setContextFlags(JSC::ExecState *, uint); diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index 063075d..461c994 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -724,6 +724,31 @@ void tst_QScriptContext::backtrace_data() QTest::newRow("call native") << source << expected; } + + { + QLatin1String func( "function f1() {\n" + " eval('var q = 4');\n" + " return custom_call(bt, 22);\n" + "}"); + + QString source = QString::fromLatin1("\n" + "function f2() {\n" + " func = %1\n" + " return custom_call(func, 12);\n" + "}\n" + "f2();\n").arg(func); + + QStringList expected; + expected << "<native>(22) at -1" + << "<native>(function () {\n [native code]\n}, 22) at -1" + << "f1(12) at testfile:5" + << QString::fromLatin1("<native>(%1, 12) at -1").arg(func) + << "f2() at testfile:7" + << "<global>() at testfile:9"; + + + QTest::newRow("calls with closures") << source << expected; + } } |