aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlcompiler.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-10-09 09:37:08 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-11 22:55:08 +0200
commit28f67263a181e2d99b2c240f9d698bf64100ac92 (patch)
tree3c7c6287e00d6032ff53a78b7a9b0caa51cc9d23 /src/qml/qml/qqmlcompiler.cpp
parent774963f52f569e637f45d6c6079121253e54b61b (diff)
Compile signal handler expressions in the loader thread
Handle them similar to function declarations, except that we need to synthesize the expression into a function declaration that includes the signal parameter names. This is done quite similar to the code path in the new compiler. Change-Id: I751081f7f1052692da6e2ed60c7f5c017372d829 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml/qqmlcompiler.cpp')
-rw-r--r--src/qml/qml/qqmlcompiler.cpp58
1 files changed, 56 insertions, 2 deletions
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index d14c790aad..697d255a3e 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -812,6 +812,7 @@ bool QQmlCompiler::compile(QQmlEngine *engine,
this->output = out;
this->functionsToCompile.clear();
this->compiledMetaMethods.clear();
+ this->compiledSignalHandlers.clear();
// Compile types
const QList<QQmlTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes();
@@ -963,6 +964,10 @@ void QQmlCompiler::compileTree(QQmlScript::Object *tree)
md.runtimeFunctionIndex = runtimeFunctionIndices.at(cmm.compiledFunctionIndex);
}
+ foreach (const CompiledSignalHandlerExpression &expr, compiledSignalHandlers) {
+ expr.signal->signalData.functionIndex = runtimeFunctionIndices.at(expr.compiledHandlerIndex);
+ }
+
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Compiler::JSUnitGenerator jsUnitGenerator(&jsModule);
QScopedPointer<QQmlJS::EvalInstructionSelection> isel(v4->iselFactory->create(v4->executableAllocator, &jsModule, &jsUnitGenerator));
@@ -1380,11 +1385,12 @@ void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
} else if (v->type == Value::SignalExpression) {
Instruction::StoreSignal store;
+ store.runtimeFunctionIndex = v->signalData.functionIndex;
store.handlerName = output->indexForString(prop->name().toString());
store.parameters = output->indexForString(obj->metatype->signalParameterStringForJS(prop->index));
store.signalIndex = prop->index;
store.value = output->indexForString(v->value.asScript());
- store.context = v->signalExpressionContextStack;
+ store.context = v->signalData.signalExpressionContextStack;
store.line = v->location.start.line;
store.column = v->location.start.column;
output->addInstruction(store);
@@ -1678,6 +1684,42 @@ int QQmlCompiler::translationContextIndex()
return cachedTranslationContextIndex;
}
+static AST::FunctionDeclaration *convertSignalHandlerExpressionToFunctionDeclaration(QQmlJS::Engine *jsEngine,
+ AST::Node *node,
+ const QString &signalName,
+ const QList<QByteArray> &parameters)
+{
+ QQmlJS::MemoryPool *pool = jsEngine->pool();
+
+ AST::FormalParameterList *paramList = 0;
+ foreach (const QByteArray &param, parameters) {
+ QStringRef paramNameRef = jsEngine->newStringRef(QString::fromUtf8(param));
+
+ if (paramList)
+ paramList = new (pool) AST::FormalParameterList(paramList, paramNameRef);
+ else
+ paramList = new (pool) AST::FormalParameterList(paramNameRef);
+ }
+
+ if (paramList)
+ paramList = paramList->finish();
+
+ AST::Statement *statement = node->statementCast();
+ if (!statement) {
+ AST::ExpressionNode *expr = node->expressionCast();
+ Q_ASSERT(expr);
+ statement = new (pool) AST::ExpressionStatement(expr);
+ }
+ AST::SourceElement *sourceElement = new (pool) AST::StatementSourceElement(statement);
+ AST::SourceElements *elements = new (pool) AST::SourceElements(sourceElement);
+ elements = elements->finish();
+
+ AST::FunctionBody *body = new (pool) AST::FunctionBody(elements);
+
+ AST::FunctionDeclaration *functionDeclaration = new (pool) AST::FunctionDeclaration(jsEngine->newStringRef(signalName), paramList, body);
+ return functionDeclaration;
+}
+
bool QQmlCompiler::buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj,
const BindingContext &ctxt)
{
@@ -1744,7 +1786,19 @@ bool QQmlCompiler::buildSignal(QQmlScript::Property *prop, QQmlScript::Object *o
//all handlers should be on the original, rather than cloned signals in order
//to ensure all parameters are available (see qqmlboundsignal constructor for more details)
prop->index = obj->metatype->originalClone(prop->index);
- prop->values.first()->signalExpressionContextStack = ctxt.stack;
+ prop->values.first()->signalData.signalExpressionContextStack = ctxt.stack;
+
+ CompiledSignalHandlerExpression expr;
+ expr.signal = prop->values.first();
+
+ QList<QByteArray> parameters = obj->metatype->signalParameterNames(prop->index);
+
+ AST::FunctionDeclaration *funcDecl = convertSignalHandlerExpressionToFunctionDeclaration(unit->parser().jsEngine(), prop->values.first()->value.asAST(), propName.toString(), parameters);
+ functionsToCompile.append(funcDecl);
+
+ expr.compiledHandlerIndex = functionsToCompile.count() - 1;
+ compiledSignalHandlers.append(expr);
+ prop->values.first()->signalData.functionIndex = 0; // To be filled in before gen()
QString errorString;
obj->metatype->signalParameterStringForJS(prop->index, &errorString);