diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-10-09 09:37:08 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-10-11 22:55:08 +0200 |
commit | 28f67263a181e2d99b2c240f9d698bf64100ac92 (patch) | |
tree | 3c7c6287e00d6032ff53a78b7a9b0caa51cc9d23 /src/qml/qml/qqmlcompiler.cpp | |
parent | 774963f52f569e637f45d6c6079121253e54b61b (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.cpp | 58 |
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> ¶meters) +{ + QQmlJS::MemoryPool *pool = jsEngine->pool(); + + AST::FormalParameterList *paramList = 0; + foreach (const QByteArray ¶m, 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); |