summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp14
-rw-r--r--src/script/api/qscriptengine.cpp17
-rw-r--r--src/script/api/qscriptengine_p.h3
-rw-r--r--tests/auto/qscriptcontext/tst_qscriptcontext.cpp25
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 &registerFile = 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;
+ }
}